work around gdb issues recognizing sigreturn trampoline on x86_64
authorRich Felker <dalias@aerifal.cx>
Sun, 13 Nov 2016 00:43:37 +0000 (19:43 -0500)
committerRich Felker <dalias@aerifal.cx>
Sun, 13 Nov 2016 00:54:43 +0000 (19:54 -0500)
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 [new file with mode: 0644]
arch/x86_64/ksigaction.h [new file with mode: 0644]
src/signal/x32/restore.s
src/signal/x86_64/restore.s

diff --git a/arch/x32/ksigaction.h b/arch/x32/ksigaction.h
new file mode 100644 (file)
index 0000000..7743c5c
--- /dev/null
@@ -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 (file)
index 0000000..7743c5c
--- /dev/null
@@ -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
index 27cd3cef9b7c5eebe756ce0347eae5ff333a0caa..2f06e787680a993fc62da5849311771ab84b812c 100644 (file)
@@ -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
index 682af2dd84accf2f8f5e1442e200ced3d03c9f26..b5c6e37f77bb986e20757ea1c6847cbb99a4bc46 100644 (file)
@@ -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