summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2004-05-04 15:57:07 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2004-05-04 15:57:07 +0000
commit6ad82160203c4fca197d07d09d81c1e625169875 (patch)
tree7984d0cb851ffd4d739922c29b323a412d6cc795 /lib/libc
parentb9eb02a88d66a896d3db2744fcf33d9409b6762e (diff)
In _longjmp(), flush windows rather than attempting to backtrack manually,
since the latter is not reliable in all cases. This allows ruby to work on sparc64. Problem spotted by claudio@; fix adapted from NetBSD for sparc, FreeBSD for sparc64; ok deraadt@
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/arch/sparc/gen/_setjmp.S47
-rw-r--r--lib/libc/arch/sparc64/gen/_setjmp.S47
2 files changed, 35 insertions, 59 deletions
diff --git a/lib/libc/arch/sparc/gen/_setjmp.S b/lib/libc/arch/sparc/gen/_setjmp.S
index 487970b0c4d..3c6f3d05883 100644
--- a/lib/libc/arch/sparc/gen/_setjmp.S
+++ b/lib/libc/arch/sparc/gen/_setjmp.S
@@ -34,7 +34,7 @@
#if defined(LIBC_SCCS)
.text
- .asciz "$OpenBSD: _setjmp.S,v 1.5 2003/06/02 20:18:32 millert Exp $"
+ .asciz "$OpenBSD: _setjmp.S,v 1.6 2004/05/04 15:57:04 miod Exp $"
#endif /* LIBC_SCCS */
/*
@@ -44,44 +44,35 @@
* will generate a "return(v?v:1)" from
* the last call to
* _setjmp(a)
- * by unwinding the call stack.
+ * by restoring the previous context.
* The previous signal state is NOT restored.
*/
#include "DEFS.h"
+#include <machine/trap.h> /* T_FLUSHWIN */
+#define CCFSZ 96 /* from locore.S */
ENTRY(_setjmp)
- st %sp, [%o0+0] /* store caller's stack pointer */
- st %o7, [%o0+4] /* ... return pc */
- st %fp, [%o0+8] /* ... and frame pointer */
+ st %sp, [%o0 + 0] /* store caller's stack pointer */
+ st %o7, [%o0 + 4] /* ... and return pc */
retl
clr %o0 ! return 0
ENTRY(_longjmp)
- addcc %o1, %g0, %g6 ! compute v ? v : 1 in a global register
+ sub %sp, CCFSZ, %sp ! set up a local stack frame
+ tst %o1 ! compute v ? v : 1
be,a 0f
- mov 1, %g6
+ mov 1, %o1
0:
- mov %o0, %g1 ! save a in another global register
- ld [%g1+8], %g7 /* get caller's frame */
-1:
- cmp %fp, %g7 ! compare against desired frame
- bl,a 1b ! if below,
- restore ! pop frame and loop
- be,a 2f ! if there,
- ld [%g1+0], %o2 ! fetch return %sp
+ t ST_FLUSHWIN ! flush register windows out to the stack
-Lbotch:
- call _C_LABEL(longjmperror) ! otherwise, went too far; bomb out
- nop
- unimp 0
+ /*
+ * We restore the saved stack pointer to %fp, then issue
+ * a `restore' instruction which will reload the register
+ * window from the stack.
+ */
+ ld [%o0 + 4], %o7 /* restore return pc */
+ ld [%o0 + 0], %fp /* and stack pointer */
-2:
- cmp %o2, %sp ! %sp must not decrease
- bge,a 3f
- mov %o2, %sp ! it is OK, put it in place
- b,a Lbotch
-3:
- ld [%g1+4], %o3 ! fetch pc
- jmp %o3 + 8 ! success, return %g6
- mov %g6, %o0
+ retl ! success, return %g6
+ restore %o1, 0, %o0
diff --git a/lib/libc/arch/sparc64/gen/_setjmp.S b/lib/libc/arch/sparc64/gen/_setjmp.S
index f5fd46b3ccb..ea43264ea98 100644
--- a/lib/libc/arch/sparc64/gen/_setjmp.S
+++ b/lib/libc/arch/sparc64/gen/_setjmp.S
@@ -1,3 +1,4 @@
+/* $OpenBSD: _setjmp.S,v 1.3 2004/05/04 15:57:06 miod Exp $ */
/* $NetBSD: _setjmp.S,v 1.4 1998/10/08 02:27:59 eeh Exp $ */
/*
@@ -35,6 +36,9 @@
#include <machine/asm.h>
+ .register %g2,#ignore
+ .register %g3,#ignore
+
/*
* C library -- _setjmp, _longjmp
*
@@ -42,41 +46,22 @@
* will generate a "return(v?v:1)" from
* the last call to
* _setjmp(a)
- * by unwinding the call stack.
+ * by restoring the previous context.
* The previous signal state is NOT restored.
*/
ENTRY(_setjmp)
- stx %sp, [%o0+0x00] /* store caller's stack pointer */
- stx %o7, [%o0+0x08] /* ... return pc */
- stx %fp, [%o0+0x10] /* ... and frame pointer */
+ stx %sp, [%o0 + 0x00] /* store caller's stack pointer */
+ stx %o7, [%o0 + 0x08] /* ... and return pc */
retl
- clr %o0 ! return 0
+ clr %o0 ! return 0
ENTRY(_longjmp)
- mov 1, %g6
- movrnz %o1, %o1, %g6 ! compute v ? v : 1 in a global register
- mov %o0, %g1 ! save a in another global register
- ldx [%g1+0x10], %g7 /* get caller's frame */
-1:
- cmp %fp, %g7 ! compare against desired frame
- bl,a 1b ! if below,
- restore ! pop frame and loop
- be,a 2f ! if there,
- ldx [%g1+0], %o2 ! fetch return %sp
-
-Lbotch:
- call _C_LABEL(longjmperror) ! otherwise, went too far; bomb out
- nop
- unimp 0
-
-2:
- cmp %o2, %sp ! %sp must not decrease
- bge,a 3f
- mov %o2, %sp ! it is OK, put it in place
- b,a Lbotch
-3:
- ldx [%g1+0x8], %o3 ! fetch pc
- jmp %o3 + 8 ! success, return %g6
- mov %g6, %o0
-
+ save %sp, -CC64FSZ, %sp
+ flushw
+ ldx [%i0 + 0x00], %fp
+ ldx [%i0 + 0x08], %i7
+ mov 1, %i0
+ movrnz %i1, %i1, %i0 ! compute v ? v : 1
+ ret
+ restore