summaryrefslogtreecommitdiff
path: root/libdw/cfi.c
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2020-09-03 17:46:53 +0200
committerMark Wielaard <mark@klomp.org>2020-09-07 12:21:10 +0200
commit5ed73d79bf5670484963cb5b57b8da50c68d5c3e (patch)
tree2253b44f8322d2520ccd3538d832f97aecc1bb26 /libdw/cfi.c
parent18d64cd8e7ce0761568631bb40136ca7a154b6e0 (diff)
downloadelfutils-5ed73d79bf5670484963cb5b57b8da50c68d5c3e.tar.gz
libdw,readelf: Recognize DW_CFA_AARCH64_negate_ra_state
DW_CFA_AARCH64_negate_ra_state is used on aarch64 to indicate whether or not the return address is mangled or not. This has the same value as the DW_CFA_GNU_window_save. So we have to pass around the e_machine value of the process or core we are inspecting to know which one to use. Note that it isn't actually implemented yet. It needs ARMv8.3 hardware. If we don't have such hardware it is enough to simply ignore the DW_CFA_AARCH64_negate_ra_state (and not confuse it with DW_CFA_GNU_window_save) to get backtraces to work on aarch64. Add a testcase for eu-readelf --debug-dump=frames to show the value is correctly recognized. Also don't warn we cannot find any DWARF if we are just dumping frames (those will come from .eh_frame if there is no .debug_frame). Signed-off-by: Mark Wielaard <mark@klomp.org>
Diffstat (limited to 'libdw/cfi.c')
-rw-r--r--libdw/cfi.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/libdw/cfi.c b/libdw/cfi.c
index 6705294f..a73fb03f 100644
--- a/libdw/cfi.c
+++ b/libdw/cfi.c
@@ -350,24 +350,35 @@ execute_cfi (Dwarf_CFI *cache,
case DW_CFA_nop:
continue;
- case DW_CFA_GNU_window_save:
- /* This is magic shorthand used only by SPARC. It's equivalent
- to a bunch of DW_CFA_register and DW_CFA_offset operations. */
- if (unlikely (! enough_registers (31, &fs, &result)))
- goto out;
- for (regno = 8; regno < 16; ++regno)
+ case DW_CFA_GNU_window_save: /* DW_CFA_AARCH64_negate_ra_state */
+ if (cache->e_machine == EM_AARCH64)
{
- /* Find each %oN in %iN. */
- fs->regs[regno].rule = reg_register;
- fs->regs[regno].value = regno + 16;
+ /* Toggles the return address state, indicating whether
+ the return address is encrypted or not on
+ aarch64. XXX not handled yet. */
}
- unsigned int address_size = (cache->e_ident[EI_CLASS] == ELFCLASS32
- ? 4 : 8);
- for (; regno < 32; ++regno)
+ else
{
- /* Find %l0..%l7 and %i0..%i7 in a block at the CFA. */
- fs->regs[regno].rule = reg_offset;
- fs->regs[regno].value = (regno - 16) * address_size;
+ /* This is magic shorthand used only by SPARC. It's
+ equivalent to a bunch of DW_CFA_register and
+ DW_CFA_offset operations. */
+ if (unlikely (! enough_registers (31, &fs, &result)))
+ goto out;
+ for (regno = 8; regno < 16; ++regno)
+ {
+ /* Find each %oN in %iN. */
+ fs->regs[regno].rule = reg_register;
+ fs->regs[regno].value = regno + 16;
+ }
+ unsigned int address_size;
+ address_size = (cache->e_ident[EI_CLASS] == ELFCLASS32
+ ? 4 : 8);
+ for (; regno < 32; ++regno)
+ {
+ /* Find %l0..%l7 and %i0..%i7 in a block at the CFA. */
+ fs->regs[regno].rule = reg_offset;
+ fs->regs[regno].value = (regno - 16) * address_size;
+ }
}
continue;