diff options
author | Christophe Lyon <christophe.lyon@linaro.org> | 2021-04-14 14:22:38 +0000 |
---|---|---|
committer | Christophe Lyon <christophe.lyon@linaro.org> | 2021-04-14 14:22:38 +0000 |
commit | 666c20f65ebe79576949e989640d938928daad05 (patch) | |
tree | b4b80ca9bce9f6ff844a6ffb59e8851f21d7720a | |
parent | 82934b09cd4edee8ab0c005c3b4b25bee7c51910 (diff) | |
download | binutils-666c20f65ebe79576949e989640d938928daad05.zip binutils-666c20f65ebe79576949e989640d938928daad05.tar.gz binutils-666c20f65ebe79576949e989640d938928daad05.tar.bz2 |
ARM/FDPIC: Allow backtrace to cross signal handler
2021-04-14 Mickael Guene <mickael.guene@st.com>
Christophe Lyon <christophe.lyon@st.com>
* gdb/arm-linux-tdep.c (THUMB2_SET_R7_RT_SIGRETURN): New define.
(FDPIC_LDR_R12_WITH_FUNCDESC): New define.
(FDPIC_LDR_R9_WITH_GOT): New define.
(FDPIC_LDR_PC_WITH_RESTORER): New define.
(arm_linux_sigreturn_fdpic_init): New.
(arm_linux_sigreturn_tramp_frame_fdpic): New.
(arm_linux_init_abi): Handle signal handler for FDPIC.
-rw-r--r-- | gdb/arm-linux-tdep.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index b2bdb12..3da1011 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -251,6 +251,12 @@ static const char arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa0 }; #define ARM_LDR_PC_SP_12 0xe49df00c #define ARM_LDR_PC_SP_4 0xe49df004 +/* FDPIC specific definition. */ +#define THUMB2_SET_R7_RT_SIGRETURN 0x07adf04f +#define FDPIC_LDR_R12_WITH_FUNCDESC 0xe59fc004 +#define FDPIC_LDR_R9_WITH_GOT 0xe59c9004 +#define FDPIC_LDR_PC_WITH_RESTORER 0xe59cf000 + static void arm_linux_sigtramp_cache (struct frame_info *this_frame, struct trad_frame_cache *this_cache, @@ -338,6 +344,34 @@ arm_linux_sigreturn_init (const struct tramp_frame *self, } static void +arm_linux_sigreturn_fdpic_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM); + CORE_ADDR funcdesc = read_memory_unsigned_integer (func + 12, 4, byte_order); + CORE_ADDR handler = read_memory_unsigned_integer (funcdesc, 4, byte_order); + unsigned int first_handler_instruction + = read_memory_unsigned_integer (handler & ~1, 4, byte_order); + + /* We look for either arm or thumb2 code. */ + /* This only works well for libc registered handler. */ + if (first_handler_instruction == ARM_SET_R7_RT_SIGRETURN + || first_handler_instruction == THUMB2_SET_R7_RT_SIGRETURN) + arm_linux_sigtramp_cache (this_frame, this_cache, func, + ARM_NEW_RT_SIGFRAME_UCONTEXT + + ARM_UCONTEXT_SIGCONTEXT + + ARM_SIGCONTEXT_R0); + else + arm_linux_sigtramp_cache (this_frame, this_cache, func, + ARM_UCONTEXT_SIGCONTEXT + + ARM_SIGCONTEXT_R0); +} + +static void arm_linux_rt_sigreturn_init (const struct tramp_frame *self, struct frame_info *this_frame, struct trad_frame_cache *this_cache, @@ -465,6 +499,18 @@ static struct tramp_frame arm_kernel_linux_restart_syscall_tramp_frame = { arm_linux_restart_syscall_init }; +static struct tramp_frame arm_linux_sigreturn_tramp_frame_fdpic = { + SIGTRAMP_FRAME, + 4, + { + { FDPIC_LDR_R12_WITH_FUNCDESC, -1 }, + { FDPIC_LDR_R9_WITH_GOT, -1 }, + { FDPIC_LDR_PC_WITH_RESTORER, -1 }, + { TRAMP_SENTINEL_INSN } + }, + arm_linux_sigreturn_fdpic_init +}; + /* Core file and register set support. */ #define ARM_LINUX_SIZEOF_GREGSET (18 * INT_REGISTER_SIZE) @@ -1264,6 +1310,8 @@ arm_linux_init_abi (struct gdbarch_info info, &arm_linux_restart_syscall_tramp_frame); tramp_frame_prepend_unwinder (gdbarch, &arm_kernel_linux_restart_syscall_tramp_frame); + tramp_frame_prepend_unwinder (gdbarch, + &arm_linux_sigreturn_tramp_frame_fdpic); /* Core file support. */ set_gdbarch_regset_from_core_section (gdbarch, |