summaryrefslogtreecommitdiff
path: root/libdw/dwarf_hasattr.c
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2014-12-10 18:33:34 -0800
committerJosh Stone <jistone@redhat.com>2014-12-11 11:23:26 -0800
commit64e44dfc9420940d238e5fdad4fadce3c1f5f05e (patch)
tree19fb9c6d48344c9f153ed9f0b7f818f3d2fb28c4 /libdw/dwarf_hasattr.c
parentb849f813e6753ea60784175321d4bde78c0c2ad9 (diff)
downloadelfutils-64e44dfc9420940d238e5fdad4fadce3c1f5f05e.tar.gz
libdw: optimize dwarf_hasattr to just look at abbrev
To just check the presence of an attribute, we only need to look at the abbreviation data. This optimization avoids reading over die data at all, except possibly just to get the abbrev code. Signed-off-by: Josh Stone <jistone@redhat.com>
Diffstat (limited to 'libdw/dwarf_hasattr.c')
-rw-r--r--libdw/dwarf_hasattr.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c
index fb7e1d5e..6ed1a98c 100644
--- a/libdw/dwarf_hasattr.c
+++ b/libdw/dwarf_hasattr.c
@@ -43,10 +43,44 @@ dwarf_hasattr (die, search_name)
if (die == NULL)
return 0;
- /* Search for the attribute with the given name. */
- unsigned int code;
- unsigned char *addr = __libdw_find_attr (die, search_name, &code, NULL);
+ /* Find the abbreviation entry. */
+ Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
+ if (unlikely (abbrevp == DWARF_END_ABBREV))
+ {
+ invalid_dwarf:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return 0;
+ }
- return addr != NULL && code == search_name;
+ Dwarf *dbg = die->cu->dbg;
+
+ /* Search the name attribute. */
+ unsigned char *const endp
+ = ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf
+ + dbg->sectiondata[IDX_debug_abbrev]->d_size);
+
+ const unsigned char *attrp = abbrevp->attrp;
+ while (1)
+ {
+ /* Are we still in bounds? This test needs to be refined. */
+ if (unlikely (attrp + 1 >= 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);
+ unsigned int attr_form;
+ get_uleb128 (attr_form, attrp);
+
+ /* We can stop if we found the attribute with value zero. */
+ if (attr_name == 0 || attr_form == 0)
+ return 0;
+
+ if (attr_name == search_name)
+ return 1;
+ }
}
INTDEF (dwarf_hasattr)