readelf: Warn, don't assert, if loclist or rangelist offset is too big.
authorMark Wielaard <mjw@redhat.com>
Mon, 15 Dec 2014 18:43:02 +0000 (19:43 +0100)
committerMark Wielaard <mjw@redhat.com>
Wed, 17 Dec 2014 15:47:16 +0000 (16:47 +0100)
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 <mjw@redhat.com>
src/ChangeLog
src/readelf.c

index 1f91de6..f401c35 100644 (file)
@@ -1,5 +1,11 @@
 2014-12-15  Mark Wielaard  <mjw@redhat.com>
 
+       * 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  <mjw@redhat.com>
+
        * readelf.c (print_ops): Don't assert when addr_size or ref_size
        is not 4 or 8, just report invalid data.
 
index aa85d73..e9a356d 100644 (file)
@@ -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: