aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/dwarf2read.c187
2 files changed, 177 insertions, 16 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8ae0ed2..2c5fb08 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2004-03-09 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.
+
+2004-03-09 Daniel Jacobowitz <drow@mvista.com>
+
* arm-tdep.c (arm_use_struct_convention): Look through typedefs.
* gdbtypes.c (check_typedef): Update comments.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index ffc18e5..ffc76c8 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -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,
@@ -937,6 +939,9 @@ static void
dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu);
+static char *skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
+ struct dwarf2_cu *cu);
+
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something. */
@@ -1765,8 +1770,154 @@ add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr,
return info_ptr;
}
-/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next DIE
- after ORIG_PDI. */
+/* Read the initial uleb128 in the die at INFO_PTR in compilation unit CU.
+ Return the corresponding abbrev, or NULL if the number is zero (indicating
+ an empty DIE). In either case *BYTES_READ will be set to the length of
+ the initial number. */
+
+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;
+}
+
+/* Scan the debug information for CU starting at INFO_PTR. Returns a
+ pointer to the end of a series of DIEs, terminated by an empty
+ DIE. Any children of the skipped DIEs will also be skipped. */
+
+static char *
+skip_children (char *info_ptr, struct dwarf2_cu *cu)
+{
+ struct abbrev_info *abbrev;
+ unsigned int bytes_read;
+
+ 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);
+ }
+}
+
+/* Scan the debug information for CU starting at INFO_PTR. INFO_PTR
+ should point just after the initial uleb128 of a DIE, and the
+ abbrev corresponding to that skipped uleb128 should be passed in
+ ABBREV. Returns a pointer to this DIE's sibling, skipping any
+ children. */
+
+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++)
+ {
+ /* The only abbrev we care about is DW_AT_sibling. */
+ 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);
+ }
+
+ /* If it isn't DW_AT_sibling, skip this attribute. */
+ form = abbrev->attrs[i].form;
+ skip_attribute:
+ switch (form)
+ {
+ case DW_FORM_addr:
+ case DW_FORM_ref_addr:
+ info_ptr += cu->header.addr_size;
+ break;
+ case DW_FORM_data1:
+ case DW_FORM_ref1:
+ case DW_FORM_flag:
+ info_ptr += 1;
+ 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_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_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;
+ /* We need to continue parsing from here, so just go back to
+ the top. */
+ goto skip_attribute;
+
+ 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 start of
+ the next DIE after ORIG_PDI. */
static char *
locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr,
@@ -1782,21 +1933,9 @@ locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr,
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;
-
- info_ptr = read_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. */
@@ -4950,6 +5089,22 @@ read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
return result;
}
+/* Return a pointer to just past the end of an LEB128 number in BUF. */
+
+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)
{