diff options
author | Mark Wielaard <mark@klomp.org> | 2018-05-29 00:59:28 +0200 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2018-05-31 14:42:27 +0200 |
commit | b37feac1a8ceebb0748cb28d219aa8387d0885dd (patch) | |
tree | 33beb2c916d4bd0d94fcb94ceb5cdef0d809c9a5 /libdw | |
parent | c7fc54a27c0eac667f0060f277606df8208f05d7 (diff) | |
download | elfutils-b37feac1a8ceebb0748cb28d219aa8387d0885dd.tar.gz |
readelf, libdw: Add GNU DebugFission .debug_loc support.
GNU DebugFission .debug_loc location lists uses the .debug_loc section
in the split dwarf .dwo file. The encoding is a mix of old style DWARF
.debug_loc and new style .debug_loclists.
Add two testcases for the readelf and libdw decoders.
Signed-off-by: Mark Wielaard <mark@klomp.org>
Diffstat (limited to 'libdw')
-rw-r--r-- | libdw/ChangeLog | 9 | ||||
-rw-r--r-- | libdw/dwarf.h | 10 | ||||
-rw-r--r-- | libdw/dwarf_ranges.c | 65 |
3 files changed, 83 insertions, 1 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog index d1879308..eb0b01ad 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,12 @@ +2018-05-29 Mark Wielaard <mark@klomp.org> + + * dwarf.h: Add GNU DebugFission list entry encodings + DW_LLE_GNU_end_of_list_entry, + DW_LLE_GNU_base_address_selection_entry, + DW_LLE_GNU_start_end_entry and DW_LLE_GNU_start_length_entry. + * dwarf_ranges.c (__libdw_read_begin_end_pair_inc): Handle + GNU DebugFission list entries. + 2018-05-28 Mark Wielaard <mark@klomp.org> * libdw_find_split_unit.c (__libdw_find_split_unit): End split_dwarf diff --git a/libdw/dwarf.h b/libdw/dwarf.h index 8985a9d4..dc597335 100644 --- a/libdw/dwarf.h +++ b/libdw/dwarf.h @@ -915,6 +915,16 @@ enum }; +/* GNU DebugFission list entry encodings (.debug_loc.dwo). */ +enum + { + DW_LLE_GNU_end_of_list_entry = 0x0, + DW_LLE_GNU_base_address_selection_entry = 0x1, + DW_LLE_GNU_start_end_entry = 0x2, + DW_LLE_GNU_start_length_entry = 0x3 + }; + + /* DWARF call frame instruction encodings. */ enum { diff --git a/libdw/dwarf_ranges.c b/libdw/dwarf_ranges.c index 0f3ee6b5..f67d8a5a 100644 --- a/libdw/dwarf_ranges.c +++ b/libdw/dwarf_ranges.c @@ -49,7 +49,70 @@ __libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index, Dwarf_Addr *basep) { Dwarf *dbg = cu->dbg; - if (sec_index == IDX_debug_ranges || sec_index == IDX_debug_loc) + if (sec_index == IDX_debug_loc + && cu->version < 5 + && cu->unit_type == DW_UT_split_compile) + { + /* GNU DebugFission. */ + 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_LLE_GNU_end_of_list_entry: + *addrp = addr; + return 2; + + case DW_LLE_GNU_base_address_selection_entry: + 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_LLE_GNU_start_end_entry: + 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_LLE_GNU_start_length_entry: + 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 < 4) + goto invalid; + end = read_4ubyte_unaligned_inc (dbg, addr); + + *beginp = begin; + *endp = begin + end; + *addrp = addr; + return 0; + + default: + goto invalid; + } + } + else if (sec_index == IDX_debug_ranges || sec_index == IDX_debug_loc) { Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1 : (Elf64_Addr) (Elf32_Addr) -1); |