diff options
author | Doug Rupp <rupp@adacore.com> | 2022-04-14 10:59:37 -0700 |
---|---|---|
committer | Pierre-Marie de Rodat <derodat@adacore.com> | 2022-06-01 08:43:16 +0000 |
commit | c97f3a7dc230dab0877d0c27b84eb06132cf7bf8 (patch) | |
tree | 12de08f6e77110e19a5258c91835690b82428ccd /gcc/ada/init.c | |
parent | f3949a2e785eb387d7e25d5ab06f4662d643d8fc (diff) | |
download | gcc-c97f3a7dc230dab0877d0c27b84eb06132cf7bf8.zip gcc-c97f3a7dc230dab0877d0c27b84eb06132cf7bf8.tar.gz gcc-c97f3a7dc230dab0877d0c27b84eb06132cf7bf8.tar.bz2 |
[Ada] arm-qnx-7.1: unwind goes wrong after regs restore
The usual increment of the pc to pc+2 for ARM is needed.
gcc/ada/
* init.c (QNX): __gnat_adjust_context_for_raise: New
implementation for arm-qnx.
Diffstat (limited to 'gcc/ada/init.c')
-rw-r--r-- | gcc/ada/init.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/gcc/ada/init.c b/gcc/ada/init.c index 89f16a1..7322a54 100644 --- a/gcc/ada/init.c +++ b/gcc/ada/init.c @@ -2560,6 +2560,29 @@ __gnat_install_handler (void) #include <errno.h> #include "sigtramp.h" +#if defined (__ARMEL__) && !defined (__aarch64__) + +/* ARM-QNX case with arm unwinding exceptions */ +#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE + +#include <ucontext.h> +#include <arm/cpu.h> +#include <stdint.h> + +void +__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, + void *sc ATTRIBUTE_UNUSED) +{ + /* In case of ARM exceptions, the registers context have the PC pointing + to the instruction that raised the signal. However the unwinder expects + the instruction to be in the range [PC+2,PC+3]. */ + uintptr_t *pc_addr; + mcontext_t *mcontext = &((ucontext_t *) sc)->uc_mcontext; + pc_addr = (uintptr_t *)&mcontext->cpu.gpr [ARM_REG_PC]; + *pc_addr += 2; +} +#endif /* ARMEL */ + void __gnat_map_signal (int sig, siginfo_t *si ATTRIBUTE_UNUSED, @@ -2597,6 +2620,13 @@ __gnat_map_signal (int sig, static void __gnat_error_handler (int sig, siginfo_t *si, void *ucontext) { +#ifdef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE + /* We need to sometimes to adjust the PC in case of signals so that it + doesn't reference the exception that actually raised the signal but the + instruction before it. */ + __gnat_adjust_context_for_raise (sig, ucontext); +#endif + __gnat_sigtramp (sig, (void *) si, (void *) ucontext, (__sigtramphandler_t *)&__gnat_map_signal); } |