We use a couple of bits to keep track of the addr size, dwarf size and
warning given for a loclist or rangelist offset. Normally offset won't
be that big and will fit in 61-bits easily. But if not, don't assert,
but just warn we don't handle such large offsets.

Signed-off-by: Mark Wielaard <[email protected]>
---
 src/ChangeLog |  6 ++++++
 src/readelf.c | 45 +++++++++++++++++++++++++++++----------------
 2 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 08f9ee4..bb3e84f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,11 @@
 2014-12-15  Mark Wielaard  <[email protected]>
 
+       * readelf.c (notice_listptr): Return false if offset doesn't fit
+       in 61-bits.
+       (attr_callback): Warn if loclist or rangelist offset doesn't fit.
+
+2014-12-15  Mark Wielaard  <[email protected]>
+
        * readelf.c (print_ops): Don't assert when addr_size or ref_size
        is not 4 or 8, just report invalid data.
 
diff --git a/src/readelf.c b/src/readelf.c
index aa85d73..e9a356d 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -4426,7 +4426,8 @@ reset_listptr (struct listptr_table *table)
   table->n = table->alloc = 0;
 }
 
-static void
+/* Returns false if offset doesn't fit.  See struct listptr.  */
+static bool
 notice_listptr (enum section_e section, struct listptr_table *table,
                uint_fast8_t address_size, uint_fast8_t offset_size,
                struct Dwarf_CU *cu, Dwarf_Off offset)
@@ -4452,8 +4453,14 @@ notice_listptr (enum section_e section, struct 
listptr_table *table,
          .offset = offset,
          .cu = cu
        };
-      assert (p->offset == offset);
+
+      if (p->offset != offset)
+       {
+         table->n--;
+         return false;
+       }
     }
+  return true;
 }
 
 static void
@@ -5849,23 +5856,29 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
        case DW_AT_GNU_call_site_data_value:
        case DW_AT_GNU_call_site_target:
        case DW_AT_GNU_call_site_target_clobbered:
-         notice_listptr (section_loc, &known_loclistptr,
-                         cbargs->addrsize, cbargs->offset_size,
-                         cbargs->cu, num);
-         if (!cbargs->silent)
-           printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]\n",
-                   (int) (level * 2), "", dwarf_attr_name (attr),
-                   dwarf_form_name (form), (uintmax_t) num);
+         {
+           bool nlpt = notice_listptr (section_loc, &known_loclistptr,
+                                       cbargs->addrsize, cbargs->offset_size,
+                                       cbargs->cu, num);
+           if (!cbargs->silent)
+             printf ("           %*s%-20s (%s) location list [%6" PRIxMAX 
"]%s\n",
+                     (int) (level * 2), "", dwarf_attr_name (attr),
+                     dwarf_form_name (form), (uintmax_t) num,
+                     nlpt ? "" : " <WARNING offset too big>");
+         }
          return DWARF_CB_OK;
 
        case DW_AT_ranges:
-         notice_listptr (section_ranges, &known_rangelistptr,
-                         cbargs->addrsize, cbargs->offset_size,
-                         cbargs->cu, num);
-         if (!cbargs->silent)
-           printf ("           %*s%-20s (%s) range list [%6" PRIxMAX "]\n",
-                   (int) (level * 2), "", dwarf_attr_name (attr),
-                   dwarf_form_name (form), (uintmax_t) num);
+         {
+           bool nlpt = notice_listptr (section_ranges, &known_rangelistptr,
+                                       cbargs->addrsize, cbargs->offset_size,
+                                       cbargs->cu, num);
+           if (!cbargs->silent)
+             printf ("           %*s%-20s (%s) range list [%6" PRIxMAX "]%s\n",
+                     (int) (level * 2), "", dwarf_attr_name (attr),
+                     dwarf_form_name (form), (uintmax_t) num,
+                     nlpt ? "" : " <WARNING offset too big>");
+         }
          return DWARF_CB_OK;
 
        case DW_AT_language:
-- 
1.8.3.1

Reply via email to