summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux
diff options
context:
space:
mode:
authorChris Zankel <chris@zankel.net>2008-02-20 00:30:54 +0000
committerChris Zankel <chris@zankel.net>2008-02-20 00:30:54 +0000
commitd8f106289ffc338f15568f373b209f0c47755a54 (patch)
tree68d366e9f056bd36acb747c69cd02e5d595e2467 /libc/sysdeps/linux
parent5bb327a1dbe37208a812a9134763aa5adfa90e12 (diff)
Xtensa: Provide an architecture specific sigaction and sa_restorer function in libc to avoid having to place executable code on stack.
Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'libc/sysdeps/linux')
-rw-r--r--libc/sysdeps/linux/xtensa/Makefile.arch6
-rw-r--r--libc/sysdeps/linux/xtensa/sigaction.c59
-rw-r--r--libc/sysdeps/linux/xtensa/sigrestorer.S19
3 files changed, 81 insertions, 3 deletions
diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch b/libc/sysdeps/linux/xtensa/Makefile.arch
index 74510c9f6..f54886444 100644
--- a/libc/sysdeps/linux/xtensa/Makefile.arch
+++ b/libc/sysdeps/linux/xtensa/Makefile.arch
@@ -1,14 +1,14 @@
# Makefile for uClibc
#
-# Copyright (C) 2007 Tensilica Inc.
+# Copyright (C) 2007, 2008 Tensilica Inc.
#
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
#
CSRC := brk.c fork.c posix_fadvise.c posix_fadvise64.c pread_write.c \
- __syscall_error.c
+ sigaction.c __syscall_error.c
SSRC := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
- syscall.S mmap.S windowspill.S __longjmp.S vfork.S
+ sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S
include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch
diff --git a/libc/sysdeps/linux/xtensa/sigaction.c b/libc/sysdeps/linux/xtensa/sigaction.c
new file mode 100644
index 000000000..5ef40c36e
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/sigaction.c
@@ -0,0 +1,59 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * sigaction() for Xtensa uClibc
+ *
+ * Copyright (C) 2007, 2008 Tensilica Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/syscall.h>
+#include <string.h>
+#include <bits/kernel_sigaction.h>
+
+#define SA_RESTORER 0x04000000
+
+extern void __default_sa_restorer (void);
+
+libc_hidden_proto(memcpy)
+
+int __libc_sigaction (int signum, const struct sigaction *act,
+ struct sigaction *oldact)
+{
+ struct kernel_sigaction kact, koldact;
+ int result;
+
+ if (act) {
+ kact.k_sa_handler = act->sa_handler;
+ memcpy(&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask));
+ kact.sa_flags = act->sa_flags;
+
+ if (kact.sa_flags & SA_RESTORER) {
+ kact.sa_restorer = act->sa_restorer;
+ } else {
+ kact.sa_restorer = __default_sa_restorer;
+ kact.sa_flags |= SA_RESTORER;
+ }
+ }
+
+ result = __syscall_rt_sigaction(signum, act ? __ptrvalue (&kact) : NULL,
+ oldact ? __ptrvalue (&koldact) : NULL,
+ _NSIG / 8);
+
+ if (oldact && result >= 0) {
+ oldact->sa_handler = koldact.k_sa_handler;
+ memcpy(&oldact->sa_mask, &koldact.sa_mask, sizeof(oldact->sa_mask));
+ oldact->sa_flags = koldact.sa_flags;
+ oldact->sa_restorer = koldact.sa_restorer;
+ }
+
+ return result;
+}
+
+#ifndef LIBC_SIGACTION
+libc_hidden_proto (sigaction)
+weak_alias (__libc_sigaction, sigaction)
+libc_hidden_weak (sigaction)
+#endif
diff --git a/libc/sysdeps/linux/xtensa/sigrestorer.S b/libc/sysdeps/linux/xtensa/sigrestorer.S
new file mode 100644
index 000000000..474a89319
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/sigrestorer.S
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2008 Tensilica Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <sys/syscall.h>
+
+#if __NR_rt_sigreturn > 255
+# error value of __NR_rt_sigreturn is too big!
+#endif
+
+ .text
+ .align 4
+ .global __default_sa_restorer
+ .type __default_sa_restorer, @function
+__default_sa_restorer:
+ movi a2, __NR_rt_sigreturn
+ syscall