aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2018-05-20 23:30:01 +0200
committerMark Wielaard <mark@klomp.org>2018-05-25 15:07:58 +0200
commit6e3d2521a2b5a3b436901f52cfb9785887a7c961 (patch)
tree649d9c157ac680e9f99b61df772e429883602bf5 /src
parent184fd30d1a453dc165ffc187b22dec6d196522ad (diff)
downloadelfutils-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/ChangeLog9
-rw-r--r--src/readelf.c64
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;