mirror of
https://github.com/openharmony/third_party_elfutils.git
synced 2026-07-19 19:43:34 -04:00
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>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
+64
-1
@@ -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);
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
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
|
||||
|
||||
+74
-6
@@ -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);
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
2018-05-29 Mark Wielaard <mark@klomp.org>
|
||||
|
||||
* run-readelf-loc.sh: Add GNU DebugFission split-dwarf variant.
|
||||
* run-varlocs.sh: Likewise.
|
||||
|
||||
2018-05-29 Mark Wielaard <mark@klomp.org>
|
||||
|
||||
* run-readelf-twofiles.sh: Add --debug-dump=loc testcase.
|
||||
|
||||
@@ -727,4 +727,145 @@ Table at Offset 0x0:
|
||||
|
||||
EOF
|
||||
|
||||
# GNU DebugFission split-dwarf variant. Still uses .debug_loc, but now in
|
||||
# .dwo file, with somewhat similar, but different encoding from DWARF5.
|
||||
testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo
|
||||
testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc --dwarf-skeleton=testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo <<\EOF
|
||||
|
||||
testfile-hello4.dwo:
|
||||
|
||||
|
||||
DWARF section [ 3] '.debug_loc.dwo' at offset 0x253:
|
||||
|
||||
CU [ b] base: 0x0000000000401160 <foo>
|
||||
[ 0] range 401160, 40116a
|
||||
0x0000000000401160 <foo>..
|
||||
0x0000000000401169 <foo+0x9>
|
||||
[ 0] reg5
|
||||
range 40116a, 401194
|
||||
0x000000000040116a <foo+0xa>..
|
||||
0x0000000000401193 <foo+0x33>
|
||||
[ 0] GNU_entry_value:
|
||||
[ 0] reg5
|
||||
[ 3] stack_value
|
||||
[ 16] range 40117b, 40118d
|
||||
0x000000000040117b <foo+0x1b>..
|
||||
0x000000000040118c <foo+0x2c>
|
||||
[ 0] GNU_addr_index [18] 0x404038 <m>
|
||||
[ 21] range 40117b, 401181
|
||||
0x000000000040117b <foo+0x1b>..
|
||||
0x0000000000401180 <foo+0x20>
|
||||
[ 0] reg5
|
||||
[ 2b] range 40117b, 401187
|
||||
0x000000000040117b <foo+0x1b>..
|
||||
0x0000000000401186 <foo+0x26>
|
||||
[ 0] reg5
|
||||
range 401189, 40118d
|
||||
0x0000000000401189 <foo+0x29>..
|
||||
0x000000000040118c <foo+0x2c>
|
||||
[ 0] reg5
|
||||
[ 3e] range 401181, 401187
|
||||
0x0000000000401181 <foo+0x21>..
|
||||
0x0000000000401186 <foo+0x26>
|
||||
[ 0] reg5
|
||||
range 401189, 40118d
|
||||
0x0000000000401189 <foo+0x29>..
|
||||
0x000000000040118c <foo+0x2c>
|
||||
[ 0] reg5
|
||||
[ 51] range 401181, 40118d
|
||||
0x0000000000401181 <foo+0x21>..
|
||||
0x000000000040118c <foo+0x2c>
|
||||
[ 0] reg5
|
||||
[ 5b] range 40118d, 401193
|
||||
0x000000000040118d <foo+0x2d>..
|
||||
0x0000000000401192 <foo+0x32>
|
||||
[ 0] reg5
|
||||
[ 65] range 4011a0, 4011af
|
||||
0x00000000004011a0 <baz>..
|
||||
0x00000000004011ae <baz+0xe>
|
||||
[ 0] reg5
|
||||
range 4011af, 4011b1
|
||||
0x00000000004011af <baz+0xf>..
|
||||
0x00000000004011b0 <baz+0x10>
|
||||
[ 0] GNU_entry_value:
|
||||
[ 0] reg5
|
||||
[ 3] stack_value
|
||||
[ 7b] range 4011a0, 4011b0
|
||||
0x00000000004011a0 <baz>..
|
||||
0x00000000004011af <baz+0xf>
|
||||
[ 0] reg5
|
||||
|
||||
testfile-world4.dwo:
|
||||
|
||||
|
||||
DWARF section [ 3] '.debug_loc.dwo' at offset 0x225:
|
||||
|
||||
CU [ b] base: 000000000000000000
|
||||
[ 0] range 401060, 401074
|
||||
0x0000000000401060 <main>..
|
||||
0x0000000000401073 <main+0x13>
|
||||
[ 0] reg5
|
||||
range 401074, 401080
|
||||
0x0000000000401074 <main+0x14>..
|
||||
0x000000000040107f <main+0x1f>
|
||||
[ 0] GNU_entry_value:
|
||||
[ 0] reg5
|
||||
[ 3] stack_value
|
||||
[ 16] range 401060, 401078
|
||||
0x0000000000401060 <main>..
|
||||
0x0000000000401077 <main+0x17>
|
||||
[ 0] reg4
|
||||
range 401078, 40107e
|
||||
0x0000000000401078 <main+0x18>..
|
||||
0x000000000040107d <main+0x1d>
|
||||
[ 0] GNU_entry_value:
|
||||
[ 0] reg4
|
||||
[ 3] stack_value
|
||||
[ 2c] range 401071, 401078
|
||||
0x0000000000401071 <main+0x11>..
|
||||
0x0000000000401077 <main+0x17>
|
||||
[ 0] reg0
|
||||
[ 36] range 4011c0, 4011c8
|
||||
0x00000000004011c0 <calc>..
|
||||
0x00000000004011c7 <calc+0x7>
|
||||
[ 0] reg5
|
||||
range 4011c8, 4011eb
|
||||
0x00000000004011c8 <calc+0x8>..
|
||||
0x00000000004011ea <calc+0x2a>
|
||||
[ 0] GNU_entry_value:
|
||||
[ 0] reg5
|
||||
[ 3] stack_value
|
||||
[ 4c] range 4011d8, 4011e3
|
||||
0x00000000004011d8 <calc+0x18>..
|
||||
0x00000000004011e2 <calc+0x22>
|
||||
[ 0] reg0
|
||||
[ 56] range 4011d8, 4011da
|
||||
0x00000000004011d8 <calc+0x18>..
|
||||
0x00000000004011d9 <calc+0x19>
|
||||
[ 0] reg1
|
||||
range 4011da, 4011df
|
||||
0x00000000004011da <calc+0x1a>..
|
||||
0x00000000004011de <calc+0x1e>
|
||||
[ 0] reg5
|
||||
range 4011df, 4011e3
|
||||
0x00000000004011df <calc+0x1f>..
|
||||
0x00000000004011e2 <calc+0x22>
|
||||
[ 0] GNU_entry_value:
|
||||
[ 0] reg5
|
||||
[ 3] deref_size 1
|
||||
[ 5] const1u 56
|
||||
[ 7] shl
|
||||
[ 8] const1u 56
|
||||
[10] shra
|
||||
[11] stack_value
|
||||
[ 7d] range 4011d8, 4011da
|
||||
0x00000000004011d8 <calc+0x18>..
|
||||
0x00000000004011d9 <calc+0x19>
|
||||
[ 0] reg1
|
||||
range 4011da, 4011e3
|
||||
0x00000000004011da <calc+0x1a>..
|
||||
0x00000000004011e2 <calc+0x22>
|
||||
[ 0] reg5
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -277,6 +277,80 @@ module 'testfilesplitranges5.debug'
|
||||
[4011c0,4011d0) {reg4}
|
||||
EOF
|
||||
|
||||
# GNU DebugFissuon Multi CU Split DWARF. See run-dwarf-ranges.sh.
|
||||
testfiles testfilesplitranges4.debug
|
||||
testfiles testfile-ranges-hello.dwo testfile-ranges-world.dwo
|
||||
testrun_compare ${abs_top_builddir}/tests/varlocs --debug -e testfilesplitranges4.debug <<\EOF
|
||||
module 'testfilesplitranges4.debug'
|
||||
[b] CU 'hello.c'
|
||||
[18] function 'no_say'@4004f0
|
||||
frame_base: {call_frame_cfa {...}}
|
||||
[2f] parameter 'prefix'
|
||||
[4004f0,4004fa) {reg5}
|
||||
[4004fa,4004ff) {GNU_entry_value(1) {reg5}, stack_value}
|
||||
[3b] variable 'world'
|
||||
<no value>
|
||||
[60] function 'main'@4003e0
|
||||
frame_base: {call_frame_cfa {...}}
|
||||
[77] parameter 'argc'
|
||||
[4003e0,4003f2) {reg5}
|
||||
[4003f2,4003f7) {GNU_entry_value(1) {reg5}, stack_value}
|
||||
[83] parameter 'argv'
|
||||
[4003e0,4003f6) {reg4}
|
||||
[4003f6,1004003f5) {GNU_entry_value(1) {reg4}, stack_value}
|
||||
[8f] inlined function 'subject'@4003e3
|
||||
[a3] parameter 'count'
|
||||
[4003e3,4003ef) {reg5}
|
||||
[ac] parameter 'word'
|
||||
[4003e3,4003ef) {reg0}
|
||||
[e7] function 'subject'@4004e0
|
||||
frame_base: {call_frame_cfa {...}}
|
||||
[fb] parameter 'word'
|
||||
[4004e0,4004f0) {reg5}
|
||||
[102] parameter 'count'
|
||||
[4004e0,4004f0) {reg4}
|
||||
module 'testfilesplitranges4.debug'
|
||||
[b] CU 'world.c'
|
||||
[18] function 'no_main'@400550
|
||||
frame_base: {call_frame_cfa {...}}
|
||||
[2f] parameter 'argc'
|
||||
[400550,400562) {reg5}
|
||||
[400562,400567) {GNU_entry_value(1) {reg5}, stack_value}
|
||||
[3b] parameter 'argv'
|
||||
[400550,400566) {reg4}
|
||||
[400566,100400565) {GNU_entry_value(1) {reg4}, stack_value}
|
||||
[47] inlined function 'no_subject'@400553
|
||||
[5b] parameter 'count'
|
||||
[400553,40055f) {reg5}
|
||||
[64] parameter 'word'
|
||||
[400553,40055f) {reg0}
|
||||
[af] function 'say'@400500
|
||||
frame_base: {call_frame_cfa {...}}
|
||||
[c9] parameter 'prefix'
|
||||
[400500,40050e) {reg5}
|
||||
[40050e,40051c) {reg3}
|
||||
[40051c,400527) {GNU_entry_value(1) {reg5}, stack_value}
|
||||
[400527,400535) {reg3}
|
||||
[400535,400540) {GNU_entry_value(1) {reg5}, stack_value}
|
||||
[d5] variable 'world'
|
||||
[400513,40051b) {reg0}
|
||||
[400527,400534) {reg0}
|
||||
[e1] inlined function 'happy'@40051c
|
||||
[f1] parameter 'w'
|
||||
[400527,400534) {reg0}
|
||||
[fa] inlined function 'sad'@40051c
|
||||
[106] parameter 'c'
|
||||
[40051b,400526) {reg0}
|
||||
[400526,400527) {GNU_entry_value(1) {reg5}}
|
||||
[400534,40053f) {reg0}
|
||||
[15c] function 'no_subject'@400540
|
||||
frame_base: {call_frame_cfa {...}}
|
||||
[170] parameter 'word'
|
||||
[400540,400550) {reg5}
|
||||
[177] parameter 'count'
|
||||
[400540,400550) {reg4}
|
||||
EOF
|
||||
|
||||
# DW_OP_addrx and DW_OP_constx testcases.
|
||||
#
|
||||
# int i, j, k;
|
||||
|
||||
Reference in New Issue
Block a user