The RA state register is local to a frame, so it should not be copied to the target frame during the context installation.
This patch adds a new backend handler that check whether a register needs to be skipped or not before its installation. libgcc/ChangeLog: * config/aarch64/aarch64-unwind.h (MD_FRAME_LOCAL_REGISTER_P): new handler checking whether a register from the current context needs to be skipped before installation into the target context. (aarch64_frame_local_register): * unwind-dw2.c (uw_install_context_1): use MD_FRAME_LOCAL_REGISTER_P. --- libgcc/config/aarch64/aarch64-unwind.h | 11 +++++++++++ libgcc/unwind-dw2.c | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h index 94ea5891b4e..52bfd540979 100644 --- a/libgcc/config/aarch64/aarch64-unwind.h +++ b/libgcc/config/aarch64/aarch64-unwind.h @@ -53,6 +53,9 @@ typedef enum { #define MD_DEMANGLE_RETURN_ADDR(context, fs, addr) \ aarch64_demangle_return_addr (context, fs, addr) +#define MD_FRAME_LOCAL_REGISTER_P(reg) \ + aarch64_frame_local_register (reg) + static inline aarch64_ra_signing_method_t aarch64_context_ra_state_get (struct _Unwind_Context *context) { @@ -127,6 +130,14 @@ aarch64_arch_extension_frame_init (struct _Unwind_Context *context ATTRIBUTE_UNU aarch64_fs_ra_state_set (fs, aarch64_ra_no_signing); } +/* Before copying the current context to the target context, check whether + the register is local to this context and should not be forwarded. */ +static inline bool +aarch64_frame_local_register(long reg) +{ + return (reg == AARCH64_DWARF_REGNUM_RA_STATE); +} + /* Do AArch64 private extraction on ADDR_WORD based on context info CONTEXT and unwind frame info FS. If ADDR_WORD is signed, we do address authentication on it using CFA of current frame. diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c index 40d64c0c0a3..5f33f80670a 100644 --- a/libgcc/unwind-dw2.c +++ b/libgcc/unwind-dw2.c @@ -1423,6 +1423,11 @@ uw_install_context_1 (struct _Unwind_Context *current, void *c = (void *) (_Unwind_Internal_Ptr) current->reg[i]; void *t = (void *) (_Unwind_Internal_Ptr)target->reg[i]; +#ifdef MD_FRAME_LOCAL_REGISTER_P + if (MD_FRAME_LOCAL_REGISTER_P (i)) + continue; +#endif + gcc_assert (current->by_value[i] == 0); if (target->by_value[i] && c) { -- 2.46.0