summaryrefslogtreecommitdiffstats
path: root/libc
diff options
context:
space:
mode:
authorMatt Fischer <matt.fischer@garmin.com>2010-01-11 10:02:06 +0800
committerGarmin Android technology group <android@garmin.com>2010-05-12 14:18:36 -0500
commite4fa46e75cd0d433b5c6c064720ed7e195cba7c8 (patch)
tree88ab07e29e66cff45b3588718fa778c8218c4b6e /libc
parentc3581dc78a51180d3550d0d04596657cb2db852c (diff)
downloadbionic-e4fa46e75cd0d433b5c6c064720ed7e195cba7c8.zip
bionic-e4fa46e75cd0d433b5c6c064720ed7e195cba7c8.tar.gz
bionic-e4fa46e75cd0d433b5c6c064720ed7e195cba7c8.tar.bz2
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
Diffstat (limited to 'libc')
-rw-r--r--libc/Android.mk2
-rw-r--r--libc/SYSCALLS.TXT5
-rw-r--r--libc/arch-arm/bionic/__sig_restorer.S7
-rw-r--r--libc/arch-arm/bionic/sigaction.c29
-rw-r--r--libc/arch-arm/syscalls.mk2
-rw-r--r--libc/arch-arm/syscalls/__sigaction.S (renamed from libc/arch-arm/syscalls/sigaction.S)6
-rw-r--r--libc/include/sys/linux-syscalls.h4
-rw-r--r--libc/include/sys/linux-unistd.h1
8 files changed, 50 insertions, 6 deletions
diff --git a/libc/Android.mk b/libc/Android.mk
index f627640..8dd124e 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -295,6 +295,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 684b43e..eaeea2b 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -167,7 +167,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
@@ -175,6 +175,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 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_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
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
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index 5d2b55e..d904473 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -103,7 +103,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)
@@ -155,6 +154,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)
@@ -209,6 +209,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_epoll_create (__NR_SYSCALL_BASE + 254)
#define __NR_epoll_ctl (__NR_SYSCALL_BASE + 255)
@@ -248,6 +249,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 12f7704..eb04011 100644
--- a/libc/include/sys/linux-unistd.h
+++ b/libc/include/sys/linux-unistd.h
@@ -141,6 +141,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);