From d389af10b70d4c5be1a4a7d1317c0e6020cac979 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Mon, 27 Apr 2009 08:36:17 +0000 Subject: [PATCH] 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. --- gdb/ChangeLog | 6 ++ gdb/dwarf2read.c | 99 ++++++++++++++++++++++++ gdb/testsuite/ChangeLog | 4 + gdb/testsuite/gdb.cp/abstract-origin.cc | 42 ++++++++++ gdb/testsuite/gdb.cp/abstract-origin.exp | 31 ++++++++ 5 files changed, 182 insertions(+) create mode 100644 gdb/testsuite/gdb.cp/abstract-origin.cc create mode 100644 gdb/testsuite/gdb.cp/abstract-origin.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 44d76e3215d..32622b4ae71 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2009-04-27 Jan Kratochvil + + PR gdb/9675: + * dwarf2read.c (unsigned_int_compar, inherit_abstract_dies): New. + (read_func_scope): Call inherit_abstract_dies. + 2009-04-25 Eli Zaretskii * Makefile.in (ALLDEPFILES): Remove duplicate entries for diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index c3f38385882..ee1490d61c7 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, diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 1bb8743c8a8..fac1f1970c3 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2009-04-27 Jan Kratochvil + + * gdb.cp/abstract-origin.exp, gdb.cp/abstract-origin.cc: New test. + 2009-04-22 Joseph Myers * lib/gdb.exp (get_compiler_info): Use -E -o in remote-host case. diff --git a/gdb/testsuite/gdb.cp/abstract-origin.cc b/gdb/testsuite/gdb.cp/abstract-origin.cc new file mode 100644 index 00000000000..9621ed65fa3 --- /dev/null +++ b/gdb/testsuite/gdb.cp/abstract-origin.cc @@ -0,0 +1,42 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +extern void f (int *); + +class A +{ +public: + A(int i); +}; + +A::A(int i) +{ + static int *problem = new int(i); + f (problem); /* break-here */ +} + +void f (int *) +{ +} + +int +main (void) +{ + A a(42); + return 0; +} diff --git a/gdb/testsuite/gdb.cp/abstract-origin.exp b/gdb/testsuite/gdb.cp/abstract-origin.exp new file mode 100644 index 00000000000..9ba1194e8d1 --- /dev/null +++ b/gdb/testsuite/gdb.cp/abstract-origin.exp @@ -0,0 +1,31 @@ +# Copyright 2009 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set testfile abstract-origin +set srcfile ${testfile}.cc +if [prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}] { + return -1 +} + +if ![runto_main] { + untested abstract-origin + return -1 +} + +gdb_breakpoint [gdb_get_line_number "break-here"] +gdb_continue_to_breakpoint "break-here" + +# The Bug was: No symbol "problem" in current context. +gdb_test "p problem" " = \\(int \\*\\) 0x.*" -- 2.30.2