diff options
author | Mark Wielaard <mark@klomp.org> | 2018-05-20 23:30:01 +0200 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2018-05-25 15:07:58 +0200 |
commit | 6e3d2521a2b5a3b436901f52cfb9785887a7c961 (patch) | |
tree | 649d9c157ac680e9f99b61df772e429883602bf5 /src | |
parent | 184fd30d1a453dc165ffc187b22dec6d196522ad (diff) | |
download | elfutils-6e3d2521a2b5a3b436901f52cfb9785887a7c961.tar.gz |
libdw: Support DW_OP_addrx/constx and split DWARF addrx/constx support.
DW_OP_addrx/constx and GNU DebugFission DW_OP_GNU_addr/const_index take
as argument an index into the .debug_addr section for the associated CU.
This index gets resolved through dwarf_getlocation_attr. A new fake addr
CU is created per Dwarf for use with this new attribute. For split DWARF
files, the IDX_debug_addr gets replaced with the skeleton section and the
addr base is resolved immediately when constructing the split DWARF CU.
Move __libdw_cu_addr_base to libdwP.h to share with eu-readelf. Also
make it possible to resolve addrx[1234]/GNU_addr_index also as constant
indexes to (also) show when displaying these attributes in eu-readelf.
A new varlocs tests is added to test the resolving for both the DWARF4
and DWARF5 DW_OP variants. And now that addrx forms are resolved in
split DWARF files add the new DIEs with "single ranges" (those DIEs that
have a lowpc/highpc attribute pair) to run-all-dwarf-ranges.sh.
Signed-off-by: Mark Wielaard <mark@klomp.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 9 | ||||
-rw-r--r-- | src/readelf.c | 64 |
2 files changed, 66 insertions, 7 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index e1872775..1a9f4a33 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2018-01-21 Mark Wielaard <mark@klomp.org> + + * readelf.c (get_indexed_addr): New function. + (print_ops): Handle DW_OP_addrx, DW_OP_GNU_addr_index, + DW_OP_constx, DW_OP_GNU_const_index separately and resolve + address. + (attr_callback): Print index and address for + DW_FORM_GNU_addr_index and DW_FORM_addrx[1234]. + 2018-01-19 Mark Wielaard <mark@klomp.org> * readelf.c (options): Add info+. diff --git a/src/readelf.c b/src/readelf.c index 466d941e..18588022 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -4180,6 +4180,29 @@ print_bytes (size_t n, const unsigned char *bytes) } } +static int +get_indexed_addr (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr) +{ + Elf_Data *debug_addr = cu->dbg->sectiondata[IDX_debug_addr]; + if (debug_addr == NULL) + return -1; + + Dwarf_Off base = __libdw_cu_addr_base (cu); + Dwarf_Word off = idx * cu->address_size; + if (base > debug_addr->d_size + || off > debug_addr->d_size - base + || cu->address_size > debug_addr->d_size - base - off) + return -1; + + const unsigned char *addrp = debug_addr->d_buf + base + off; + if (cu->address_size == 4) + *addr = read_4ubyte_unaligned (cu->dbg, addrp); + else + *addr = read_8ubyte_unaligned (cu->dbg, addrp); + + return 0; +} + static void print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, unsigned int vers, unsigned int addrsize, unsigned int offset_size, @@ -4348,19 +4371,36 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_piece: case DW_OP_regx: case DW_OP_plus_uconst: - case DW_OP_constu: + case DW_OP_constu:; + const unsigned char *start = data; + uint64_t uleb; + NEED (1); + get_uleb128 (uleb, data, data + len); + printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n", + indent, "", (uintmax_t) offset, op_name, uleb); + CONSUME (data - start); + offset += 1 + (data - start); + break; + case DW_OP_addrx: case DW_OP_GNU_addr_index: case DW_OP_constx: case DW_OP_GNU_const_index:; - const unsigned char *start = data; - uint64_t uleb; + start = data; NEED (1); get_uleb128 (uleb, data, data + len); - printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n", + printf ("%*s[%2" PRIuMAX "] %s [%" PRIu64 "] ", indent, "", (uintmax_t) offset, op_name, uleb); CONSUME (data - start); offset += 1 + (data - start); + if (get_indexed_addr (cu, uleb, &addr) != 0) + printf ("???\n"); + else + { + a = format_dwarf_addr (dwflmod, 0, addr, addr); + printf ("%s\n", a); + free (a); + } break; case DW_OP_bit_piece: @@ -6148,9 +6188,19 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) } char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr); - printf (" %*s%-20s (%s) %s\n", - (int) (level * 2), "", dwarf_attr_name (attr), - dwarf_form_name (form), a); + if (form != DW_FORM_addr ) + { + Dwarf_Word index; + if (dwarf_formudata (attrp, &index) != 0) + goto attrval_out; + printf (" %*s%-20s (%s) [%" PRIx64 "] %s\n", + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), index, a); + } + else + printf (" %*s%-20s (%s) %s\n", + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), a); free (a); } break; |