summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-01-31 15:49:34 +0000
committerEric Andersen <andersen@codepoet.org>2002-01-31 15:49:34 +0000
commit8dd9c51eb2f6c5dc659b426dc3bd114751adb405 (patch)
tree5eeeb11b1f38660340b91c83128cdb88cad6d65b
parent290b06002e9d168438c418c508e6ab5431b05b62 (diff)
Fixup setjmp and longjmp so they behave themselves properly now
on both x86 and arm... -Erik
-rw-r--r--libc/sysdeps/linux/arm/Makefile2
-rw-r--r--libc/sysdeps/linux/arm/__longjmp.S40
-rw-r--r--libc/sysdeps/linux/arm/bsd-_setjmp.S34
-rw-r--r--libc/sysdeps/linux/arm/bsd-setjmp.S34
-rw-r--r--libc/sysdeps/linux/arm/clone.S43
-rw-r--r--libc/sysdeps/linux/arm/longjmp.S45
-rw-r--r--libc/sysdeps/linux/arm/setjmp.S21
-rw-r--r--libc/sysdeps/linux/arm/vfork.S2
-rw-r--r--libc/sysdeps/linux/common/Makefile2
-rw-r--r--libc/sysdeps/linux/common/longjmp.c46
-rw-r--r--libc/sysdeps/linux/i386/Makefile2
-rw-r--r--libc/sysdeps/linux/i386/jmp-unwind.c29
-rw-r--r--libc/sysdeps/linux/i386/longjmp.c54
13 files changed, 199 insertions, 155 deletions
diff --git a/libc/sysdeps/linux/arm/Makefile b/libc/sysdeps/linux/arm/Makefile
index 9e826aa48..5651d6d7b 100644
--- a/libc/sysdeps/linux/arm/Makefile
+++ b/libc/sysdeps/linux/arm/Makefile
@@ -30,7 +30,7 @@ TARGET_MACHINE_TYPE=$(shell $(CC) -dumpmachine)
CRT0=crt0.S
CRT0_OBJ=crt0.o
-SSRC=longjmp.S setjmp.S vfork.S
+SSRC=__longjmp.S vfork.S clone.S setjmp.S bsd-setjmp.S bsd-_setjmp.S
SOBJS=$(patsubst %.S,%.o, $(SSRC))
CSRC=inout_bwl.c brk.c
diff --git a/libc/sysdeps/linux/arm/__longjmp.S b/libc/sysdeps/linux/arm/__longjmp.S
new file mode 100644
index 000000000..4c12a748c
--- /dev/null
+++ b/libc/sysdeps/linux/arm/__longjmp.S
@@ -0,0 +1,40 @@
+/* longjmp for ARM.
+ Copyright (C) 1997, 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <features.h>
+#define _SETJMP_H
+#define _ASM
+#include <bits/setjmp.h>
+
+
+.globl __longjmp;
+.type __longjmp,%function
+.align 4;
+__longjmp:
+ mov ip, r0 /* save jmp_buf pointer */
+
+ movs r0, r1 /* get the return value in place */
+ moveq r0, #1 /* can't let setjmp() return zero! */
+
+#ifdef __UCLIBC_HAS_FLOATS__
+ lfmfd f4, 4, [ip] ! /* load the floating point regs */
+#endif
+
+ ldmia ip , {v1-v6, sl, fp, sp, pc}
+.size __longjmp,.-__longjmp;
diff --git a/libc/sysdeps/linux/arm/bsd-_setjmp.S b/libc/sysdeps/linux/arm/bsd-_setjmp.S
new file mode 100644
index 000000000..7f092c18b
--- /dev/null
+++ b/libc/sysdeps/linux/arm/bsd-_setjmp.S
@@ -0,0 +1,34 @@
+/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. ARM version.
+ Copyright (C) 1997, 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+#define _SETJMP_H
+#define _ASM
+#include <bits/setjmp.h>
+
+.globl _setjmp;
+.type _setjmp,%function
+.align 4;
+_setjmp:
+ mov r1, #0
+ b __sigsetjmp (PLT)
+.size _setjmp,.-_setjmp;
diff --git a/libc/sysdeps/linux/arm/bsd-setjmp.S b/libc/sysdeps/linux/arm/bsd-setjmp.S
new file mode 100644
index 000000000..16f077a79
--- /dev/null
+++ b/libc/sysdeps/linux/arm/bsd-setjmp.S
@@ -0,0 +1,34 @@
+/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. ARM version.
+ Copyright (C) 1997, 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+#define _SETJMP_H
+#define _ASM
+#include <bits/setjmp.h>
+
+.globl setjmp;
+.type setjmp,%function
+.align 4;
+setjmp:
+ mov r1, #1
+ b __sigsetjmp (PLT)
+.size setjmp,.-setjmp;
diff --git a/libc/sysdeps/linux/arm/clone.S b/libc/sysdeps/linux/arm/clone.S
index c9a1ec23a..f417be07f 100644
--- a/libc/sysdeps/linux/arm/clone.S
+++ b/libc/sysdeps/linux/arm/clone.S
@@ -20,19 +20,21 @@
/* 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 1
-#include <bits/errno.h>
+#include <asm/errno.h>
+#include <sys/syscall.h>
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
- .text
-ENTRY(__clone)
+.text
+.globl __clone;
+.type __clone,%function
+.align 4;
+__clone:
@ sanity check args
cmp r0, #0
cmpne r1, #0
moveq r0, #-EINVAL
- beq PLTJMP(syscall_error)
+ beq __syscall_error (PLT)
@ insert the args onto the new stack
sub r1, r1, #8
@@ -44,10 +46,10 @@ ENTRY(__clone)
@ get flags
mov r0, r2
@ new sp is already in r1
- swi SYS_ify(clone)
+ swi __NR_clone
movs a1, a1
- blt PLTJMP(C_SYMBOL_NAME(__syscall_error))
- RETINSTR(movne, pc, lr)
+ blt __syscall_error (PLT)
+ movne pc, lr
@ pick the function arg and call address off the stack and execute
ldr r0, [sp, #4]
@@ -55,8 +57,25 @@ ENTRY(__clone)
ldr pc, [sp]
@ and we are done, passing the return value through r0
- b PLTJMP(_exit)
+ b _exit (PLT)
-PSEUDO_END (__clone)
+__syscall_error:
+ /* Looks like the syscall choked -- set errno */
+ ldr r3, .L4
+ /* Calculate the - of the syscall result, in case we need it */
+ rsb r2, r0, $0
+
+ /* errno = -result */
+ str r2, [r9,r3]
+
+ /* return -1 */
+ mvn r0, $0
+ mov pc, lr
+.size __clone,.-__clone;
+
+.L4: .word errno
+
+
+.globl clone;
+ clone = __clone
-weak_alias (__clone, clone)
diff --git a/libc/sysdeps/linux/arm/longjmp.S b/libc/sysdeps/linux/arm/longjmp.S
deleted file mode 100644
index c21758524..000000000
--- a/libc/sysdeps/linux/arm/longjmp.S
+++ /dev/null
@@ -1,45 +0,0 @@
-/* longjmp for ARM.
- Copyright (C) 1997, 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 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
- Library General Public License for more details.
-
- 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. */
-
-#define _SETJMP_H
-#define _ASM
-#include <bits/setjmp.h>
-
-/* __longjmp(jmpbuf, val) */
-
-.globl longjmp;
-.type longjmp,#function
-.align 4; \
-longjmp:
- mov ip, r0
- movs r0, r1 /* get the return value in place */
- moveq r0, #1 /* can't let setjmp() return zero! */
-
- ldmia ip,{v1-v6, sl, fp, sp, pc}
-.size longjmp,.-longjmp;
-
-.weak _longjmp;
- _longjmp = longjmp;
-
-.weak siglongjmp;
- siglongjmp = longjmp;
-
-.weak __sigprocmask;
- __sigprocmask = sigprocmask;
-
diff --git a/libc/sysdeps/linux/arm/setjmp.S b/libc/sysdeps/linux/arm/setjmp.S
index a993f8c59..166e4efab 100644
--- a/libc/sysdeps/linux/arm/setjmp.S
+++ b/libc/sysdeps/linux/arm/setjmp.S
@@ -17,25 +17,24 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include <features.h>
#define _SETJMP_H
#define _ASM
#include <bits/setjmp.h>
- /* Binary compatibility entry point. */
-.globl _setjmp;
-.type _setjmp,#function
-.align 4;
-_setjmp:
- mov r1, #0
-
-
.globl __sigsetjmp;
-.type __sigsetjmp,#function
+.type __sigsetjmp,%function
.align 4;
__sigsetjmp:
/* Save registers */
- stmia r0, {v1-v6, sl, fp, sp, lr}
+#ifdef __UCLIBC_HAS_FLOATS__
+ sfmea f4, 4, [r0]!
+#endif
+ stmia r0, {v1-v6, sl, fp, sp, lr}
+
+ /* Restore pointer to jmp_buf */
+ sub r0, r0, #48
/* Make a tail call to __sigjmp_save; it takes the same args. */
- B __sigjmp_save
+ B __sigjmp_save (PLT)
.size __sigsetjmp,.-__sigsetjmp;
diff --git a/libc/sysdeps/linux/arm/vfork.S b/libc/sysdeps/linux/arm/vfork.S
index ccf815f12..361153214 100644
--- a/libc/sysdeps/linux/arm/vfork.S
+++ b/libc/sysdeps/linux/arm/vfork.S
@@ -21,7 +21,7 @@
*/
#include <asm/errno.h>
-#include <asm/unistd.h>
+#include <sys/syscall.h>
.global errno;
diff --git a/libc/sysdeps/linux/common/Makefile b/libc/sysdeps/linux/common/Makefile
index d84648724..e4820e3f8 100644
--- a/libc/sysdeps/linux/common/Makefile
+++ b/libc/sysdeps/linux/common/Makefile
@@ -27,7 +27,7 @@ include $(TOPDIR)Rules.mak
CSRC= waitpid.c kernel_version.c statfix.c getdnnm.c gethstnm.c \
mkfifo.c setegid.c wait.c errno.c getpagesize.c seteuid.c \
wait3.c setpgrp.c getdtablesize.c create_module.c ptrace.c \
- cmsg_nxthdr.c open64.c statfix64.c statfs64.c
+ cmsg_nxthdr.c open64.c statfix64.c statfs64.c longjmp.c
ifneq ($(strip $(EXCLUDE_BRK)),true)
CSRC+=sbrk.c
endif
diff --git a/libc/sysdeps/linux/common/longjmp.c b/libc/sysdeps/linux/common/longjmp.c
new file mode 100644
index 000000000..95c7fef48
--- /dev/null
+++ b/libc/sysdeps/linux/common/longjmp.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 1991, 92, 94, 95, 97, 98, 2000 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stddef.h>
+#include <setjmp.h>
+#include <signal.h>
+
+
+/* Set the signal mask to the one specified in ENV, and jump
+ to the position specified in ENV, causing the setjmp
+ call there to return VAL, or 1 if VAL is 0. */
+void __libc_siglongjmp (sigjmp_buf env, int val)
+{
+#if 0
+ /* Perform any cleanups needed by the frames being unwound. */
+ _longjmp_unwind (env, val);
+#endif
+
+ if (env[0].__mask_was_saved)
+ /* Restore the saved signal mask. */
+ (void) sigprocmask (SIG_SETMASK, &env[0].__saved_mask,
+ (sigset_t *) NULL);
+
+ /* Call the machine-dependent function to restore machine state. */
+ __longjmp (env[0].__jmpbuf, val ?: 1);
+}
+
+strong_alias (__libc_siglongjmp, __libc_longjmp)
+weak_alias (__libc_siglongjmp, _longjmp)
+weak_alias (__libc_siglongjmp, longjmp)
+weak_alias (__libc_siglongjmp, siglongjmp)
diff --git a/libc/sysdeps/linux/i386/Makefile b/libc/sysdeps/linux/i386/Makefile
index 67dd89ebf..143162ccb 100644
--- a/libc/sysdeps/linux/i386/Makefile
+++ b/libc/sysdeps/linux/i386/Makefile
@@ -42,7 +42,7 @@ ifeq ($(UNIFIED_SYSCALL),true)
endif
SOBJS=$(patsubst %.S,%.o, $(SSRC))
-CSRC=brk.c longjmp.c #jmp-unwind.c
+CSRC=brk.c
COBJS=$(patsubst %.c,%.o, $(CSRC))
OBJS=$(SOBJS) $(COBJS)
diff --git a/libc/sysdeps/linux/i386/jmp-unwind.c b/libc/sysdeps/linux/i386/jmp-unwind.c
deleted file mode 100644
index 083dc74a8..000000000
--- a/libc/sysdeps/linux/i386/jmp-unwind.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* _longjmp_unwind -- Clean up stack frames unwound by longjmp. Stub version.
- Copyright (C) 1995, 1997 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 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
- Library General Public License for more details.
-
- 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. */
-
-#include <setjmp.h>
-
-void
-_longjmp_unwind (jmp_buf env, int val)
-{
-
- /* This function can perform any cleanups necessary to safely unwind the
- stack frames around the current context which ENV unwinds past. */
-
-}
diff --git a/libc/sysdeps/linux/i386/longjmp.c b/libc/sysdeps/linux/i386/longjmp.c
deleted file mode 100644
index 46e48f569..000000000
--- a/libc/sysdeps/linux/i386/longjmp.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright (C) 1991, 92, 94, 95, 97, 98 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 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
- Library General Public License for more details.
-
- 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. */
-
-#include <stddef.h>
-#include <setjmp.h>
-#define __USE_GNU
-#include <signal.h>
-
-
-#if 0
-extern void _longjmp_unwind (jmp_buf env, int val);
-#endif
-extern void __longjmp(__jmp_buf __env, int __val)
- __attribute__ ((__noreturn__));
-
-/* Set the signal mask to the one specified in ENV, and jump
- to the position specified in ENV, causing the setjmp
- call there to return VAL, or 1 if VAL is 0. */
-void
-__uClibc_siglongjmp (sigjmp_buf env, int val)
-{
-#if 0
- /* Perform any cleanups needed by the frames being unwound. */
- _longjmp_unwind (env, val);
-#endif
-
- if (env[0].__mask_was_saved)
- /* Restore the saved signal mask. */
- (void) sigprocmask (SIG_SETMASK, &env[0].__saved_mask,
- (sigset_t *) NULL);
-
- /* Call the machine-dependent function to restore machine state. */
- __longjmp (env[0].__jmpbuf, val ?: 1);
-}
-
-__asm__(".weak longjmp; longjmp = __uClibc_siglongjmp");
-__asm__(".weak _longjmp; _longjmp = __uClibc_siglongjmp");
-__asm__(".weak siglongjmp; siglongjmp = __uClibc_siglongjmp");
-__asm__(".weak __sigprocmask; __sigprocmask = sigprocmask");