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
