[rfa] add 'parent' field to struct die_info

David Carlton carlton@kealia.com
Tue Sep 30 16:29:00 GMT 2003


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);
     }
 }
 



More information about the Gdb-patches mailing list