aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Evans <dje@google.com>2010-09-29 16:41:24 +0000
committerDoug Evans <dje@google.com>2010-09-29 16:41:24 +0000
commitabc72ce4c676be2f368fa0ace766ed29cd444020 (patch)
treed7ebaf967e24d8c0e7cf31dfaef509e183e15339
parent5f79eb72c24bb79e981896542831374b54fb96ba (diff)
downloadgdb-abc72ce4c676be2f368fa0ace766ed29cd444020.zip
gdb-abc72ce4c676be2f368fa0ace766ed29cd444020.tar.gz
gdb-abc72ce4c676be2f368fa0ace766ed29cd444020.tar.bz2
Workaround for gcc/45682.
* 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.
-rw-r--r--gdb/ChangeLog14
-rw-r--r--gdb/dwarf2read.c204
2 files changed, 180 insertions, 38 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e8b81e8..c9c4524 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,17 @@
+2010-09-29 Doug Evans <dje@google.com>
+
+ Workaround for gcc/45682.
+ * 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.
+
2010-09-28 Joel Brobecker <brobecker@adacore.com>
* configure.tgt (sparc-*-*): Set gdb_sim to ../sim/erc32/libsim.a.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 4289a49..743ba89 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -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
@@ -3903,40 +3911,6 @@ add_partial_subprogram (struct partial_die_info *pdi,
}
}
-/* 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
@@ -8801,6 +8775,7 @@ read_partial_die (struct partial_die_info *part_die,
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;
@@ -8984,6 +8959,57 @@ find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
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. */
@@ -8991,6 +9017,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. */
@@ -9017,10 +9049,21 @@ fixup_partial_die (struct partial_die_info *part_die,
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. */
@@ -11264,6 +11307,77 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu)
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.
@@ -11390,6 +11504,20 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
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);
}