1*0abf123aSmartin /* $NetBSD: longjmp.c,v 1.7 2012/03/17 21:35:06 martin Exp $ */
24c7dd803Schristos
34c7dd803Schristos /*-
44c7dd803Schristos * Copyright (c) 2003 The NetBSD Foundation, Inc.
54c7dd803Schristos * All rights reserved.
64c7dd803Schristos *
74c7dd803Schristos * This code is derived from software contributed to The NetBSD Foundation
84c7dd803Schristos * by Christian Limpach.
94c7dd803Schristos *
104c7dd803Schristos * Redistribution and use in source and binary forms, with or without
114c7dd803Schristos * modification, are permitted provided that the following conditions
124c7dd803Schristos * are met:
134c7dd803Schristos * 1. Redistributions of source code must retain the above copyright
144c7dd803Schristos * notice, this list of conditions and the following disclaimer.
154c7dd803Schristos * 2. Redistributions in binary form must reproduce the above copyright
164c7dd803Schristos * notice, this list of conditions and the following disclaimer in the
174c7dd803Schristos * documentation and/or other materials provided with the distribution.
184c7dd803Schristos *
194c7dd803Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
204c7dd803Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
214c7dd803Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
224c7dd803Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
234c7dd803Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
244c7dd803Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
254c7dd803Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
264c7dd803Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
274c7dd803Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
284c7dd803Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
294c7dd803Schristos * POSSIBILITY OF SUCH DAMAGE.
304c7dd803Schristos */
314c7dd803Schristos
324c7dd803Schristos #include "namespace.h"
334c7dd803Schristos #include <sys/types.h>
344c7dd803Schristos #include <ucontext.h>
354c7dd803Schristos #include <signal.h>
364c7dd803Schristos #include <stdlib.h>
374c7dd803Schristos #include <string.h>
384c7dd803Schristos #include <stdio.h>
39d21307a5Smartin #include <stddef.h>
404c7dd803Schristos
414c7dd803Schristos #define __LIBC12_SOURCE__
424c7dd803Schristos #include <setjmp.h>
434c7dd803Schristos #include <compat/include/setjmp.h>
444c7dd803Schristos
454c7dd803Schristos typedef struct {
4644283e6eSmartin __greg_t g3;
4744283e6eSmartin __greg_t g6;
4844283e6eSmartin __greg_t g7;
4944283e6eSmartin __greg_t dummy;
5044283e6eSmartin __greg_t save_mask;
514c7dd803Schristos } __jmp_buf_regs_t;
524c7dd803Schristos
53d21307a5Smartin /*
54d21307a5Smartin * setjmp.S uses hard coded offsets into the jump_buf,
55d21307a5Smartin * make sure any changes cause a compile failure here
56d21307a5Smartin */
57*0abf123aSmartin #ifndef lint /* XXX this is too much for lint */
5844283e6eSmartin __CTASSERT(0x68 == offsetof(__jmp_buf_regs_t,save_mask) +
59d21307a5Smartin sizeof(struct sigcontext));
609881f8deSmartin __CTASSERT(sizeof(sigjmp_buf) >= sizeof(__jmp_buf_regs_t) +
61c6700876Smartin sizeof(struct sigcontext));
62*0abf123aSmartin #endif
63d21307a5Smartin
644c7dd803Schristos void
__longjmp14(jmp_buf env,int val)654c7dd803Schristos __longjmp14(jmp_buf env, int val)
664c7dd803Schristos {
674c7dd803Schristos struct sigcontext *sc = (void *)env;
684c7dd803Schristos __jmp_buf_regs_t *r = (void *)&sc[1];
694c7dd803Schristos ucontext_t uc;
704c7dd803Schristos
714c7dd803Schristos /* Ensure non-zero SP */
724c7dd803Schristos if (sc->sc_sp == 0)
734c7dd803Schristos goto err;
744c7dd803Schristos
754c7dd803Schristos /*
764c7dd803Schristos * Set _UC_CPU. No FPU data saved, so we can't restore
774c7dd803Schristos * that. Set _UC_{SET,CLR}STACK according to SS_ONSTACK
784c7dd803Schristos */
794c7dd803Schristos memset(&uc, 0, sizeof(uc));
804c7dd803Schristos uc.uc_flags = _UC_CPU | (sc->sc_onstack ? _UC_SETSTACK : _UC_CLRSTACK);
814c7dd803Schristos
824c7dd803Schristos /*
834c7dd803Schristos * Set the signal mask - this is a weak symbol, so don't use
844c7dd803Schristos * _UC_SIGMASK in the mcontext, libpthread might override sigprocmask.
854c7dd803Schristos */
864c7dd803Schristos sigprocmask(SIG_SETMASK, &sc->sc_mask, NULL);
874c7dd803Schristos
884c7dd803Schristos /* Fill other registers */
894c7dd803Schristos uc.uc_mcontext.__gregs[_REG_CCR] = sc->sc_tstate;
904c7dd803Schristos uc.uc_mcontext.__gregs[_REG_PC] = sc->sc_pc;
91d21307a5Smartin uc.uc_mcontext.__gregs[_REG_nPC] = sc->sc_pc+4;
924c7dd803Schristos uc.uc_mcontext.__gregs[_REG_G1] = sc->sc_g1;
934c7dd803Schristos uc.uc_mcontext.__gregs[_REG_G2] = sc->sc_o0;
9444283e6eSmartin uc.uc_mcontext.__gregs[_REG_G3] = r->g3;
9544283e6eSmartin uc.uc_mcontext.__gregs[_REG_G4] = 0;
9644283e6eSmartin uc.uc_mcontext.__gregs[_REG_G5] = 0;
9744283e6eSmartin uc.uc_mcontext.__gregs[_REG_G6] = r->g6;
9844283e6eSmartin uc.uc_mcontext.__gregs[_REG_G7] = r->g7;
994c7dd803Schristos uc.uc_mcontext.__gregs[_REG_O6] = sc->sc_sp;
1004c7dd803Schristos
101d21307a5Smartin
1024c7dd803Schristos /* Make return value non-zero */
1034c7dd803Schristos if (val == 0)
1044c7dd803Schristos val = 1;
1054c7dd803Schristos
1064c7dd803Schristos /* Save return value in context */
1074c7dd803Schristos uc.uc_mcontext.__gregs[_REG_O0] = val;
1084c7dd803Schristos
1094c7dd803Schristos setcontext(&uc);
1104c7dd803Schristos
1114c7dd803Schristos err:
1124c7dd803Schristos longjmperror();
1134c7dd803Schristos abort();
1144c7dd803Schristos /* NOTREACHED */
1154c7dd803Schristos }
116