xref: /netbsd-src/lib/libc/arch/sparc64/gen/longjmp.c (revision 0abf123a7171c0c558a34b4f0e1881e518dc2100)
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