From 8dd9c51eb2f6c5dc659b426dc3bd114751adb405 Mon Sep 17 00:00:00 2001
From: Eric Andersen <andersen@codepoet.org>
Date: Thu, 31 Jan 2002 15:49:34 +0000
Subject: Fixup setjmp and longjmp so they behave themselves properly now on
 both x86 and arm...  -Erik

---
 libc/sysdeps/linux/arm/Makefile      |  2 +-
 libc/sysdeps/linux/arm/__longjmp.S   | 40 ++++++++++++++++++++++++++
 libc/sysdeps/linux/arm/bsd-_setjmp.S | 34 +++++++++++++++++++++++
 libc/sysdeps/linux/arm/bsd-setjmp.S  | 34 +++++++++++++++++++++++
 libc/sysdeps/linux/arm/clone.S       | 43 ++++++++++++++++++++--------
 libc/sysdeps/linux/arm/longjmp.S     | 45 ------------------------------
 libc/sysdeps/linux/arm/setjmp.S      | 21 +++++++-------
 libc/sysdeps/linux/arm/vfork.S       |  2 +-
 libc/sysdeps/linux/common/Makefile   |  2 +-
 libc/sysdeps/linux/common/longjmp.c  | 46 ++++++++++++++++++++++++++++++
 libc/sysdeps/linux/i386/Makefile     |  2 +-
 libc/sysdeps/linux/i386/jmp-unwind.c | 29 -------------------
 libc/sysdeps/linux/i386/longjmp.c    | 54 ------------------------------------
 13 files changed, 199 insertions(+), 155 deletions(-)
 create mode 100644 libc/sysdeps/linux/arm/__longjmp.S
 create mode 100644 libc/sysdeps/linux/arm/bsd-_setjmp.S
 create mode 100644 libc/sysdeps/linux/arm/bsd-setjmp.S
 delete mode 100644 libc/sysdeps/linux/arm/longjmp.S
 create mode 100644 libc/sysdeps/linux/common/longjmp.c
 delete mode 100644 libc/sysdeps/linux/i386/jmp-unwind.c
 delete mode 100644 libc/sysdeps/linux/i386/longjmp.c

(limited to 'libc/sysdeps')

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");
-- 
cgit v1.2.3