summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <dan@debian.org>2004-02-21 20:37:00 +0000
committerDaniel Jacobowitz <dan@debian.org>2004-02-21 20:37:00 +0000
commit323998df13e42f4b16da31bcf185fb0d28c609be (patch)
treee765671d4ccdd646f4fe1290d6dff6607727a8d3
parentc2f9db74adc86d60c1cffb00973cbf6aa93b0d2f (diff)
downloadgdb-323998df13e42f4b16da31bcf185fb0d28c609be.tar.gz
* 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.
-rw-r--r--gdb/ChangeLog.intercu7
-rw-r--r--gdb/dwarf2read.c197
2 files changed, 177 insertions, 27 deletions
diff --git a/gdb/ChangeLog.intercu b/gdb/ChangeLog.intercu
index 9e0cc3ca991..75e438a7c02 100644
--- a/gdb/ChangeLog.intercu
+++ b/gdb/ChangeLog.intercu
@@ -1,5 +1,12 @@
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,
broken out from read_partial_die.
(read_partial_die): Remove function.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 1dae8f34b6f..db2ad7ed408 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,
@@ -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)
{