summaryrefslogtreecommitdiff
path: root/libdw
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2018-05-29 00:59:28 +0200
committerMark Wielaard <mark@klomp.org>2018-05-31 14:42:27 +0200
commitb37feac1a8ceebb0748cb28d219aa8387d0885dd (patch)
tree33beb2c916d4bd0d94fcb94ceb5cdef0d809c9a5 /libdw
parentc7fc54a27c0eac667f0060f277606df8208f05d7 (diff)
downloadelfutils-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/ChangeLog9
-rw-r--r--libdw/dwarf.h10
-rw-r--r--libdw/dwarf_ranges.c65
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);