From e4fa46e75cd0d433b5c6c064720ed7e195cba7c8 Mon Sep 17 00:00:00 2001 From: Matt Fischer Date: Mon, 11 Jan 2010 10:02:06 +0800 Subject: 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 --- libc/Android.mk | 2 ++ libc/SYSCALLS.TXT | 5 ++++- libc/arch-arm/bionic/__sig_restorer.S | 7 +++++++ libc/arch-arm/bionic/sigaction.c | 29 +++++++++++++++++++++++++++++ libc/arch-arm/syscalls.mk | 2 +- libc/arch-arm/syscalls/__sigaction.S | 19 +++++++++++++++++++ libc/arch-arm/syscalls/sigaction.S | 19 ------------------- libc/include/sys/linux-syscalls.h | 4 +++- libc/include/sys/linux-unistd.h | 1 + 9 files changed, 66 insertions(+), 22 deletions(-) create mode 100644 libc/arch-arm/bionic/__sig_restorer.S create mode 100644 libc/arch-arm/bionic/sigaction.c create mode 100644 libc/arch-arm/syscalls/__sigaction.S delete mode 100644 libc/arch-arm/syscalls/sigaction.S (limited to 'libc') 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 + +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 new file mode 100644 index 0000000..aba44b8 --- /dev/null +++ b/libc/arch-arm/syscalls/__sigaction.S @@ -0,0 +1,19 @@ +/* autogenerated by gensyscalls.py */ +#include + + .text + .type __sigaction, #function + .globl __sigaction + .align 4 + .fnstart + +__sigaction: + .save {r4, r7} + stmfd sp!, {r4, r7} + ldr r7, =__NR_sigaction + swi #0 + ldmfd sp!, {r4, r7} + movs r0, r0 + bxpl lr + b __set_syscall_errno + .fnend diff --git a/libc/arch-arm/syscalls/sigaction.S b/libc/arch-arm/syscalls/sigaction.S deleted file mode 100644 index 2696f1e..0000000 --- a/libc/arch-arm/syscalls/sigaction.S +++ /dev/null @@ -1,19 +0,0 @@ -/* autogenerated by gensyscalls.py */ -#include - - .text - .type sigaction, #function - .globl sigaction - .align 4 - .fnstart - -sigaction: - .save {r4, r7} - stmfd sp!, {r4, r7} - ldr r7, =__NR_sigaction - swi #0 - ldmfd sp!, {r4, r7} - movs r0, r0 - bxpl lr - b __set_syscall_errno - .fnend 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); -- cgit v1.1