summaryrefslogtreecommitdiffstats
path: root/libdw/dwarf_child.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdw/dwarf_child.c')
-rw-r--r--libdw/dwarf_child.c68
1 files changed, 27 insertions, 41 deletions
diff --git a/libdw/dwarf_child.c b/libdw/dwarf_child.c
index 1d3a3371..58a438b5 100644
--- a/libdw/dwarf_child.c
+++ b/libdw/dwarf_child.c
@@ -1,5 +1,5 @@
/* Return child of current DIE.
- Copyright (C) 2003-2011 Red Hat, Inc.
+ Copyright (C) 2003-2011, 2014 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <[email protected]>, 2003.
@@ -44,21 +44,11 @@ __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
unsigned int *codep, unsigned int *formp)
{
Dwarf *dbg = die->cu->dbg;
- const unsigned char *readp = (unsigned char *) die->addr;
-
- /* First we have to get the abbreviation code so that we can decode
- the data in the DIE. */
- unsigned int abbrev_code;
- get_uleb128 (abbrev_code, readp);
+ const unsigned char *readp;
/* Find the abbreviation entry. */
- Dwarf_Abbrev *abbrevp = die->abbrev;
- if (abbrevp == NULL)
- {
- abbrevp = __libdw_findabbrev (die->cu, abbrev_code);
- die->abbrev = abbrevp ?: DWARF_END_ABBREV;
- }
- if (unlikely (die->abbrev == DWARF_END_ABBREV))
+ Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &readp);
+ if (unlikely (abbrevp == DWARF_END_ABBREV))
{
invalid_dwarf:
__libdw_seterrno (DWARF_E_INVALID_DWARF);
@@ -70,21 +60,19 @@ __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
= ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf
+ dbg->sectiondata[IDX_debug_abbrev]->d_size);
- const unsigned char *attrp = die->abbrev->attrp;
+ const unsigned char *attrp = abbrevp->attrp;
while (1)
{
- /* Are we still in bounds? This test needs to be refined. */
- if (unlikely (attrp + 1 >= endp))
+ /* Get attribute name and form. */
+ if (unlikely (attrp >= endp))
goto invalid_dwarf;
-
- /* Get attribute name and form.
-
- XXX We don't check whether this reads beyond the end of the
- section. */
unsigned int attr_name;
- get_uleb128 (attr_name, attrp);
+ get_uleb128 (attr_name, attrp, endp);
+
+ if (unlikely (attrp >= endp))
+ goto invalid_dwarf;
unsigned int attr_form;
- get_uleb128 (attr_form, attrp);
+ get_uleb128 (attr_form, attrp, endp);
/* We can stop if we found the attribute with value zero. */
if (attr_name == 0 && attr_form == 0)
@@ -104,15 +92,14 @@ __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
/* Skip over the rest of this attribute (if there is any). */
if (attr_form != 0)
{
- size_t len = __libdw_form_val_len (dbg, die->cu, attr_form, readp);
-
+ size_t len = __libdw_form_val_len (die->cu, attr_form, readp);
if (unlikely (len == (size_t) -1l))
{
readp = NULL;
break;
}
- // XXX We need better boundary checks.
+ // __libdw_form_val_len will have done a bounds check.
readp += len;
}
}
@@ -136,33 +123,32 @@ dwarf_child (die, result)
if (die == NULL)
return -1;
- /* Skip past the last attribute. */
- void *addr = NULL;
-
- /* If we already know there are no children do not search. */
- if (die->abbrev != DWARF_END_ABBREV
- && (die->abbrev == NULL || die->abbrev->has_children))
- addr = __libdw_find_attr (die, INVALID, NULL, NULL);
- if (unlikely (die->abbrev == (Dwarf_Abbrev *) -1l))
- return -1;
+ /* Find the abbreviation entry. */
+ Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
+ if (unlikely (abbrevp == DWARF_END_ABBREV))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
- /* Make sure the DIE really has children. */
- if (! die->abbrev->has_children)
- /* There cannot be any children. */
+ /* If there are no children, do not search. */
+ if (! abbrevp->has_children)
return 1;
+ /* Skip past the last attribute. */
+ void *addr = __libdw_find_attr (die, INVALID, NULL, NULL);
+
if (addr == NULL)
return -1;
/* RESULT can be the same as DIE. So preserve what we need. */
struct Dwarf_CU *cu = die->cu;
- Elf_Data *cu_sec = cu_data (cu);
/* It's kosher (just suboptimal) to have a null entry first thing (7.5.3).
So if this starts with ULEB128 of 0 (even with silly encoding of 0),
it is a kosher null entry and we do not really have any children. */
const unsigned char *code = addr;
- const unsigned char *endp = (cu_sec->d_buf + cu_sec->d_size);
+ const unsigned char *endp = cu->endp;
while (1)
{
if (unlikely (code >= endp)) /* Truncated section. */