summaryrefslogtreecommitdiff
path: root/gdb/dwarf2read.c
diff options
context:
space:
mode:
authorDavid Carlton <carlton@bactrian.org>2003-09-30 22:29:28 +0000
committerDavid Carlton <carlton@bactrian.org>2003-09-30 22:29:28 +0000
commitb3aa7ee199af8bd98aa8adf3177870fc09443a98 (patch)
tree4395515ed36755300eb3ccd8638d011a2e8c759d /gdb/dwarf2read.c
parent14885d79428474cfeea52c825de2efe4f898c98f (diff)
downloadgdb-b3aa7ee199af8bd98aa8adf3177870fc09443a98.tar.gz
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.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r--gdb/dwarf2read.c219
1 files changed, 123 insertions, 96 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index bb614e5ef9a..3c3ec918ef1 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -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 partial_die_info *,
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 die_info *, struct objfile *,
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_symtab *pst)
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, struct objfile *objfile,
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, struct objfile *objfile,
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, struct objfile *objfile,
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, struct objfile *objfile,
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_info *die, struct objfile *objfile,
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 *die, struct objfile *objfile,
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 *die, struct objfile *objfile,
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, struct objfile *objfile,
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, struct objfile *objfile,
/* 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, struct objfile *objfile,
}
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, struct objfile *objfile,
"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, struct objfile *objfile,
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 *die, struct objfile *objfile,
|| 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 *die, struct objfile *objfile,
/* 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 *die, struct objfile *objfile,
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_info *part_die, bfd *abfd,
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, bfd *abfd, char *info_ptr,
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, bfd *abfd, char *info_ptr,
}
*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);
}
}