Set SA_RESTORER in sigaction()

GDB looks for specific opcode sequences when trying to recognize a stack
frame as a signal trampoline.  The sequences it looks for happen to be those
created when SA_RESTORER is set, since glibc always sets a restorer.  This
patch does the same here, so that the trampolines can be correctly identified.

Change-Id: I0ac574a68818cb24d939c3527f3aaeb04b853d04
diff --git a/libc/arch-arm/bionic/__sig_restorer.S b/libc/arch-arm/bionic/__sig_restorer.S
new file mode 100644
index 0000000..3f6f284
--- /dev/null
+++ b/libc/arch-arm/bionic/__sig_restorer.S
@@ -0,0 +1,7 @@
+.global __sig_restorer
+
+/* This is the opcode sequence GDB looks for in order to recognize
+   this stack frame as a signal trampoline (see sigaction.c) */
+__sig_restorer:
+    mov r7, #119 /* __NR_sigreturn */
+    swi #0
diff --git a/libc/arch-arm/bionic/sigaction.c b/libc/arch-arm/bionic/sigaction.c
new file mode 100644
index 0000000..96ca7c6
--- /dev/null
+++ b/libc/arch-arm/bionic/sigaction.c
@@ -0,0 +1,29 @@
+#include <signal.h>
+
+extern int __sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
+extern void __sig_restorer();
+
+int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
+{
+    struct sigaction real_act;
+
+    /* If the caller has not set a custom restorer, then set up a default one.
+     * The code will function properly without this, however GDB will not be
+     * able to recognize the stack frame as a signal trampoline, because it
+     * is hardcoded to look for the instruction sequence that glibc uses in
+     * its custom restorer.  By creating our own restorer with the same
+     * sequence, we ensure that GDB correctly identifies this as a signal
+     * trampoline frame.
+     *
+     * See http://sourceware.org/ml/gdb/2010-01/msg00143.html for more
+     * information on this.*/
+    if(act && !(act->sa_flags & SA_RESTORER)) {
+        real_act = *act;
+        real_act.sa_flags |= SA_RESTORER;
+        real_act.sa_restorer = __sig_restorer;
+
+        act = &real_act;
+    }
+
+    return __sigaction(signum, act, oldact);
+}
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index 706cb0c..f4cb63a 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -120,13 +120,13 @@
 syscall_src += arch-arm/syscalls/__timer_getoverrun.S
 syscall_src += arch-arm/syscalls/__timer_delete.S
 syscall_src += arch-arm/syscalls/utimes.S
-syscall_src += arch-arm/syscalls/sigaction.S
 syscall_src += arch-arm/syscalls/sigprocmask.S
 syscall_src += arch-arm/syscalls/__sigsuspend.S
 syscall_src += arch-arm/syscalls/__rt_sigaction.S
 syscall_src += arch-arm/syscalls/__rt_sigprocmask.S
 syscall_src += arch-arm/syscalls/__rt_sigtimedwait.S
 syscall_src += arch-arm/syscalls/sigpending.S
+syscall_src += arch-arm/syscalls/__sigaction.S
 syscall_src += arch-arm/syscalls/socket.S
 syscall_src += arch-arm/syscalls/socketpair.S
 syscall_src += arch-arm/syscalls/bind.S
diff --git a/libc/arch-arm/syscalls/sigaction.S b/libc/arch-arm/syscalls/__sigaction.S
similarity index 81%
rename from libc/arch-arm/syscalls/sigaction.S
rename to libc/arch-arm/syscalls/__sigaction.S
index 2696f1e..aba44b8 100644
--- a/libc/arch-arm/syscalls/sigaction.S
+++ b/libc/arch-arm/syscalls/__sigaction.S
@@ -2,12 +2,12 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type sigaction, #function
-    .globl sigaction
+    .type __sigaction, #function
+    .globl __sigaction
     .align 4
     .fnstart
 
-sigaction:
+__sigaction:
     .save   {r4, r7}
     stmfd   sp!, {r4, r7}
     ldr     r7, =__NR_sigaction