Teach inherit_abstract_dies about inter-cu references

Pedro Alves pedro@codesourcery.com
Tue Aug 24 16:57:00 GMT 2010


Doug, here's the patch we were talking about on IRC.  Below's also 
(a slightly tweaked) original description of the problem.

A while ago, I stumbled on this crash using a customer's binary compiled
with RealView:

 Program received signal SIGSEGV, Segmentation fault.
 0x00000000005793c2 in add_symbol_to_list (symbol=0x182ed130, listhead=0x0) at ../../src/gdb/buildsym.c:139
 139       if (*listhead == NULL || (*listhead)->nsyms == PENDINGSIZE)
 (top-gdb)

The crash was here:

 #1  0x000000000059c014 in new_symbol (die=0x182eeab0, type=0x182ecf10, cu=0x9f91cf0)
     at ../../src/gdb/dwarf2read.c:8406
 #2  0x0000000000590815 in process_die (die=0x182eeab0, cu=0x9f91cf0) at ../../src/gdb/dwarf2read.c:3087
 #3  0x0000000000591903 in inherit_abstract_dies (die=0x180b09a0, cu=0x9f91cf0) at ../../src/gdb/dwarf2read.c:3586
 #4  0x0000000000591bf2 in read_func_scope (die=0x180b09a0, cu=0x91bcaf0) at ../../src/gdb/dwarf2read.c:3667
 #5  0x000000000059079f in process_die (die=0x180b09a0, cu=0x91bcaf0) at ../../src/gdb/dwarf2read.c:3053

That is, `cu->list_in_scope' is NULL when new_symbol is called.

The problem is that inherit_abstract_dies isn't coping with inter-cu
references, and so is assuming the origin die is always in the same
compilation unit as the incoming die.  In the issue's binary, when the
crash occurs, this in `inherit_abstract_dies':

  origin_die = follow_die_ref (die, attr, &cu);
                                           ^^

(that's a inout parameter) returns a different cu from what was passed in.  This
other CU doesn't have the list_in_scope member set yet.  Also, further
below, we'll pass the origin_die's cu to other functions, paired with a die
from another cu.  E.g.:

 struct die_info *child_origin_die = child_die;
 attr = dwarf2_attr (child_origin_die, DW_AT_abstract_origin, cu);

This should have been the incoming DIE's cu, or child_origin_die's in
following iterations.

Here's the patch to fix these issues.  It fixed the crash and had no
regressions with ARM RealView, and I just retested it on x86_64-linux-gnu
with no regression as well.

-- 
Pedro Alves

2010-08-24  Pedro Alves  <pedro@codesourcery.com>

	gdb/
	* dwarf2read.c (inherit_abstract_dies): Handle origin die's
	compilation unit being different from target die's.

Index: gdb/dwarf2read.c
===================================================================
--- gdb/dwarf2read.c	(revisão 278502)
+++ gdb/dwarf2read.c	(revisão 278503)
@@ -3977,12 +3977,24 @@ inherit_abstract_dies (struct die_info *
   struct die_info *origin_child_die;
   struct cleanup *cleanups;
   struct attribute *attr;
+  struct dwarf2_cu *origin_cu;
+  struct pending **origin_previous_list_in_scope;
 
   attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
   if (!attr)
     return;
 
-  origin_die = follow_die_ref (die, attr, &cu);
+  /* Note that following die references may follow to a die in a
+     different cu.  */
+
+  origin_cu = cu;
+  origin_die = follow_die_ref (die, attr, &origin_cu);
+
+  /* We're inheriting ORIGIN's children into the scope we'd put DIE's
+     symbols in.  */
+  origin_previous_list_in_scope = origin_cu->list_in_scope;
+  origin_cu->list_in_scope = cu->list_in_scope;
+
   if (die->tag != origin_die->tag
       && !(die->tag == DW_TAG_inlined_subroutine
 	   && origin_die->tag == DW_TAG_subprogram))
@@ -4010,12 +4022,15 @@ inherit_abstract_dies (struct die_info *
 	 but GCC versions at least through 4.4 generate this (GCC PR
 	 40573).  */
       struct die_info *child_origin_die = child_die;
+      struct dwarf2_cu *child_origin_cu = cu;
       while (1)
 	{
-	  attr = dwarf2_attr (child_origin_die, DW_AT_abstract_origin, cu);
+	  attr = dwarf2_attr (child_origin_die, DW_AT_abstract_origin,
+			      child_origin_cu);
 	  if (attr == NULL)
 	    break;
-	  child_origin_die = follow_die_ref (child_origin_die, attr, &cu);
+	  child_origin_die = follow_die_ref (child_origin_die, attr,
+					     &child_origin_cu);
 	}
 
       /* According to DWARF3 3.3.8.2 #3 new entries without their abstract
@@ -4057,10 +4072,11 @@ inherit_abstract_dies (struct die_info *
       if (offsetp >= offsets_end || *offsetp > origin_child_die->offset)
 	{
 	  /* Found that ORIGIN_CHILD_DIE is really not referenced.  */
-	  process_die (origin_child_die, cu);
+	  process_die (origin_child_die, origin_cu);
 	}
       origin_child_die = sibling_die (origin_child_die);
     }
+  origin_cu->list_in_scope = origin_previous_list_in_scope;
 
   do_cleanups (cleanups);
 }



More information about the Gdb-patches mailing list