summaryrefslogtreecommitdiffstats
path: root/tests/varlocs.c
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2018-05-20 23:30:01 +0200
committerMark Wielaard <[email protected]>2018-05-25 15:07:58 +0200
commit6e3d2521a2b5a3b436901f52cfb9785887a7c961 (patch)
tree649d9c157ac680e9f99b61df772e429883602bf5 /tests/varlocs.c
parent184fd30d1a453dc165ffc187b22dec6d196522ad (diff)
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 <[email protected]>
Diffstat (limited to 'tests/varlocs.c')
-rw-r--r--tests/varlocs.c65
1 files changed, 51 insertions, 14 deletions
diff --git a/tests/varlocs.c b/tests/varlocs.c
index b2ceda2e..859068d6 100644
--- a/tests/varlocs.c
+++ b/tests/varlocs.c
@@ -652,6 +652,42 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
}
break;
+ case DW_OP_GNU_addr_index:
+ case DW_OP_addrx:
+ /* Address from the .debug_addr section (indexed based on CU). */
+ {
+ Dwarf_Attribute addr_attr;
+ if (dwarf_getlocation_attr (attr, expr, &addr_attr) != 0)
+ error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for addr: %s",
+ dwarf_errmsg (-1));
+
+ Dwarf_Addr address;
+ if (dwarf_formaddr (&addr_attr, &address) != 0)
+ error (EXIT_FAILURE, 0, "dwarf_formaddr address failed: %s",
+ dwarf_errmsg (-1));
+
+ printf ("addr: 0x%" PRIx64, address);
+ }
+ break;
+
+ case DW_OP_GNU_const_index:
+ case DW_OP_constx:
+ /* Constant from the .debug_addr section (indexed based on CU). */
+ {
+ Dwarf_Attribute addr_attr;
+ if (dwarf_getlocation_attr (attr, expr, &addr_attr) != 0)
+ error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for addr: %s",
+ dwarf_errmsg (-1));
+
+ Dwarf_Word constant;
+ if (dwarf_formudata (&addr_attr, &constant) != 0)
+ error (EXIT_FAILURE, 0, "dwarf_formudata constant failed: %s",
+ dwarf_errmsg (-1));
+
+ printf ("const: 0x%" PRIx64, constant);
+ }
+ break;
+
default:
error (EXIT_FAILURE, 0, "unhandled opcode: DW_OP_%s (0x%x)",
opname, atom);
@@ -1019,9 +1055,18 @@ main (int argc, char *argv[])
/* Only walk actual compile units (not partial units) that
contain code if we are only interested in the function variable
locations. */
+ Dwarf_Die cudie;
+ Dwarf_Die subdie;
+ uint8_t unit_type;
+ if (dwarf_cu_info (cu->cu, NULL, &unit_type, &cudie, &subdie,
+ NULL, NULL, NULL) != 0)
+ error (EXIT_FAILURE, 0, "dwarf_cu_info: %s", dwarf_errmsg (-1));
+ if (unit_type == DW_UT_skeleton)
+ cudie = subdie;
+
Dwarf_Addr cubase;
- if (dwarf_tag (cu) == DW_TAG_compile_unit
- && (exprlocs || dwarf_lowpc (cu, &cubase) == 0))
+ if (dwarf_tag (&cudie) == DW_TAG_compile_unit
+ && (exprlocs || dwarf_lowpc (&cudie, &cubase) == 0))
{
found_cu = true;
@@ -1043,7 +1088,7 @@ main (int argc, char *argv[])
? modname
: basename (mainfile));
printf ("module '%s'\n", name);
- print_die (cu, "CU", 0);
+ print_die (&cudie, "CU", 0);
Dwarf_Addr elfbias;
Elf *elf = dwfl_module_getelf (mod, &elfbias);
@@ -1060,18 +1105,10 @@ main (int argc, char *argv[])
GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
is_ET_REL = ehdr->e_type == ET_REL;
- // Get the actual CU DIE and walk all all DIEs (or just the
- // functions) inside it.
- Dwarf_Die cudie;
- uint8_t offsize;
- uint8_t addrsize;
- if (dwarf_diecu (cu, &cudie, &addrsize, &offsize) == NULL)
- error (EXIT_FAILURE, 0, "dwarf_diecu %s", dwarf_errmsg (-1));
-
if (exprlocs)
{
Dwarf_Addr entrypc;
- if (dwarf_entrypc (cu, &entrypc) != 0)
+ if (dwarf_entrypc (&cudie, &entrypc) != 0)
entrypc = 0;
/* XXX - Passing true for has_frame_base is not really true.
@@ -1079,9 +1116,9 @@ main (int argc, char *argv[])
attributes. Technically we should check that the DIE
(types) are referenced from variables that are defined in
a context (function) that has a frame base. */
- handle_die (cu, 0, true /* Should be false */, entrypc);
+ handle_die (&cudie, 0, true /* Should be false */, entrypc);
}
- else if (dwarf_getfuncs (cu, handle_function, NULL, 0) != 0)
+ else if (dwarf_getfuncs (&cudie, handle_function, NULL, 0) != 0)
error (EXIT_FAILURE, 0, "dwarf_getfuncs %s",
dwarf_errmsg (-1));
}