]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Squashed commit of the following:
authorUlrich Drepper <drepper@redhat.com>
Mon, 15 Jun 2009 03:19:45 +0000 (20:19 -0700)
committerUlrich Drepper <drepper@redhat.com>
Mon, 15 Jun 2009 03:19:45 +0000 (20:19 -0700)
commit 77abb31cb8d55980ef92260917a7ecdd228b1a44
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon Jun 8 15:46:16 2009 +0200

    Fix a bug in offset checking

commit b794eac4f8d3e08101b5d2924523b1259bbc1b17
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed Jun 3 16:00:01 2009 +0200

    Cosmetic, get rid of defining several variables per line

commit a23938fe35d515a3d75a51f6204771f3cf6c9ec4
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed Jun 3 15:50:03 2009 +0200

    Restructure the code to decrease the binary size

commit 7c301e3d4e8584dfb3174855fb6af3d5791dfeed
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon Jun 1 19:43:28 2009 +0200

    Shuffle a couple pieces of code around to make the code smaller

commit 6325323482c2a3e17409d32c7feec9461be26614
Merge: 83ac53d... e94b1b2...
Author: Petr Machata <pmachata@redhat.com>
Date:   Fri May 22 08:49:07 2009 +0200

    Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks

    Conflicts:
     libdw/ChangeLog

commit 83ac53db400945c074e77ec9904efe550903a0e2
Author: Petr Machata <pmachata@redhat.com>
Date:   Fri May 22 08:40:25 2009 +0200

    Call reloc hook with the original address, not incremented

commit f1996388745566abc1ca1c1700b3b7eded208575
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed May 6 16:53:03 2009 +0200

    Rewrite boundary checking logic so that it's immune to arithmetic overflow

    * ... also get rid of some code redundancy.

commit 0c1df732822d83548edd0d005f3450281ed1701b
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed May 6 16:25:09 2009 +0200

    __libdw_read_offset* take extra argument for header size checks

    * also presence of debug data and buffer is checked in __libdw_in_section

commit 6fb192e360f842cacb34a90c03cd0524cccc3dec
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed May 6 15:51:20 2009 +0200

    Check for presence of data before loading the offset

commit a2e7612b165d83dd241225f87075fa4f58d18781
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed May 6 15:04:16 2009 +0200

    Cosmetic changes

commit 8b1aad2c2f6c8dc02b3e704e4f386c1827e385cb
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue May 5 15:34:13 2009 +0200

    Improve reader hook functions a bit

    * ... so that they are closer match to what's need on call sites

commit 3854b7fbab2fe331711365f94a295af82164d0d2
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue May 5 14:33:50 2009 +0200

    Fixes in use of reader hooks in __libdw_formptr and dwarf_formudata

    * and a bit more

commit 335075596b6acef6e59919155e2b087e690a572d
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue May 5 14:32:39 2009 +0200

    Rename __libdw_read_udata_addr to __libdw_formptr

commit 8273a2adaf8cb2ee203926af2849e4f96f8a6eaf
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue May 5 02:53:40 2009 +0200

    Introduce __libdw_read_udata_address

    * the use in dwarf_ranges is iffy, there's a functionality mismatch.
      Need to find some better way

commit 1c897f4abde1530038d332f4fc03a596a24f6aaf
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon May 4 18:09:13 2009 +0200

    ChangeLog entries for previous commit

commit 90d7c39454468b91c0fd6514a4e8d821222d6adb
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon May 4 18:07:54 2009 +0200

    Fix bugs, introduce __libdw_read_begin_end_pair_inc

commit 9b3923f5b69a3e56590769435c4693f057acdc1f
Merge: 6200ba6... 589b3d3...
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon May 4 12:22:21 2009 +0200

    Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks

commit 6200ba62aa9ea3cb9318f73a27181907a528dbe4
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed Apr 29 15:31:28 2009 +0200

    dwarf_getlocation_addr uses read hooks

commit ecbb8cdd8b500e37dc34fc246b912f704fe31ca4
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed Apr 29 15:16:09 2009 +0200

    dwarf_ranges and dwarf_formref use read hooks

commit cb8f67b29a896c2660c10aa1028a9dbb377553e9
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue Apr 28 18:39:04 2009 +0200

    Convert several new functions to use read hooks

commit b130453eb16a8cf042915e312cc5f189b8b92c01
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue Apr 28 18:38:27 2009 +0200

    Add length read hooks

commit bd885ff694817b965231d99f1ab867947998e734
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue Apr 28 18:36:17 2009 +0200

    Constify read hook arguments

commit 66fe03f1e489a88b89a15c9e13f9bd33db2729b1
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue Apr 28 16:11:05 2009 +0200

    Change type of return value of offset read hooks to Dwarf_Off

commit 22b36e00cc228f5a966f84ca3323e5d652923ce8
Merge: 5b3534b... a7cb532...
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon Apr 27 19:05:25 2009 +0200

    Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks

commit 5b3534b62cbd45fe4f11dd1be3e492237938cce0
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon Apr 27 18:53:06 2009 +0200

    Rewrites in read hooks

    * Have the checking and reading logic itself in the header so that it gets
      optimized out/inlined.  Call external relocating hook from there, there
      will presumably be more work to do, and we presumably don't want to keep
      this in the header.

commit 9e265d71d0eb900e76d6fdb0196ef4fc6507f3a7
Merge: 1783089... 300f3a4...
Author: Petr Machata <pmachata@redhat.com>
Date:   Thu Apr 23 17:45:25 2009 +0200

    Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks

commit 1783089b184ddea2081bbe5ac4e80420cb6b0803
Author: Petr Machata <pmachata@redhat.com>
Date:   Thu Apr 23 17:44:48 2009 +0200

    Use the new reader hooks in several places

commit 11c3d97a5b40ea15edf324092b03da3050610d01
Author: Petr Machata <pmachata@redhat.com>
Date:   Thu Apr 23 17:40:03 2009 +0200

    Introduce reader hooks

12 files changed:
libdw/ChangeLog
libdw/dwarf_formaddr.c
libdw/dwarf_formref_die.c
libdw/dwarf_formstring.c
libdw/dwarf_formudata.c
libdw/dwarf_getaranges.c
libdw/dwarf_getlocation.c
libdw/dwarf_getpubnames.c
libdw/dwarf_getsrclines.c
libdw/dwarf_nextcu.c
libdw/dwarf_ranges.c
libdw/libdwP.h

index 0e317d7c77dca7be4c01b599e5d09618bd678cae..525bb329b6629dc877fc411b19d0840a09c7e43f 100644 (file)
@@ -1,3 +1,37 @@
+2009-05-05  Petr Machata  <pmachata@redhat.com>
+
+       * libdwP.h (__libdw_formptr): Declare new function.
+       * dwarf_formudata.c: Implement it here.
+       * dwarf_getlocation.c (dwarf_getlocation_addr):
+       Call it instead of hand-rolled offset handling code.
+       * dwarf_getsrclines.c (dwarf_getsrclines): Likewise.
+       * dwarf_ranges.c (dwarf_ranges): Likewise.
+
+2009-05-04  Petr Machata  <pmachata@redhat.com>
+
+       * libdwP.h (__libdw_read_begin_end_pair_inc): Declare new function.
+       * dwarf_ranges.c: Implement it here.
+       (dwarf_ranges): Call it.
+       * dwarf_getlocation.c (dwarf_getlocation_addr): Call it also here.
+
+2009-04-23  Petr Machata  <pmachata@redhat.com>
+
+       * dwarf_formaddr.c (dwarf_formaddr): Call __libdw_read_* instead
+       of read_*ubyte_unaligned.
+       * dwarf_formref_die.c (dwarf_formref_die): Likewise.
+       * dwarf_formstring.c (dwarf_formstring): Likewise.
+       * dwarf_formudate.c (dwarf_formudata): Likewise.
+       * dwarf_getaranges.c (dwarf_getaranges): Likewise.
+       * dwarf_getlocation.c (dwarf_getlocation_addr): Likewise.
+       * dwarf_getpubnames.c (get_offsets): Likewise.
+       * dwarf_nextcu.c (dwarf_nextcu): Likewise.
+
+2009-04-23  Petr Machata  <pmachata@redhat.com>
+
+       * libdwP.h (__libdw_read_addr_inc, __libdw_read_off_inc,
+       __libdw_read_addr, __libdw_read_off): Add four new internal
+       functions.
+
 2009-05-07  Roland McGrath  <roland@redhat.com>
 
        * dwarf_getmacros.c (dwarf_getmacros): Use absolute section offset in
index dcb58d43348c79babc83b044754f9dcbe449594d..9938be7e2d5621dc214f0ca80c82aee00d195dfc 100644 (file)
@@ -70,10 +70,10 @@ dwarf_formaddr (attr, return_addr)
       return -1;
     }
 
-  if (attr->cu->address_size == 8)
-    *return_addr = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
-  else
-    *return_addr = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+  if (__libdw_read_address (attr->cu->dbg,
+                           IDX_debug_info, attr->valp,
+                           attr->cu->address_size, return_addr))
+    return -1;
 
   return 0;
 }
index 90a4b2d358d5301fc4ca7232ed34898c841b148e..a004a0fd40263ae35f8f015d74e978c9e6aec7b9 100644 (file)
@@ -72,10 +72,9 @@ dwarf_formref_die (attr, die_mem)
                          ? attr->cu->address_size
                          : attr->cu->offset_size);
 
-      if (ref_size == 8)
-       offset = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
-      else
-       offset = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+      if (__libdw_read_offset (attr->cu->dbg, IDX_debug_info, attr->valp,
+                              ref_size, &offset, IDX_debug_info, 0))
+       return NULL;
     }
   else
     {
index 790831ea3e7bca5401dfcc3792f8e3d1320ec7e3..f95d31b827fe8262c8222c279ab27b8048fd2cb0 100644 (file)
@@ -74,20 +74,14 @@ dwarf_formstring (attrp)
   if (unlikely (attrp->form != DW_FORM_strp)
       || dbg->sectiondata[IDX_debug_str] == NULL)
     {
-    invalid_error:
       __libdw_seterrno (DWARF_E_NO_STRING);
       return NULL;
     }
 
   uint64_t off;
-  // XXX We need better boundary checks.
-  if (attrp->cu->offset_size == 8)
-    off = read_8ubyte_unaligned (dbg, attrp->valp);
-  else
-    off = read_4ubyte_unaligned (dbg, attrp->valp);
-
-  if (off  >= dbg->sectiondata[IDX_debug_str]->d_size)
-    goto invalid_error;
+  if (__libdw_read_offset (dbg, IDX_debug_info, attrp->valp,
+                          attrp->cu->offset_size, &off, IDX_debug_str, 1))
+    return NULL;
 
   return (const char *) dbg->sectiondata[IDX_debug_str]->d_buf + off;
 }
index b5c40bb5da5fac76262b2b1cc87bbee06364eb75..04f04aae8bb1251569c21e93688bf03faa16d0e4 100644 (file)
 #include <dwarf.h>
 #include "libdwP.h"
 
+internal_function unsigned char *
+__libdw_formptr (Dwarf_Attribute *attr, int sec_index,
+                int err_nodata, unsigned char **endpp,
+                Dwarf_Off *offsetp)
+{
+  if (attr == NULL)
+    return NULL;
+
+  const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
+  if (unlikely (d == NULL))
+    {
+      __libdw_seterrno (err_nodata);
+      return NULL;
+    }
+
+  Dwarf_Word offset;
+  switch (attr->form)
+    {
+    case DW_FORM_data4:
+    case DW_FORM_data8:
+      if (__libdw_read_offset (attr->cu->dbg, IDX_debug_info, attr->valp,
+                              attr->form == DW_FORM_data4 ? 4 : 8,
+                              &offset, sec_index, 0))
+       return NULL;
+      break;
+
+    default:
+      if (INTUSE(dwarf_formudata) (attr, &offset))
+       return NULL;
+    };
+
+  unsigned char *readp = d->d_buf + offset;
+  unsigned char *endp = d->d_buf + d->d_size;
+  if (unlikely (readp >= endp))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  if (endpp != NULL)
+    *endpp = endp;
+  if (offsetp != NULL)
+    *offsetp = offset;
+  return readp;
+}
 
 int
 dwarf_formudata (attr, return_uval)
@@ -77,11 +122,11 @@ dwarf_formudata (attr, return_uval)
       break;
 
     case DW_FORM_data4:
-      *return_uval = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
-      break;
-
     case DW_FORM_data8:
-      *return_uval = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+      if (__libdw_read_address (attr->cu->dbg, IDX_debug_info, attr->valp,
+                               attr->form == DW_FORM_data4 ? 4 : 8,
+                               return_uval))
+       return -1;
       break;
 
     case DW_FORM_sdata:
index 96e9962060b4a6fdb6c292d8237ad7f36465df75..74f04ea571e6e2a616ce29e68a3fc67594feda53 100644 (file)
@@ -149,14 +149,10 @@ dwarf_getaranges (dbg, aranges, naranges)
        }
 
       Dwarf_Word offset;
-      if (length_bytes == 4)
-       offset = read_4ubyte_unaligned_inc (dbg, readp);
-      else
-       offset = read_8ubyte_unaligned_inc (dbg, readp);
-
-      /* Sanity-check the offset.  */
-      if (offset + 4 > dbg->sectiondata[IDX_debug_info]->d_size)
-       goto invalid;
+      if (__libdw_read_offset_inc (dbg,
+                                  IDX_debug_aranges, (unsigned char **)&readp,
+                                  length_bytes, &offset, IDX_debug_info, 4))
+       return -1;
 
       unsigned int address_size = *readp++;
       if (address_size != 4 && address_size != 8)
@@ -175,16 +171,15 @@ dwarf_getaranges (dbg, aranges, naranges)
          Dwarf_Word range_address;
          Dwarf_Word range_length;
 
+         if (__libdw_read_address_inc (dbg, IDX_debug_aranges,
+                                       (unsigned char **)&readp,
+                                       address_size, &range_address))
+           return -1;
+
          if (address_size == 4)
-           {
-             range_address = read_4ubyte_unaligned_inc (dbg, readp);
-             range_length = read_4ubyte_unaligned_inc (dbg, readp);
-           }
+           range_length = read_4ubyte_unaligned_inc (dbg, readp);
          else
-           {
-             range_address = read_8ubyte_unaligned_inc (dbg, readp);
-             range_length = read_8ubyte_unaligned_inc (dbg, readp);
-           }
+           range_length = read_8ubyte_unaligned_inc (dbg, readp);
 
          /* Two zero values mark the end.  */
          if (range_address == 0 && range_length == 0)
index f680aa9692e3673c66935c763be0f9186834d226..f829e72b114921567235a3550f2d803f8f45df85 100644 (file)
@@ -113,7 +113,7 @@ loc_compare (const void *p1, const void *p2)
 
 static int
 getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
-            Dwarf_Op **llbuf, size_t *listlen)
+            Dwarf_Op **llbuf, size_t *listlen, int sec_index)
 {
   Dwarf *dbg = cu->dbg;
 
@@ -151,24 +151,9 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
        {
        case DW_OP_addr:
          /* Address, depends on address size of CU.  */
-         if (cu->address_size == 4)
-           {
-             if (unlikely (data + 4 > end_data))
-               {
-               invalid:
-                 __libdw_seterrno (DWARF_E_INVALID_DWARF);
-                 return -1;
-               }
-
-             newloc->number = read_4ubyte_unaligned_inc (dbg, data);
-           }
-         else
-           {
-             if (unlikely (data + 8 > end_data))
-               goto invalid;
-
-             newloc->number = read_8ubyte_unaligned_inc (dbg, data);
-           }
+         if (__libdw_read_address_inc (dbg, sec_index, (unsigned char **)&data,
+                                       cu->address_size, &newloc->number))
+           return -1;
          break;
 
        case DW_OP_deref:
@@ -211,7 +196,11 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
        case DW_OP_deref_size:
        case DW_OP_xderef_size:
          if (unlikely (data >= end_data))
-           goto invalid;
+           {
+           invalid:
+             __libdw_seterrno (DWARF_E_INVALID_DWARF);
+             return -1;
+           }
 
          newloc->number = *data++;
          break;
@@ -352,7 +341,7 @@ dwarf_getlocation (attr, llbuf, listlen)
   if (INTUSE(dwarf_formblock) (attr, &block) != 0)
     return -1;
 
-  return getlocation (attr->cu, &block, llbuf, listlen);
+  return getlocation (attr->cu, &block, llbuf, listlen, IDX_debug_info);
 }
 
 int
@@ -376,7 +365,8 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
       if (maxlocs == 0)
        return 0;
       if (llbufs != NULL &&
-         getlocation (attr->cu, &block, &llbufs[0], &listlens[0]) != 0)
+         getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
+                      IDX_debug_info) != 0)
        return -1;
       return listlens[0] == 0 ? 0 : 1;
     }
@@ -388,25 +378,17 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
       return -1;
     }
 
-  /* Must have the form data4 or data8 which act as an offset.  */
-  Dwarf_Word offset;
-  if (unlikely (INTUSE(dwarf_formudata) (attr, &offset) != 0))
+  unsigned char *endp;
+  unsigned char *readp = __libdw_formptr (attr, IDX_debug_loc,
+                                         DWARF_E_NO_LOCLIST, &endp, NULL);
+  if (readp == NULL)
     return -1;
 
-  const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_loc];
-  if (unlikely (d == NULL))
-    {
-      __libdw_seterrno (DWARF_E_NO_LOCLIST);
-      return -1;
-    }
-
   Dwarf_Addr base = (Dwarf_Addr) -1;
-  unsigned char *readp = d->d_buf + offset;
   size_t got = 0;
   while (got < maxlocs)
     {
-      if ((unsigned char *) d->d_buf + d->d_size - readp
-         < attr->cu->address_size * 2)
+      if (endp - readp < attr->cu->address_size * 2)
        {
        invalid:
          __libdw_seterrno (DWARF_E_INVALID_DWARF);
@@ -415,42 +397,25 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
 
       Dwarf_Addr begin;
       Dwarf_Addr end;
-      if (attr->cu->address_size == 8)
-       {
-         begin = read_8ubyte_unaligned_inc (attr->cu->dbg, readp);
-         end = read_8ubyte_unaligned_inc (attr->cu->dbg, readp);
-
-         if (begin == (Elf64_Addr) -1l) /* Base address entry.  */
-           {
-             base = end;
-             if (unlikely (base == (Dwarf_Addr) -1))
-               goto invalid;
-             continue;
-           }
-       }
-      else
-       {
-         begin = read_4ubyte_unaligned_inc (attr->cu->dbg, readp);
-         end = read_4ubyte_unaligned_inc (attr->cu->dbg, readp);
-
-         if (begin == (Elf32_Addr) -1) /* Base address entry.  */
-           {
-             base = end;
-             continue;
-           }
-       }
 
-      if (begin == 0 && end == 0) /* End of list entry.  */
+      int status
+       = __libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc,
+                                          &readp, attr->cu->address_size,
+                                          &begin, &end, &base);
+      if (status == 2) /* End of list entry.  */
        break;
+      else if (status == 1) /* Base address selected.  */
+       continue;
+      else if (status < 0)
+       return status;
 
-      if ((unsigned char *) d->d_buf + d->d_size - readp < 2)
+      if (endp - readp < 2)
        goto invalid;
 
       /* We have a location expression.  */
       block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
       block.data = readp;
-      if ((unsigned char *) d->d_buf + d->d_size - readp
-         < (ptrdiff_t) block.length)
+      if (endp - readp < (ptrdiff_t) block.length)
        goto invalid;
       readp += block.length;
 
@@ -486,7 +451,8 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
          /* This one matches the address.  */
          if (llbufs != NULL
              && unlikely (getlocation (attr->cu, &block,
-                                       &llbufs[got], &listlens[got]) != 0))
+                                       &llbufs[got], &listlens[got],
+                                       IDX_debug_loc) != 0))
            return -1;
          ++got;
        }
index 1b054e26d9756a9a7e768442efc74472c82df3d1..5560a7588e594d37010c7137b6829f86d6404413 100644 (file)
@@ -102,7 +102,6 @@ get_offsets (Dwarf *dbg)
       else if (unlikely (len >= DWARF3_LENGTH_MIN_ESCAPE_CODE
                         && len <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
        {
-       invalid_dwarf:
          __libdw_seterrno (DWARF_E_INVALID_DWARF);
          goto err_return;
        }
@@ -124,18 +123,12 @@ get_offsets (Dwarf *dbg)
        }
 
       /* Get the CU offset.  */
-      if (len_bytes == 4)
-       mem[cnt].cu_offset = read_4ubyte_unaligned (dbg, readp + 2);
-      else
-       mem[cnt].cu_offset = read_8ubyte_unaligned (dbg, readp + 2);
+      if (__libdw_read_offset (dbg, IDX_debug_pubnames, readp + 2, len_bytes,
+                              &mem[cnt].cu_offset, IDX_debug_info, 3))
+       /* Error has been already set in reader.  */
+       goto err_return;
 
       /* Determine the size of the CU header.  */
-      if (unlikely (dbg->sectiondata[IDX_debug_info] == NULL
-                   || dbg->sectiondata[IDX_debug_info]->d_buf == NULL
-                   || (mem[cnt].cu_offset + 3
-                       >= dbg->sectiondata[IDX_debug_info]->d_size)))
-       goto invalid_dwarf;
-
       unsigned char *infop
        = ((unsigned char *) dbg->sectiondata[IDX_debug_info]->d_buf
           + mem[cnt].cu_offset);
index fe0e67d6a00142b9d2bbe87ac3f745ea02def5c5..efd0459f59bfe2fcfb5e47ca3525acc5d27acfa5 100644 (file)
@@ -135,20 +135,13 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
 
       /* Get the offset into the .debug_line section.  NB: this call
         also checks whether the previous dwarf_attr call failed.  */
-      Dwarf_Word offset;
-      if (INTUSE(dwarf_formudata) (stmt_list, &offset) != 0)
+      const unsigned char *lineendp;
+      const unsigned char *linep
+       = __libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
+                          (unsigned char **) &lineendp, NULL);
+      if (linep == NULL)
        goto out;
 
-      Dwarf *dbg = cu->dbg;
-      if (dbg->sectiondata[IDX_debug_line] == NULL)
-       {
-         __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
-         goto out;
-       }
-      const uint8_t *linep = dbg->sectiondata[IDX_debug_line]->d_buf + offset;
-      const uint8_t *lineendp = (dbg->sectiondata[IDX_debug_line]->d_buf
-                                + dbg->sectiondata[IDX_debug_line]->d_size);
-
       /* Get the compilation directory.  */
       Dwarf_Attribute compdir_attr_mem;
       Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
@@ -162,6 +155,8 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
          __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
          goto out;
        }
+
+      Dwarf *dbg = cu->dbg;
       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
       unsigned int length = 4;
       if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
@@ -429,10 +424,10 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
                  /* The value is an address.  The size is defined as
                     apporiate for the target machine.  We use the
                     address size field from the CU header.  */
-                 if (cu->address_size == 4)
-                   address = read_4ubyte_unaligned_inc (dbg, linep);
-                 else
-                   address = read_8ubyte_unaligned_inc (dbg, linep);
+                 if (__libdw_read_address_inc (dbg, IDX_debug_line,
+                                               (unsigned char **)&linep,
+                                               cu->address_size, &address))
+                   goto out;
                  break;
 
                case DW_LNE_define_file:
index 9e5a96bc64c1eb8a1742e96b4800d253fef2aa40..66cde78a57598a666f9b5dc8baf8dab604568d16 100644 (file)
@@ -84,7 +84,8 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
 
   /* This points into the .debug_info section to the beginning of the
      CU entry.  */
-  char *bytes = (char *) dwarf->sectiondata[IDX_debug_info]->d_buf + off;
+  unsigned char *data = dwarf->sectiondata[IDX_debug_info]->d_buf;
+  unsigned char *bytes = data + off;
 
   /* The format of the CU header is described in dwarf2p1 7.5.1:
 
@@ -144,10 +145,10 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
   /* Get offset in .debug_abbrev.  Note that the size of the entry
      depends on whether this is a 32-bit or 64-bit DWARF definition.  */
   uint64_t abbrev_offset;
-  if (offset_size == 4)
-    abbrev_offset = read_4ubyte_unaligned_inc (dwarf, bytes);
-  else
-    abbrev_offset = read_8ubyte_unaligned_inc (dwarf, bytes);
+  if (__libdw_read_offset_inc (dwarf, IDX_debug_info, &bytes, offset_size,
+                              &abbrev_offset, IDX_debug_abbrev, 0))
+    return -1;
+
   if (abbrev_offsetp != NULL)
     *abbrev_offsetp = abbrev_offset;
 
@@ -162,9 +163,7 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
 
   /* Store the header length.  */
   if (header_sizep != NULL)
-    *header_sizep = (bytes
-                    - ((char *) dwarf->sectiondata[IDX_debug_info]->d_buf
-                       + off));
+    *header_sizep = bytes - (data + off);
 
   /* See definition of DIE_OFFSET_FROM_CU_OFFSET macro
      for an explanation of the trick in this expression.  */
index 1eef617b5aacb801b2aab69d5987061c70438408..50fb6ba2ddc4a57ca212bd5549bc8e00c796437c 100644 (file)
 #include <dwarf.h>
 #include <assert.h>
 
+/* Read up begin/end pair and increment read pointer.
+    - If it's normal range record, set up `*beginp' and `*endp' and return 0.
+    - If it's base address selection record, set up `*basep' and return 1.
+    - If it's end of rangelist, don't set anything and return 2
+    - If an error occurs, don't set anything and return -1.  */
+internal_function int
+__libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index,
+                                unsigned char **addrp, int width,
+                                Dwarf_Addr *beginp, Dwarf_Addr *endp,
+                                Dwarf_Addr *basep)
+{
+  Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1
+                      : (Elf64_Addr) (Elf32_Addr) -1);
+  Dwarf_Addr begin;
+  Dwarf_Addr end;
+
+  unsigned char *addr = *addrp;
+  bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address, begin);
+  bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address, end);
+  *addrp = addr;
+
+  /* Unrelocated escape for begin means base address selection.  */
+  if (begin == escape && !begin_relocated)
+    {
+      if (unlikely (end == escape))
+       {
+         __libdw_seterrno (DWARF_E_INVALID_DWARF);
+         return -1;
+       }
+
+      if (basep != NULL)
+       *basep = end;
+      return 1;
+    }
+
+  /* Unrelocated pair of zeroes means end of range list.  */
+  if (begin == 0 && end == 0 && !begin_relocated && !end_relocated)
+    return 2;
+
+  /* Don't check for begin_relocated == end_relocated.  Serve the data
+     to the client even though it may be buggy.  */
+  *beginp = begin;
+  *endp = end;
+
+  return 0;
+}
 
 ptrdiff_t
 dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
@@ -80,11 +126,12 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
   const Elf_Data *d = die->cu->dbg->sectiondata[IDX_debug_ranges];
   if (d == NULL && offset != 0)
     {
-    no_ranges:
       __libdw_seterrno (DWARF_E_NO_DEBUG_RANGES);
       return -1;
     }
 
+  unsigned char *readp;
+  unsigned char *readendp;
   if (offset == 0)
     {
       Dwarf_Attribute attr_mem;
@@ -94,14 +141,12 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
        /* No PC attributes in this DIE at all, so an empty range list.  */
        return 0;
 
-      /* Must have the form data4 or data8 which act as an offset.  */
       Dwarf_Word start_offset;
-      if (INTUSE(dwarf_formudata) (attr, &start_offset) != 0)
+      if ((readp = __libdw_formptr (attr, IDX_debug_ranges,
+                                   DWARF_E_NO_DEBUG_RANGES,
+                                   &readendp, &start_offset)) == NULL)
        return -1;
 
-      if (d == NULL)
-       goto no_ranges;
-
       offset = start_offset;
       assert ((Dwarf_Word) offset == start_offset);
 
@@ -127,45 +172,37 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
          return -1;
        }
     }
-  else if (offset < 0 || (size_t) offset >= d->d_size)
+  else
     {
-      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
-      return -1l;
-    }
+      if (__libdw_offset_in_section (die->cu->dbg,
+                                    IDX_debug_ranges, offset, 1))
+       return -1l;
 
-  unsigned char *readp = d->d_buf + offset;
+      readp = d->d_buf + offset;
+      readendp = d->d_buf + d->d_size;
+    }
 
  next:
-  if ((unsigned char *) d->d_buf + d->d_size - readp
-      < die->cu->address_size * 2)
+  if (readendp - readp < die->cu->address_size * 2)
     goto invalid;
 
   Dwarf_Addr begin;
   Dwarf_Addr end;
-  if (die->cu->address_size == 8)
-    {
-      begin = read_8ubyte_unaligned_inc (die->cu->dbg, readp);
-      end = read_8ubyte_unaligned_inc (die->cu->dbg, readp);
-      if (begin == (uint64_t) -1l) /* Base address entry.  */
-       {
-         *basep = end;
-         goto next;
-       }
-    }
-  else
+
+  switch (__libdw_read_begin_end_pair_inc (die->cu->dbg, IDX_debug_ranges,
+                                          &readp, die->cu->address_size,
+                                          &begin, &end, basep))
     {
-      begin = read_4ubyte_unaligned_inc (die->cu->dbg, readp);
-      end = read_4ubyte_unaligned_inc (die->cu->dbg, readp);
-      if (begin == (uint32_t) -1) /* Base address entry.  */
-       {
-         *basep = end;
-         goto next;
-       }
+    case 0:
+      break;
+    case 1:
+      goto next;
+    case 2:
+      return 0;
+    default:
+      return -1l;
     }
 
-  if (begin == 0 && end == 0) /* End of list entry.  */
-    return 0;
-
   /* We have an address range entry.  */
   *startp = *basep + begin;
   *endp = *basep + end;
index 1d5a9b27f2bbcbcdb32ebe8f49dbfedc8c59871f..97a2e042f6837ca3fd04a54a16817d46819083ff 100644 (file)
@@ -419,6 +419,156 @@ extern int __libdw_visit_scopes (unsigned int depth,
 extern int __dwarf_errno_internal (void);
 
 
+/* Reader hooks.  */
+
+/* Relocation hooks return -1 on error (in that case the error code
+   must already have been set), 0 if there is no relocation and 1 if a
+   relocation was present.*/
+
+static inline int
+__libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)),
+                         int sec_index __attribute__ ((unused)),
+                         const void *addr __attribute__ ((unused)),
+                         int width __attribute__ ((unused)),
+                         Dwarf_Addr *val __attribute__ ((unused)))
+{
+  return 0;
+}
+
+static inline int
+__libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)),
+                        int sec_index __attribute__ ((unused)),
+                        const void *addr __attribute__ ((unused)),
+                        int width __attribute__ ((unused)),
+                        Dwarf_Off *val __attribute__ ((unused)))
+{
+  return 0;
+}
+
+static inline Elf_Data *
+__libdw_checked_get_data (Dwarf *dbg, int sec_index)
+{
+  Elf_Data *data = dbg->sectiondata[sec_index];
+  if (unlikely (data == NULL)
+      || unlikely (data->d_buf == NULL))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+  return data;
+}
+
+static inline int
+__libdw_offset_in_section (Dwarf *dbg, int sec_index,
+                          Dwarf_Off offset, size_t size)
+{
+  Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
+  if (data == NULL)
+    return -1;
+  if (unlikely (offset > data->d_size)
+      || unlikely (data->d_size - offset < size))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return -1;
+    }
+
+  return 0;
+}
+
+static inline bool
+__libdw_in_section (Dwarf *dbg, int sec_index,
+                   const void *addr, size_t size)
+{
+  Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
+  if (data == NULL)
+    return false;
+  if (unlikely (addr < data->d_buf)
+      || unlikely (data->d_size - (addr - data->d_buf) < size))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return false;
+    }
+
+  return true;
+}
+
+#define READ_AND_RELOCATE(RELOC_HOOK, VAL)                             \
+  ({                                                                   \
+    if (!__libdw_in_section (dbg, sec_index, addr, width))             \
+      return -1;                                                       \
+                                                                       \
+    const unsigned char *orig_addr = addr;                             \
+    if (width == 4)                                                    \
+      VAL = read_4ubyte_unaligned_inc (dbg, addr);                     \
+    else                                                               \
+      VAL = read_8ubyte_unaligned_inc (dbg, addr);                     \
+                                                                       \
+    int status = RELOC_HOOK (dbg, sec_index, orig_addr, width, &VAL);  \
+    if (status < 0)                                                    \
+      return status;                                                   \
+    status > 0;                                                                \
+   })
+
+static inline int
+__libdw_read_address_inc (Dwarf *dbg,
+                         int sec_index, unsigned char **addrp,
+                         int width, Dwarf_Addr *ret)
+{
+  unsigned char *addr = *addrp;
+  READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
+  *addrp = addr;
+  return 0;
+}
+
+static inline int
+__libdw_read_address (Dwarf *dbg,
+                     int sec_index, const unsigned char *addr,
+                     int width, Dwarf_Addr *ret)
+{
+  READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
+  return 0;
+}
+
+static inline int
+__libdw_read_offset_inc (Dwarf *dbg,
+                        int sec_index, unsigned char **addrp,
+                        int width, Dwarf_Off *ret, int sec_ret,
+                        size_t size)
+{
+  unsigned char *addr = *addrp;
+  READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
+  *addrp = addr;
+  return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
+}
+
+static inline int
+__libdw_read_offset (Dwarf *dbg,
+                    int sec_index, const unsigned char *addr,
+                    int width, Dwarf_Off *ret, int sec_ret,
+                    size_t size)
+{
+  READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
+  return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
+}
+
+/* Read up begin/end pair and increment read pointer.
+    - If it's normal range record, set up *BEGINP and *ENDP and return 0.
+    - If it's base address selection record, set up *BASEP and return 1.
+    - If it's end of rangelist, don't set anything and return 2
+    - If an error occurs, don't set anything and return <0.  */
+int __libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index,
+                                    unsigned char **addr, int width,
+                                    Dwarf_Addr *beginp, Dwarf_Addr *endp,
+                                    Dwarf_Addr *basep)
+  internal_function;
+
+unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
+                                int err_nodata, unsigned char **endpp,
+                                Dwarf_Off *offsetp)
+  internal_function;
+
+
+
 /* Aliases to avoid PLTs.  */
 INTDECL (dwarf_attr)
 INTDECL (dwarf_attr_integrate)