Tue Mar 12 19:38:20 2013 UTC ()
Save the GP register value and restore it on longjmp.

While formally GP is not a callee-saved register, for static linking
the link time optimization described in section 3.2.3 of the "Calling
Standard for Alpha Systems" allows the caller to rely on GP being the
value needed within setjmp() - and not restore it after return if setjmp
and the call site share a GP value.

This fixes longjmp/setjmp for statically linked programs, e.g. /rescue/csh
or the static tcsh variant from pkgsrc.


(martin)
diff -r1.5 -r1.6 src/lib/libc/arch/alpha/gen/__longjmp14.c
diff -r1.5 -r1.6 src/lib/libc/arch/alpha/gen/__setjmp14.S

cvs diff -r1.5 -r1.6 src/lib/libc/arch/alpha/gen/__longjmp14.c (expand / switch to unified diff)

--- src/lib/libc/arch/alpha/gen/__longjmp14.c 2008/04/28 20:22:55 1.5
+++ src/lib/libc/arch/alpha/gen/__longjmp14.c 2013/03/12 19:38:20 1.6
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: __longjmp14.c,v 1.5 2008/04/28 20:22:55 martin Exp $ */ 1/* $NetBSD: __longjmp14.c,v 1.6 2013/03/12 19:38:20 martin Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc. 4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christian Limpach and Matt Thomas. 8 * by Christian Limpach and Matt Thomas.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -46,44 +46,47 @@ void @@ -46,44 +46,47 @@ void
46__longjmp14(jmp_buf env, int val) 46__longjmp14(jmp_buf env, int val)
47{ 47{
48 struct sigcontext *sc = (void *)env; 48 struct sigcontext *sc = (void *)env;
49 ucontext_t uc; 49 ucontext_t uc;
50 50
51 /* Ensure non-zero SP */ 51 /* Ensure non-zero SP */
52 if (sc->sc_sp == 0 || sc->sc_regs[R_ZERO] != 0xacedbade) 52 if (sc->sc_sp == 0 || sc->sc_regs[R_ZERO] != 0xacedbade)
53 goto err; 53 goto err;
54 54
55 /* Ensure non-zero return value */ 55 /* Ensure non-zero return value */
56 if (val == 0) 56 if (val == 0)
57 val = -1; 57 val = -1;
58 58
 59 memset(&uc, 0, sizeof uc);
 60
59 /* Set _UC_SIGMASK and _UC_CPU */ 61 /* Set _UC_SIGMASK and _UC_CPU */
60 uc.uc_flags = _UC_SIGMASK | _UC_CPU; 62 uc.uc_flags = _UC_SIGMASK | _UC_CPU;
61 63
62 /* Clear uc_link */ 64 /* Clear uc_link */
63 uc.uc_link = 0; 65 uc.uc_link = 0;
64 66
65 /* Save return value in context */ 67 /* Save return value in context */
66 uc.uc_mcontext.__gregs[_REG_V0] = val; 68 uc.uc_mcontext.__gregs[_REG_V0] = val;
67 69
68 /* Copy saved registers */ 70 /* Copy saved registers */
69 uc.uc_mcontext.__gregs[_REG_S0] = sc->sc_regs[R_S0]; 71 uc.uc_mcontext.__gregs[_REG_S0] = sc->sc_regs[R_S0];
70 uc.uc_mcontext.__gregs[_REG_S1] = sc->sc_regs[R_S1]; 72 uc.uc_mcontext.__gregs[_REG_S1] = sc->sc_regs[R_S1];
71 uc.uc_mcontext.__gregs[_REG_S2] = sc->sc_regs[R_S2]; 73 uc.uc_mcontext.__gregs[_REG_S2] = sc->sc_regs[R_S2];
72 uc.uc_mcontext.__gregs[_REG_S3] = sc->sc_regs[R_S3]; 74 uc.uc_mcontext.__gregs[_REG_S3] = sc->sc_regs[R_S3];
73 uc.uc_mcontext.__gregs[_REG_S4] = sc->sc_regs[R_S4]; 75 uc.uc_mcontext.__gregs[_REG_S4] = sc->sc_regs[R_S4];
74 uc.uc_mcontext.__gregs[_REG_S5] = sc->sc_regs[R_S5]; 76 uc.uc_mcontext.__gregs[_REG_S5] = sc->sc_regs[R_S5];
75 uc.uc_mcontext.__gregs[_REG_S6] = sc->sc_regs[R_S6]; 77 uc.uc_mcontext.__gregs[_REG_S6] = sc->sc_regs[R_S6];
76 uc.uc_mcontext.__gregs[_REG_RA] = sc->sc_regs[R_RA]; 78 uc.uc_mcontext.__gregs[_REG_RA] = sc->sc_regs[R_RA];
 79 uc.uc_mcontext.__gregs[_REG_GP] = sc->sc_regs[R_GP];
77 uc.uc_mcontext.__gregs[_REG_SP] = sc->sc_sp; 80 uc.uc_mcontext.__gregs[_REG_SP] = sc->sc_sp;
78 uc.uc_mcontext.__gregs[_REG_PC] = sc->sc_pc; 81 uc.uc_mcontext.__gregs[_REG_PC] = sc->sc_pc;
79 uc.uc_mcontext.__gregs[_REG_PS] = 82 uc.uc_mcontext.__gregs[_REG_PS] =
80 (sc->sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR; 83 (sc->sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR;
81 84
82 /* Copy FP state */ 85 /* Copy FP state */
83 if (sc->sc_ownedfp) { 86 if (sc->sc_ownedfp) {
84 memcpy(&uc.uc_mcontext.__fpregs.__fp_fr, 87 memcpy(&uc.uc_mcontext.__fpregs.__fp_fr,
85 &sc->sc_fpregs, 31 * sizeof(unsigned long)); 88 &sc->sc_fpregs, 31 * sizeof(unsigned long));
86 uc.uc_mcontext.__fpregs.__fp_fpcr = sc->sc_fpcr; 89 uc.uc_mcontext.__fpregs.__fp_fpcr = sc->sc_fpcr;
87 /* XXX sc_fp_control */ 90 /* XXX sc_fp_control */
88 uc.uc_flags |= _UC_FPU; 91 uc.uc_flags |= _UC_FPU;
89 } 92 }

cvs diff -r1.5 -r1.6 src/lib/libc/arch/alpha/gen/__setjmp14.S (expand / switch to unified diff)

--- src/lib/libc/arch/alpha/gen/__setjmp14.S 2011/06/12 05:44:36 1.5
+++ src/lib/libc/arch/alpha/gen/__setjmp14.S 2013/03/12 19:38:20 1.6
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: __setjmp14.S,v 1.5 2011/06/12 05:44:36 matt Exp $ */ 1/* $NetBSD: __setjmp14.S,v 1.6 2013/03/12 19:38:20 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1994, 1995 Carnegie-Mellon University. 4 * Copyright (c) 1994, 1995 Carnegie-Mellon University.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Author: Chris G. Demetriou 7 * Author: Chris G. Demetriou
8 *  8 *
9 * Permission to use, copy, modify and distribute this software and 9 * Permission to use, copy, modify and distribute this software and
10 * its documentation is hereby granted, provided that both the copyright 10 * its documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the 11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions 12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation. 13 * thereof, and that both notices appear in supporting documentation.
14 *  14 *
@@ -45,26 +45,27 @@ @@ -45,26 +45,27 @@
45 45
46LEAF(__setjmp14, 1) 46LEAF(__setjmp14, 1)
47 LDGP(pv) 47 LDGP(pv)
48 stq ra, SC_PC(a0) /* sc_pc = return address */ 48 stq ra, SC_PC(a0) /* sc_pc = return address */
49 stq s0, (SC_REGS+_REG_S0)(a0) /* saved bits of sc_regs */ 49 stq s0, (SC_REGS+_REG_S0)(a0) /* saved bits of sc_regs */
50 stq s1, (SC_REGS+_REG_S1)(a0) 50 stq s1, (SC_REGS+_REG_S1)(a0)
51 stq s2, (SC_REGS+_REG_S2)(a0) 51 stq s2, (SC_REGS+_REG_S2)(a0)
52 stq s3, (SC_REGS+_REG_S3)(a0) 52 stq s3, (SC_REGS+_REG_S3)(a0)
53 stq s4, (SC_REGS+_REG_S4)(a0) 53 stq s4, (SC_REGS+_REG_S4)(a0)
54 stq s5, (SC_REGS+_REG_S5)(a0) 54 stq s5, (SC_REGS+_REG_S5)(a0)
55 stq s6, (SC_REGS+_REG_S6)(a0) 55 stq s6, (SC_REGS+_REG_S6)(a0)
56 stq ra, (SC_REGS+_REG_RA)(a0) 56 stq ra, (SC_REGS+_REG_RA)(a0)
57 stq sp, (SC_REGS+_REG_SP)(a0) 57 stq sp, (SC_REGS+_REG_SP)(a0)
 58 stq gp, (SC_REGS+_REG_GP)(a0)
58 59
59 /* 60 /*
60 * get signal information 61 * get signal information
61 */ 62 */
62 mov a0, s0 /* squirrel away ptr to sc */ 63 mov a0, s0 /* squirrel away ptr to sc */
63 64
64 /* see what's blocked */ 65 /* see what's blocked */
65 mov zero, a0 /* how (insignificant) */ 66 mov zero, a0 /* how (insignificant) */
66 mov zero, a1 /* set (NULL) */ 67 mov zero, a1 /* set (NULL) */
67 lda a2, SC_MASK(s0) /* point to mask in sc */ 68 lda a2, SC_MASK(s0) /* point to mask in sc */
68 CALL(__sigprocmask14) 69 CALL(__sigprocmask14)
69 70
70 lda sp, -24(sp) /* sizeof struct sigaltstack */ 71 lda sp, -24(sp) /* sizeof struct sigaltstack */