This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[intercu] Clean up partial DIE name handling
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sources dot redhat dot com
- Date: Thu, 1 Apr 2004 21:47:17 -0500
- Subject: [intercu] Clean up partial DIE name handling
Just revisiting the part of partial DIE support that I found most gross at
the time. It's still a little gross, but not half as bad as it used to be,
and some of my uglier games with memory allocation are fixed now. Better
comments, too.
Committed to the intercu branch.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
2004-04-01 Daniel Jacobowitz <drow@mvista.com>
* dwarf2read.c (struct partial_die_info): Replace full_name and
full_name_set with scope and scope_set.
(partial_die_parent_scope): New function.
(partial_die_full_name): Use it.
(add_partial_symbol): Don't check full_name_set or set full_name.
(add_partial_namespace): Remove unused variable.
(guess_partial_structure): New function, broken out from
add_partial_structure. Set the name field of the partial DIE.
(add_partial_structure): Simplify.
(find_partial_die): Always set *TARGET_CU.
(fixup_partial_die): Call guess_structure_scope. Set the names
of anonymous classes and namespaces.
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.135.2.37
diff -u -p -r1.135.2.37 dwarf2read.c
--- dwarf2read.c 1 Apr 2004 18:05:56 -0000 1.135.2.37
+++ dwarf2read.c 2 Apr 2004 02:38:54 -0000
@@ -526,9 +526,14 @@ struct partial_die_info
unsigned int has_type : 1;
unsigned int has_specification : 1;
unsigned int has_pc_info : 1;
- unsigned int full_name_set : 1;
+ unsigned int scope_set : 1;
char *name;
- char *full_name;
+
+ /* The scope to prepend to our children. This is generally
+ allocated on the partial_die_obstack, so will disappear
+ when this compilation unit leaves the cache. */
+ char *scope;
+
struct dwarf_block *locdesc;
CORE_ADDR lowpc;
CORE_ADDR highpc;
@@ -1747,64 +1752,98 @@ scan_partial_symbols (struct partial_die
}
}
-/* Return the fully scoped name associated with PDI, from compilation unit
- CU. The result will be allocated with malloc, or NULL if PDI->NAME should
- be used. */
+/* Functions used to compute the fully scoped name of a partial DIE.
+
+ Normally, this is simple. For C++, the parent DIE's fully scoped
+ name is concatenated with "::" and the partial DIE's name.
+ Enumerators are an exception; they use the scope of their parent
+ enumeration type, i.e. the name of the enumeration type is not
+ prepended to the enumerator.
+
+ There are two complexities. One is DW_AT_specification; in this
+ case "parent" means the parent of the target of the specification,
+ instead of the direct parent of the DIE. The other is compilers
+ which do not emit DW_TAG_namespace; in this case we try to guess
+ the fully qualified name of structure types from their members'
+ linkage names. This must be done using the DIE's children rather
+ than the children of any DW_AT_specification target. We only need
+ to do this for structures at the top level, i.e. if the target of
+ any DW_AT_specification (if any; otherwise the DIE itself) does not
+ have a parent. */
+
+/* Compute the scope prefix associated with PDI's parent, in
+ compilation unit CU. The result will be allocated on CU's
+ partial_die_obstack, or a copy of the already allocated PDI->NAME
+ field. NULL is returned if no prefix is necessary. */
static char *
-partial_die_full_name (struct partial_die_info *pdi,
- struct dwarf2_cu *cu)
+partial_die_parent_scope (struct partial_die_info *pdi,
+ struct dwarf2_cu *cu)
{
- char *parent_name = NULL, *full_name;
- struct partial_die_info *real_pdi, *real_parent;
+ char *grandparent_scope;
+ struct partial_die_info *parent, *real_pdi;
struct dwarf2_cu *spec_cu;
- int free_parent_name = 0;
- /* We shouldn't even have been called in this case. */
- gdb_assert (!pdi->full_name_set);
-
- /* Note: this code could probably be micro-optimized. We may be
- able to avoid redoing the hash table lookup, and we might be able
- to use real_pdi->full_name if there is a specification. */
+ /* We need to look at our parent DIE; if we have a DW_AT_specification,
+ then this means the parent of the specification DIE. */
real_pdi = pdi;
spec_cu = cu;
while (real_pdi->has_specification)
real_pdi = find_partial_die (real_pdi->spec_offset, spec_cu, &spec_cu);
- /* NOTE drow/2004-02-22: The following code is a hack. It's only used when
- visiting the DIEs out of order, i.e. due to DW_AT_specification in another
- CU or later in this CU. It's correct, but somewhat inefficient. */
+ parent = real_pdi->die_parent;
+ if (parent == NULL)
+ return NULL;
- if (real_pdi->full_name_set)
- return xstrdup (real_pdi->full_name);
+ if (parent->scope_set)
+ return parent->scope;
- real_parent = real_pdi->die_parent;
- if (real_parent == NULL)
+ fixup_partial_die (parent, cu);
+
+ grandparent_scope = partial_die_parent_scope (parent, spec_cu);
+
+ if (parent->tag == DW_TAG_namespace
+ || parent->tag == DW_TAG_structure_type
+ || parent->tag == DW_TAG_class_type
+ || parent->tag == DW_TAG_union_type)
{
- real_pdi->full_name_set = 1;
- return NULL;
+ if (grandparent_scope == NULL)
+ parent->scope = parent->name;
+ else
+ parent->scope = obconcat (&cu->partial_die_obstack, grandparent_scope,
+ "::", parent->name);
}
-
- if (!real_parent->full_name_set)
+ else if (parent->tag == DW_TAG_enumeration_type)
+ /* Enumerators should not get the name of the enumeration as a prefix. */
+ parent->scope = grandparent_scope;
+ else
{
- fixup_partial_die (real_parent, spec_cu);
- parent_name = partial_die_full_name (real_parent, spec_cu);
- /* Could cache the full name, too. */
- if (parent_name != NULL)
- free_parent_name = 1;
+ /* FIXME drow/2004-04-01: What should we be doing with
+ function-local names? For partial symbols, we should probably be
+ ignoring them. */
+ complaint (&symfile_complaints,
+ "unhandled containing DIE tag %d for DIE at %d",
+ parent->tag, pdi->offset);
+ parent->scope = grandparent_scope;
}
+
+ parent->scope_set = 1;
+ return parent->scope;
+}
- /* End hack zone. */
-
- if (parent_name == NULL)
- parent_name = real_parent->full_name;
- if (parent_name == NULL)
- parent_name = real_parent->name;
+/* Return the fully scoped name associated with PDI, from compilation unit
+ CU. The result will be allocated with malloc. */
+static char *
+partial_die_full_name (struct partial_die_info *pdi,
+ struct dwarf2_cu *cu)
+{
+ char *parent_scope;
- full_name = concat (parent_name, "::", real_pdi->name, NULL);
- if (free_parent_name)
- free (parent_name);
- return full_name;
+ parent_scope = partial_die_parent_scope (pdi, cu);
+ if (parent_scope == NULL)
+ return NULL;
+ else
+ return concat (parent_scope, "::", pdi->name, NULL);
}
static void
@@ -1821,9 +1860,8 @@ add_partial_symbol (struct partial_die_i
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
actual_name = NULL;
- if (!pdi->full_name_set
- && pdi_needs_namespace (pdi->tag)
- && pdi->full_name == NULL)
+
+ if (pdi_needs_namespace (pdi->tag))
{
actual_name = partial_die_full_name (pdi, cu);
if (actual_name)
@@ -1831,14 +1869,7 @@ add_partial_symbol (struct partial_die_i
}
if (actual_name == NULL)
- {
- if (pdi->full_name != NULL)
- actual_name = pdi->full_name;
- else
- actual_name = pdi->name;
- }
-
- pdi->full_name_set = 1;
+ actual_name = pdi->name;
switch (pdi->tag)
{
@@ -1976,7 +2007,6 @@ add_partial_symbol (struct partial_die_i
/* psym2 should always be set in the built_actual_name case,
because the same set are used in pdi_needs_namespace. See
FIXME above. */
- pdi->full_name = SYMBOL_LINKAGE_NAME (psym2);
xfree (actual_name);
}
}
@@ -2013,7 +2043,6 @@ add_partial_namespace (struct partial_di
struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
- char *full_name;
/* Calculate the full name of the namespace that we just entered. */
@@ -2028,27 +2057,18 @@ add_partial_namespace (struct partial_di
scan_partial_symbols (pdi->die_child, lowpc, highpc, cu);
}
-/* Read a partial die corresponding to a class or structure. */
+/* 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
-add_partial_structure (struct partial_die_info *struct_pdi,
- struct dwarf2_cu *cu)
+void
+guess_structure_name (struct partial_die_info *struct_pdi,
+ struct dwarf2_cu *cu)
{
- bfd *abfd = cu->objfile->obfd;
- char *full_name;
-
- if (struct_pdi->name == NULL)
- struct_pdi->name = "(anonymous class)";
-
if (cu->language == language_cplus
&& cu->has_namespace_info == 0
&& struct_pdi->has_children)
{
- /* See if we can figure out if the class lives in a namespace
- (or is nested within another class.) We do this by looking
- for a member function; its demangled name will contain
- namespace info, if there is any. */
-
/* 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
@@ -2056,6 +2076,20 @@ add_partial_structure (struct partial_di
prefix (but see comment in read_structure_type). */
struct partial_die_info *child_pdi = struct_pdi->die_child;
+ struct partial_die_info *real_pdi;
+ struct dwarf2_cu *spec_cu;
+
+ /* 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;
+ spec_cu = cu;
+ while (real_pdi->has_specification)
+ real_pdi = find_partial_die (real_pdi->spec_offset, spec_cu, &spec_cu);
+
+ if (real_pdi->die_parent != NULL)
+ return;
while (child_pdi != NULL)
{
@@ -2065,7 +2099,7 @@ add_partial_structure (struct partial_di
= class_name_from_physname (child_pdi->name);
if (actual_class_name != NULL)
{
- struct_pdi->full_name
+ struct_pdi->name
= obsavestring (actual_class_name,
strlen (actual_class_name),
&cu->partial_die_obstack);
@@ -2077,6 +2111,18 @@ add_partial_structure (struct partial_di
child_pdi = child_pdi->die_sibling;
}
}
+}
+
+/* Read a partial die corresponding to a class or structure. */
+
+static void
+add_partial_structure (struct partial_die_info *struct_pdi,
+ struct dwarf2_cu *cu)
+{
+ bfd *abfd = cu->objfile->obfd;
+
+ if (struct_pdi->name == NULL)
+ struct_pdi->name = "(anonymous class)";
add_partial_symbol (struct_pdi, cu);
}
@@ -5362,7 +5408,10 @@ find_partial_die (unsigned long offset,
if (offset >= cu->header.offset
&& offset < cu->header.offset + cu->header.length)
- return find_partial_die_in_comp_unit (offset, cu);
+ {
+ *target_cu = cu;
+ return find_partial_die_in_comp_unit (offset, cu);
+ }
per_cu = dwarf2_find_containing_comp_unit (offset, cu);
gdb_assert (per_cu != NULL);
@@ -5383,8 +5432,8 @@ static void
fixup_partial_die (struct partial_die_info *part_die,
struct dwarf2_cu *cu)
{
- /* If we found a reference attribute and the die has no name, try
- to find a name in the referred to die. */
+ /* If we found a reference attribute and the DIE has no name, try
+ to find a name in the referred to DIE. */
if (part_die->name == NULL && part_die->has_specification)
{
@@ -5404,6 +5453,19 @@ fixup_partial_die (struct partial_die_in
part_die->is_external = spec_die->is_external;
}
}
+
+ /* Set default names for some unnamed DIEs. */
+ if (part_die->name == NULL && (part_die->tag == DW_TAG_structure_type
+ || part_die->tag == DW_TAG_class_type))
+ part_die->name = "(anonymous class)";
+
+ 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_structure_type
+ || part_die->tag == DW_TAG_union_type)
+ guess_structure_name (part_die, cu);
}
/* Read the die from the .debug_info section buffer. Set DIEP to