This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch] Work around gcc bug 45682
- From: dje at google dot com (Doug Evans)
- To: gdb-patches at sourceware dot org
- Date: Wed, 15 Sep 2010 12:23:35 -0700 (PDT)
- Subject: [patch] Work around gcc bug 45682
Hi.
This patch works around a bug in gcc's dwarf generation when using -gdwarf-4.
ref: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45682
The error can be seen with, e.g.,
bash$ runtest namespace.exp CXX_FOR_TARGET='g++-4.5.0 -gdwarf-4'
[...]
FAIL: gdb.cp/namespace.exp: info func xyzq
FAIL: gdb.cp/namespace.exp: print 'BBB::Class::xyzq'
FAIL: gdb.cp/namespace.exp: print BBB::Class::xyzq
FAIL: gdb.cp/namespace.exp: break BBB::Class::xyzq (got interactive prompt)
I plan to check this in, but I'm going to give it a fair while for review,
at least a week. [And if anyone has a better solution, by all means ...]
Function guess_structure_name is currently a nop, and could be deleted.
This patch resurrects its original purpose, but predicates
the effects on the presence of the .debug_types section.
I had to apply the workaround twice, once for partial dies
and once for full dies (to make sure symbols in psymtabs match their
corresponding symbols in symtabs).
Maybe there's a better way.
Regression tested on amd64-linux with/without -gdwarf-4.
[There's still some -gdwarf-4 failures, but they aren't regressions.]
2010-09-15 Doug Evans <dje@google.com>
* dwarf2read.c (partial_die_info): New fields fixup_called,
linkage_name.
(guess_partial_die_structure_name): Renamed from guess_structure_name.
Move definition next to use. Use linkage_name to determine if class
is in a namespace. All callers updated.
(fixup_partial_die): Return early if already called.
Set fixup_called when done.
(guess_full_die_structure_name): New function.
(determine_prefix): Call it for class/struct/union dies if c++ and
.debug_types section is present and parent is DW_TAG_compile_unit.
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.458
diff -u -p -r1.458 dwarf2read.c
--- dwarf2read.c 15 Sep 2010 18:14:47 -0000 1.458
+++ dwarf2read.c 15 Sep 2010 18:40:45 -0000
@@ -577,10 +577,16 @@ struct partial_die_info
/* Flag set if any of the DIE's children are template arguments. */
unsigned int has_template_arguments : 1;
+ /* Flag set if fixup_partial_die has been called on this die. */
+ unsigned int fixup_called : 1;
+
/* The name of this DIE. Normally the value of DW_AT_name, but
sometimes a default name for unnamed DIEs. */
char *name;
+ /* The linkage name, if present. */
+ const char *linkage_name;
+
/* The scope to prepend to our children. This is generally
allocated on the comp_unit_obstack, so will disappear
when this compilation unit leaves the cache. */
@@ -595,6 +601,8 @@ struct partial_die_info
/* Pointer into the info_buffer (or types_buffer) pointing at the target of
DW_AT_sibling, if any. */
+ /* NOTE: This member isn't strictly necessary, read_partial_die could
+ return DW_AT_sibling values to its caller load_partial_dies. */
gdb_byte *sibling;
/* If HAS_SPECIFICATION, the offset of the DIE referred to by
@@ -3900,40 +3908,6 @@ add_partial_subprogram (struct partial_d
}
}
-/* See if we can figure out if the class lives in a namespace. We do
- this by looking for a member function; its demangled name will
- contain namespace info, if there is any. */
-
-static void
-guess_structure_name (struct partial_die_info *struct_pdi,
- struct dwarf2_cu *cu)
-{
- if ((cu->language == language_cplus
- || cu->language == language_java)
- && cu->has_namespace_info == 0
- && struct_pdi->has_children)
- {
- /* NOTE: carlton/2003-10-07: Getting the info this way changes
- what template types look like, because the demangler
- frequently doesn't give the same name as the debug info. We
- could fix this by only using the demangled name to get the
- prefix (but see comment in read_structure_type). */
-
- struct partial_die_info *real_pdi;
-
- /* If this DIE (this DIE's specification, if any) has a parent, then
- we should not do this. We'll prepend the parent's fully qualified
- name when we create the partial symbol. */
-
- real_pdi = struct_pdi;
- while (real_pdi->has_specification)
- real_pdi = find_partial_die (real_pdi->spec_offset, cu);
-
- if (real_pdi->die_parent != NULL)
- return;
- }
-}
-
/* Read a partial die corresponding to an enumeration type. */
static void
@@ -8795,6 +8769,7 @@ read_partial_die (struct partial_die_inf
one we see. */
if (cu->language == language_ada)
part_die->name = DW_STRING (&attr);
+ part_die->linkage_name = DW_STRING (&attr);
break;
case DW_AT_low_pc:
has_low_pc_attr = 1;
@@ -8978,6 +8953,57 @@ find_partial_die (unsigned int offset, s
return pd;
}
+/* See if we can figure out if the class lives in a namespace. We do
+ this by looking for a member function; its demangled name will
+ contain namespace info, if there is any. */
+
+static void
+guess_partial_die_structure_name (struct partial_die_info *struct_pdi,
+ struct dwarf2_cu *cu)
+{
+ /* NOTE: carlton/2003-10-07: Getting the info this way changes
+ what template types look like, because the demangler
+ frequently doesn't give the same name as the debug info. We
+ could fix this by only using the demangled name to get the
+ prefix (but see comment in read_structure_type). */
+
+ struct partial_die_info *real_pdi;
+ struct partial_die_info *child_pdi;
+
+ /* If this DIE (this DIE's specification, if any) has a parent, then
+ we should not do this. We'll prepend the parent's fully qualified
+ name when we create the partial symbol. */
+
+ real_pdi = struct_pdi;
+ while (real_pdi->has_specification)
+ real_pdi = find_partial_die (real_pdi->spec_offset, cu);
+
+ if (real_pdi->die_parent != NULL)
+ return;
+
+ for (child_pdi = struct_pdi->die_child;
+ child_pdi != NULL;
+ child_pdi = child_pdi->die_sibling)
+ {
+ if (child_pdi->tag == DW_TAG_subprogram
+ && child_pdi->linkage_name != NULL)
+ {
+ char *actual_class_name
+ = language_class_name_from_physname (cu->language_defn,
+ child_pdi->linkage_name);
+ if (actual_class_name != NULL)
+ {
+ struct_pdi->name
+ = obsavestring (actual_class_name,
+ strlen (actual_class_name),
+ &cu->objfile->objfile_obstack);
+ xfree (actual_class_name);
+ }
+ break;
+ }
+ }
+}
+
/* Adjust PART_DIE before generating a symbol for it. This function
may set the is_external flag or change the DIE's name. */
@@ -8985,6 +9011,12 @@ static void
fixup_partial_die (struct partial_die_info *part_die,
struct dwarf2_cu *cu)
{
+ /* Once we've fixed up a die, there's no point in doing so again.
+ This also avoids a memory leak if we were to call
+ guess_partial_die_structure_name multiple times. */
+ if (part_die->fixup_called)
+ return;
+
/* If we found a reference attribute and the DIE has no name, try
to find a name in the referred to DIE. */
@@ -9011,10 +9043,21 @@ fixup_partial_die (struct partial_die_in
if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
part_die->name = "(anonymous namespace)";
- if (part_die->tag == DW_TAG_structure_type
- || part_die->tag == DW_TAG_class_type
- || part_die->tag == DW_TAG_union_type)
- guess_structure_name (part_die, cu);
+ /* If there is no parent die to provide a namespace, and there are
+ children, see if we can determine the namespace from their linkage
+ name.
+ NOTE: We need to do this even if cu->has_namespace_info != 0.
+ gcc-4.5 -gdwarf-4 can drop the enclosing namespace. */
+ if (cu->language == language_cplus
+ && dwarf2_per_objfile->types.asection != NULL
+ && part_die->die_parent == NULL
+ && part_die->has_children
+ && (part_die->tag == DW_TAG_class_type
+ || part_die->tag == DW_TAG_structure_type
+ || part_die->tag == DW_TAG_union_type))
+ guess_partial_die_structure_name (part_die, cu);
+
+ part_die->fixup_called = 1;
}
/* Read an attribute value described by an attribute form. */
@@ -11257,6 +11300,77 @@ read_type_die_1 (struct die_info *die, s
return this_type;
}
+/* See if we can figure out if the class lives in a namespace. We do
+ this by looking for a member function; its demangled name will
+ contain namespace info, if there is any.
+ Return the computed name or NULL.
+ Space for the result is allocated on the objfile's obstack.
+ This is the full-die version of guess_partial_die_structure_name.
+ In this case we know DIE has no useful parent. */
+
+static char *
+guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct die_info *spec_die;
+ struct dwarf2_cu *spec_cu;
+ struct die_info *child;
+
+ spec_cu = cu;
+ spec_die = die_specification (die, &spec_cu);
+ if (spec_die != NULL)
+ {
+ die = spec_die;
+ cu = spec_cu;
+ }
+
+ for (child = die->child;
+ child != NULL;
+ child = child->sibling)
+ {
+ if (child->tag == DW_TAG_subprogram)
+ {
+ struct attribute *attr;
+
+ attr = dwarf2_attr (child, DW_AT_linkage_name, cu);
+ if (attr == NULL)
+ attr = dwarf2_attr (child, DW_AT_MIPS_linkage_name, cu);
+ if (attr != NULL)
+ {
+ char *actual_name
+ = language_class_name_from_physname (cu->language_defn,
+ DW_STRING (attr));
+ char *name = NULL;
+
+ if (actual_name != NULL)
+ {
+ char *die_name = dwarf2_name (die, cu);
+
+ if (die_name != NULL
+ && strcmp (die_name, actual_name) != 0)
+ {
+ /* Strip off the class name from the full name.
+ We want the prefix. */
+ int die_name_len = strlen (die_name);
+ int actual_name_len = strlen (actual_name);
+
+ /* Test for '::' as a sanity check. */
+ if (actual_name_len > die_name_len + 2
+ && actual_name[actual_name_len - die_name_len - 1] == ':')
+ name =
+ obsavestring (actual_name,
+ actual_name_len - die_name_len - 2,
+ &cu->objfile->objfile_obstack);
+ }
+ }
+ xfree (actual_name);
+ return name;
+ }
+ }
+ }
+
+ return NULL;
+}
+
/* Return the name of the namespace/class that DIE is defined within,
or "" if we can't tell. The caller should not xfree the result.
@@ -11383,6 +11497,20 @@ determine_prefix (struct die_info *die,
members; no typedefs, no member functions, et cetera.
So it does not need a prefix. */
return "";
+ case DW_TAG_compile_unit:
+ /* gcc-4.5 -gdwarf-4 can drop the enclosing namespace. Cope. */
+ if (cu->language == language_cplus
+ && dwarf2_per_objfile->types.asection != NULL
+ && die->child != NULL
+ && (die->tag == DW_TAG_class_type
+ || die->tag == DW_TAG_structure_type
+ || die->tag == DW_TAG_union_type))
+ {
+ char *name = guess_full_die_structure_name (die, cu);
+ if (name != NULL)
+ return name;
+ }
+ return "";
default:
return determine_prefix (parent, cu);
}