diff options
author | Mark Wielaard <mark@klomp.org> | 2020-09-03 17:46:53 +0200 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2020-09-07 12:21:10 +0200 |
commit | 5ed73d79bf5670484963cb5b57b8da50c68d5c3e (patch) | |
tree | 2253b44f8322d2520ccd3538d832f97aecc1bb26 /libdw/cfi.c | |
parent | 18d64cd8e7ce0761568631bb40136ca7a154b6e0 (diff) | |
download | elfutils-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.c | 41 |
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; |