Fix offsets used in the assembly code to save global registers into a

jmp_buf, add a compile time assert to catch this kind of divergence
in the C code.
Move the fixed "%npc = %pc + 4" computation to longjmp, this frees
the sigcontext sc_npc value. Use this space to save the savemask
for siglongjmp (we have run out of space behind the globals).
Fixes the tests/lib/libc/setjmp/t_threadjmp tests, and also hopefully
fixes PR port-sparc64/44902.
This commit is contained in:
martin 2011-04-27 21:08:48 +00:00
parent fe857470e2
commit d21307a5d2
3 changed files with 31 additions and 19 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: longjmp.c,v 1.2 2008/04/28 20:22:57 martin Exp $ */
/* $NetBSD: longjmp.c,v 1.3 2011/04/27 21:08:48 martin Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -36,6 +36,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>
#define __LIBC12_SOURCE__
#include <setjmp.h>
@ -45,6 +46,13 @@ typedef struct {
__greg_t __glob[5];
} __jmp_buf_regs_t;
/*
* setjmp.S uses hard coded offsets into the jump_buf,
* make sure any changes cause a compile failure here
*/
__CTASSERT(0x68 == offsetof(__jmp_buf_regs_t,__glob[4])+
sizeof(struct sigcontext));
void
__longjmp14(jmp_buf env, int val)
{
@ -72,7 +80,7 @@ __longjmp14(jmp_buf env, int val)
/* Fill other registers */
uc.uc_mcontext.__gregs[_REG_CCR] = sc->sc_tstate;
uc.uc_mcontext.__gregs[_REG_PC] = sc->sc_pc;
uc.uc_mcontext.__gregs[_REG_nPC] = sc->sc_npc;
uc.uc_mcontext.__gregs[_REG_nPC] = sc->sc_pc+4;
uc.uc_mcontext.__gregs[_REG_G1] = sc->sc_g1;
uc.uc_mcontext.__gregs[_REG_G2] = sc->sc_o0;
uc.uc_mcontext.__gregs[_REG_G3] = r->__glob[0];
@ -82,6 +90,7 @@ __longjmp14(jmp_buf env, int val)
uc.uc_mcontext.__gregs[_REG_G7] = r->__glob[4];
uc.uc_mcontext.__gregs[_REG_O6] = sc->sc_sp;
/* Make return value non-zero */
if (val == 0)
val = 1;

View File

@ -1,4 +1,4 @@
/* $NetBSD: setjmp.S,v 1.7 2005/10/16 17:15:38 christos Exp $ */
/* $NetBSD: setjmp.S,v 1.8 2011/04/27 21:08:48 martin Exp $ */
/*
* Copyright (c) 1992, 1993
@ -42,7 +42,7 @@
#if 0
.asciz "@(#)setjmp.s 8.1 (Berkeley) 6/4/93"
#else
RCSID("$NetBSD: setjmp.S,v 1.7 2005/10/16 17:15:38 christos Exp $")
RCSID("$NetBSD: setjmp.S,v 1.8 2011/04/27 21:08:48 martin Exp $")
#endif
#endif /* LIBC_SCCS and not lint */
@ -118,19 +118,17 @@ ENTRY(__setjmp14)
stx %fp, [%i0 + 0x08] /* sc.sc_sp = sp */
add %i7, 8, %o0
stx %o0, [%i0 + 0x10] /* sc.sc_pc = return_pc */
add %i7, 12, %o0
stx %o0, [%i0 + 0x18] /* sc.sc_npc = return_pc + 4 */
stx %g0, [%i0 + 0x20] /* sc.sc_tstate = (clean ccr) */
stx %l1, [%i0 + 0x28] /* sc.sc_g1 */
stx %l2, [%i0 + 0x30] /* sc.sc_o0, set in longjmp, use as %g2 */
/* 0x38 */ /* sc.sc_mask was already saved above */
/* 0x38: 4x32bit */ /* sc.sc_mask was already saved above */
/* save additional registers needed to fill a complete mcontext */
stx %l3, [%i0 + 0x40]
stx %l4, [%i0 + 0x48]
stx %l5, [%i0 + 0x50]
stx %l6, [%i0 + 0x58]
stx %l7, [%i0 + 0x60]
stx %l3, [%i0 + 0x48]
stx %l4, [%i0 + 0x50] /* adjust asserts in longjmp.c */
stx %l5, [%i0 + 0x58] /* if you change any of these */
stx %l6, [%i0 + 0x60] /* offsets! */
stx %l7, [%i0 + 0x68]
ret /* return 0 */
restore %g0, 0, %o0

View File

@ -1,4 +1,4 @@
/* $NetBSD: sigsetjmp.S,v 1.8 2005/10/16 17:15:38 christos Exp $ */
/* $NetBSD: sigsetjmp.S,v 1.9 2011/04/27 21:08:48 martin Exp $ */
/*
* Copyright (c) 1995 Paul Kranenburg
* All rights reserved.
@ -32,12 +32,17 @@
#include "SYS.h"
/*
* We use the sc_npc field inside the sigcontext to store the save mask
*/
#define MASK_OFFSET 0x18
#ifdef PIC
#ifdef BIGPIC
ENTRY(__sigsetjmp14)
PIC_PROLOGUE(%g1,%o2) ! %g1 = _GLOBAL_OFFSET_TABLE
st %o1,[%o0+0x68] ! jmpbuf[JBLEN]
st %o1,[%o0+MASK_OFFSET] ! jmp_buf.sc.sc_npc
sethi %hi(_C_LABEL(__setjmp14)), %o2
sethi %hi(_C_LABEL(_setjmp)), %o3
or %o2, %lo(_C_LABEL(__setjmp14)), %o2
@ -51,7 +56,7 @@ ENTRY(__sigsetjmp14)
ENTRY(__siglongjmp14)
PIC_PROLOGUE(%g1,%o2) ! %g1 = _GLOBAL_OFFSET_TABLE
ld [%o0+0x68], %o2 ! jmpbuf[JBLEN]
ld [%o0+MASK_OFFSET], %o2 ! jmp_buf.sc.sc_npc
sethi %hi(_C_LABEL(__longjmp14)), %o3
sethi %hi(_C_LABEL(_longjmp)), %o4
or %o3, %lo(_C_LABEL(__longjmp14)), %o3
@ -68,7 +73,7 @@ ENTRY(__siglongjmp14)
ENTRY(__sigsetjmp14)
PIC_PROLOGUE(%g1,%o2) ! %g1 = _GLOBAL_OFFSET_TABLE
cmp %o1,0
st %o1,[%o0+0x68] ! jmpbuf[JBLEN]
st %o1,[%o0+MASK_OFFSET] ! jmp_buf.sc.sc_npc
bne,a 1f
ldx [%g1+_C_LABEL(__setjmp14)], %g1 ! if (%o1 != 0) goto __setjmp;
ldx [%g1+_C_LABEL(_setjmp)], %g1 ! else goto _setjmp;
@ -78,7 +83,7 @@ ENTRY(__sigsetjmp14)
ENTRY(__siglongjmp14)
PIC_PROLOGUE(%g1,%o2) ! %g1 = _GLOBAL_OFFSET_TABLE
ld [%o0+0x68],%o2 ! jmpbuf[JBLEN]
ld [%o0+MASK_OFFSET],%o2 ! jmp_buf.sc.sc_npc
cmp %o2,0
bne,a 1f
ldx [%g1+_C_LABEL(__longjmp14)], %g1 ! if (%o2 != 0) goto __longjmp;
@ -93,12 +98,12 @@ ENTRY(__siglongjmp14)
ENTRY(__sigsetjmp14)
cmp %o1,0
be _C_LABEL(_setjmp)
st %o1,[%o0+0x68] ! jmpbuf[JBLEN]
st %o1,[%o0+MASK_OFFSET] ! jmp_buf.sc.sc_npc
ba,a _C_LABEL(__setjmp14)
unimp 0
ENTRY(__siglongjmp14)
ld [%o0+0x68],%g1
ld [%o0+MASK_OFFSET],%g1
cmp %g1,0
be _C_LABEL(_longjmp)
nop