]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
* dwarf2read.c (skip_leb128, peek_die_abbrev, skip_one_die)
authorDaniel Jacobowitz <drow@false.org>
Sat, 21 Feb 2004 20:37:00 +0000 (20:37 +0000)
committerDaniel Jacobowitz <drow@false.org>
Sat, 21 Feb 2004 20:37:00 +0000 (20:37 +0000)
(skip_children): New functions.
(locate_pdi_sibling): Call skip_children.
(load_partial_dies): Use peek_die_abbrev and skip_one_die.

gdb/ChangeLog.intercu
gdb/dwarf2read.c

index 9e0cc3ca9918f66397ef79fbc29ed93117874f06..75e438a7c02e8cd2b6df53c72ed67b742cb62207 100644 (file)
@@ -1,3 +1,10 @@
+2004-02-21  Daniel Jacobowitz  <drow@mvista.com>
+
+       * dwarf2read.c (skip_leb128, peek_die_abbrev, skip_one_die)
+       (skip_children): New functions.
+       (locate_pdi_sibling): Call skip_children.
+       (load_partial_dies): Use peek_die_abbrev and skip_one_die.
+
 2004-02-21  Daniel Jacobowitz  <drow@mvista.com>
 
        * dwarf2read.c (find_partial_die, fixup_partial_die): New functions,
index 1dae8f34b6fd512e003b68cfff9b9a1d8625ebef..db2ad7ed40802e8041ff91534da9a30bd1e2c9b8 100644 (file)
@@ -734,6 +734,8 @@ static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
 
 static long read_signed_leb128 (bfd *, char *, unsigned int *);
 
+static char *skip_leb128 (bfd *, char *);
+
 static void set_cu_language (unsigned int, struct dwarf2_cu *);
 
 static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
@@ -1755,6 +1757,139 @@ add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr,
   return info_ptr;
 }
 
+static struct abbrev_info *
+peek_die_abbrev (char *info_ptr, int *bytes_read, struct dwarf2_cu *cu)
+{
+  bfd *abfd = cu->objfile->obfd;
+  unsigned int abbrev_number;
+  struct abbrev_info *abbrev;
+
+  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
+
+  if (abbrev_number == 0)
+    return NULL;
+
+  abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
+  if (!abbrev)
+    {
+      error ("Dwarf Error: Could not find abbrev number %d [in module %s]", abbrev_number,
+                     bfd_get_filename (abfd));
+    }
+
+  return abbrev;
+}
+
+static char *skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
+                          struct dwarf2_cu *cu);
+
+static char *
+skip_children (char *info_ptr, struct dwarf2_cu *cu)
+{
+  struct abbrev_info *abbrev;
+  unsigned int bytes_read;
+
+  /* Skip a series of DIEs (and their children) starting at INFO_PTR.
+     Continue until we run into one without a tag; return whatever
+     follows it.  */
+
+  while (1)
+    {
+      abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu);
+      if (abbrev == NULL)
+       return info_ptr + bytes_read;
+      else
+       info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu);
+    }
+}
+
+
+static char *
+skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
+             struct dwarf2_cu *cu)
+{
+  unsigned int bytes_read;
+  struct attribute attr;
+  bfd *abfd = cu->objfile->obfd;
+  unsigned int form, i;
+
+  for (i = 0; i < abbrev->num_attrs; i++)
+    {
+      if (abbrev->attrs[i].name == DW_AT_sibling)
+       {
+         read_attribute (&attr, &abbrev->attrs[i],
+                         abfd, info_ptr, cu);
+         if (attr.form == DW_FORM_ref_addr)
+           complaint (&symfile_complaints, "ignoring absolute DW_AT_sibling");
+         else
+           return dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr, cu);
+       }
+      form = abbrev->attrs[i].form;
+    top:
+      switch (form)
+       {
+       case DW_FORM_addr:
+       case DW_FORM_ref_addr:
+         info_ptr += cu->header.addr_size;
+         break;
+       case DW_FORM_block2:
+         info_ptr += 2 + read_2_bytes (abfd, info_ptr);
+         break;
+       case DW_FORM_block4:
+         info_ptr += 4 + read_4_bytes (abfd, info_ptr);
+         break;
+       case DW_FORM_data2:
+       case DW_FORM_ref2:
+         info_ptr += 2;
+         break;
+       case DW_FORM_data4:
+       case DW_FORM_ref4:
+         info_ptr += 4;
+         break;
+       case DW_FORM_data8:
+       case DW_FORM_ref8:
+         info_ptr += 8;
+         break;
+       case DW_FORM_string:
+         read_string (abfd, info_ptr, &bytes_read);
+         info_ptr += bytes_read;
+         break;
+       case DW_FORM_strp:
+         info_ptr += cu->header.offset_size;
+         break;
+       case DW_FORM_block:
+         info_ptr += read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+         info_ptr += bytes_read;
+         break;
+       case DW_FORM_block1:
+         info_ptr += 1 + read_1_byte (abfd, info_ptr);
+         break;
+       case DW_FORM_data1:
+       case DW_FORM_ref1:
+       case DW_FORM_flag:
+         info_ptr += 1;
+         break;
+       case DW_FORM_sdata:
+       case DW_FORM_udata:
+       case DW_FORM_ref_udata:
+         info_ptr = skip_leb128 (abfd, info_ptr);
+         break;
+       case DW_FORM_indirect:
+         form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+         info_ptr += bytes_read;
+         goto top;
+       default:
+         error ("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]",
+                dwarf_form_name (form),
+                bfd_get_filename (abfd));
+       }
+    }
+
+  if (abbrev->has_children)
+    return skip_children (info_ptr, cu);
+  else
+    return info_ptr;
+}
+
 /* Locate ORIG_PDI's sibling; INFO_PTR should point to the next DIE
    after ORIG_PDI.  */
 
@@ -1762,31 +1897,19 @@ static char *
 locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr,
                    bfd *abfd, struct dwarf2_cu *cu)
 {
-  /* Do we know the sibling already?  */
-  
-  if (orig_pdi->sibling)
-    return orig_pdi->sibling;
-
   /* Are there any children to deal with?  */
 
   if (!orig_pdi->has_children)
     return info_ptr;
 
-  /* Okay, we don't know the sibling, but we have children that we
-     want to skip.  So read children until we run into one without a
-     tag; return whatever follows it.  */
-
-  while (1)
-    {
-      struct partial_die_info pdi;
+  /* Do we know the sibling already?  */
+  
+  if (orig_pdi->sibling)
+    return orig_pdi->sibling;
 
-      info_ptr = load_partial_die (&pdi, abfd, info_ptr, cu);
+  /* Skip the children the long way.  */
 
-      if (pdi.tag == 0)
-       return info_ptr;
-      else
-       info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu);
-    }
+  return skip_children (info_ptr, cu);
 }
 
 /* Expand this partial symbol table into a full symbol table.  */
@@ -4353,6 +4476,8 @@ load_partial_dies (bfd *abfd, char *info_ptr, struct dwarf2_cu *cu)
 {
   struct partial_die_info *part_die;
   struct partial_die_info *parent_die, *last_die;
+  struct abbrev_info *abbrev;
+  unsigned int bytes_read;
 
   /* FIXME: Obviously we need a nesting level passed in for incremental use.  */
   int nesting_level = 1;
@@ -4368,33 +4493,37 @@ load_partial_dies (bfd *abfd, char *info_ptr, struct dwarf2_cu *cu)
 
   while (1)
     {
-      //      fprintf_unfiltered (gdb_stderr, "Loading DIE %x\n", info_ptr - dwarf_info_buffer);
-      info_ptr = load_partial_die (part_die, abfd, info_ptr, cu);
+      abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu);
 
-      if (part_die->tag == 0)
+      if (abbrev == NULL)
        {
          if (--nesting_level == 0)
            {
              xfree (part_die);
              return;
            }
+         info_ptr += bytes_read;
          last_die = parent_die;
          parent_die = parent_die->die_parent;
          continue;
        }
 
       /* Check whether this DIE is interesting enough to save.  */
-      if (!is_type_tag (part_die->tag)
-         && part_die->tag != DW_TAG_enumerator
-         && part_die->tag != DW_TAG_subprogram
-         && part_die->tag != DW_TAG_variable
-         && part_die->tag != DW_TAG_namespace)
+      if (!is_type_tag (abbrev->tag)
+         && abbrev->tag != DW_TAG_enumerator
+         && abbrev->tag != DW_TAG_subprogram
+         && abbrev->tag != DW_TAG_variable
+         && abbrev->tag != DW_TAG_namespace)
        {
+         // printf ("Wasted DIE\n");
          /* Otherwise we skip to the next sibling, if any.  */
-         info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu);
+         info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu);
          continue;
        }
 
+      //      fprintf_unfiltered (gdb_stderr, "Loading DIE %x\n", info_ptr - dwarf_info_buffer);
+      info_ptr = load_partial_die (part_die, abfd, info_ptr, cu);
+
       /* We'll save this DIE so link it in.  */
       part_die->die_parent = parent_die;
       part_die->die_sibling = NULL;
@@ -5100,6 +5229,20 @@ read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
   return result;
 }
 
+static char *
+skip_leb128 (bfd *abfd, char *buf)
+{
+  int byte;
+
+  while (1)
+    {
+      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+      buf++;
+      if ((byte & 128) == 0)
+       return buf;
+    }
+}
+
 static void
 set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
 {