[rfa] add 'parent' field to struct die_info

David Carlton
2003-09-30T16:29:38Z

This patch adds a 'parent' field to struct die_info. There's no way
to get that information out of our current data structures, and it is
necessary for nested type support: die A might reference a type die B
via DW_AT_specification, and to correctly deal with the possibility
that B might be a nested type, we'll have to know B's parent (if any).
(See the thread starting in
<http://sources.redhat.com/ml/gdb/2003-05/msg00173.html>.) I was
going to do this as part of a big nested type patch, but I figured
Elena was going to ask me to commit this part separately anyways. :-)
(But I would appreciate it if you could review it quickly: it's
simple.)

While I was at it, I replaced the existing 'has_children' and 'next'
fields by 'child' and 'sibling' fields: it seems clearer to me that
way. The result of this is that the function 'sibling_die' isn't
really pulling its weight any more; I left it in there for now,
though.

Tested on i686-pc-linux-gnu, GCC 3.2, DWARF 2. OK to commit?

David Carlton
carlton@kealia.com

2003-09-30 David Carlton <carlton@kealia.com>

* dwarf2read.c (struct die_info): Add 'parent' field; replace
'has_children' and 'next' by 'child' and 'sibling'.
(read_comp_unit): Rework algorithm, breaking body into
read_die_and_children and read_die_and_siblings.
(read_die_and_children, read_die_and_siblings): New.
(read_full_die): Add 'has_children' argument; set it instead of
the die's 'has_children' field. Minor formatting cleanup.
(free_die_list): Use die->child and die->sibling instead of
die->next.
(dump_die_list): Ditto.
(sibling_die): Use die->sibling.
(psymtab_to_symtab_1): Use die's 'child' field in place of its
'has_children' and 'next' fields.
(process_die, read_file_scope, read_func_scope)
(read_lexical_block_scope, read_structure_scope)
(read_enumeration, read_array_type, read_common_block)
(read_namespace, read_subroutine_type, dump_die): Ditto.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.108
diff -u -p -r1.108 dwarf2read.c
--- dwarf2read.c 23 Sep 2003 16:25:13 -0000 1.108
+++ dwarf2read.c 30 Sep 2003 15:58:30 -0000
@@ -315,13 +315,14 @@ struct attr_abbrev
struct die_info
{
enum dwarf_tag tag; /* Tag indicating type of die */
- unsigned short has_children; /* Does the die have children */
unsigned int abbrev; /* Abbrev number */
unsigned int offset; /* Offset in .debug_info section */
unsigned int num_attrs; /* Number of attributes */
struct attribute *attrs; /* An array of attributes */
struct die_info *next_ref; /* Next die in ref hash table */
- struct die_info *next; /* Next die in linked list */
+ struct die_info *child; /* Its first child, if any. */
+ struct die_info *sibling; /* Its next sibling, if any. */
+ struct die_info *parent; /* Its parent, if any. */
struct type *type; /* Cached type information */
};

@@ -716,7 +717,7 @@ static char *read_partial_die (struct pa
const struct comp_unit_head *);

static char *read_full_die (struct die_info **, bfd *, char *,
- const struct comp_unit_head *);
+ const struct comp_unit_head *, int *);

static char *read_attribute (struct attribute *, struct attr_abbrev *,
bfd *, char *, const struct comp_unit_head *);
@@ -873,6 +874,16 @@ static void read_subroutine_type (struct
static struct die_info *read_comp_unit (char *, bfd *,
const struct comp_unit_head *);

+static struct die_info *read_die_and_children (char *info_ptr, bfd *abfd,
+ const struct comp_unit_head *,
+ char **new_info_ptr,
+ struct die_info *parent);
+
+static struct die_info *read_die_and_siblings (char *info_ptr, bfd *abfd,
+ const struct comp_unit_head *,
+ char **new_info_ptr,
+ struct die_info *parent);
+
static void free_die_list (struct die_info *);

static struct cleanup *make_cleanup_free_die_list (struct die_info *);
@@ -1836,9 +1847,9 @@ psymtab_to_symtab_1 (struct partial_symt
the compilation unit. If the DW_AT_high_pc is missing,
synthesize it, by scanning the DIE's below the compilation unit. */
highpc = 0;
- if (dies->has_children)
+ if (dies->child != NULL)
{
- child_die = dies->next;
+ child_die = dies->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_subprogram)
@@ -1958,7 +1969,7 @@ process_die (struct die_info *die, struc
processing_has_namespace_info = 1;
processing_current_namespace = "";
}
- gdb_assert (!die->has_children);
+ gdb_assert (die->child == NULL);
break;
default:
new_symbol (die, NULL, objfile, cu_header);
@@ -1988,9 +1999,9 @@ read_file_scope (struct die_info *die, s

if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
{
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_subprogram)
@@ -2069,9 +2080,9 @@ read_file_scope (struct die_info *die, s
initialize_cu_func_list ();

/* Process all dies in compilation unit. */
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
process_die (child_die, objfile, cu_header);
@@ -2209,9 +2220,9 @@ read_func_scope (struct die_info *die, s

list_in_scope = &local_symbols;

- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
process_die (child_die, objfile, cu_header);
@@ -2259,9 +2270,9 @@ read_lexical_block_scope (struct die_inf
highpc += baseaddr;

push_context (0, lowpc);
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
process_die (child_die, objfile, cu_header);
@@ -2936,7 +2947,7 @@ read_structure_scope (struct die_info *d
type within the structure itself. */
die->type = type;

- if (die->has_children && ! die_is_declaration (die))
+ if (die->child != NULL && ! die_is_declaration (die))
{
struct field_info fi;
struct die_info *child_die;
@@ -2944,7 +2955,7 @@ read_structure_scope (struct die_info *d

memset (&fi, 0, sizeof (struct field_info));

- child_die = die->next;
+ child_die = die->child;

while (child_die && child_die->tag)
{
@@ -3082,9 +3093,9 @@ read_enumeration (struct die_info *die,

num_fields = 0;
fields = NULL;
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag != DW_TAG_enumerator)
@@ -3163,7 +3174,7 @@ read_array_type (struct die_info *die, s

/* Irix 6.2 native cc creates array types without children for
arrays with unspecified length. */
- if (die->has_children == 0)
+ if (die->child == NULL)
{
index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
range_type = create_range_type (NULL, index_type, 0, -1);
@@ -3172,7 +3183,7 @@ read_array_type (struct die_info *die, s
}

back_to = make_cleanup (null_cleanup, NULL);
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_subrange_type)
@@ -3324,9 +3335,9 @@ read_common_block (struct die_info *die,
"common block member");
}
}
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
sym = new_symbol (child_die, NULL, objfile, cu_header);
@@ -3412,9 +3423,9 @@ read_namespace (struct die_info *die, st
strlen (processing_current_namespace));
}

- if (die->has_children)
+ if (die->child != NULL)
{
- struct die_info *child_die = die->next;
+ struct die_info *child_die = die->child;

while (child_die && child_die->tag)
{
@@ -3649,7 +3660,7 @@ read_subroutine_type (struct die_info *d
|| cu_language == language_cplus)
TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;

- if (die->has_children)
+ if (die->child != NULL)
{
struct die_info *child_die;
int nparams = 0;
@@ -3658,7 +3669,7 @@ read_subroutine_type (struct die_info *d
/* Count the number of parameters.
FIXME: GDB currently ignores vararg functions, but knows about
vararg member functions. */
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_formal_parameter)
@@ -3673,7 +3684,7 @@ read_subroutine_type (struct die_info *d
TYPE_FIELDS (ftype) = (struct field *)
TYPE_ALLOC (ftype, nparams * sizeof (struct field));

- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_formal_parameter)
@@ -3808,46 +3819,89 @@ static struct die_info *
read_comp_unit (char *info_ptr, bfd *abfd,
const struct comp_unit_head *cu_header)
{
- struct die_info *first_die, *last_die, *die;
- char *cur_ptr;
- int nesting_level;
-
/* Reset die reference table; we are
building new ones now. */
dwarf2_empty_hash_tables ();

+ return read_die_and_children (info_ptr, abfd, cu_header, &info_ptr, NULL);
+}
+
+/* Read a single die and all its descendents. Set the die's sibling
+ field to NULL; set other fields in the die correctly, and set all
+ of the descendents' fields correctly. Set *NEW_INFO_PTR to the
+ location of the info_ptr after reading all of those dies. PARENT
+ is the parent of the die in question. */
+
+static struct die_info *
+read_die_and_children (char *info_ptr, bfd *abfd,
+ const struct comp_unit_head *cu_header,
+ char **new_info_ptr,
+ struct die_info *parent)
+{
+ struct die_info *die;
+ char *cur_ptr;
+ int has_children;
+
+ cur_ptr = read_full_die (&die, abfd, info_ptr, cu_header, &has_children);
+ store_in_ref_table (die->offset, die);
+
+ if (has_children)
+ {
+ die->child = read_die_and_siblings (cur_ptr, abfd, cu_header,
+ new_info_ptr, die);
+ }
+ else
+ {
+ die->child = NULL;
+ *new_info_ptr = cur_ptr;
+ }
+
+ die->sibling = NULL;
+ die->parent = parent;
+ return die;
+}
+
+/* Read a die, all of its descendents, and all of its siblings; set
+ all of the fields of all of the dies correctly. Arguments are as
+ in read_die_and_children. */
+
+static struct die_info *
+read_die_and_siblings (char *info_ptr, bfd *abfd,
+ const struct comp_unit_head *cu_header,
+ char **new_info_ptr,
+ struct die_info *parent)
+{
+ struct die_info *first_die, *last_sibling;
+ char *cur_ptr;
+
cur_ptr = info_ptr;
- nesting_level = 0;
- first_die = last_die = NULL;
- do
+ first_die = last_sibling = NULL;
+
+ while (1)
{
- cur_ptr = read_full_die (&die, abfd, cur_ptr, cu_header);
- if (die->has_children)
+ struct die_info *die
+ = read_die_and_children (cur_ptr, abfd, cu_header,
+ &cur_ptr, parent);
+
+ if (!first_die)
{
- nesting_level++;
+ first_die = die;
}
- if (die->tag == 0)
+ else
{
- nesting_level--;
+ last_sibling->sibling = die;
}

- die->next = NULL;
-
- /* Enter die in reference hash table */
- store_in_ref_table (die->offset, die);
-
- if (!first_die)
+ if (die->tag == 0)
{
- first_die = last_die = die;
+ *new_info_ptr = cur_ptr;
+ return first_die;
}
else
{
- last_die->next = die;
- last_die = die;
+ last_sibling = die;
}
}
- while (nesting_level > 0);
- return first_die;
}

/* Free a linked list of dies. */
@@ -3860,7 +3914,9 @@ free_die_list (struct die_info *dies)
die = dies;
while (die)
{
- next = die->next;
+ if (die->child != NULL)
+ free_die_list (die->child);
+ next = die->sibling;
xfree (die->attrs);
xfree (die);
die = next;
@@ -4173,12 +4229,14 @@ read_partial_die (struct partial_die_inf
return info_ptr;
}

-/* Read the die from the .debug_info section buffer. And set diep to
- point to a newly allocated die with its information. */
+/* Read the die from the .debug_info section buffer. Set DIEP to
+ point to a newly allocated die with its information, except for its
+ child, sibling, and parent fields. Set HAS_CHILDREN to tell
+ whether the die has children or not. */

static char *
read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
- const struct comp_unit_head *cu_header)
+ const struct comp_unit_head *cu_header, int *has_children)
{
unsigned int abbrev_number, bytes_read, i, offset;
struct abbrev_info *abbrev;
@@ -4194,19 +4252,20 @@ read_full_die (struct die_info **diep, b
die->abbrev = abbrev_number;
die->type = NULL;
*diep = die;
+ *has_children = 0;
return info_ptr;
}

abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
if (!abbrev)
{
- error ("Dwarf Error: could not find abbrev number %d [in module %s]", abbrev_number,
- bfd_get_filename (abfd));
+ error ("Dwarf Error: could not find abbrev number %d [in module %s]",
+ abbrev_number,
+ bfd_get_filename (abfd));
}
die = dwarf_alloc_die ();
die->offset = offset;
die->tag = abbrev->tag;
- die->has_children = abbrev->has_children;
die->abbrev = abbrev_number;
die->type = NULL;

@@ -4221,6 +4280,7 @@ read_full_die (struct die_info **diep, b
}

*diep = die;
+ *has_children = abbrev->has_children;
return info_ptr;
}

@@ -5822,43 +5882,7 @@ copy_die (struct die_info *old_die)
static struct die_info *
sibling_die (struct die_info *die)
{
- int nesting_level = 0;
-
- if (!die->has_children)
- {
- if (die->next && (die->next->tag == 0))
- {
- return NULL;
- }
- else
- {
- return die->next;
- }
- }
- else
- {
- do
- {
- if (die->has_children)
- {
- nesting_level++;
- }
- if (die->tag == 0)
- {
- nesting_level--;
- }
- die = die->next;
- }
- while (nesting_level);
- if (die && (die->tag == 0))
- {
- return NULL;
- }
- else
- {
- return die;
- }
- }
+ return die->sibling;
}

/* Get linkage name of a die, return NULL if not found. */
@@ -6727,7 +6751,7 @@ dump_die (struct die_info *die)
fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n",
dwarf_tag_name (die->tag), die->abbrev, die->offset);
fprintf_unfiltered (gdb_stderr, "\thas children: %s\n",
- dwarf_bool_name (die->has_children));
+ dwarf_bool_name (die->child != NULL));

fprintf_unfiltered (gdb_stderr, "\tattributes:\n");
for (i = 0; i < die->num_attrs; ++i)
@@ -6790,7 +6814,10 @@ dump_die_list (struct die_info *die)
while (die)
{
dump_die (die);
- die = die->next;
+ if (die->child != NULL)
+ dump_die_list (die->child);
+ if (die->sibling != NULL)
+ dump_die_list (die->sibling);
}
}