diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2009-04-27 08:36:17 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2009-04-27 08:36:17 +0000 |
commit | d389af10b70d4c5be1a4a7d1317c0e6020cac979 (patch) | |
tree | 52d05451272d5f317846080fd73425ed19da5a00 /gdb/dwarf2read.c | |
parent | 8f3e5e92ceedfb5c8eae40e10c387508b8e76cee (diff) | |
download | gdb-d389af10b70d4c5be1a4a7d1317c0e6020cac979.zip gdb-d389af10b70d4c5be1a4a7d1317c0e6020cac979.tar.gz gdb-d389af10b70d4c5be1a4a7d1317c0e6020cac979.tar.bz2 |
gdb/
PR gdb/9675:
* dwarf2read.c (unsigned_int_compar, inherit_abstract_dies): New.
(read_func_scope): Call inherit_abstract_dies.
gdb/testsuite/
* gdb.cp/abstract-origin.exp, gdb.cp/abstract-origin.cc: New test.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index c3f3838..ee1490d 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -3089,6 +3089,103 @@ add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc, cu->last_fn = thisfn; } +/* qsort helper for inherit_abstract_dies. */ + +static int +unsigned_int_compar (const void *ap, const void *bp) +{ + unsigned int a = *(unsigned int *) ap; + unsigned int b = *(unsigned int *) bp; + + return (a > b) - (b > a); +} + +/* DW_AT_abstract_origin inherits whole DIEs (not just their attributes). + Inherit only the children of the DW_AT_abstract_origin DIE not being already + referenced by DW_AT_abstract_origin from the children of the current DIE. */ + +static void +inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu) +{ + struct die_info *child_die; + unsigned die_children_count; + /* CU offsets which were referenced by children of the current DIE. */ + unsigned *offsets; + unsigned *offsets_end, *offsetp; + /* Parent of DIE - referenced by DW_AT_abstract_origin. */ + struct die_info *origin_die; + /* Iterator of the ORIGIN_DIE children. */ + struct die_info *origin_child_die; + struct cleanup *cleanups; + struct attribute *attr; + + attr = dwarf2_attr (die, DW_AT_abstract_origin, cu); + if (!attr) + return; + + origin_die = follow_die_ref (die, attr, &cu); + if (die->tag != origin_die->tag) + complaint (&symfile_complaints, + _("DIE 0x%x and its abstract origin 0x%x have different tags"), + die->offset, origin_die->offset); + + child_die = die->child; + die_children_count = 0; + while (child_die && child_die->tag) + { + child_die = sibling_die (child_die); + die_children_count++; + } + offsets = xmalloc (sizeof (*offsets) * die_children_count); + cleanups = make_cleanup (xfree, offsets); + + offsets_end = offsets; + child_die = die->child; + while (child_die && child_die->tag) + { + attr = dwarf2_attr (child_die, DW_AT_abstract_origin, cu); + /* According to DWARF3 3.3.8.2 #3 new entries without their abstract + counterpart may exist. */ + if (attr) + { + struct die_info *child_origin_die; + + child_origin_die = follow_die_ref (child_die, attr, &cu); + if (child_die->tag != child_origin_die->tag) + complaint (&symfile_complaints, + _("Child DIE 0x%x and its abstract origin 0x%x have " + "different tags"), child_die->offset, + child_origin_die->offset); + *offsets_end++ = child_origin_die->offset; + } + child_die = sibling_die (child_die); + } + qsort (offsets, offsets_end - offsets, sizeof (*offsets), + unsigned_int_compar); + for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++) + if (offsetp[-1] == *offsetp) + complaint (&symfile_complaints, _("Multiple children of DIE 0x%x refer " + "to DIE 0x%x as their abstract origin"), + die->offset, *offsetp); + + offsetp = offsets; + origin_child_die = origin_die->child; + while (origin_child_die && origin_child_die->tag) + { + /* Is ORIGIN_CHILD_DIE referenced by any of the DIE children? */ + while (offsetp < offsets_end && *offsetp < origin_child_die->offset) + offsetp++; + if (offsetp >= offsets_end || *offsetp > origin_child_die->offset) + { + /* Found that ORIGIN_CHILD_DIE is really not referenced. */ + process_die (origin_child_die, cu); + } + origin_child_die = sibling_die (origin_child_die); + } + + do_cleanups (cleanups); +} + static void read_func_scope (struct die_info *die, struct dwarf2_cu *cu) { @@ -3147,6 +3244,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) } } + inherit_abstract_dies (die, cu); + new = pop_context (); /* Make a block for the local symbols within. */ block = finish_block (new->name, &local_symbols, new->old_blocks, |