GDB: Work around buggy Dwarf lineinfo produced by third party compiler.

Message ID 20181003084907.29538-1-john@darrington.wattle.id.au
State New, archived
Headers

Commit Message

John Darrington Oct. 3, 2018, 8:49 a.m. UTC
  * gdb/dwarf2read.c (producer_is_codewarrior): New function.
* gdb/dwarf2read.c (lnp_state_machine::record_line): Ignore is_stmt
  flag for records produced by codewarrior.
---
 gdb/dwarf2read.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)
  

Comments

Simon Marchi Oct. 7, 2018, 10:21 p.m. UTC | #1
On 2018-10-03 4:49 a.m., John Darrington wrote:
> * gdb/dwarf2read.c (producer_is_codewarrior): New function.
> * gdb/dwarf2read.c (lnp_state_machine::record_line): Ignore is_stmt
>   flag for records produced by codewarrior.

Hi John,

The code looks good to me, but could you mention (both in the commit log and the
code) what compiler version you are using?  If somebody comes up later and says
this workaround breaks their debugging of codewarrior-generated code, we'll have
a bit of data to sort it out.

I think we've talked about it on IRC, but if I understand correctly, this is not
a maintained product anymore, so there's no use of notifying the publisher so they
fix the problem in the compiler?

On nit, you could use "bool" as a return type for producer_is_codewarrior (the other
producer_is_* functions were written pre-switch-to-C++).

For the ChangeLog, the paths should be relative to the ChangeLog (gdb/ChangeLog)
in this case, so you would remove the leading gdb/.  Also, you would not repeat
the same filename, just put the entries in the same file after.  Finally, there
are some entries missing.  Overall, it could look like this:

	* dwarf2read.c (dwarf2_cu) <producer_is_codewarrior>: New field.
	(check_producer): Check if the producer is codewarrior.
	(producer_is_codewarrior): New function.
	(lnp_state_machine::record_line): Ignore is_stmt flag for records
	produced by codewarrior.
	(dwarf2_cu::dwarf2_cu): Initialize producer_is_codewarrior.

Thanks,

Simon
  

Patch

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 4a35e389e9..62f2937f3f 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -552,6 +552,7 @@  struct dwarf2_cu
   unsigned int producer_is_gxx_lt_4_6 : 1;
   unsigned int producer_is_gcc_lt_4_3 : 1;
   unsigned int producer_is_icc_lt_14 : 1;
+  unsigned int producer_is_codewarrior : 1;
 
   /* When set, the file that we're processing is known to have
      debugging info for C++ namespaces.  GCC 3.3.x did not produce
@@ -14903,6 +14904,8 @@  check_producer (struct dwarf2_cu *cu)
     }
   else if (producer_is_icc (cu->producer, &major, &minor))
     cu->producer_is_icc_lt_14 = major < 14;
+  else if (startswith (cu->producer, "CodeWarrior S12/L-ISA"))
+    cu->producer_is_codewarrior = true;
   else
     {
       /* For other non-GCC compilers, expect their behavior is DWARF version
@@ -14925,6 +14928,19 @@  producer_is_gxx_lt_4_6 (struct dwarf2_cu *cu)
   return cu->producer_is_gxx_lt_4_6;
 }
 
+
+/* Codewarrior generates dwarf line information with incorrect is_stmt
+   attributes.  */
+
+static int
+producer_is_codewarrior (struct dwarf2_cu *cu)
+{
+  if (!cu->checked_producer)
+    check_producer (cu);
+
+  return cu->producer_is_codewarrior;
+}
+
 /* Return the default accessibility type if it is not overriden by
    DW_AT_accessibility.  */
 
@@ -20789,7 +20805,7 @@  lnp_state_machine::record_line (bool end_sequence)
   else if (m_op_index == 0 || end_sequence)
     {
       fe->included_p = 1;
-      if (m_record_lines_p && m_is_stmt)
+      if (m_record_lines_p && (producer_is_codewarrior (m_cu) || m_is_stmt))
 	{
 	  if (m_last_subfile != m_cu->builder->get_current_subfile ()
 	      || end_sequence)
@@ -25120,6 +25136,7 @@  dwarf2_cu::dwarf2_cu (struct dwarf2_per_cu_data *per_cu_)
     producer_is_gxx_lt_4_6 (0),
     producer_is_gcc_lt_4_3 (0),
     producer_is_icc_lt_14 (0),
+    producer_is_codewarrior (0),
     processing_has_namespace_info (0)
 {
   per_cu->cu = this;