diff options
Diffstat (limited to 'libc')
-rw-r--r-- | libc/stdlib/system.c | 3 | ||||
-rw-r--r-- | libc/sysdeps/linux/arm/clone.S | 61 | ||||
-rw-r--r-- | libc/sysdeps/linux/arm/sysdep.h | 36 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/Makefile.in | 2 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/bits/mathcalls.h | 18 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/eventfd_read.c | 27 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/eventfd_write.c | 28 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/sys/eventfd.h | 4 | ||||
-rw-r--r-- | libc/sysdeps/linux/cris/sys/procfs.h | 6 | ||||
-rw-r--r-- | libc/sysdeps/linux/cris/sysdep.S | 2 | ||||
-rw-r--r-- | libc/sysdeps/linux/m68k/sys/reg.h | 88 | ||||
-rw-r--r-- | libc/sysdeps/linux/xtensa/Makefile.arch | 5 | ||||
-rw-r--r-- | libc/sysdeps/linux/xtensa/clone.S | 101 | ||||
-rw-r--r-- | libc/sysdeps/linux/xtensa/fork.c | 8 | ||||
-rw-r--r-- | libc/sysdeps/linux/xtensa/jmpbuf-unwind.h | 38 | ||||
-rw-r--r-- | libc/sysdeps/linux/xtensa/sys/ptrace.h | 155 | ||||
-rw-r--r-- | libc/sysdeps/linux/xtensa/sysdep.h | 39 | ||||
-rw-r--r-- | libc/sysdeps/linux/xtensa/vfork.S | 104 | ||||
-rw-r--r-- | libc/unistd/daemon.c | 1 |
19 files changed, 474 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/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); |