]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdw: optimize dwarf_hasattr to just look at abbrev
authorJosh Stone <jistone@redhat.com>
Thu, 11 Dec 2014 02:33:34 +0000 (18:33 -0800)
committerJosh Stone <jistone@redhat.com>
Thu, 11 Dec 2014 19:23:26 +0000 (11:23 -0800)
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>
libdw/ChangeLog
libdw/dwarf_hasattr.c

index 0d3150b91845e3efbb0c685d7fbd3e2ab0addb3a..90c080926c414126032cd6465778cf0710680342 100644 (file)
@@ -1,3 +1,7 @@
+2014-12-10  Josh Stone  <jistone@redhat.com>
+
+       * dwarf_hasattr.c (dwarf_hasattr): Just walk abbrev for presence.
+
 2014-12-10  Josh Stone  <jistone@redhat.com>
 
        * libdwP.h (__libdw_dieabbrev): New die->abbrev lookup function.
index fb7e1d5ed495110449c919710c15a56353a708fb..6ed1a98cbb49e1c9558df23e0a3833d4995a3942 100644 (file)
@@ -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)