diff --git a/libc/Android.mk b/libc/Android.mk
index d8cc721ca..590afbea3 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -309,6 +309,8 @@ libc_common_src_files += \
 	arch-arm/bionic/sigsetjmp.S \
 	arch-arm/bionic/strlen.c.arm \
 	arch-arm/bionic/syscall.S \
+	arch-arm/bionic/sigaction.c \
+	arch-arm/bionic/__sig_restorer.S \
 	string/memmove.c.arm \
 	string/bcopy.c \
 	string/strcmp.c \
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 8c664d759..11407b9f4 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -173,7 +173,7 @@ int           __timer_delete:timer_delete(timer_t)
 int           utimes(const char*, const struct timeval tvp[2])                          269, 271
 
 # signals
-int     sigaction(int, const struct sigaction *, struct sigaction *)  67
+int     sigaction(int, const struct sigaction *, struct sigaction *)  -1,67,67
 int     sigprocmask(int, const sigset_t *, sigset_t *)  126
 int     __sigsuspend:sigsuspend(int unused1, int unused2, unsigned mask)  72
 int     __rt_sigaction:rt_sigaction (int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize)  174
@@ -181,6 +181,9 @@ int     __rt_sigprocmask:rt_sigprocmask (int  how, const sigset_t *set, sigset_t
 int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t *set, struct siginfo_t  *info, struct timespec_t  *timeout, size_t  sigset_size)  177
 int     sigpending(sigset_t *)  73
 
+# special stub for ARM, see arch-arm/bionic/sigaction.c
+int     __sigaction:sigaction(int, const struct sigaction *, struct sigaction *)  67,-1,-1
+
 # sockets
 int           socket(int, int, int)              281,-1
 int           socketpair(int, int, int, int*)    288,-1
diff --git a/libc/arch-arm/bionic/__sig_restorer.S b/libc/arch-arm/bionic/__sig_restorer.S
new file mode 100644
index 000000000..3f6f284f2
--- /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 000000000..96ca7c65f
--- /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 4a8caaca2..9cdd28a92 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -121,13 +121,13 @@ syscall_src += arch-arm/syscalls/__timer_gettime.S
 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 2696f1eaa..aba44b823 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
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index 30c58fd9f..6e373e05f 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -104,7 +104,6 @@
 #define __NR_nanosleep                    (__NR_SYSCALL_BASE + 162)
 #define __NR_getitimer                    (__NR_SYSCALL_BASE + 105)
 #define __NR_setitimer                    (__NR_SYSCALL_BASE + 104)
-#define __NR_sigaction                    (__NR_SYSCALL_BASE + 67)
 #define __NR_sigprocmask                  (__NR_SYSCALL_BASE + 126)
 #define __NR_sigsuspend                   (__NR_SYSCALL_BASE + 72)
 #define __NR_rt_sigaction                 (__NR_SYSCALL_BASE + 174)
@@ -156,6 +155,7 @@
 #define __NR_timer_getoverrun             (__NR_SYSCALL_BASE + 260)
 #define __NR_timer_delete                 (__NR_SYSCALL_BASE + 261)
 #define __NR_utimes                       (__NR_SYSCALL_BASE + 269)
+#define __NR_sigaction                    (__NR_SYSCALL_BASE + 67)
 #define __NR_socket                       (__NR_SYSCALL_BASE + 281)
 #define __NR_socketpair                   (__NR_SYSCALL_BASE + 288)
 #define __NR_bind                         (__NR_SYSCALL_BASE + 282)
@@ -212,6 +212,7 @@
 #define __NR_timer_getoverrun             (__NR_SYSCALL_BASE + 262)
 #define __NR_timer_delete                 (__NR_SYSCALL_BASE + 263)
 #define __NR_utimes                       (__NR_SYSCALL_BASE + 271)
+#define __NR_sigaction                    (__NR_SYSCALL_BASE + 67)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 289)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 290)
@@ -253,6 +254,7 @@
 #define __NR_timer_getoverrun             (__NR_SYSCALL_BASE + 262)
 #define __NR_timer_delete                 (__NR_SYSCALL_BASE + 263)
 #define __NR_utimes                       (__NR_SYSCALL_BASE + 271)
+#define __NR_sigaction                    (__NR_SYSCALL_BASE + 67)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
diff --git a/libc/include/sys/linux-unistd.h b/libc/include/sys/linux-unistd.h
index 116d0476a..b0e7822df 100644
--- a/libc/include/sys/linux-unistd.h
+++ b/libc/include/sys/linux-unistd.h
@@ -142,6 +142,7 @@ int              __rt_sigaction (int sig, const struct sigaction *act, struct si
 int              __rt_sigprocmask (int  how, const sigset_t *set, sigset_t *oset, size_t sigsetsize);
 int              __rt_sigtimedwait (const sigset_t *set, struct siginfo_t  *info, struct timespec_t  *timeout, size_t  sigset_size);
 int              sigpending (sigset_t *);
+int              __sigaction (int, const struct sigaction *, struct sigaction *);
 int              socket (int, int, int);
 int              socketpair (int, int, int, int*);
 int              bind (int, struct sockaddr *, int);