Module Name: src
Committed By: riastradh
Date: Thu Apr 4 00:46:42 UTC 2024
Modified Files:
src/lib/libc/arch/i386/gen: setjmp.S sigsetjmp.S
src/tests/lib/libc/setjmp: t_sigstack.c
Log Message:
i386 longjmp: Restore stack first, then signal mask.
Otherwise, a pending signal may be delivered on the wrong stack when
we restore the signal mask.
While here:
- Tidy the code a little bit.
- Sprinkle comments to explain what's going on.
- Use forward branches for statically predicted not-taken.
=> val==0 is unlikely in longjmp
PR lib/57946
To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.18 src/lib/libc/arch/i386/gen/setjmp.S
cvs rdiff -u -r1.18 -r1.19 src/lib/libc/arch/i386/gen/sigsetjmp.S
cvs rdiff -u -r1.8 -r1.9 src/tests/lib/libc/setjmp/t_sigstack.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libc/arch/i386/gen/setjmp.S
diff -u src/lib/libc/arch/i386/gen/setjmp.S:1.17 src/lib/libc/arch/i386/gen/setjmp.S:1.18
--- src/lib/libc/arch/i386/gen/setjmp.S:1.17 Fri May 23 03:05:56 2014
+++ src/lib/libc/arch/i386/gen/setjmp.S Thu Apr 4 00:46:41 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: setjmp.S,v 1.17 2014/05/23 03:05:56 uebayasi Exp $ */
+/* $NetBSD: setjmp.S,v 1.18 2024/04/04 00:46:41 riastradh Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,7 +36,7 @@
#include <machine/asm.h>
#if defined(LIBC_SCCS)
- RCSID("$NetBSD: setjmp.S,v 1.17 2014/05/23 03:05:56 uebayasi Exp $")
+ RCSID("$NetBSD: setjmp.S,v 1.18 2024/04/04 00:46:41 riastradh Exp $")
#endif
/*
@@ -49,12 +49,24 @@
* The previous signal state is restored.
*/
+/*
+ * setjmp(jmp_buf env@esp[4,8))
+ *
+ * ELF symbol: __setjmp14, because the size of jmp_buf changed on some
+ * platforms in 1.4.
+ */
ENTRY(__setjmp14)
- movl 4(%esp),%ecx
- movl 0(%esp),%edx
- movl %edx, 0(%ecx)
- movl %ebx, 4(%ecx)
- movl %esp, 8(%ecx)
+ /*
+ * Save the callee-saves registers: %ebp, %ebx, %edi, %esi,
+ * plus %esp and the return address on the stack since it
+ * will be overwritten if the caller makes any subroutine
+ * calls before longjmp.
+ */
+ movl 4(%esp),%ecx /* ecx := env */
+ movl 0(%esp),%edx /* edx := return address */
+ movl %edx,0(%ecx)
+ movl %ebx,4(%ecx)
+ movl %esp,8(%ecx)
movl %ebp,12(%ecx)
movl %esi,16(%ecx)
movl %edi,20(%ecx)
@@ -63,49 +75,65 @@ ENTRY(__setjmp14)
leal 24(%ecx),%edx
PIC_PROLOGUE
- pushl %edx
- pushl $0
- pushl $0
+ pushl %edx /* oset (signal mask saved to) */
+ pushl $0 /* set := NULL */
+ pushl $0 /* how := 0 (ignored) */
#ifdef __PIC__
call PIC_PLT(_C_LABEL(__sigprocmask14))
#else
call _C_LABEL(__sigprocmask14)
#endif
- addl $12,%esp
+ addl $12,%esp /* pop sigprocmask args */
PIC_EPILOGUE
- xorl %eax,%eax
+ xorl %eax,%eax /* return 0 first time around */
ret
END(__setjmp14)
+/*
+ * longjmp(jmp_buf env@esp[4,8), int val@[8,12))
+ *
+ * ELF symbol: __longjmp14, because the size of jmp_buf changed on some
+ * platforms in 1.4.
+ */
ENTRY(__longjmp14)
+ /*
+ * Restore the callee-saves registers: %ebp, %ebx, %edi, %esi,
+ * plus %esp and the return address on the stack.
+ */
+ movl 4(%esp),%edx /* edx := env */
+ movl 8(%esp),%eax /* eax := val */
+ movl 0(%edx),%ecx /* ecx := return address */
+ movl 4(%edx),%ebx
+ movl 8(%edx),%esp
+ movl 12(%edx),%ebp
+ movl 16(%edx),%esi
+ movl 20(%edx),%edi
+ movl %ecx,0(%esp) /* restore return address */
+
/* Restore the signal mask. */
- movl 4(%esp),%ecx
- leal 24(%ecx),%edx
+ leal 24(%edx),%edx
+
+ pushl %eax /* save val@eax */
PIC_PROLOGUE
- pushl $0
- pushl %edx
- pushl $3 /* SIG_SETMASK */
+ pushl $0 /* oset := NULL */
+ pushl %edx /* set (signal mask restored from) */
+ pushl $3 /* how := SIG_SETMASK */
#ifdef __PIC__
call PIC_PLT(_C_LABEL(__sigprocmask14))
#else
call _C_LABEL(__sigprocmask14)
#endif
- addl $12,%esp
+ addl $12,%esp /* pop sigprocmask args */
PIC_EPILOGUE
- movl 4(%esp),%edx
- movl 8(%esp),%eax
- movl 0(%edx),%ecx
- movl 4(%edx),%ebx
- movl 8(%edx),%esp
- movl 12(%edx),%ebp
- movl 16(%edx),%esi
- movl 20(%edx),%edi
- testl %eax,%eax
- jnz 1f
- incl %eax
-1: movl %ecx,0(%esp)
- ret
+ popl %eax /* restore val@eax */
+
+ testl %eax,%eax /* val == 0? */
+ jz 3f /* jump if val == 0 */
+ ret /* return val@eax */
+
+3: incl %eax /* val@eax := 1 */
+ ret /* return val@eax */
END(__longjmp14)
Index: src/lib/libc/arch/i386/gen/sigsetjmp.S
diff -u src/lib/libc/arch/i386/gen/sigsetjmp.S:1.18 src/lib/libc/arch/i386/gen/sigsetjmp.S:1.19
--- src/lib/libc/arch/i386/gen/sigsetjmp.S:1.18 Fri May 23 02:34:19 2014
+++ src/lib/libc/arch/i386/gen/sigsetjmp.S Thu Apr 4 00:46:41 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: sigsetjmp.S,v 1.18 2014/05/23 02:34:19 uebayasi Exp $ */
+/* $NetBSD: sigsetjmp.S,v 1.19 2024/04/04 00:46:41 riastradh Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,76 +36,104 @@
#include <machine/asm.h>
#if defined(LIBC_SCCS)
- RCSID("$NetBSD: sigsetjmp.S,v 1.18 2014/05/23 02:34:19 uebayasi Exp $")
+ RCSID("$NetBSD: sigsetjmp.S,v 1.19 2024/04/04 00:46:41 riastradh Exp $")
#endif
+/*
+ * sigsetjmp(sigjmp_buf env@esp[4,8), savemask@esp[8,12))
+ *
+ * ELF symbol: __sigsetjmp14, because the size of sigjmp_buf changed on
+ * some platforms in 1.4.
+ */
ENTRY(__sigsetjmp14)
- movl 4(%esp),%ecx
- movl 0(%esp),%edx
- movl %edx, 0(%ecx)
- movl %ebx, 4(%ecx)
- movl %esp, 8(%ecx)
+ /*
+ * Save the callee-saves registers: %ebp, %ebx, %edi, %esi,
+ * plus %esp and the return address on the stack since it
+ * will be overwritten if the caller makes any subroutine
+ * calls before siglongjmp.
+ */
+ movl 4(%esp),%ecx /* ecx := env */
+ movl 0(%esp),%edx /* edx := return address */
+ movl %edx,0(%ecx)
+ movl %ebx,4(%ecx)
+ movl %esp,8(%ecx)
movl %ebp,12(%ecx)
movl %esi,16(%ecx)
movl %edi,20(%ecx)
/* Check if we should save the signal mask, and remember it. */
- movl 8(%esp),%eax
+ movl 8(%esp),%eax /* eax := savemask */
movl %eax,40(%ecx)
- testl %eax,%eax
- jz 2f /* no, skip */
+ testl %eax,%eax /* savemask == 0? */
+ jz 2f /* jump if savemask == 0 */
/* Get the signal mask. */
leal 24(%ecx),%edx
PIC_PROLOGUE
- pushl %edx
- pushl $0
- pushl $0
+ pushl %edx /* oset (signal mask saved to) */
+ pushl $0 /* set := NULL */
+ pushl $0 /* how := 0 (ignored) */
#ifdef __PIC__
call PIC_PLT(_C_LABEL(__sigprocmask14))
#else
call _C_LABEL(__sigprocmask14)
#endif
- addl $12,%esp
+ addl $12,%esp /* pop sigprocmask args */
PIC_EPILOGUE
-2: xorl %eax,%eax
+2: xorl %eax,%eax /* return 0 first time around */
ret
END(__sigsetjmp14)
+/*
+ * siglongjmp(sigjmp_buf env@esp[4,8), int val@[8,12))
+ *
+ * ELF symbol: __siglongjmp14, because the size of sigjmp_buf changed
+ * on some platforms in 1.4.
+ */
ENTRY(__siglongjmp14)
+ /*
+ * Restore the callee-saves registers: %ebp, %ebx, %edi, %esi,
+ * plus %esp and the return address on the stack.
+ */
+ movl 4(%esp),%edx /* edx := env */
+ movl 8(%esp),%eax /* eax := val */
+ movl 0(%edx),%ecx /* ecx := return address */
+ movl 4(%edx),%ebx
+ movl 8(%edx),%esp
+ movl 12(%edx),%ebp
+ movl 16(%edx),%esi
+ movl 20(%edx),%edi
+ movl %ecx,0(%esp) /* restore return address */
+
/* Check to see if we need to restore the signal mask. */
- movl 4(%esp),%ecx
- cmpl $0,40(%ecx)
- jz 2f /* no, skip */
+ cmpl $0,40(%edx) /* savemask == 0 */
+ jz 2f /* jump if savemask == 0 */
/* Restore the signal mask. */
- leal 24(%ecx),%edx
+ leal 24(%edx),%edx
+
+ pushl %eax /* save val@eax */
PIC_PROLOGUE
- pushl $0
- pushl %edx
- pushl $3 /* SIG_SETMASK */
+ pushl $0 /* oset := NULL */
+ pushl %edx /* set (signal mask restored from) */
+ pushl $3 /* how := SIG_SETMASK */
#ifdef __PIC__
call PIC_PLT(_C_LABEL(__sigprocmask14))
#else
call _C_LABEL(__sigprocmask14)
#endif
- addl $12,%esp
+ addl $12,%esp /* pop sigprocmask args */
PIC_EPILOGUE
-2: movl 4(%esp),%edx
- movl 8(%esp),%eax
- movl 0(%edx),%ecx
- movl 4(%edx),%ebx
- movl 8(%edx),%esp
- movl 12(%edx),%ebp
- movl 16(%edx),%esi
- movl 20(%edx),%edi
- testl %eax,%eax
- jnz 3f
- incl %eax
-3: movl %ecx,0(%esp)
- ret
+ popl %eax /* restore val@eax */
+
+2: testl %eax,%eax /* val == 0? */
+ jz 3f /* jump if val == 0 */
+ ret /* return val@eax */
+
+3: incl %eax /* val@eax := 1 */
+ ret /* return val@eax */
END(__siglongjmp14)
Index: src/tests/lib/libc/setjmp/t_sigstack.c
diff -u src/tests/lib/libc/setjmp/t_sigstack.c:1.8 src/tests/lib/libc/setjmp/t_sigstack.c:1.9
--- src/tests/lib/libc/setjmp/t_sigstack.c:1.8 Thu Apr 4 00:46:30 2024
+++ src/tests/lib/libc/setjmp/t_sigstack.c Thu Apr 4 00:46:42 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: t_sigstack.c,v 1.8 2024/04/04 00:46:30 riastradh Exp $ */
+/* $NetBSD: t_sigstack.c,v 1.9 2024/04/04 00:46:42 riastradh Exp $ */
/*-
* Copyright (c) 2024 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: t_sigstack.c,v 1.8 2024/04/04 00:46:30 riastradh Exp $");
+__RCSID("$NetBSD: t_sigstack.c,v 1.9 2024/04/04 00:46:42 riastradh Exp $");
#include <setjmp.h>
#include <signal.h>
@@ -81,10 +81,18 @@ on_sigusr1(int signo, siginfo_t *si, voi
* On some architectures, this is broken. Those that appear to
* get this right are:
*
- * aarch64, alpha, m68k, or1k, powerpc, powerpc64, riscv,
- * vax, x86_64
+ * aarch64
+ * alpha
+ * i386
+ * m68k
+ * or1k
+ * powerpc
+ * powerpc64
+ * riscv
+ * vax
+ * x86_64
*/
-#if defined __arm__ || defined __hppa__ || defined __i386__ || \
+#if defined __arm__ || defined __hppa__ || \
defined __ia64__ || defined __mips__ || defined __sh3__ || \
defined __sparc__ || defined __sparc64__
if (nentries > 0)