aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
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 'src')
-rw-r--r--src/ChangeLog5
-rw-r--r--src/readelf.c80
2 files changed, 79 insertions, 6 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index e7ba6cb1..f424fb7f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,10 @@
2018-05-29 Mark Wielaard <mark@klomp.org>
+ * readelf.c (print_debug_loc_section): Handle GNU DebugFission list
+ entries.
+
+2018-05-29 Mark Wielaard <mark@klomp.org>
+
* readelf.c (print_debug): Record and reset section_info status in
implicit_debug_sections and print_debug_sections.
diff --git a/src/readelf.c b/src/readelf.c
index 390f2444..2ccbea5b 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -9276,15 +9276,81 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
continue;
}
- if (unlikely (data->d_size - offset < (size_t) address_size * 2))
- {
+ /* GNU DebugFission encoded addresses as addrx. */
+ bool is_debugfission = ((cu != NULL
+ || split_dwarf_cu_base (dbg, &cu, &base))
+ && (cu->version < 5
+ && cu->unit_type == DW_UT_split_compile));
+ if (!is_debugfission
+ && unlikely (data->d_size - offset < (size_t) address_size * 2))
+ {
+ invalid_data:
printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
break;
}
Dwarf_Addr begin;
Dwarf_Addr end;
- if (address_size == 8)
+ bool use_base = true;
+ if (is_debugfission)
+ {
+ const unsigned char *locp = readp;
+ const unsigned char *locendp = readp + data->d_size;
+ if (locp >= locendp)
+ goto invalid_data;
+
+ Dwarf_Word idx;
+ unsigned char code = *locp++;
+ switch (code)
+ {
+ case DW_LLE_GNU_end_of_list_entry:
+ begin = 0;
+ end = 0;
+ break;
+
+ case DW_LLE_GNU_base_address_selection_entry:
+ if (locp >= locendp)
+ goto invalid_data;
+ begin = (Dwarf_Addr) -1;
+ get_uleb128 (idx, locp, locendp);
+ if (get_indexed_addr (cu, idx, &end) != 0)
+ end = idx; /* ... */
+ break;
+
+ case DW_LLE_GNU_start_end_entry:
+ if (locp >= locendp)
+ goto invalid_data;
+ get_uleb128 (idx, locp, locendp);
+ if (get_indexed_addr (cu, idx, &begin) != 0)
+ end = idx; /* ... */
+ if (locp >= locendp)
+ goto invalid_data;
+ get_uleb128 (idx, locp, locendp);
+ if (get_indexed_addr (cu, idx, &end) != 0)
+ end = idx; /* ... */
+ use_base = false;
+ break;
+
+ case DW_LLE_GNU_start_length_entry:
+ if (locp >= locendp)
+ goto invalid_data;
+ get_uleb128 (idx, locp, locendp);
+ if (get_indexed_addr (cu, idx, &begin) != 0)
+ begin = idx; /* ... */
+ if (locendp - locp < 4)
+ goto invalid_data;
+ end = read_4ubyte_unaligned_inc (dbg, locp);
+ end += begin;
+ use_base = false;
+ break;
+
+ default:
+ goto invalid_data;
+ }
+
+ readp = (unsigned char *) locp;
+ }
+ else if (address_size == 8)
{
begin = read_8ubyte_unaligned_inc (dbg, readp);
end = read_8ubyte_unaligned_inc (dbg, readp);
@@ -9323,10 +9389,12 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
if (! print_unresolved_addresses)
{
- char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
- base + begin);
+ Dwarf_Addr dab = use_base ? base + begin : begin;
+ Dwarf_Addr dae = use_base ? base + end : end;
+ char *b = format_dwarf_addr (dwflmod, address_size,
+ dab, dab);
char *e = format_dwarf_addr (dwflmod, address_size,
- base + end - 1, base + end);
+ dae - 1, dae);
printf (" %s..\n", b);
printf (" %s\n", e);
free (b);