From 54991729fd1e3d3a0cb71884d758d86afe6da9e0 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 12 Nov 2016 19:43:37 -0500 Subject: [PATCH] work around gdb issues recognizing sigreturn trampoline on x86_64 gdb can only backtrace/unwind across signal handlers if it recognizes the sa_restorer trampoline. for x86_64, gdb first attempts to determine the symbol name for the function in which the program counter resides and match it against "__restore_rt". if no name can be found (e.g. in the case of a stripped binary), the exact instruction sequence is matched instead. when matching the function name, however, gdb's unwind code wrongly considers the interval [sym,sym+size] rather than [sym,sym+size). thus, if __restore_rt begins immediately after another function, gdb wrongly identifies pc as lying within the previous adjacent function. this patch adds a nop before __restore_rt to preclude that possibility. it also removes the symbol name __restore and replaces it with a macro since the stability of whether gdb identifies the function as __restore_rt or __restore is not clear. for the no-symbols case, the instruction sequence is changed to use %rax rather than %eax to match what gdb expects. based on patch by Szabolcs Nagy, with extended description and corresponding x32 changes added. --- arch/x32/ksigaction.h | 9 +++++++++ arch/x86_64/ksigaction.h | 9 +++++++++ src/signal/x32/restore.s | 7 +++---- src/signal/x86_64/restore.s | 7 +++---- 4 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 arch/x32/ksigaction.h create mode 100644 arch/x86_64/ksigaction.h diff --git a/arch/x32/ksigaction.h b/arch/x32/ksigaction.h new file mode 100644 index 00000000..7743c5c6 --- /dev/null +++ b/arch/x32/ksigaction.h @@ -0,0 +1,9 @@ +struct k_sigaction { + void (*handler)(int); + unsigned long flags; + void (*restorer)(void); + unsigned mask[2]; +}; + +void __restore_rt(); +#define __restore __restore_rt diff --git a/arch/x86_64/ksigaction.h b/arch/x86_64/ksigaction.h new file mode 100644 index 00000000..7743c5c6 --- /dev/null +++ b/arch/x86_64/ksigaction.h @@ -0,0 +1,9 @@ +struct k_sigaction { + void (*handler)(int); + unsigned long flags; + void (*restorer)(void); + unsigned mask[2]; +}; + +void __restore_rt(); +#define __restore __restore_rt diff --git a/src/signal/x32/restore.s b/src/signal/x32/restore.s index 27cd3cef..2f06e787 100644 --- a/src/signal/x32/restore.s +++ b/src/signal/x32/restore.s @@ -1,8 +1,7 @@ + nop .global __restore_rt -.global __restore .type __restore_rt,@function -.type __restore,@function __restore_rt: -__restore: - movl $0x40000201, %eax /* SYS_rt_sigreturn */ + mov $0x40000201, %rax /* SYS_rt_sigreturn */ syscall +.size __restore_rt,.-__restore_rt diff --git a/src/signal/x86_64/restore.s b/src/signal/x86_64/restore.s index 682af2dd..b5c6e37f 100644 --- a/src/signal/x86_64/restore.s +++ b/src/signal/x86_64/restore.s @@ -1,8 +1,7 @@ + nop .global __restore_rt -.global __restore .type __restore_rt,@function -.type __restore,@function __restore_rt: -__restore: - movl $15, %eax + mov $15, %rax syscall +.size __restore_rt,.-__restore_rt -- 2.25.1