summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2012-08-12 17:14:40 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2012-08-12 17:14:40 +0000
commit267d571a28d0ed97f7430c50e1314752e0ef0a61 (patch)
tree4799c702428926461fc9cde81a4e2b810bdd2ec6
parenta8126f65865211b447b89f67e4686a1860c66479 (diff)
Fix almost ten-years old bug in siglongjmp(), which would not restore a signal
mask of zero (because of flawed logic assuming finding zero in the sigjmp_buf signal mask means sigsetjmp was invoked with a zero `savemask' argument). While there, clean comments of all *{set,long}jmp routines, and shave a few instructions by using bcnd insead of cmp + bb to test for zero values. Passes the regress tests, and now devel/libsigsegv configure siglongjmp test will not spin (this test is however flawed as it expects a signal handler declared as running on the sigaltstack and `returning' through siglongjmp to be invoked on the signal stack the next time the signal is raised).
-rw-r--r--lib/libc/arch/m88k/gen/_setjmp.S35
-rw-r--r--lib/libc/arch/m88k/gen/setjmp.S35
-rw-r--r--lib/libc/arch/m88k/gen/sigsetjmp.S74
3 files changed, 57 insertions, 87 deletions
diff --git a/lib/libc/arch/m88k/gen/_setjmp.S b/lib/libc/arch/m88k/gen/_setjmp.S
index 616d0da9d9c..4e74b39fcb3 100644
--- a/lib/libc/arch/m88k/gen/_setjmp.S
+++ b/lib/libc/arch/m88k/gen/_setjmp.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: _setjmp.S,v 1.8 2005/08/07 16:40:14 espie Exp $ */
+/* $OpenBSD: _setjmp.S,v 1.9 2012/08/12 17:14:39 miod Exp $ */
/*-
* Copyright (c) 2002 Steve Murphree, Jr.
* All rights reserved.
@@ -35,26 +35,20 @@
* C library -- _setjmp, _longjmp
*
* _longjmp(a,v)
- * will generate a "return(v)" from
- * the last call to
+ * will generate a "return(v)" from the last call to
* _setjmp(a)
- * by restoring registers from the stack,
- * The previous signal state is NOT saved
- * or restored.
+ * by restoring registers from the stack. The previous signal state is
+ * neither saved nor restored.
*
- * For m88k, we define our jmp_buf length
- * to be the size of 21 longs. <machine/setjmp.h>
- * The buffer's usage is as follows:
+ * For m88k, we define our jmp_buf length to be the size of 21 (_JBLEN) longs.
+ * The buffer layout is as follows:
*
* jmp_buf[0] return address
- * jmp_buf[1] signal set (if used)
+ * jmp_buf[1] unused
* jmp_buf[2 to 19] r14 to r31
* jmp_buf[20] setjmp type
- *
*/
-#include <machine/setjmp.h>
-
#define U_SETJMP_SIG 0x1764
/*
@@ -62,7 +56,6 @@ int _setjmp(jmp_buf env);
*/
ENTRY(_setjmp)
st r1, r2,0 /* save registers to the environment buffer */
- st r0, r2,4 /* no signal set */
st r14,r2,8
st r15,r2,12
st r16,r2,16
@@ -81,18 +74,16 @@ ENTRY(_setjmp)
st r29,r2,68
st r30,r2,72
st r31,r2,76
- or r4,r0,0 /* clear r4 */
- or r4,r0,U_SETJMP_SIG /* r4 now contains setjmp type */
- st r4,r2,80 /* setjmp type to _setjmp */
- jmp.n r1 /* return 0 */
- or r2,r0,0
-
+ or r4,r0,U_SETJMP_SIG /* setjmp type to _setjmp */
+ st r4,r2,80
+ jmp.n r1
+ or r2,r0,0 /* return 0 */
+
/*
void _longjmp(jmp_buf env, int val);
*/
ENTRY(_longjmp)
- cmp r4,r2,r0 /* check for bad environment buffer address. */
- bb1 eq,r4,2f /* if == 0, abort. */
+ bcnd eq0,r2,2f /* check for bad environment buffer address. */
ld r4,r2,80 /* check setjmp type. */
cmp r4,r4,U_SETJMP_SIG /* should be U_SETJMP_SIG */
bb1 ne,r4,2f /* if != U_SETJMP_SIG, abort. */
diff --git a/lib/libc/arch/m88k/gen/setjmp.S b/lib/libc/arch/m88k/gen/setjmp.S
index 76bd978ddba..e5f145f57de 100644
--- a/lib/libc/arch/m88k/gen/setjmp.S
+++ b/lib/libc/arch/m88k/gen/setjmp.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: setjmp.S,v 1.9 2005/08/07 16:40:14 espie Exp $ */
+/* $OpenBSD: setjmp.S,v 1.10 2012/08/12 17:14:39 miod Exp $ */
/*-
* Copyright (c) 2002 Steve Murphree, Jr.
* All rights reserved.
@@ -35,25 +35,19 @@
* C library -- setjmp, longjmp
*
* longjmp(a,v)
- * will generate a "return(v)" from
- * the last call to
+ * will generate a "return(v)" from the last call to
* setjmp(a)
- * by restoring registers from the stack,
- * and a struct sigcontext, see <signal.h>
+ * by restoring registers from the stack, as well as the signal mask.
*
- * For m88k, we define our jmp_buf length
- * to be the size of 21 longs. <machine/setjmp.h>
- * The buffer's usage is as follows:
+ * For m88k, we define our jmp_buf length to be the size of 21 (_JBLEN) longs.
+ * The buffer layout is as follows:
*
* jmp_buf[0] return address
- * jmp_buf[1] signal set (if used)
+ * jmp_buf[1] signal set
* jmp_buf[2 to 19] r14 to r31
* jmp_buf[20] setjmp type
- *
*/
-#include <machine/setjmp.h>
-
#define SETJMP_SIG 0x5824
/*
@@ -79,16 +73,13 @@ ENTRY(setjmp)
st r29,r2,68
st r30,r2,72
st r31,r2,76
- or r4,r0,0 /* clear r4 */
or r4,r0,SETJMP_SIG /* r4 now contains setjmp type */
st r4,r2,80 /* setjmp type to _setjmp */
- or r15,r1,0 /* store return address in r15 */
or r14,r2,0 /* store address of env in r14 */
bsr.n _C_LABEL(sigblock) /* r2 = sigblock(0) */
or r2,r0,0
- or r1,r15,0
st r2,r14,4 /* save signal set in offset 4 of env */
- ld r15,r14,12
+ ld r1,r14,0
ld r14,r14,8
jmp.n r1 /* return 0 */
or r2,r0,0
@@ -97,13 +88,11 @@ ENTRY(setjmp)
void longjmp(jmp_buf env, int retval);
*/
ENTRY(longjmp)
- cmp r4,r2,r0 /* check for bad environment buffer address. */
- bb1 eq,r4,2f /* if == 0, abort. */
+ bcnd eq0,r2,2f /* check for bad environment buffer address. */
ld r4,r2,80 /* check setjmp type. */
cmp r4,r4,SETJMP_SIG /* should be SETJMP_SIG */
bb1 ne,r4,2f /* if != SETJMP_SIG, abort. */
- subu r31,r31,16 /* get a temporary stack */
ld r14,r2,8 /* restore registers from the environment buffer */
ld r15,r2,12
ld r16,r2,16
@@ -120,13 +109,15 @@ ENTRY(longjmp)
ld r27,r2,60
ld r28,r2,64
ld r29,r2,68
-
+ ld r30,r2,72
+ ld r31,r2,76
+
+ subu r31,r31,16 /* get a temporary stack */
st.d r2,r31,0 /* save r2 and r3 on stack (env + return val) */
bsr.n _C_LABEL(sigsetmask) /* restore the signal set */
ld r2,r2,4
ld.d r2,r31,0 /* restore r2 and r3 */
- ld r30,r2,72 /* restore r30 */
- ld r31,r2,76 /* restore r31 (sp)*/
+ addu r31,r31,16
ld r1,r2,0 /* restore r1 */
bcnd.n ne0,r3,1f
or r2,r3,r0
diff --git a/lib/libc/arch/m88k/gen/sigsetjmp.S b/lib/libc/arch/m88k/gen/sigsetjmp.S
index 93a3b9d8dbb..019e149a905 100644
--- a/lib/libc/arch/m88k/gen/sigsetjmp.S
+++ b/lib/libc/arch/m88k/gen/sigsetjmp.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: sigsetjmp.S,v 1.10 2005/08/07 16:40:14 espie Exp $ */
+/* $OpenBSD: sigsetjmp.S,v 1.11 2012/08/12 17:14:39 miod Exp $ */
/*-
* Copyright (c) 2002 Steve Murphree, Jr.
* All rights reserved.
@@ -35,29 +35,25 @@
* C library -- sigsetjmp, siglongjmp
*
* siglongjmp(a,v)
- * will generate a "return(v)" from
- * the last call to
- * sigsetjmp(a,m)
- * by restoring registers from the stack,
- * The previous signal state is restored if 'm' was non-zero.
+ * will generate a "return(v)" from the last call to
+ * sigsetjmp(a,savemask)
+ * by restoring registers from the stack, as well as the signal mask if the
+ * `savemask' parameter was non-zero.
*
- * For m88k, we define our jmp_buf length
- * to be the size of 21 longs. <machine/setjmp.h>
- * The buffer's usage is as follows:
- *
- * jmp_buf[0] return address
- * jmp_buf[1] signal set (if used)
- * jmp_buf[2 to 19] r14 to r31
- * jmp_buf[20] setjmp type
+ * For m88k, we define our sigjmp_buf length to be the size of 22 (_JBLEN + 1)
+ * longs. The buffer layout is as follows:
*
+ * sigjmp_buf[0] return address
+ * sigjmp_buf[1] signal set (if used)
+ * sigjmp_buf[2 to 19] r14 to r31
+ * sigjmp_buf[20] setjmp type
+ * sigjmp_buf[21] value of `savemask' parameter
*/
-#include <machine/setjmp.h>
-
#define SIGSETJMP_SIG 0x582e
/*
-int sigsetjmp(jmp_buf env, int savemask);
+int sigsetjmp(sigjmp_buf env, int savemask);
*/
ENTRY(sigsetjmp)
st r1, r2,0 /* save registers to the environment buffer */
@@ -79,25 +75,17 @@ ENTRY(sigsetjmp)
st r29,r2,68
st r30,r2,72
st r31,r2,76
- or r4,r0,0 /* clear r4 */
or r4,r0,SIGSETJMP_SIG /* r4 now contains setjmp type */
st r4,r2,80 /* setjmp type to _setjmp */
-
- or r15,r1,0 /* store return address in r15 */
+ bcnd.n eq0,r3,1f /* skip signal stuff if savemask == 0 */
+ st r3,r2,84 /* save `savemask' value */
or r14,r2,0 /* store address of env in r14 */
- or r13,r3,0 /* store savemask in r13 */
-
- cmp r11,r13,r0 /* see if sigmask == 0 */
- bb1.n eq,r11,1f /* skip sig stuff */
- st r0,r14,4 /* but save 0 set in offset 4 of env first */
-
bsr.n _C_LABEL(sigblock) /* r2 = sigblock(0) */
or r2,r0,r0
st r2,r14,4 /* save signal set in offset 4 of env */
-
-1: or r1,r15,0
- ld r15,r14,12
+ ld r1,r14,0
ld r14,r14,8
+1:
jmp.n r1 /* return 0 */
or r2,r0,0
@@ -105,13 +93,11 @@ ENTRY(sigsetjmp)
void siglongjmp(sigjmp_buf env, int val);
*/
ENTRY(siglongjmp)
- cmp r4,r2,r0 /* check for bad environment buffer address. */
- bb1 eq,r4,3f /* if == 0, abort. */
+ bcnd eq0,r2,2f /* check for bad environment buffer address. */
ld r4,r2,80 /* check setjmp type. */
cmp r4,r4,SIGSETJMP_SIG /* should be SIGSETJMP_SIG */
- bb1 ne,r4,3f /* if != SIGSETJMP_SIG, abort. */
+ bb1 ne,r4,2f /* if != SIGSETJMP_SIG, abort. */
- subu r31,r31,16 /* get a temporary stack */
ld r14,r2,8 /* restore registers from the environment buffer */
ld r15,r2,12
ld r16,r2,16
@@ -128,22 +114,24 @@ ENTRY(siglongjmp)
ld r27,r2,60
ld r28,r2,64
ld r29,r2,68
-
- ld r4,r2,4 /* get the signal set from env */
- cmp r4,r4,r0 /* if r2 == 0 then skip signal stuff */
- bb1 eq,r4,1f
+ ld r30,r2,72
+ ld r4,r2,84 /* get `savemask' value */
+ bcnd.n eq0,r4,1f
+ ld r31,r2,76
+ subu r31,r31,16 /* get a temporary stack */
st.d r2,r31,0 /* save r2 and r3 on stack (env + return val) */
bsr.n _C_LABEL(sigsetmask) /* restore the signal set */
ld r2,r2,4
ld.d r2,r31,0 /* restore r2 and r3 from stack */
-1: ld r30,r2,72 /* restore r30 */
- ld r31,r2,76 /* restore r31 (sp)*/
- ld r1,r2,0 /* restore r1 */
- bcnd.n ne0,r3,3f
+ addu r31,r31,16
+1:
+ bcnd.n ne0,r3,1f
+ ld r1,r2,0 /* restore r1 */
+ or r3,r0,1 /* never return zero! */
+1:
+ jmp.n r1
or r2,r3,r0
- or r2,r0,1 /* never return zero! */
-3: jmp r1
2: subu r31,r31,16 /* get a temporary stack */
st r1,r31,0 /* save r1 on stack (return address) */