]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdw: pre-compute leb128 loop limits
authorJosh Stone <jistone@redhat.com>
Mon, 15 Dec 2014 20:18:25 +0000 (12:18 -0800)
committerMark Wielaard <mjw@redhat.com>
Wed, 17 Dec 2014 15:35:56 +0000 (16:35 +0100)
Signed-off-by: Josh Stone <jistone@redhat.com>
libdw/ChangeLog
libdw/memory-access.h

index f5c73bbae761dcce40125df266defbaa81bbb36c..8bc5d9d118a0bf30f1d9e9c5ed5d504f46e21da4 100644 (file)
@@ -1,3 +1,9 @@
+2014-12-15  Josh Stone  <jistone@redhat.com>
+
+       * memory-access.h (__libdw_max_len_leb128): New.
+       (__libdw_get_uleb128): Use __libdw_max_len_leb128.
+       (__libdw_get_sleb128): Likewise.
+
 2014-12-14  Mark Wielaard  <mjw@redhat.com>
 
        * cfi.c (execute_cfi): Add program bounds checks.
index 8226d00e9b33b57fd87359d2c7302a1d02a23d3b..99c827af22bd33f1a5dc7b56f29212c84f72ec21 100644 (file)
 
 #define len_leb128(var) ((8 * sizeof (var) + 6) / 7)
 
+static inline size_t
+__libdw_max_len_leb128 (const unsigned char *addr, const unsigned char *end)
+{
+  const size_t type_len = len_leb128 (uint64_t);
+  const size_t pointer_len = likely (addr < end) ? end - addr : 0;
+  return likely (type_len <= pointer_len) ? type_len : pointer_len;
+}
+
 #define get_uleb128_step(var, addr, nth)                                     \
   do {                                                                       \
     unsigned char __b = *(addr)++;                                           \
@@ -51,10 +59,13 @@ static inline uint64_t
 __libdw_get_uleb128 (const unsigned char **addrp, const unsigned char *end)
 {
   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);
-  for (unsigned int i = 1; i < len_leb128 (acc) && *addrp < end; ++i)
+
+  const size_t max = __libdw_max_len_leb128 (*addrp - 1, end);
+  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.  */
@@ -82,8 +93,10 @@ static inline int64_t
 __libdw_get_sleb128 (const unsigned char **addrp, const unsigned char *end)
 {
   int64_t acc = 0;
+
   /* Unrolling 0 like uleb128 didn't prove to benefit optimization.  */
-  for (unsigned int i = 0; i < len_leb128 (acc) && *addrp < end; ++i)
+  const size_t max = __libdw_max_len_leb128 (*addrp, end);
+  for (size_t i = 0; i < max; ++i)
     get_sleb128_step (acc, *addrp, i);
   /* Other implementations set VALUE to INT_MAX in this
      case.  So we better do this as well.  */