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
This commit is contained in:
parent
df443a3d17
commit
3e7604f627
|
@ -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 signal mask. */
|
||||
movl 4(%esp),%ecx
|
||||
leal 24(%ecx),%edx
|
||||
|
||||
PIC_PROLOGUE
|
||||
pushl $0
|
||||
pushl %edx
|
||||
pushl $3 /* SIG_SETMASK */
|
||||
#ifdef __PIC__
|
||||
call PIC_PLT(_C_LABEL(__sigprocmask14))
|
||||
#else
|
||||
call _C_LABEL(__sigprocmask14)
|
||||
#endif
|
||||
addl $12,%esp
|
||||
PIC_EPILOGUE
|
||||
|
||||
movl 4(%esp),%edx
|
||||
movl 8(%esp),%eax
|
||||
movl 0(%edx),%ecx
|
||||
/*
|
||||
* 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
|
||||
testl %eax,%eax
|
||||
jnz 1f
|
||||
incl %eax
|
||||
1: movl %ecx,0(%esp)
|
||||
ret
|
||||
movl %ecx,0(%esp) /* restore return address */
|
||||
|
||||
/* Restore the signal mask. */
|
||||
leal 24(%edx),%edx
|
||||
|
||||
pushl %eax /* save val@eax */
|
||||
|
||||
PIC_PROLOGUE
|
||||
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 /* pop sigprocmask args */
|
||||
PIC_EPILOGUE
|
||||
|
||||
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)
|
||||
|
|
|
@ -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)
|
||||
/* Check to see if we need to restore the signal mask. */
|
||||
movl 4(%esp),%ecx
|
||||
cmpl $0,40(%ecx)
|
||||
jz 2f /* no, skip */
|
||||
|
||||
/* Restore the signal mask. */
|
||||
leal 24(%ecx),%edx
|
||||
|
||||
PIC_PROLOGUE
|
||||
pushl $0
|
||||
pushl %edx
|
||||
pushl $3 /* SIG_SETMASK */
|
||||
#ifdef __PIC__
|
||||
call PIC_PLT(_C_LABEL(__sigprocmask14))
|
||||
#else
|
||||
call _C_LABEL(__sigprocmask14)
|
||||
#endif
|
||||
addl $12,%esp
|
||||
PIC_EPILOGUE
|
||||
|
||||
2: movl 4(%esp),%edx
|
||||
movl 8(%esp),%eax
|
||||
movl 0(%edx),%ecx
|
||||
/*
|
||||
* 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
|
||||
testl %eax,%eax
|
||||
jnz 3f
|
||||
incl %eax
|
||||
3: movl %ecx,0(%esp)
|
||||
ret
|
||||
movl %ecx,0(%esp) /* restore return address */
|
||||
|
||||
/* Check to see if we need to restore the signal mask. */
|
||||
cmpl $0,40(%edx) /* savemask == 0 */
|
||||
jz 2f /* jump if savemask == 0 */
|
||||
|
||||
/* Restore the signal mask. */
|
||||
leal 24(%edx),%edx
|
||||
|
||||
pushl %eax /* save val@eax */
|
||||
|
||||
PIC_PROLOGUE
|
||||
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 /* pop sigprocmask args */
|
||||
PIC_EPILOGUE
|
||||
|
||||
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)
|
||||
|
|
|
@ -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, void *ctx)
|
|||
* 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)
|
||||
|
|
Loading…
Reference in New Issue