]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdw: New get_uleb128_unchecked to use with already checked Dwarf_Abbrev.
authorMark Wielaard <mark@klomp.org>
Tue, 26 Dec 2017 10:52:06 +0000 (11:52 +0100)
committerMark Wielaard <mark@klomp.org>
Mon, 1 Jan 2018 21:48:56 +0000 (22:48 +0100)
When creating a Dwarf_Abbrev in dwarf_getabbrev (__libdw_getabbrev) we
already check it is fully readable from the .debug_abbrev section. So
whenever we reread it later using the attrp pointer we don't have to
check it again. Introduce get_uleb128_unchecked to use for ulebs we
know are safe to read directly.

Signed-off-by: Mark Wielaard <mark@klomp.org>
libdw/ChangeLog
libdw/dwarf_child.c
libdw/dwarf_getabbrevattr.c
libdw/dwarf_getattrs.c
libdw/dwarf_hasattr.c
libdw/memory-access.h

index 97155de1fd763a801f32951a30ad5a27ea4aba45..ba9bbe1abff8a610919672d8b30c9610991bd8ad 100644 (file)
@@ -1,3 +1,13 @@
+2017-12-26  Mark Wielaard  <mark@klomp.org>
+
+       * memory-access.h (__libdw_get_uleb128_unchecked): New function.
+       (get_uleb128_unchecked): New define.
+       * dwarf_child.c (__libdw_find_attr): Use get_uleb128_unchecked to
+       read attr name and form.
+       * dwarf_getabbrevattr.c (dwarf_getabbrevattr): Likewise.
+       * dwarf_getattrs.c (dwarf_getattrs): Likewise.
+       * dwarf_hasattr.c (dwarf_hasattr): Likewise.
+
 2017-12-28  Mark Wielaard  <mark@klomp.org>
 
        * dwarf_offdie.c (__libdw_offdie): Check sectiondata exists.
index cc95fb3fad73a34222cccb6d7c848f555befacba..248338eb2339d8e13fd107e327e1c3103be3826a 100644 (file)
@@ -1,5 +1,5 @@
 /* Return child of current DIE.
-   Copyright (C) 2003-2011, 2014 Red Hat, Inc.
+   Copyright (C) 2003-2011, 2014, 2017 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -43,36 +43,27 @@ internal_function
 __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;
 
   /* Find the abbreviation entry.  */
   Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &readp);
   if (unlikely (abbrevp == DWARF_END_ABBREV))
     {
-    invalid_dwarf:
       __libdw_seterrno (DWARF_E_INVALID_DWARF);
       return NULL;
     }
 
-  /* Search the name attribute.  */
-  unsigned char *const endp
-    = ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf
-       + dbg->sectiondata[IDX_debug_abbrev]->d_size);
-
+  /* Search the name attribute.  Attribute has been checked when
+     Dwarf_Abbrev was created, we can read unchecked.  */
   const unsigned char *attrp = abbrevp->attrp;
   while (1)
     {
       /* Get attribute name and form.  */
-      if (unlikely (attrp >= endp))
-       goto invalid_dwarf;
       unsigned int attr_name;
-      get_uleb128 (attr_name, attrp, endp);
+      get_uleb128_unchecked (attr_name, attrp);
 
-      if (unlikely (attrp >= endp))
-       goto invalid_dwarf;
       unsigned int attr_form;
-      get_uleb128 (attr_form, attrp, endp);
+      get_uleb128_unchecked (attr_form, attrp);
 
       /* We can stop if we found the attribute with value zero.  */
       if (attr_name == 0 && attr_form == 0)
index 3b4da99ce3da786d662d270dd64db92c01579d64..57fe363771d063053533bcc00e1cff2d8e401375 100644 (file)
@@ -1,5 +1,5 @@
 /* Get specific attribute of abbreviation.
-   Copyright (C) 2003, 2004, 2005, 2014 Red Hat, Inc.
+   Copyright (C) 2003, 2004, 2005, 2014, 2017 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -53,10 +53,10 @@ dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx, unsigned int *namep,
     {
       start_attrp = attrp;
 
-      /* Attribute code and form are encoded as ULEB128 values.i
-         XXX We have no way to bounds check.  */
-      get_uleb128 (name, attrp, attrp + len_leb128 (name));
-      get_uleb128 (form, attrp, attrp + len_leb128 (form));
+      /* Attribute code and form are encoded as ULEB128 values.
+         Already checked when Dwarf_Abbrev was created, read unchecked.  */
+      get_uleb128_unchecked (name, attrp);
+      get_uleb128_unchecked (form, attrp);
 
       /* If both values are zero the index is out of range.  */
       if (name == 0 && form == 0)
index 0da8b5ba08b7bb5ec11661a0788293170327cb38..7f55fafcb254eb7b180adc7a88d7494fcd77de30 100644 (file)
@@ -1,5 +1,5 @@
 /* Get attributes of the DIE.
-   Copyright (C) 2004, 2005, 2008, 2009, 2014 Red Hat, Inc.
+   Copyright (C) 2004, 2005, 2008, 2009, 2014, 2017 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -51,7 +51,6 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
 
   if (unlikely (abbrevp == DWARF_END_ABBREV))
     {
-    invalid_dwarf:
       __libdw_seterrno (DWARF_E_INVALID_DWARF);
       return -1l;
     }
@@ -61,24 +60,15 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
   const unsigned char *const offset_attrp = abbrevp->attrp + offset;
 
   /* Go over the list of attributes.  */
-  Dwarf *dbg = die->cu->dbg;
-  const unsigned char *endp;
-  endp = ((const unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf
-         + dbg->sectiondata[IDX_debug_abbrev]->d_size);
   while (1)
     {
-      /* Are we still in bounds?  */
-      if (unlikely (attrp >= endp))
-       goto invalid_dwarf;
-
-      /* Get attribute name and form.  */
+      /* Get attribute name and form.  Dwarf_Abbrev was checked when
+        created, so we can read unchecked.  */
       Dwarf_Attribute attr;
       const unsigned char *remembered_attrp = attrp;
 
-      get_uleb128 (attr.code, attrp, endp);
-      if (unlikely (attrp >= endp))
-       goto invalid_dwarf;
-      get_uleb128 (attr.form, attrp, endp);
+      get_uleb128_unchecked (attr.code, attrp);
+      get_uleb128_unchecked (attr.form, attrp);
 
       /* We can stop if we found the attribute with value zero.  */
       if (attr.code == 0 && attr.form == 0)
index 2bb8dc82631135405ec3141bc9c50f175b9fe1e3..90b333e6289853bd5f30999fd88d404336557ac9 100644 (file)
@@ -1,5 +1,5 @@
 /* Check whether given DIE has specific attribute.
-   Copyright (C) 2003, 2005, 2014 Red Hat, Inc.
+   Copyright (C) 2003, 2005, 2014, 2017 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -45,32 +45,20 @@ dwarf_hasattr (Dwarf_Die *die, unsigned int search_name)
   Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
   if (unlikely (abbrevp == DWARF_END_ABBREV))
     {
-    invalid_dwarf:
       __libdw_seterrno (DWARF_E_INVALID_DWARF);
       return 0;
     }
 
-  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);
-
+  /* Search the name attribute.  Dwarf_Abbrev was checked when created,
+     so we can read unchecked here.  */
   const unsigned char *attrp = abbrevp->attrp;
   while (1)
     {
-      /* Are we still in bounds?  This test needs to be refined.  */
-      if (unlikely (attrp >= endp))
-       goto invalid_dwarf;
-
       /* Get attribute name and form.  */
       unsigned int attr_name;
-      get_uleb128 (attr_name, attrp, endp);
+      get_uleb128_unchecked (attr_name, attrp);
       unsigned int attr_form;
-      if (unlikely (attrp >= endp))
-       goto invalid_dwarf;
-      get_uleb128 (attr_form, attrp, endp);
+      get_uleb128_unchecked (attr_form, attrp);
 
       /* We can stop if we found the attribute with value zero.  */
       if (attr_name == 0 || attr_form == 0)
index afb651fce7322649e3e76f8493d42827f540e65d..ed68bdb9f840d7def1edbb49d9d9b1ff38084cbc 100644 (file)
@@ -87,8 +87,26 @@ __libdw_get_uleb128 (const unsigned char **addrp, const unsigned char *end)
   return UINT64_MAX;
 }
 
+static inline uint64_t
+__libdw_get_uleb128_unchecked (const unsigned char **addrp)
+{
+  uint64_t acc = 0;
+
+  /* Unroll the first step to help the compiler optimize
+     for the common single-byte case.  */
+  get_uleb128_step (acc, *addrp, 0);
+
+  const size_t max = len_leb128 (uint64_t);
+  for (size_t i = 1; i < max; ++i)
+    get_uleb128_step (acc, *addrp, i);
+  /* Other implementations set VALUE to UINT_MAX in this
+     case.  So we better do this as well.  */
+  return UINT64_MAX;
+}
+
 /* Note, addr needs to me smaller than end. */
 #define get_uleb128(var, addr, end) ((var) = __libdw_get_uleb128 (&(addr), end))
+#define get_uleb128_unchecked(var, addr) ((var) = __libdw_get_uleb128_unchecked (&(addr)))
 
 /* The signed case is similar, but we sign-extend the result.  */