Handle all new DW_RLE opcodes in .debug_rnglists in dwarf_ranges. Extract code for reading .debug_addr indexes from dwarf_formaddr as __libdw_addrx to reuse in __libdw_read_begin_end_pair_inc. And add new testcase.
Signed-off-by: Mark Wielaard <m...@klomp.org> --- libdw/ChangeLog | 15 ++ libdw/dwarf_formaddr.c | 76 ++++---- libdw/dwarf_getlocation.c | 2 +- libdw/dwarf_ranges.c | 258 +++++++++++++++++++++++---- libdw/libdwP.h | 84 ++++++++- src/ChangeLog | 3 +- src/readelf.c | 2 + tests/ChangeLog | 6 + tests/Makefile.am | 2 +- tests/run-all-dwarf-ranges.sh | 55 ++++++ tests/run-dwarf-ranges.sh | 18 ++ tests/testfile-ranges-hello5.dwo.bz2 | Bin 0 -> 1296 bytes tests/testfile-ranges-world5.dwo.bz2 | Bin 0 -> 1466 bytes tests/testfileranges5.debug.bz2 | Bin 0 -> 2857 bytes tests/testfilesplitranges5.debug.bz2 | Bin 0 -> 2235 bytes 15 files changed, 442 insertions(+), 79 deletions(-) create mode 100644 tests/testfile-ranges-hello5.dwo.bz2 create mode 100644 tests/testfile-ranges-world5.dwo.bz2 create mode 100755 tests/testfileranges5.debug.bz2 create mode 100755 tests/testfilesplitranges5.debug.bz2 diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 9c0ab3c5..b19ebe96 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,18 @@ +2018-04-06 Mark Wielaard <m...@klomp.org> + + * dwarf_formaddr.c (__libdw_addrx): New function, extracted from... + (dwarf_formaddr): here. Use __libdw_addrx. + * dwarf_getlocation.c (getlocations_addr): Pass cu to + __libdw_read_begin_end_pair_inc. + * dwarf_ranges.c (__libdw_read_begin_end_pair_inc): Take cu as + argument. Handle .debug_rnglists. + (initial_offset): Handle .debug_rnglists and DW_FORM_rnglistx. + (dwarf_ranges): Likewise. Check cu isn't NULL before use. Pass cu to + __libdw_read_begin_end_pair_inc. + * libdwP.h (__libdw_read_begin_end_pair_inc): Take cu as argument. + (__libdw_cu_ranges_base): Handle DW_AT_rnglists_base. + (__libdw_addrx): New function definition. + 2018-04-11 Mark Wielaard <m...@klomp.org> * dwarf.h: Add DWARF5 range list entry DW_RLE encodings. diff --git a/libdw/dwarf_formaddr.c b/libdw/dwarf_formaddr.c index 3c89a5d2..9cd3d200 100644 --- a/libdw/dwarf_formaddr.c +++ b/libdw/dwarf_formaddr.c @@ -34,6 +34,48 @@ #include "libdwP.h" +int +__libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr) +{ + Dwarf_Off addr_off = __libdw_cu_addr_base (cu); + if (addr_off == (Dwarf_Off) -1) + return -1; + + Dwarf *dbg = cu->dbg; + if (dbg->sectiondata[IDX_debug_addr] == NULL) + { + __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR); + return -1; + } + + /* The section should at least contain room for one address. */ + int address_size = cu->address_size; + if (cu->address_size > dbg->sectiondata[IDX_debug_addr]->d_size) + { + invalid_offset: + __libdw_seterrno (DWARF_E_INVALID_OFFSET); + return -1; + } + + if (addr_off > (dbg->sectiondata[IDX_debug_addr]->d_size + - address_size)) + goto invalid_offset; + + idx *= address_size; + if (idx > (dbg->sectiondata[IDX_debug_addr]->d_size + - address_size - addr_off)) + goto invalid_offset; + + const unsigned char *datap; + datap = dbg->sectiondata[IDX_debug_addr]->d_buf + addr_off + idx; + if (address_size == 4) + *addr = read_4ubyte_unaligned (dbg, datap); + else + *addr = read_8ubyte_unaligned (dbg, datap); + + return 0; +} + int dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr) { @@ -98,41 +140,9 @@ dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr) /* So we got an index. Lets see if it is valid and we can get the actual address. */ - - Dwarf_Off addr_off = __libdw_cu_addr_base (cu); - if (addr_off == (Dwarf_Off) -1) + if (__libdw_addrx (cu, idx, return_addr) != 0) return -1; - if (dbg->sectiondata[IDX_debug_addr] == NULL) - { - __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR); - return -1; - } - - /* The section should at least contain room for one address. */ - int address_size = cu->address_size; - if (cu->address_size > dbg->sectiondata[IDX_debug_addr]->d_size) - { - invalid_offset: - __libdw_seterrno (DWARF_E_INVALID_OFFSET); - return -1; - } - - if (addr_off > (dbg->sectiondata[IDX_debug_addr]->d_size - - address_size)) - goto invalid_offset; - - idx *= address_size; - if (idx > (dbg->sectiondata[IDX_debug_addr]->d_size - - address_size - addr_off)) - goto invalid_offset; - - datap = dbg->sectiondata[IDX_debug_addr]->d_buf + addr_off + idx; - if (address_size == 4) - *return_addr = read_4ubyte_unaligned (dbg, datap); - else - *return_addr = read_8ubyte_unaligned (dbg, datap); - return 0; } INTDEF(dwarf_formaddr) diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index ade3e6c5..0e7115f8 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -724,7 +724,7 @@ getlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr end; next: - switch (__libdw_read_begin_end_pair_inc (dbg, secidx, + switch (__libdw_read_begin_end_pair_inc (cu, secidx, &readp, readendp, cu->address_size, &begin, &end, basep)) diff --git a/libdw/dwarf_ranges.c b/libdw/dwarf_ranges.c index 52a61eea..fa65e5c6 100644 --- a/libdw/dwarf_ranges.c +++ b/libdw/dwarf_ranges.c @@ -40,62 +40,244 @@ - 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, +__libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index, const unsigned char **addrp, const unsigned char *addrend, 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; - - const unsigned char *addr = *addrp; - if (addrend - addr < width * 2) + Dwarf *dbg = cu->dbg; + if (sec_index == IDX_debug_ranges || sec_index == IDX_debug_loc) { - invalid: - __libdw_seterrno (DWARF_E_INVALID_DWARF); - return -1; - } + Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1 + : (Elf64_Addr) (Elf32_Addr) -1); + Dwarf_Addr begin; + Dwarf_Addr end; - bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address, begin); - bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address, end); - *addrp = addr; + const unsigned char *addr = *addrp; + if (addrend - addr < width * 2) + { + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } - /* Unrelocated escape for begin means base address selection. */ - if (begin == escape && !begin_relocated) - { - if (unlikely (end == escape)) - goto invalid; + bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address, + begin); + bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address, + end); + *addrp = addr; - *basep = end; - return 1; - } + /* Unrelocated escape for begin means base address selection. */ + if (begin == escape && !begin_relocated) + { + if (unlikely (end == escape)) + goto invalid; + + *basep = end; + return 1; + } - /* Unrelocated pair of zeroes means end of range list. */ - if (begin == 0 && end == 0 && !begin_relocated && !end_relocated) - return 2; + /* 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 + *basep; - *endp = end + *basep; + /* Don't check for begin_relocated == end_relocated. Serve the data + to the client even though it may be buggy. */ + *beginp = begin + *basep; + *endp = end + *basep; - return 0; + return 0; + } + else if (sec_index == IDX_debug_rnglists) + { + const unsigned char *addr = *addrp; + if (addrend - addr < 1) + goto invalid; + + const char code = *addr++; + uint64_t begin = 0, end = 0, base = *basep, addr_idx; + switch (code) + { + case DW_RLE_end_of_list: + *addrp = addr; + return 2; + + case DW_RLE_base_addressx: + if (addrend - addr < 1) + goto invalid; + get_uleb128 (addr_idx, addr, addrend); + if (__libdw_addrx (cu, addr_idx, &base) != 0) + return -1; + + *basep = base; + *addrp = addr; + return 1; + + case DW_RLE_startx_endx: + if (addrend - addr < 1) + goto invalid; + get_uleb128 (addr_idx, addr, addrend); + if (__libdw_addrx (cu, addr_idx, &begin) != 0) + return -1; + if (addrend - addr < 1) + goto invalid; + get_uleb128 (addr_idx, addr, addrend); + if (__libdw_addrx (cu, addr_idx, &end) != 0) + return -1; + + *beginp = begin; + *endp = end; + *addrp = addr; + return 0; + + case DW_RLE_startx_length: + if (addrend - addr < 1) + goto invalid; + get_uleb128 (addr_idx, addr, addrend); + if (__libdw_addrx (cu, addr_idx, &begin) != 0) + return -1; + if (addrend - addr < 1) + goto invalid; + get_uleb128 (end, addr, addrend); + + *beginp = begin; + *endp = begin + end; + *addrp = addr; + return 0; + + case DW_RLE_offset_pair: + if (addrend - addr < 1) + goto invalid; + get_uleb128 (begin, addr, addrend); + if (addrend - addr < 1) + goto invalid; + get_uleb128 (end, addr, addrend); + + *beginp = begin + base; + *endp = end + base; + *addrp = addr; + return 0; + + case DW_RLE_base_address: + if (addrend - addr < width) + goto invalid; + __libdw_read_address_inc (dbg, sec_index, &addr, width, &base); + + *basep = base; + *addrp = addr; + return 1; + + case DW_RLE_start_end: + if (addrend - addr < 2 * width) + goto invalid; + __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin); + __libdw_read_address_inc (dbg, sec_index, &addr, width, &end); + + *beginp = begin; + *endp = end; + *addrp = addr; + return 0; + + case DW_RLE_start_length: + if (addrend - addr < width) + goto invalid; + __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin); + if (addrend - addr < 1) + goto invalid; + get_uleb128 (end, addr, addrend); + + *beginp = begin; + *endp = begin + end; + *addrp = addr; + return 0; + + default: + goto invalid; + } + } + else + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } } static int initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset) { - size_t secidx = IDX_debug_ranges; + size_t secidx = (attr->cu->version < 5 + ? IDX_debug_ranges : IDX_debug_rnglists); Dwarf_Word start_offset; - if (__libdw_formptr (attr, secidx, - DWARF_E_NO_DEBUG_RANGES, - NULL, &start_offset) == NULL) - return -1; + if (attr->form == DW_FORM_rnglistx) + { + Dwarf_Word idx; + Dwarf_CU *cu = attr->cu; + const unsigned char *datap = attr->valp; + const unsigned char *endp = cu->endp; + if (datap >= endp) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + get_uleb128 (idx, datap, endp); + + Elf_Data *data = cu->dbg->sectiondata[secidx]; + if (data == NULL && cu->unit_type == DW_UT_split_compile) + { + cu = __libdw_find_split_unit (cu); + if (cu != NULL) + data = cu->dbg->sectiondata[secidx]; + } + + if (data == NULL) + { + __libdw_seterrno (secidx == IDX_debug_ranges + ? DWARF_E_NO_DEBUG_RANGES + : DWARF_E_NO_DEBUG_RNGLISTS); + return -1; + } + + Dwarf_Off range_base_off = __libdw_cu_ranges_base (cu); + + /* The section should at least contain room for one offset. */ + size_t sec_size = cu->dbg->sectiondata[secidx]->d_size; + size_t offset_size = cu->offset_size; + if (offset_size > sec_size) + { + invalid_offset: + __libdw_seterrno (DWARF_E_INVALID_OFFSET); + return -1; + } + + /* And the base offset should be at least inside the section. */ + if (range_base_off > (sec_size - offset_size)) + goto invalid_offset; + + size_t max_idx = (sec_size - offset_size - range_base_off) / offset_size; + if (idx > max_idx) + goto invalid_offset; + + datap = (cu->dbg->sectiondata[secidx]->d_buf + + range_base_off + (idx * offset_size)); + if (offset_size == 4) + start_offset = read_4ubyte_unaligned (cu->dbg, datap); + else + start_offset = read_8ubyte_unaligned (cu->dbg, datap); + + start_offset += range_base_off; + } + else + { + if (__libdw_formptr (attr, secidx, + (secidx == IDX_debug_ranges + ? DWARF_E_NO_DEBUG_RANGES + : DWARF_E_NO_DEBUG_RNGLISTS), + NULL, &start_offset) == NULL) + return -1; + } *offset = start_offset; return 0; @@ -121,7 +303,6 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep, return 0; /* We have to look for a noncontiguous range. */ - size_t secidx = IDX_debug_ranges; Dwarf_CU *cu = die->cu; if (cu == NULL) { @@ -129,6 +310,7 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep, return -1; } + size_t secidx = (cu->version < 5 ? IDX_debug_ranges : IDX_debug_rnglists); const Elf_Data *d = cu->dbg->sectiondata[secidx]; if (d == NULL && cu->unit_type == DW_UT_split_compile) { @@ -176,7 +358,7 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep, Dwarf_Addr end; next: - switch (__libdw_read_begin_end_pair_inc (cu->dbg, secidx, + switch (__libdw_read_begin_end_pair_inc (cu, secidx, &readp, readendp, cu->address_size, &begin, &end, basep)) diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 3cfcc557..c419e37a 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -915,7 +915,7 @@ is_cudie (Dwarf_Die *cudie) - 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, +int __libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index, const unsigned char **readp, const unsigned char *readend, int width, @@ -1084,6 +1084,8 @@ static inline Dwarf_Off __libdw_cu_str_off_base (Dwarf_CU *cu) } +/* Either a direct offset into .debug_ranges for version < 5, or the + start of the offset table in .debug_rnglists for version > 5. */ static inline Dwarf_Off __libdw_cu_ranges_base (Dwarf_CU *cu) { @@ -1092,12 +1094,79 @@ __libdw_cu_ranges_base (Dwarf_CU *cu) Dwarf_Off offset = 0; Dwarf_Die cu_die = CUDIE(cu); Dwarf_Attribute attr; - if (dwarf_attr (&cu_die, DW_AT_GNU_ranges_base, &attr) != NULL) + if (cu->version < 5) { - Dwarf_Word off; - if (dwarf_formudata (&attr, &off) == 0) - offset = off; + if (dwarf_attr (&cu_die, DW_AT_GNU_ranges_base, &attr) != NULL) + { + Dwarf_Word off; + if (dwarf_formudata (&attr, &off) == 0) + offset = off; + } + } + else + { + if (dwarf_attr (&cu_die, DW_AT_rnglists_base, &attr) != NULL) + { + Dwarf_Word off; + if (dwarf_formudata (&attr, &off) == 0) + offset = off; + } + + /* There wasn't an rnglists_base, if the Dwarf does have a + .debug_rnglists section, then it might be we need the + base after the first header. */ + Elf_Data *data = cu->dbg->sectiondata[IDX_debug_rnglists]; + if (offset == 0 && data != NULL) + { + Dwarf *dbg = cu->dbg; + const unsigned char *readp = data->d_buf; + const unsigned char *const dataend + = (unsigned char *) data->d_buf + data->d_size; + + uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp); + unsigned int offset_size = 4; + if (unlikely (unit_length == 0xffffffff)) + { + if (unlikely (readp > dataend - 8)) + goto no_header; + + unit_length = read_8ubyte_unaligned_inc (dbg, readp); + offset_size = 8; + } + + if (readp > dataend - 8 + || unit_length < 8 + || unit_length > (uint64_t) (dataend - readp)) + goto no_header; + + uint16_t version = read_2ubyte_unaligned_inc (dbg, readp); + if (version != 5) + goto no_header; + + uint8_t address_size = *readp++; + if (address_size != 4 && address_size != 8) + goto no_header; + + uint8_t segment_size = *readp++; + if (segment_size != 0) + goto no_header; + + uint32_t offset_entry_count; + offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp); + + const unsigned char *offset_array_start = readp; + if (offset_entry_count <= 0) + goto no_header; + + uint64_t needed = offset_entry_count * offset_size; + if (unit_length - 8 < needed) + goto no_header; + + offset = (Dwarf_Off) (offset_array_start + - (unsigned char *) data->d_buf); + } } + no_header: cu->ranges_base = offset; } @@ -1105,6 +1174,11 @@ __libdw_cu_ranges_base (Dwarf_CU *cu) } +/* Given an address index for a CU return the address. + Returns -1 and sets libdw_errno if an error occurs. */ +int __libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr); + + /* Helper function to set debugdir field in Dwarf, used from dwarf_begin_elf and libdwfl process_file. */ char * __libdw_debugdir (int fd); diff --git a/src/ChangeLog b/src/ChangeLog index d28d89af..4772448c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -6,7 +6,8 @@ (listptr_cu): New function. (print_debug_rnglists_section): Likewise. (attr_callback): Call notice_listptr for DW_AT_ranges. Handle - DW_AT_rnglists_base. + DW_AT_rnglists_base. Handle DW_FORM_rnglistx. DW_AT_start_scope + can also have a rnglist. (print_debug_units): Do (silently) scan split DWARF also for debug_ranges before DWARF5 to catch all rangelistptrs. (print_debug): Recognize .debug_rnglists. Reset known_rnglistptr. diff --git a/src/readelf.c b/src/readelf.c index 071906fa..3f5c73b8 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -6702,6 +6702,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) break; case DW_FORM_sec_offset: + case DW_FORM_rnglistx: case DW_FORM_implicit_const: case DW_FORM_udata: case DW_FORM_sdata: @@ -6758,6 +6759,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) return DWARF_CB_OK; case DW_AT_ranges: + case DW_AT_start_scope: { bool nlpt; if (cbargs->cu->version < 5) diff --git a/tests/ChangeLog b/tests/ChangeLog index 13d168de..f26651c9 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2018-04-06 Mark Wielaard <m...@klomp.org> + + * testfileranges5.debug.bz2: New testfile. + * run-dwarf-ranges.sh: Run on testfileranges5.debug. + * tests/Makefile.am (EXTRA_DIST): Add testfileranges5.debug.bz2. + 2018-04-11 Mark Wielaard <m...@klomp.org> * run-readelf-ranges.sh: New test. diff --git a/tests/Makefile.am b/tests/Makefile.am index 54a3d1d5..bb80b78b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -203,7 +203,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ run-dwfl-addr-sect.sh run-early-offscn.sh \ run-dwarf-getmacros.sh \ run-dwarf-ranges.sh debug-ranges-no-lowpc.o.bz2 \ - testfileranges4.debug.bz2 \ + testfileranges4.debug.bz2 testfileranges5.debug.bz2 \ run-test-flag-nobits.sh \ run-dwarf-getstring.sh run-rerequest_tag.sh run-alldts.sh \ testfile15.bz2 testfile15.debug.bz2 \ diff --git a/tests/run-all-dwarf-ranges.sh b/tests/run-all-dwarf-ranges.sh index ad5e634f..cefb4231 100755 --- a/tests/run-all-dwarf-ranges.sh +++ b/tests/run-all-dwarf-ranges.sh @@ -71,4 +71,59 @@ die: no_subject (2e) EOF +# Same with -gdwarf-5 +# gcc -c -O2 -o testfile-ranges-hello5.o -gsplit-dwarf -gdwarf-5 hello.c +# gcc -c -O2 -o testfile-ranges-world5.o -gsplit-dwarf -gdwarf-5 world.c +# gcc -o testfilesplitranges5 -O2 testfile-ranges-hello5.o testfile-ranges-world5.o +# eu-strip -f testfilesplitranges5.debug testfilesplitranges5 + +testfiles testfilesplitranges5.debug +testfiles testfile-ranges-hello5.dwo testfile-ranges-world5.dwo + +testrun_compare ${abs_builddir}/all-dwarf-ranges testfilesplitranges5.debug <<\EOF +die: hello.c (11) + 401150..40117a + 401050..401067 + +die: no_say (2e) + 401160..40117a + +die: main (2e) + 401050..401067 + +die: subject (1d) + 401053..40105f + +die: subject (2e) + 401150..401160 + +die: world.c (11) + 401180..4011e7 + +die: no_main (2e) + 4011d0..4011e7 + +die: no_subject (1d) + 4011d3..4011df + +die: say (2e) + 401180..4011c0 + +die: happy (1d) + 40119b..40119b + 40119c..4011a6 + 4011b0..4011b4 + 4011b5..4011bf + +die: sad (1d) + 40119b..40119b + 40119c..4011a6 + 4011b4..4011b4 + 4011b5..4011bf + +die: no_subject (2e) + 4011c0..4011d0 + +EOF + exit 0 diff --git a/tests/run-dwarf-ranges.sh b/tests/run-dwarf-ranges.sh index f935eaf4..a58ee659 100755 --- a/tests/run-dwarf-ranges.sh +++ b/tests/run-dwarf-ranges.sh @@ -102,4 +102,22 @@ testrun_compare ${abs_builddir}/dwarf-ranges testfileranges4.debug 0x374 <<\EOF 4005a5..4005ad (base 400540) EOF +# Like above, but with -gdwarf-5. +testfiles testfileranges5.debug +testrun_compare ${abs_builddir}/dwarf-ranges testfileranges5.debug 0xc <<\EOF +4004e0..4004ff (base 0) +4003e0..4003f7 (base 0) +EOF + +testrun_compare ${abs_builddir}/dwarf-ranges testfileranges5.debug 0x289 <<\EOF +40051c..400526 (base 400500) +400530..400534 (base 400500) +400535..40053f (base 400500) +EOF + +testrun_compare ${abs_builddir}/dwarf-ranges testfileranges5.debug 0x2a9 <<\EOF +40051c..400526 (base 400500) +400535..40053f (base 400500) +EOF + exit 0 diff --git a/tests/testfile-ranges-hello5.dwo.bz2 b/tests/testfile-ranges-hello5.dwo.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..03d252e14d9ffed0a12abad13afedbe5e4e116c6 GIT binary patch literal 1296 zcmV+r1@HPoT4*^jL0KkKStVb6-~a+D|NsC0|NsC0`v3p`@Bjbr|Nr;@|Ns8~|3Ck4 z^|k;1_y52G{0C=U#&oe%Q#~d$p_)w^dLYR3hpFW<48=6{GCfa7(9;5Gnx2rv^#P3& zMobB`nr4$ns2+)v8AhL~W|>BsY}FVVnh#S=3<T3gWSV*=O+8N(Isgp-82}mp4FCWE zpay^d01W^D000Jn0000000E!?28MtD8WBj<Jx@{Uct#30sL2>@Q}s-rs%Z5xHm9kY zhJzE-FluB0wE>z&j7))srcWuR)X>2_Oh6hM8hJEL834e5G#C(IK-xV)rlci3Pf6(0 zQ`7@Y36YRA4F-TcLm}!tO$`750Lb+;XfkP_dVmIjrhotd15E%l28MtD05mkvP+CY~ zaHLZUEjsa@>H(`D147a84A@E4{gfFT3zw{b4jcyy0;a9(8A~KqYC8Xo=TtAH_<)dg zg(4(=4MGMPK@bBcDOQ=#KxyWt_OE~k@`w-#LJ0r{=Jy7w@c~693LsHLLP-RqAqXPt zYD5VOl^_tIOsK^9IjkUD12#}b8ZrYnR`2rR-14~&1$-?_RiFT{CZ4+GWGJnpW#<@; zwP#zhL5?izs@Rv(i1*^rWOqtHq!L9TsMLZ#N}$=#*>A>q<5>z8Ktqa2?arZ!<E3B> zN1KB_y5$5o>nI6w7cXNVsnHt-R8lx4kO;D!q674V49jOTP|W=GL$N7Q<t2bUbdYQq zsrs1^2*Y@tOxymVHE?~XNaT;5&0wS_jPPuEhOYRF!Vwq0wznlImpD?Wmpxr06%n!( z6xH#u`}sv*JCO704p6*h8zqwr+JaQs#dZVjPjenhJ8IXg(!`y^odIwRg3xQv4O^@n z2Pxp#pm0J#9U6QeI<#F})kc1d_7I@Hqyn!k3`ga(aOesIC;`;uNQ)Ntl{4^yugZb4 zjS($&)hjdrtxv3WJW!@Y-V_VeUn=3p`tdlpzX({Gycw;PB1)=$OX*OsiwG5tI^{dt z@k_@Kz0RhV`k*lv8>^i8y1dXrKl49x{peo@t~%otE(DnpGE^gN6GWt#y1RJ=xJS@& z86b~BSrihFTA%A??#6%w&_SV!MCJl}d;m15{DM)2mRprMyXPxIRL<diU<tm(^e!O$ z0yjr1m*WOmBt%JP1hGTk5@(QHGC(TDC|TkocWHLsOA9C$pdrxAmOM`Ztsl#TstN}# z3ABa<5rZRwf#(F{9}I}DsEhVf&kh8dApi(zW6MNfFhXpYGbuzHR4xPcM}RZ&4&(q6 zYUz3-YlmD0%E>o^1Oq`ojE-^~A^6QYoW8~57OaT4jrOLZ%Q=|MBx&*^iocP!e*vmS z=AP*l<e1`+$SmE_SfO0k@G9vdf|6-=U65JD=0gAg$yfuyDBuZ3SHKmPYb1h4W7qNO zX8SZ$r7@sBoH}rjuFfo5J|vJW<ip|=Q?Z{h#;oNLJNGk}h8V8#a+yM4d5e(GvO<4M zW5DU!?D=y#<)f{V@Kd8{BSM;uVvCW-%~Y^8)9(Lboqo%rtZ(+3-g7B6qOcW8g5TyT z_H5Gbj+vE&vRMt@f5o`ZlK1$+E<TM^H`CzJq16O+0Y=~+vOOm*2#JgwI|!X(USTRU zGUG-0c{r6hq1mmczkFA{qH|vMQmq!RKdd+|yrW}&QSMl*J9Okh<rrd>jxOYiaG@Yd GzWcyBflLkn literal 0 HcmV?d00001 diff --git a/tests/testfile-ranges-world5.dwo.bz2 b/tests/testfile-ranges-world5.dwo.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..1ee3b6ac5adc43e475a512e545736ea50e61c1c4 GIT binary patch literal 1466 zcmV;r1x5NoT4*^jL0KkKS>RD1s{jH?fB*mg|M~a-|KI=r|KGp=zyJUL-~HG2_kaKY z|Nj5~|NYPdUIVq;UN#P~!k(e!Jx@gSJwfU{Pe>VxJdk>g9+1iDJtwKAo~M-4Pauy` zqd}&JspSmPH1t6A8&erg9;VY%)I6g@!i_ya`jcu6rj1WX^i4dY#Sc@{Nc5koXwx!? z00000G|&J6pa2aT0077Vpc()G001-q88iSi000dD000000Z~Du^h^<iz|k?J+5s~{ zFab82G-Ln(22Cae(+xCC044;$j7DezU<6`d0MH4hm<fOg$VDV+q`{$(GzowKpqOYA z0GeW800E>h0T=-o08d28fC#_<000T5n3*)uff{J^&;SiIkw&MfwHiG^rk<em(gV^1 zN2nSAXaE3Y27mw$NE!eEpa2Gd00000dVm8!05kvv1c42<+XED_n!d!t$1a@1pbVRV zED@ZuH7_S)&9(q`?Pp-ByLHUPQe<FcFVbCE^~lah2}GnSB1PTQJbIxJ2iS-**^KPI zlT)vl+w<K3Cxiq*AdpG`C#FgA$B-1JSfT|eh)E!njUfblTA~Dvl^_tY2UzhyAQYe! zK-OnO!46^r@e9<`iz{zLNkG^pbqv{J6kX5qC5^>HdF5I`gE-e1wg*Kd$QS)GqzZBc zK?K4-KXQOCOqzn!bjrvSjHtq*%(f*pOOd8onM)`m0k9N~GKI5=fscI9sl`p4Gyr}^ zxYo!VNgB7)JodEzzs_?w9MEBQ`?chTn}h-c7DT7V-xSJzK71nNIJEv?p>PVg4%@jD zigZS%ks~GfE~FTJ^s*f#QaalL$cL7EM9c=S2Fz8E(PIdWx3;R9y<#0ezeHJ;KFA9% zDV6Ts0J{I$lCIW7rk8mc^03Yv@We|J&*Ctxas|Kzf>mSe9pShtoSfws1S8;yw;)tz z$OS0jc*7WG=K^GnG;Iz%|KKPKRcIkHK!hFdic<$6ghxm^>Hx1ukv!j4l#4V>A9zkT zIF<!wED&p24hI1_sAg5w!Vc0P#k!NI>XAHN0G`W*NxY4^Yc8+ISc=0gPXc11S$Lw8 zg2As*r@^QBIDnRNH$d>o$|_I!owp6ReG=%Chw)#p0@N8{+eRV>-`bt5zA|=)QR=pg zc{l;tSMDEvyb2595h*x!o*-bU!vsMmc>pW@{YMH=DNT5BnNvU{*6!|bd58OyQ*40{ z!~jeGu_L)a67+#VzJg>*j(;^f9Dy)fOa%M;2OR2hJ-}U_jY$+*0GuArf;9~FJ*1eh zQ5#Sx@_?ZPY{p;Bi;<8LSOE<OpbeWa2wTJ&iRpzTa7;rYd;-KF*f6{fM=cD&Is>78 z6XNfp3MefZsvCfYMM(Nj01^1X0~A;nfD%*9cL4FGSkHh6F(uG#yENlpYoA9;V;La@ z94h&J5gh~o57uokj0fnA6Q_Tj72|+@S4bU9eaPe1NNG8dvCrEhy%$C^k6{X=@gN^( zg$T(-IWppg3DHPy(Cofy@P7&_X-W?mVmJ!$X^lDUFo-UKNG%X-6|VfVV1j9W`P_8( zSJsNqT8>Fv(|Pg`6J}t_i3a3t!+HlH2d(eu-54v07#Ys9dW3BKr6`9yDxHYTCL0OU zd0&sE0MN-_RZ0P9TOo)^4JyfEn6GjBMqckVor#8@)kXWc`t1mYbJyI6V}81H5)%g5 z{E#E@E}BaBR}U=YszdXl&M}t5KN37|I_|oVchD42w);5IY}p(U&Y*xcAH*nda<v(N z9(_#4QAy%~{HmIE=`Rd~lhui28OX%AEwHPBV}c!kjYl;IO+5SA7_##1d^;8Ek|dk8 za4ei{U=m$^UAw6^)>lExnpO}s!&*0ehRzh$o+PgRrPAo#a7tu41#dS5SD;>B2{)am Ui?rcoB0u8pNT&)C910{AU^N7V=>Px# literal 0 HcmV?d00001 diff --git a/tests/testfileranges5.debug.bz2 b/tests/testfileranges5.debug.bz2 new file mode 100755 index 0000000000000000000000000000000000000000..b7351ef51bfe2ebfd358fff0bd790a6929ffeb04 GIT binary patch literal 2857 zcmV+^3)b{PT4*^jL0KkKSq%;?SpW-MfB*mg|NsB@_y7Or|M~y_|MT`S?sx6!ZDjPa z#zKGeed*u|PTMQ(_h>jw^!Ir#uXj}XJ)?Erb-TC#t_GSx8bF$u(w+lU{VDn++K1|o zH4KwAJt5@`nKXKhJxw&;sL6=Hhm--J9-~dEpuz*u2dT9H8Kiod41f(2L=7|(35lqi zMH@{c(LF%X>SzJw27nt-GzNeG000002dDr50004?8VDkrLPN?PqeIjH&;ZcdY5*D< z0002>0009(0000000000XbB1=)YQO?r=}<#lT4U~k5TF#pkx38O#{>#02u%P42*yP z000bt4Ff;`(1|F}27r2i2dDrVXah!rKmY&+jQ|<|00Txq007aZfEo`_G-4V6BuO+7 zqf<tHs82?xsgP;yNv4f74^SSX)EYfcQIjJ;0ff*1^#IYJ(?B#DGyu~;001-q$Kq0z z!QR2yo}7ZTF)`IbN(70jfy5^-?BtdrG!!Ke1~!-tp_e3T?W(RO7>}tKZbM3rGa-m& zjK(}rq%Yp9&t7GcHMx0nqGN1)Z$hZBXE^yROk_`haX!|dqa&3XR80nCfz-ilAK|ib zO@pE{V-BC9EoX$a*XpI!;W;s84wpL3?c~*sV#NmAVC=lM52xB{`&^HgYpTaHnLDnd zGewh(tb7!_Mb_&MMoCI!$lXo4$Y!G)L6DJatqzdd%uv$l`ks?jg>?w2^y{&^UnxbC z24-iiw!Hpih)x9njhSrJwemD`tu138F$8;$;AmS{^|U3b<O%8WP}#7%d@)$qa5*|% zXN{HM^p{etpfDN{wPG%%#%l7^2m~2()C9fjFeUtw2d04$k(U0aWmBuai^%Axut5wF zZrWRY%k<+r7&d=JB=LwWPVWK#5~KF5LXVfH`4iJ<g+MTSi~;~i*r*L;>MDppw8RI( z)?WDo=4eXp$F|I<iy4LY&MxEveK65n{ARlQ0nZ!pV?#ap7|}8seJrO-{T#>j_^yj5 zA-VY2&8vkxOGKCn2nf)G*qadBVo9+e;h07uFiJEDMkRXId7ur81W}>1STJrih~q)q z+hrPMNTL#`&V8cBAz2`jjKpFUw1@$Yk}60F)Zt+j6H1JLq@xJ#NH&`)G&VN0j3WWG z+8a$aFkPELYYyw+@C(HPRWq||1&xVP(1BLbf63hNTB)RsyGa|iBv!-)$EYA6K&WC3 z#NZ0twa`N)v~ZC&jFuZVjHaky*i2+FxC}Qf0+Z=Rtf#!4vk;-8`vbU?0Iq`%2x47J z1y+HylCuSkvC)MsYEl9(q(%E9K%R2t2}p?{By@_DhBs+PLqM6Kxmz7#W5j~X3KW7; z&NEFK+^wTX@>)F*#^!hzA3<E~<;uL}X1Wo(NZjkULpOuEY*BKaEFA?JYtR<R-1dqt zIDx^N`l|v2uW&00Mnyi|Qo(@z99p|On6FgZdhkrUwRI9&4ls7HA{XOsgD~!j&PLTO z)>vBs7OWfMCTbLH%`%#|DFlOp3e^?xK{?KLD@XCg|43DwC|eNmp;Ku31d>pZG$F;W zgd7{tti<|remyU}W0eptO-UPcDpOzg=*dQtqmEyl7nyhD>%K|1w^<XRe>>XVm6Vc5 zAcCNqP3#=)Xc~D>xZhz>pvP}AHjvA6D20^L=-9x05}Iwb1&s^w8Y!hhu-k+OzLb#& z$k&?uEnaU!s;tL&e{LCi=J{?s^|lu}5`;-C6H(ttNMp{4oU2H%dt?|58s^!-xb?4x zVRqZbh{eis+r=z1V6)AA)<i8MOZ6T7BEfn#Yf#2WfX<g2Gkk4@Yg*R923%pIX<@T6 z_+08KV2jC6ASxeKPHIE_CKMwYDKS81^-)S9bQAJI2Wkz6d9SVeZhJd<QaNDw<8*M6 zGy?V{AGQ$yWHf_)DbN<8SuSwNwlrYUh+0`T@HCNhSaAs2laYfF>t9hU5Plf;yqh_L z4sxW*<*k!NcFeVKxQxuXc&=9Fuot~;f+3Ko>%%C-I6%SF8^4$+%uTti>4pT#{&jby zQKQ8oFDnA^-Yf<<Qm}&`{6bP%%y*y5NhwQNQ6O(yS$r&@ZG(_RNWTCn6cMd*+R;(K zdJ>SXzLs&Ng&V$t7F{5$YYoPYt~cg=^dWGXXpxFGM$9+z097Q<F$1(5kjsG3VYHan z6%;`Df)R->@Y`n7JT#U@+~+n0hJN7zR_eO&;UjVqRI>EOr47-b(+pM^Y|FSD(kF)9 zRA%EGg+++X6;S|;^c2#j5l61lxB`6SA}9s?C;Ik7{@_8#qfwP@?J73OgR;OYVB0R+ zKzhq;DR}n!X^7Qcfs>n<_<EcQ<5pW(L_2|+LQ@BR)7ZyhjvwSG4VJ>Pft9F5m8iC8 zeJWeJCypE*>*JQz-QrWCENh<;gB+pAMU`J(4MBq<f^8LJ5r9B9MsEToBQm$|XkzxB zn_$k(!O_-5Jc@mMAKA*&loGWumX_Afpi;Iv$`v|YPP|;hyJT}w9E&~jFbnEdx{6O` z>!T32BLe;r$*QY|Lu+$!C4NxQ1Xp_$Gugu?f~!yt5kz@Q(-A<ePy+#P3+|}VMAyut zInDyiCQZ(Q@b#M}4e`3b*vh)Z!xCupQZ{Q9*<35*3zOb(EE~{Lk>~I_++zyOHi@*@ zHW>G#6KrhJmfKYOBOK<m9&Rb+W~{I=uRLr7OvTPKeuFMKGD;hAHq7M;5js04QnJex zQyQaAg$h}6?1iID&7sdAgaZPKhoc^AL}8>dSb4N6bmPqgQc{+q^bXe#i9QTHroupa zhB{ruAmmu=+geUXi#H;zJ%ihd@}L|n6^Ox>xQf~-jU)1f`WZ?p+qZl^0^i<aZdOqg z!f^tR>e!8@Naq=m2!WOoB<Ap?1>-RWg^q9s5XlV{bauV2ie}NqZzD)JV~7gqoFgYG z^Mo7=`&BXQ_9+#9HM>mML|s_%mJG(2d(Xmz0<cdI^UD!}zdY)K8{|2UFcdULo~j#F zC9)?y<1*ZClo-tniJ`XGq*{EOLj`UF4DJlYUKxHD_^@SD+*~3;trNo3g$2^VrWUNM z$r<ItV403u=6xtv>coUO<a7jdx+l<-A{J-srfsh_=&U87nMUMt5j^w@78wcN0!CWc z0+7nWFT`7<^JWbO97yPt9*L^+1ITFTRf$@duaYx5TB=M^6^6*J(u|4Q_N-yX;*b;8 z=DZmyJc&8~kHR&kD=VXtT1w}gND`>bw1S*2csLXGVHoB9Bp5<vnN8Zx1eU&1k_D}W zy6YBI+U>~7(^a9Wh4+Fa!$=wfNnuD)h_O0>3(B(>2tvdVsX@S5NmMSl5)-p55egZc zLcth>KbIB@&MFF|#Ckl)&)+4e^^nFaumsjj3e?D%`NlR98vtt-uuBRGAsDF2h?s^A zp)^^xXrm>rgi$=g09gliObZjwfIc61#!2rAf~ClZ06Qt32pISVunb?BVGs0;@j9JM z)6^IP0h3L;HGqIqSOM^;;gmZZP84WFq8(<|`|#TKdfd4Hs=TBn86nmr121So0kO@* zz$bi_O(1Vb%;PMquAE9ZJ}QUQQDdmIaV9~NcRUOfJLuQF4+J;!25npuMv*T^dkiuU z(f8w~D7IDXh0(oB{Cl3@>St0hm9(OXD9yVWPlb)t45oczbP`epo!V;{BS501Rf@J{ znj9SCLSvY$W7b$=3+?~q4S?Y|AeX~pM~qD}DiamZ$Z(o=rZrr0)F1eR|KjdQrwS4Q Hp~b5pMLHtc literal 0 HcmV?d00001 diff --git a/tests/testfilesplitranges5.debug.bz2 b/tests/testfilesplitranges5.debug.bz2 new file mode 100755 index 0000000000000000000000000000000000000000..7e43492f80d7aa930da386a9edd7efbffee5436c GIT binary patch literal 2235 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 J5(aqcw?Lj>;Vb|E literal 0 HcmV?d00001 -- 2.17.0