summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2014-12-10 18:28:04 -0800
committerJosh Stone <jistone@redhat.com>2014-12-11 11:23:26 -0800
commitb849f813e6753ea60784175321d4bde78c0c2ad9 (patch)
tree188555c682eb0f62537aba273dbba673f61d570a
parent2098b3d315b612d12b1425639707552e06131cde (diff)
downloadelfutils-b849f813e6753ea60784175321d4bde78c0c2ad9.tar.gz
libdw: unify die->abbrev lookups
Add a new internal function, __libdw_dieabbrev, which deals with checking a die for an abbrev, and setting it as needed. Signed-off-by: Josh Stone <jistone@redhat.com>
-rw-r--r--libdw/ChangeLog8
-rw-r--r--libdw/dwarf_child.c42
-rw-r--r--libdw/dwarf_getattrs.c19
-rw-r--r--libdw/dwarf_haschildren.c20
-rw-r--r--libdw/dwarf_tag.c20
-rw-r--r--libdw/libdwP.h25
6 files changed, 64 insertions, 70 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index b9b868b5..0d3150b9 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,11 @@
+2014-12-10 Josh Stone <jistone@redhat.com>
+
+ * libdwP.h (__libdw_dieabbrev): New die->abbrev lookup function.
+ * dwarf_child.c (__libdw_find_attr, dwarf_child): Use it.
+ * dwarf_getattrs.c (dwarf_getattrs): Likewise.
+ * dwarf_haschildren.c (dwarf_haschildren): Likewise.
+ * dwarf_tag.c (dwarf_tag): Likewise.
+
2014-12-04 Mark Wielaard <mjw@redhat.com>
* libdwP.h (__libdw_form_val_compute_len): Add endp argument.
diff --git a/libdw/dwarf_child.c b/libdw/dwarf_child.c
index fa316006..daf4c265 100644
--- a/libdw/dwarf_child.c
+++ b/libdw/dwarf_child.c
@@ -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,7 +60,7 @@ __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. */
@@ -137,21 +127,21 @@ 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;
diff --git a/libdw/dwarf_getattrs.c b/libdw/dwarf_getattrs.c
index 627a8511..9ea70fca 100644
--- a/libdw/dwarf_getattrs.c
+++ b/libdw/dwarf_getattrs.c
@@ -44,17 +44,12 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
if (unlikely (offset == 1))
return 1;
- const unsigned char *die_addr = die->addr;
+ const unsigned char *die_addr;
- /* Get the abbreviation code. */
- unsigned int u128;
- get_uleb128 (u128, die_addr);
+ /* Find the abbreviation entry. */
+ Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &die_addr);
- if (die->abbrev == NULL)
- /* Find the abbreviation. */
- die->abbrev = __libdw_findabbrev (die->cu, u128);
-
- if (unlikely (die->abbrev == DWARF_END_ABBREV))
+ if (unlikely (abbrevp == DWARF_END_ABBREV))
{
invalid_dwarf:
__libdw_seterrno (DWARF_E_INVALID_DWARF);
@@ -62,8 +57,8 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
}
/* This is where the attributes start. */
- const unsigned char *attrp = die->abbrev->attrp;
- const unsigned char *const offset_attrp = die->abbrev->attrp + offset;
+ const unsigned char *attrp = abbrevp->attrp;
+ const unsigned char *const offset_attrp = abbrevp->attrp + offset;
/* Go over the list of attributes. */
Dwarf *dbg = die->cu->dbg;
@@ -105,7 +100,7 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
/* Return the offset of the start of the attribute, so that
dwarf_getattrs() can be restarted from this point if the
caller so desires. */
- return remembered_attrp - die->abbrev->attrp;
+ return remembered_attrp - abbrevp->attrp;
}
/* Skip over the rest of this attribute (if there is any). */
diff --git a/libdw/dwarf_haschildren.c b/libdw/dwarf_haschildren.c
index b2273982..d0ce51ea 100644
--- a/libdw/dwarf_haschildren.c
+++ b/libdw/dwarf_haschildren.c
@@ -1,5 +1,5 @@
/* Return string associated with given attribute.
- Copyright (C) 2003, 2005, 2008 Red Hat, Inc.
+ Copyright (C) 2003, 2005, 2008, 2014 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
@@ -40,25 +40,13 @@ dwarf_haschildren (die)
Dwarf_Die *die;
{
/* Find the abbreviation entry. */
- Dwarf_Abbrev *abbrevp = die->abbrev;
- if (abbrevp != DWARF_END_ABBREV)
- {
- 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);
-
- 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, NULL);
+ if (unlikely (abbrevp == DWARF_END_ABBREV))
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return -1;
}
- return die->abbrev->has_children;
+ return abbrevp->has_children;
}
INTDEF (dwarf_haschildren)
diff --git a/libdw/dwarf_tag.c b/libdw/dwarf_tag.c
index ff012cf4..0b1a4b08 100644
--- a/libdw/dwarf_tag.c
+++ b/libdw/dwarf_tag.c
@@ -1,5 +1,5 @@
/* Return tag of given 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 <drepper@redhat.com>, 2003.
@@ -82,24 +82,14 @@ int
dwarf_tag (die)
Dwarf_Die *die;
{
- /* Do we already know the abbreviation? */
- if (die->abbrev == NULL)
- {
- /* Get the abbreviation code. */
- unsigned int u128;
- const unsigned char *addr = die->addr;
- get_uleb128 (u128, addr);
-
- /* Find the abbreviation. */
- die->abbrev = __libdw_findabbrev (die->cu, u128);
- }
-
- if (unlikely (die->abbrev == DWARF_END_ABBREV))
+ /* Find the abbreviation entry. */
+ Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
+ if (unlikely (abbrevp == DWARF_END_ABBREV))
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return DW_TAG_invalid;
}
- return die->abbrev->tag;
+ return abbrevp->tag;
}
INTDEF(dwarf_tag)
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 351c5b47..06338539 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -444,7 +444,7 @@ extern struct Dwarf_CU *__libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset, bool tu)
__nonnull_attribute__ (1) internal_function;
-/* Return tag of given DIE. */
+/* Get abbreviation with given code. */
extern Dwarf_Abbrev *__libdw_findabbrev (struct Dwarf_CU *cu,
unsigned int code)
__nonnull_attribute__ (1) internal_function;
@@ -455,6 +455,29 @@ extern Dwarf_Abbrev *__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu,
Dwarf_Abbrev *result)
__nonnull_attribute__ (1) internal_function;
+/* Get abbreviation of given DIE, and optionally set *READP to the DIE memory
+ just past the abbreviation code. */
+static inline Dwarf_Abbrev *
+__nonnull_attribute__ (1)
+__libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp)
+{
+ /* Do we need to get the abbreviation, or need to read after the code? */
+ if (die->abbrev == NULL || readp != NULL)
+ {
+ /* Get the abbreviation code. */
+ unsigned int code;
+ const unsigned char *addr = die->addr;
+ get_uleb128 (code, addr);
+ if (readp != NULL)
+ *readp = addr;
+
+ /* Find the abbreviation. */
+ if (die->abbrev == NULL)
+ die->abbrev = __libdw_findabbrev (die->cu, code);
+ }
+ return die->abbrev;
+}
+
/* Helper functions for form handling. */
extern size_t __libdw_form_val_compute_len (Dwarf *dbg, struct Dwarf_CU *cu,
unsigned int form,