This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Teach inherit_abstract_dies about inter-cu references
- From: Pedro Alves <pedro at codesourcery dot com>
- To: gdb-patches at sourceware dot org, Doug Evans <dje at google dot com>
- Date: Tue, 24 Aug 2010 17:57:12 +0100
- Subject: Teach inherit_abstract_dies about inter-cu references
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);
}