* dwarf2read.c (skip_leb128, peek_die_abbrev, skip_one_die)

(skip_children): New functions.
	(locate_pdi_sibling): Call skip_children.
This commit is contained in:
Daniel Jacobowitz 2004-03-09 19:38:11 +00:00
parent c7414a01d5
commit 4bb7a0a769
2 changed files with 177 additions and 16 deletions

View File

@ -1,3 +1,9 @@
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.

View 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,
@ -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. */
/* Skip the children the long way. */
while (1)
{
struct partial_die_info pdi;
info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu);
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)
{