summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/stdlib/system.c3
-rw-r--r--libc/sysdeps/linux/arm/clone.S61
-rw-r--r--libc/sysdeps/linux/arm/sysdep.h36
-rw-r--r--libc/sysdeps/linux/common/Makefile.in2
-rw-r--r--libc/sysdeps/linux/common/bits/mathcalls.h18
-rw-r--r--libc/sysdeps/linux/common/eventfd_read.c27
-rw-r--r--libc/sysdeps/linux/common/eventfd_write.c28
-rw-r--r--libc/sysdeps/linux/common/mknod.c4
-rw-r--r--libc/sysdeps/linux/common/sys/eventfd.h4
-rw-r--r--libc/sysdeps/linux/cris/sys/procfs.h6
-rw-r--r--libc/sysdeps/linux/cris/sysdep.S2
-rw-r--r--libc/sysdeps/linux/m68k/sys/reg.h88
-rw-r--r--libc/sysdeps/linux/xtensa/Makefile.arch5
-rw-r--r--libc/sysdeps/linux/xtensa/clone.S101
-rw-r--r--libc/sysdeps/linux/xtensa/fork.c8
-rw-r--r--libc/sysdeps/linux/xtensa/jmpbuf-unwind.h38
-rw-r--r--libc/sysdeps/linux/xtensa/sys/ptrace.h155
-rw-r--r--libc/sysdeps/linux/xtensa/sysdep.h39
-rw-r--r--libc/sysdeps/linux/xtensa/vfork.S104
-rw-r--r--libc/unistd/daemon.c1
20 files changed, 478 insertions, 252 deletions
diff --git a/libc/stdlib/system.c b/libc/stdlib/system.c
index 3ef9a8b1c..7f81f947a 100644
--- a/libc/stdlib/system.c
+++ b/libc/stdlib/system.c
@@ -91,9 +91,6 @@ libc_hidden_proto(waitpid)
#elif defined __sparc__
# define FORK() \
INLINE_CLONE_SYSCALL (CLONE_PARENT_SETTID | SIGCHLD, 0, &pid, NULL, NULL)
-#elif defined __s390__
-# define FORK() \
- INLINE_SYSCALL (clone, 3, 0, CLONE_PARENT_SETTID | SIGCHLD, &pid)
#else
# define FORK() \
INLINE_SYSCALL (clone, 3, CLONE_PARENT_SETTID | SIGCHLD, 0, &pid)
diff --git a/libc/sysdeps/linux/arm/clone.S b/libc/sysdeps/linux/arm/clone.S
index 03cd10e62..29045ef7b 100644
--- a/libc/sysdeps/linux/arm/clone.S
+++ b/libc/sysdeps/linux/arm/clone.S
@@ -19,12 +19,17 @@
/* clone() is even more special than fork() as it mucks with stacks
and invokes a function in the right context after its all over. */
+#include <sysdep.h>
#define _ERRNO_H
#include <features.h>
#include <bits/errno.h>
#include <sys/syscall.h>
#include <bits/arm_asm.h>
#include <bits/arm_bx.h>
+#include <sysdep-cancel.h>
+
+#define CLONE_VM 0x00000100
+#define CLONE_THREAD 0x00010000
#if defined(__NR_clone)
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
@@ -87,6 +92,8 @@ __error:
.pool
#else
__clone:
+.fnstart
+.cantunwind
@ sanity check args
cmp r0, #0
IT(te, ne)
@@ -95,32 +102,58 @@ __clone:
beq __error
@ insert the args onto the new stack
- sub r1, r1, #8
- str r3, [r1, #4]
- @ save the function pointer as the 0th element
- str r0, [r1]
+ str r3, [r1, #-4]!
+ str r0, [r1, #-4]!
@ do the system call
@ get flags
mov r0, r2
+#ifdef RESET_PID
+ mov ip, r2
+#endif
@ new sp is already in r1
- @ load remaining arguments off the stack
- stmfd sp!, {r4}
- ldr r2, [sp, #4]
- ldr r3, [sp, #8]
- ldr r4, [sp, #12]
- DO_CALL (clone)
- movs a1, a1
- IT(t, ne)
- ldmnefd sp!, {r4}
+ push {r4, r7}
+ cfi_adjust_cfa_offset (8)
+ cfi_rel_offset (r4, 0)
+ cfi_rel_offset (r7, 4)
+ ldr r2, [sp, #8]
+ ldr r3, [sp, #12]
+ ldr r4, [sp, #16]
+ ldr r7, =SYS_ify(clone)
+ swi 0x0
+ cfi_endproc
+ cmp r0, #0
+ beq 1f
+ pop {r4, r7}
blt __error
- IT(t, ne)
#if defined(__USE_BX__)
bxne lr
#else
movne pc, lr
#endif
+ cfi_startproc
+.fnend
+PSEUDO_END (__clone)
+
+1:
+ .fnstart
+ .cantunwind
+#ifdef RESET_PID
+ tst ip, #CLONE_THREAD
+ bne 3f
+ GET_TLS (lr)
+ mov r1, r0
+ tst ip, #CLONE_VM
+ ldr r7, =SYS_ify(getpid)
+ ite ne
+ movne r0, #-1
+ swieq 0x0
+ NEGOFF_ADJ_BASE (r1, TID_OFFSET)
+ str r0, NEGOFF_OFF1 (r1, TID_OFFSET)
+ str r0, NEGOFF_OFF2 (r1, PID_OFFSET, TID_OFFSET)
+3:
+#endif
@ pick the function arg and call address off the stack and execute
ldr r0, [sp, #4]
mov lr, pc
diff --git a/libc/sysdeps/linux/arm/sysdep.h b/libc/sysdeps/linux/arm/sysdep.h
index 64f40407e..2d0a9cc41 100644
--- a/libc/sysdeps/linux/arm/sysdep.h
+++ b/libc/sysdeps/linux/arm/sysdep.h
@@ -213,6 +213,42 @@ __local_syscall_error: \
sees the right arguments.
*/
+#if __ARM_ARCH > 6 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__)
+# define ARCH_HAS_HARD_TP
+#endif
+
+# ifdef __thumb2__
+# define NEGOFF_ADJ_BASE(R, OFF) add R, R, $OFF
+# define NEGOFF_ADJ_BASE2(D, S, OFF) add D, S, $OFF
+# define NEGOFF_OFF1(R, OFF) [R]
+# define NEGOFF_OFF2(R, OFFA, OFFB) [R, $((OFFA) - (OFFB))]
+# else
+# define NEGOFF_ADJ_BASE(R, OFF)
+# define NEGOFF_ADJ_BASE2(D, S, OFF) mov D, S
+# define NEGOFF_OFF1(R, OFF) [R, $OFF]
+# define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA]
+# endif
+
+# ifdef ARCH_HAS_HARD_TP
+/* If the cpu has cp15 available, use it. */
+# define GET_TLS(TMP) mrc p15, 0, r0, c13, c0, 3
+# else
+/* At this generic level we have no tricks to pull. Call the ABI routine. */
+# define GET_TLS(TMP) \
+ push { r1, r2, r3, lr }; \
+ cfi_remember_state; \
+ cfi_adjust_cfa_offset (16); \
+ cfi_rel_offset (r1, 0); \
+ cfi_rel_offset (r2, 4); \
+ cfi_rel_offset (r3, 8); \
+ cfi_rel_offset (lr, 12); \
+ bl __aeabi_read_tp; \
+ pop { r1, r2, r3, lr }; \
+ cfi_restore_state
+# endif /* ARCH_HAS_HARD_TP */
+
+
+
#undef DO_CALL
#if defined(__ARM_EABI__)
diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in
index a175ab64c..9d41771e2 100644
--- a/libc/sysdeps/linux/common/Makefile.in
+++ b/libc/sysdeps/linux/common/Makefile.in
@@ -25,6 +25,8 @@ CSRC-$(UCLIBC_LINUX_SPECIFIC) += \
capset.c \
dup3.c \
eventfd.c \
+ eventfd_read.c \
+ eventfd_write.c \
inotify.c \
ioperm.c \
iopl.c \
diff --git a/libc/sysdeps/linux/common/bits/mathcalls.h b/libc/sysdeps/linux/common/bits/mathcalls.h
index 84b793c96..427027355 100644
--- a/libc/sysdeps/linux/common/bits/mathcalls.h
+++ b/libc/sysdeps/linux/common/bits/mathcalls.h
@@ -271,7 +271,9 @@ __END_NAMESPACE_C99
#ifdef __USE_ISOC99
__BEGIN_NAMESPACE_C99
/* True gamma function. */
+# ifndef _Mdouble_is_float_
__MATHCALLI (tgamma,, (_Mdouble_))
+# endif
__END_NAMESPACE_C99
#endif
@@ -299,7 +301,9 @@ __MATHCALLI (rint,, (_Mdouble_ __x))
/* Return X + epsilon if X < Y, X - epsilon if X > Y. */
__MATHCALLX (nextafter,, (_Mdouble_ __x, _Mdouble_ __y), (__const__))
# if defined __USE_ISOC99 && !defined __LDBL_COMPAT
+# ifndef _Mdouble_is_float_
__MATHCALLX (nexttoward,, (_Mdouble_ __x, long double __y), (__const__))
+# endif
# endif
/* Return the remainder of integer divison X / Y with infinite precision. */
@@ -316,11 +320,15 @@ __MATHDECLI (int,ilogb,, (_Mdouble_ __x))
#ifdef __USE_ISOC99
/* Return X times (2 to the Nth power). */
+# ifndef _Mdouble_is_float_
__MATHCALLI (scalbln,, (_Mdouble_ __x, long int __n))
+# endif
/* Round X to integral value in floating-point format using current
rounding direction, but do not raise inexact exception. */
+# ifndef _Mdouble_is_float_
__MATHCALLI (nearbyint,, (_Mdouble_ __x))
+# endif
/* Round X to nearest integral value, rounding halfway cases away from
zero. */
@@ -333,7 +341,9 @@ __MATHCALLX (trunc,, (_Mdouble_ __x), (__const__))
/* Compute remainder of X and Y and put in *QUO a value with sign of x/y
and magnitude congruent `mod 2^n' to the magnitude of the integral
quotient x/y, with n >= 3. */
+# ifndef _Mdouble_is_float_
__MATHCALLI (remquo,, (_Mdouble_ __x, _Mdouble_ __y, int *__quo))
+# endif
/* Conversion functions. */
@@ -350,13 +360,19 @@ __MATHDECLI (long long int,llround,, (_Mdouble_ __x))
/* Return positive difference between X and Y. */
+# ifndef _Mdouble_is_float_
__MATHCALLI (fdim,, (_Mdouble_ __x, _Mdouble_ __y))
+# endif
/* Return maximum numeric value from X and Y. */
+# ifndef _Mdouble_is_float_
__MATHCALLI (fmax,, (_Mdouble_ __x, _Mdouble_ __y))
+# endif
/* Return minimum numeric value from X and Y. */
+# ifndef _Mdouble_is_float_
__MATHCALLI (fmin,, (_Mdouble_ __x, _Mdouble_ __y))
+# endif
/* Classify given number. */
@@ -367,7 +383,9 @@ __MATHDECL_PRIV (int, signbit,, (_Mdouble_ __value), (__const__))
/* Multiply-add function computed as a ternary operation. */
+# ifndef _Mdouble_is_float_
__MATHCALLI (fma,, (_Mdouble_ __x, _Mdouble_ __y, _Mdouble_ __z))
+# endif
#endif /* Use ISO C99. */
#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
diff --git a/libc/sysdeps/linux/common/eventfd_read.c b/libc/sysdeps/linux/common/eventfd_read.c
new file mode 100644
index 000000000..75f2aaa11
--- /dev/null
+++ b/libc/sysdeps/linux/common/eventfd_read.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2007-2014 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/eventfd.h>
+
+
+int
+eventfd_read (int fd, eventfd_t *value)
+{
+ return read (fd, value, sizeof (eventfd_t)) != sizeof (eventfd_t) ? -1 : 0;
+}
diff --git a/libc/sysdeps/linux/common/eventfd_write.c b/libc/sysdeps/linux/common/eventfd_write.c
new file mode 100644
index 000000000..e1509cf5c
--- /dev/null
+++ b/libc/sysdeps/linux/common/eventfd_write.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2007-2014 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/eventfd.h>
+
+
+int
+eventfd_write (int fd, eventfd_t value)
+{
+ return write (fd, &value,
+ sizeof (eventfd_t)) != sizeof (eventfd_t) ? -1 : 0;
+}
diff --git a/libc/sysdeps/linux/common/mknod.c b/libc/sysdeps/linux/common/mknod.c
index 416cab6d0..794e19f57 100644
--- a/libc/sysdeps/linux/common/mknod.c
+++ b/libc/sysdeps/linux/common/mknod.c
@@ -24,6 +24,10 @@ int mknod(const char *path, mode_t mode, dev_t dev)
/* We must convert the value to dev_t type used by the kernel. */
k_dev = (dev) & ((1ULL << 32) - 1);
+ if (k_dev != dev) {
+ __set_errno (EINVAL);
+ return -1;
+ }
return INLINE_SYSCALL(mknod, 3, path, mode, (unsigned int)k_dev);
}
#endif
diff --git a/libc/sysdeps/linux/common/sys/eventfd.h b/libc/sysdeps/linux/common/sys/eventfd.h
index 1bf785f32..91b265b2c 100644
--- a/libc/sysdeps/linux/common/sys/eventfd.h
+++ b/libc/sysdeps/linux/common/sys/eventfd.h
@@ -33,16 +33,12 @@ __BEGIN_DECLS
value to COUNT. */
extern int eventfd (int __count, int __flags) __THROW;
-#if 0 /* not (yet) implemented in uClibc */
-
/* Read event counter and possibly wait for events. */
extern int eventfd_read (int __fd, eventfd_t *__value);
/* Increment event counter. */
extern int eventfd_write (int __fd, eventfd_t __value);
-#endif
-
__END_DECLS
#endif /* sys/eventfd.h */
diff --git a/libc/sysdeps/linux/cris/sys/procfs.h b/libc/sysdeps/linux/cris/sys/procfs.h
index d4ee05134..65b57ba4e 100644
--- a/libc/sysdeps/linux/cris/sys/procfs.h
+++ b/libc/sysdeps/linux/cris/sys/procfs.h
@@ -28,10 +28,14 @@
#include <sys/types.h>
#include <sys/ucontext.h>
#include <sys/user.h>
-#include <asm/elf.h>
__BEGIN_DECLS
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
struct elf_siginfo
{
int si_signo; /* Signal number. */
diff --git a/libc/sysdeps/linux/cris/sysdep.S b/libc/sysdeps/linux/cris/sysdep.S
index 8f25fb722..a23bb260f 100644
--- a/libc/sysdeps/linux/cris/sysdep.S
+++ b/libc/sysdeps/linux/cris/sysdep.S
@@ -35,7 +35,7 @@ ENTRY (__syscall_error)
/* Note that __syscall_error is only visible within this library,
and no-one passes it on as a pointer, so can assume that R0 (GOT
pointer) is correctly set up. */
- PLTCALL (HIDDEN_JUMPTARGET(__errno_location))
+ PLTCALL (__errno_location)
move [sp+],srp
move.d [sp+],r11
diff --git a/libc/sysdeps/linux/m68k/sys/reg.h b/libc/sysdeps/linux/m68k/sys/reg.h
deleted file mode 100644
index 984898100..000000000
--- a/libc/sysdeps/linux/m68k/sys/reg.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Copyright (C) 1998 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#ifndef _SYS_REG_H
-#define _SYS_REG_H 1
-
-/* Index into an array of 4 byte integers returned from ptrace for
- location of the users' stored general purpose registers. */
-
-enum
-{
- PT_D1 = 0,
-#define PT_D1 PT_D1
- PT_D2 = 1,
-#define PT_D2 PT_D2
- PT_D3 = 2,
-#define PT_D3 PT_D3
- PT_D4 = 3,
-#define PT_D4 PT_D4
- PT_D5 = 4,
-#define PT_D5 PT_D5
- PT_D6 = 5,
-#define PT_D6 PT_D6
- PT_D7 = 6,
-#define PT_D7 PT_D7
- PT_A0 = 7,
-#define PT_A0 PT_A0
- PT_A1 = 8,
-#define PT_A1 PT_A1
- PT_A2 = 9,
-#define PT_A2 PT_A2
- PT_A3 = 10,
-#define PT_A3 PT_A3
- PT_A4 = 11,
-#define PT_A4 PT_A4
- PT_A5 = 12,
-#define PT_A5 PT_A5
- PT_A6 = 13,
-#define PT_A6 PT_A6
- PT_D0 = 14,
-#define PT_D0 PT_D0
- PT_USP = 15,
-#define PT_USP PT_USP
- PT_ORIG_D0 = 16,
-#define PT_ORIG_D0 PT_ORIG_D0
- PT_SR = 17,
-#define PT_SR PT_SR
- PT_PC = 18,
-#define PT_PC PT_PC
- PT_FP0 = 21,
-#define PT_FP0 PT_FP0
- PT_FP1 = 24,
-#define PT_FP1 PT_FP1
- PT_FP2 = 27,
-#define PT_FP2 PT_FP2
- PT_FP3 = 30,
-#define PT_FP3 PT_FP3
- PT_FP4 = 33,
-#define PT_FP4 PT_FP4
- PT_FP5 = 36,
-#define PT_FP5 PT_FP5
- PT_FP6 = 39,
-#define PT_FP6 PT_FP6
- PT_FP7 = 42,
-#define PT_FP7 PT_FP7
- PT_FPCR = 45,
-#define PT_FPCR PT_FPCR
- PT_FPSR = 46,
-#define PT_FPSR PT_FPSR
- PT_FPIAR = 47
-#define PT_FPIAR PT_FPIAR
-};
-
-#endif /* _SYS_REG_H */
diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch b/libc/sysdeps/linux/xtensa/Makefile.arch
index 277a1e325..b9b6b87d5 100644
--- a/libc/sysdeps/linux/xtensa/Makefile.arch
+++ b/libc/sysdeps/linux/xtensa/Makefile.arch
@@ -5,7 +5,10 @@
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
#
-CSRC-y := brk.c fork.c sigaction.c __syscall_error.c
+CSRC-y := brk.c sigaction.c __syscall_error.c
SSRC-y := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S
+
+CSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += fork.c
+SSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += clone.S
diff --git a/libc/sysdeps/linux/xtensa/clone.S b/libc/sysdeps/linux/xtensa/clone.S
index aa79aa736..34d68a875 100644
--- a/libc/sysdeps/linux/xtensa/clone.S
+++ b/libc/sysdeps/linux/xtensa/clone.S
@@ -1,34 +1,38 @@
-/* Copyright (C) 2001, 2005, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2005 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
+ Library General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
/* clone is even more special than fork as it mucks with stacks
- and invokes a function in the right context after it's all over. */
+ and invokes a function in the right context after its all over. */
-#include "sysdep.h"
-#include <sys/syscall.h>
+#include <features.h>
+#include <sysdep.h>
#define _ERRNO_H 1
#include <bits/errno.h>
+#ifdef RESET_PID
+#include <tls.h>
+#endif
+#define __ASSEMBLY__
+#include <linux/sched.h>
-/* int clone (a2 = int (*fn)(void *arg),
- a3 = void *child_stack,
- a4 = int flags,
- a5 = void *arg,
- a6 = pid_t *ptid,
- a7 = struct user_desc *tls,
- 16(sp) = pid_t *ctid) */
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ a2 a3 a4 a5
+ pid_t *ptid, struct user_desc *tls, pid_t *ctid)
+ a6 a7 16(sp)
+*/
.text
ENTRY (__clone)
@@ -39,7 +43,7 @@ ENTRY (__clone)
/* a2 and a3 are candidates for destruction by system-call return
parameters. We don't need the stack pointer after the system
- call. We trust that the kernel will preserve a7, a9, and a6. */
+ call. We trust that the kernel will preserve a6, a7 and a9. */
mov a9, a5 /* save function argument */
mov a5, a7
@@ -48,19 +52,18 @@ ENTRY (__clone)
mov a6, a4
mov a4, a8
l32i a8, a1, 16 /* child_tid */
- movi a2, SYS_ify (clone)
-
- /* syscall (a2 = NR_clone,
- a6 = clone_flags,
- a3 = usp,
- a4 = parent_tid,
- a5 = child_tls,
- a8 = child_tid) */
+ movi a2, SYS_ify(clone)
+
+ /* syscall(NR_clone,clone_flags, usp, parent_tid, child_tls, child_tid)
+ a2 a6 a3 a4 a5 a8
+ */
+
syscall
bltz a2, SYSCALL_ERROR_LABEL
beqz a2, .Lthread_start
- /* Fall through for parent. */
+ /* fall through for parent */
+
.Lpseudo_end:
retw
@@ -69,32 +72,38 @@ ENTRY (__clone)
j SYSCALL_ERROR_LABEL
.Lthread_start:
- /* Start child thread. */
- movi a0, 0 /* terminate the stack frame */
+
+#if CLONE_THREAD != 0x00010000 || CLONE_VM != 0x00000100
+# error invalid values for CLONE_THREAD or CLONE_VM
+#endif
#ifdef RESET_PID
- /* Check and see if we need to reset the PID. */
- bbsi.l a6, 16, 1f /* CLONE_THREAD = 0x00010000 */
+ bbsi.l a6, 16, .Lskip_restore_pid /* CLONE_THREAD = 0x00010000 */
movi a2, -1
- bbsi.l a6, 8, 2f /* CLONE_VM = 0x00000100 */
- movi a2, SYS_ify (getpid)
+ bbsi a6, 8, .Lgotpid /* CLONE_VM = 0x00000100 */
+ movi a2, SYS_ify(getpid)
syscall
-2: rur a3, THREADPTR
- movi a4, PID_OFFSET
- add a4, a4, a3
- s32i a2, a4, 0
- movi a4, TID_OFFSET
- add a4, a4, a3
- s32i a2, a3, 0
-1:
-#endif /* RESET_PID */
-
+.Lgotpid:
+ rur a3, threadptr
+ movi a0, TLS_PRE_TCB_SIZE
+ sub a3, a3, a0
+ s32i a2, a3, PID
+ s32i a2, a3, TID
+.Lskip_restore_pid:
+#endif
+
+ /* start child thread */
+ movi a0, 0 /* terminate the stack frame */
mov a6, a9 /* load up the 'arg' parameter */
callx4 a7 /* call the user's function */
/* Call _exit. Note that any return parameter from the user's
- function in a6 is seen as inputs to _exit. */
- movi a2, JUMPTARGET(_exit)
+ function in a6 is seen as inputs to _exit. */
+#ifdef PIC
+ movi a2, _exit@PLT
+#else
+ movi a2, _exit
+#endif
callx4 a2
PSEUDO_END (__clone)
diff --git a/libc/sysdeps/linux/xtensa/fork.c b/libc/sysdeps/linux/xtensa/fork.c
index e9b681c67..4e4f937a0 100644
--- a/libc/sysdeps/linux/xtensa/fork.c
+++ b/libc/sysdeps/linux/xtensa/fork.c
@@ -20,6 +20,10 @@ pid_t fork(void)
{
return (pid_t) INLINE_SYSCALL(clone, 2, SIGCHLD, 0);
}
-lt_strong_alias(fork)
-lt_libc_hidden(fork)
+# ifdef __UCLIBC_HAS_THREADS__
+strong_alias(fork,__libc_fork)
+libc_hidden_weak(fork)
+# else
+libc_hidden_def(fork)
+# endif
#endif
diff --git a/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h b/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h
index 41f81dbad..4516d9398 100644
--- a/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h
+++ b/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h
@@ -1,25 +1,23 @@
-/* Copyright (C) 1997, 1998, 2007 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-/* Test if longjmp to JMPBUF would unwind the frame containing a local
- variable at ADDRESS. */
-
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
#include <setjmp.h>
#include <jmpbuf-offsets.h>
+/* Test if longjmp to JMPBUF would unwind the frame
+ containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address) \
((void *) (address) < (void *) (jmpbuf)[JB_SP])
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <stdint.h>
+#include <unwind.h>
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj))
+#endif
diff --git a/libc/sysdeps/linux/xtensa/sys/ptrace.h b/libc/sysdeps/linux/xtensa/sys/ptrace.h
new file mode 100644
index 000000000..882b8c8ed
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/sys/ptrace.h
@@ -0,0 +1,155 @@
+/* `ptrace' debugger support interface. Linux version.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_PTRACE_H
+#define _SYS_PTRACE_H 1
+
+#include <features.h>
+
+/* Kludge away careless namespace pollution from the kernel. */
+
+#undef PTRACE_GETREGS
+#undef PTRACE_SETREGS
+#undef PTRACE_GETFPREGS
+#undef PTRACE_SETFPREGS
+#undef PTRACE_GETFPREGSIZE
+
+
+__BEGIN_DECLS
+
+/* Type of the REQUEST argument to `ptrace.' */
+enum __ptrace_request
+{
+ /* Indicate that the process making this request should be traced.
+ All signals received by this process can be intercepted by its
+ parent, and its parent can use the other `ptrace' requests. */
+ PTRACE_TRACEME = 0,
+#define PT_TRACE_ME PTRACE_TRACEME
+
+ /* Return the word in the process's text space at address ADDR. */
+ PTRACE_PEEKTEXT = 1,
+#define PT_READ_I PTRACE_PEEKTEXT
+
+ /* Return the word in the process's data space at address ADDR. */
+ PTRACE_PEEKDATA = 2,
+#define PT_READ_D PTRACE_PEEKDATA
+
+ /* Return the word in the process's user area at offset ADDR. */
+ PTRACE_PEEKUSER = 3,
+#define PT_READ_U PTRACE_PEEKUSER
+
+ /* Write the word DATA into the process's text space at address ADDR. */
+ PTRACE_POKETEXT = 4,
+#define PT_WRITE_I PTRACE_POKETEXT
+
+ /* Write the word DATA into the process's data space at address ADDR. */
+ PTRACE_POKEDATA = 5,
+#define PT_WRITE_D PTRACE_POKEDATA
+
+ /* Write the word DATA into the process's user area at offset ADDR. */
+ PTRACE_POKEUSER = 6,
+#define PT_WRITE_U PTRACE_POKEUSER
+
+ /* Continue the process. */
+ PTRACE_CONT = 7,
+#define PT_CONTINUE PTRACE_CONT
+
+ /* Kill the process. */
+ PTRACE_KILL = 8,
+#define PT_KILL PTRACE_KILL
+
+ /* Single step the process.
+ This is not supported on all machines. */
+ PTRACE_SINGLESTEP = 9,
+#define PT_STEP PTRACE_SINGLESTEP
+
+ /* Get all general purpose registers used by a processes.
+ This is not supported on all machines. */
+ PTRACE_GETREGS = 12,
+#define PT_GETREGS PTRACE_GETREGS
+
+ /* Set all general purpose registers used by a processes.
+ This is not supported on all machines. */
+ PTRACE_SETREGS = 13,
+#define PT_SETREGS PTRACE_SETREGS
+
+ /* Get all floating point registers used by a processes.
+ This is not supported on all machines. */
+ PTRACE_GETFPREGS = 14,
+#define PT_GETFPREGS PTRACE_GETFPREGS
+
+ /* Set all floating point registers used by a processes.
+ This is not supported on all machines. */
+ PTRACE_SETFPREGS = 15,
+#define PT_SETFPREGS PTRACE_SETFPREGS
+
+ /* Attach to a process that is already running. */
+ PTRACE_ATTACH = 16,
+#define PT_ATTACH PTRACE_ATTACH
+
+ /* Detach from a process attached to with PTRACE_ATTACH. */
+ PTRACE_DETACH = 17,
+#define PT_DETACH PTRACE_DETACH
+
+ /* Get size required for the buffer holding the floating point registers.
+ This is not supported on all machines. */
+ PTRACE_GETFPREGSIZE = 18,
+#define PT_GETFPREGSIZE PTRACE_GETFPREGSIZE
+
+ /* Continue and stop at the next (return from) syscall. */
+ PTRACE_SYSCALL = 24
+#define PT_SYSCALL PTRACE_SYSCALL
+};
+
+/* Options set using PTRACE_SETOPTIONS. */
+enum __ptrace_setoptions {
+ PTRACE_O_TRACESYSGOOD = 0x00000001,
+ PTRACE_O_TRACEFORK = 0x00000002,
+ PTRACE_O_TRACEVFORK = 0x00000004,
+ PTRACE_O_TRACECLONE = 0x00000008,
+ PTRACE_O_TRACEEXEC = 0x00000010,
+ PTRACE_O_TRACEVFORKDONE = 0x00000020,
+ PTRACE_O_TRACEEXIT = 0x00000040,
+ PTRACE_O_MASK = 0x0000007f
+};
+
+/* Wait extended result codes for the above trace options. */
+enum __ptrace_eventcodes {
+ PTRACE_EVENT_FORK = 1,
+ PTRACE_EVENT_VFORK = 2,
+ PTRACE_EVENT_CLONE = 3,
+ PTRACE_EVENT_EXEC = 4,
+ PTRACE_EVENT_VFORK_DONE = 5,
+ PTRACE_EVENT_EXIT = 6
+};
+
+/* Perform process tracing functions. REQUEST is one of the values
+ above, and determines the action to be taken.
+ For all requests except PTRACE_TRACEME, PID specifies the process to be
+ traced.
+
+ PID and the other arguments described above for the various requests should
+ appear (those that are used for the particular request) as:
+ pid_t PID, void *ADDR, int DATA, void *ADDR2
+ after REQUEST. */
+extern long int ptrace (enum __ptrace_request __request, ...) __THROW;
+
+__END_DECLS
+
+#endif /* _SYS_PTRACE_H */
diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h
index afe95cc6a..cab4a2f8d 100644
--- a/libc/sysdeps/linux/xtensa/sysdep.h
+++ b/libc/sysdeps/linux/xtensa/sysdep.h
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#ifndef _LINUX_XTENSA_SYSDEP_H
+#define _LINUX_XTENSA_SYSDEP_H 1
+
+#include <common/sysdep.h>
#include <sys/syscall.h>
#ifdef __ASSEMBLER__
@@ -24,12 +28,6 @@
#define ASM_TYPE_DIRECTIVE(name, typearg) .type name, typearg
#define ASM_SIZE_DIRECTIVE(name) .size name, . - name
-#ifdef __STDC__
-#define C_LABEL(name) name :
-#else
-#define C_LABEL(name) name/**/:
-#endif
-
#define ENTRY(name) \
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function); \
@@ -52,6 +50,15 @@
#undef END
#define END(name) ASM_SIZE_DIRECTIVE(name)
+/* Local label name for asm code. */
+#ifndef L
+# ifdef HAVE_ELF
+# define L(name) .L##name
+# else
+# define L(name) name
+# endif
+#endif
+
/* Define a macro for this directive so it can be removed in a few places. */
#define LITERAL_POSITION .literal_position
@@ -123,19 +130,7 @@
#define PSEUDO_END_ERRVAL(name) \
END (name)
-#undef ret_ERRVAL
-#define ret_ERRVAL retw
-
-#if defined RTLD_PRIVATE_ERRNO
-# define SYSCALL_ERROR_HANDLER \
-0: movi a4, rtld_errno; \
- neg a2, a2; \
- s32i a2, a4, 0; \
- movi a2, -1; \
- j .Lpseudo_end;
-
-#elif defined _LIBC_REENTRANT
-
+#if defined _LIBC_REENTRANT
# if defined USE___THREAD
# ifndef NOT_IN_libc
# define SYSCALL_ERROR_ERRNO __libc_errno
@@ -170,3 +165,9 @@
#endif /* _LIBC_REENTRANT */
#endif /* __ASSEMBLER__ */
+
+/* Pointer mangling is not yet supported for Xtensa. */
+#define PTR_MANGLE(var) (void) (var)
+#define PTR_DEMANGLE(var) (void) (var)
+
+#endif /* _LINUX_XTENSA_SYSDEP_H */
diff --git a/libc/sysdeps/linux/xtensa/vfork.S b/libc/sysdeps/linux/xtensa/vfork.S
index f094ae38f..6aced0a50 100644
--- a/libc/sysdeps/linux/xtensa/vfork.S
+++ b/libc/sysdeps/linux/xtensa/vfork.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -19,72 +19,67 @@
#include <sys/syscall.h>
#define _SIGNAL_H
#include <bits/signum.h>
+#define __ASSEMBLY__
+#include <linux/sched.h>
-/* Clone the calling process, but without copying the whole address space.
+/*
+ Clone the calling process, but without copying the whole address space.
The calling process is suspended until the new process exits or is
replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
and the process ID of the new process to the old process.
Note that it is important that we don't create a new stack frame for the
- caller. */
+ caller.
-
-/* The following are defined in linux/sched.h, which unfortunately
- is not safe for inclusion in an assembly file. */
-#define CLONE_VM 0x00000100 /* set if VM shared between processes */
-#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to
- wake it up on mm_release */
+*/
#ifndef SAVE_PID
-#define SAVE_PID
+#define SAVE_PID(a,b,c,d)
#endif
-
#ifndef RESTORE_PID
-#define RESTORE_PID
+#define RESTORE_PID(a,b,c)
+#endif
+#ifndef RESTORE_PID12
+#define RESTORE_PID12(a,b,c)
#endif
+/*
+ pid_t vfork(void);
+ Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)
+ */
-/* pid_t vfork(void);
- Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */
HIDDEN_ENTRY (__vfork)
+ .literal .Ljumptable, 0, .L4, .L8, .L12
- movi a6, .Ljumptable
- extui a2, a0, 30, 2 /* call-size: call4/8/12 = 1/2/3 */
- addx4 a4, a2, a6 /* find return address in jumptable */
- l32i a4, a4, 0
- add a4, a4, a6
-
+ mov a3, a0 # move return address out of the way
+ movi a0, .Ljumptable
+ extui a2, a3, 30, 2 # call-size: call4/8/12 = 1/2/3
+ addx4 a0, a2, a0 # find return address in jumptable
slli a2, a2, 30
- xor a3, a0, a2 /* remove call-size from return addr */
- extui a5, a4, 30, 2 /* get high bits of jump target */
- slli a5, a5, 30
- or a3, a3, a5 /* stuff them into the return address */
- xor a4, a4, a5 /* clear high bits of jump target */
- or a0, a4, a2 /* create temporary return address */
- retw /* "return" to .L4, .L8, or .L12 */
-
- .align 4
-.Ljumptable:
- .word 0
- .word .L4 - .Ljumptable
- .word .L8 - .Ljumptable
- .word .L12 - .Ljumptable
+ l32i a0, a0, 0
+
+ xor a3, a3, a2 # remove call-size from return address
+ or a0, a0, a2 # create temporary return address
+ retw
/* a7: return address */
+
.L4: mov a12, a2
mov a13, a3
- SAVE_PID
+ SAVE_PID(a5,a15,a2,a3)
+
+ /* use syscall 'clone' and set new stack pointer to the same address */
- /* Use syscall 'clone'. Set new stack pointer to the same address. */
- movi a2, SYS_ify (clone)
+ movi a2, SYS_ify(clone)
movi a3, 0
movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD
+
syscall
- RESTORE_PID
+ RESTORE_PID(a5,a15,a2)
movi a5, -4096
@@ -94,22 +89,24 @@ HIDDEN_ENTRY (__vfork)
bgeu a6, a5, 1f
jx a7
-1: call4 .Lerr /* returns to original caller */
+1: call4 .Lerr
/* a11: return address */
+
.L8: mov a12, a2
mov a13, a3
mov a14, a6
- SAVE_PID
+ SAVE_PID(a9,a15,a2,a3)
- movi a2, SYS_ify (clone)
+ movi a2, SYS_ify(clone)
movi a3, 0
movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD
+
syscall
- RESTORE_PID
+ RESTORE_PID(a9,a15,a2)
movi a9, -4096
@@ -120,22 +117,25 @@ HIDDEN_ENTRY (__vfork)
bgeu a10, a9, 1f
jx a11
-1: call8 .Lerr /* returns to original caller */
+
+1: call8 .Lerr
/* a15: return address */
+
.L12: mov a12, a2
mov a13, a3
mov a14, a6
- SAVE_PID
+ SAVE_PID (a2,a3,a2,a6)
- movi a2, SYS_ify (clone)
+ movi a2, SYS_ify(clone)
movi a3, 0
movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD
+
syscall
- RESTORE_PID
+ RESTORE_PID12(a3,a6,a15)
mov a3, a13
movi a13, -4096
@@ -147,18 +147,18 @@ HIDDEN_ENTRY (__vfork)
bgeu a14, a13, 1f
jx a15
-1: call12 .Lerr /* returns to original caller */
+1: call12 .Lerr
.align 4
+
.Lerr: entry a1, 16
- /* Restore the return address. */
- extui a4, a0, 30, 2 /* get the call-size bits */
+ /* Restore return address */
+
+ extui a4, a0, 30, 2
slli a4, a4, 30
- slli a3, a3, 2 /* clear high bits of target address */
- srli a3, a3, 2
- or a0, a3, a4 /* combine them */
+ or a0, a3, a4
PSEUDO_END (__vfork)
.Lpseudo_end:
diff --git a/libc/unistd/daemon.c b/libc/unistd/daemon.c
index 435d4f1ff..8fa292850 100644
--- a/libc/unistd/daemon.c
+++ b/libc/unistd/daemon.c
@@ -69,7 +69,6 @@
/* use clone() to get fork() like behavior here -- we just want to disassociate
* from the controlling terminal
*/
-static inline attribute_optimize("O3")
pid_t _fork_parent(void)
{
INTERNAL_SYSCALL_DECL(err);