1331722Seadler/* 2132399Sgrehan * Copyright (c) 2004 Marcel Moolenaar, Peter Grehan 3132399Sgrehan * All rights reserved. 4132399Sgrehan * 5132399Sgrehan * Redistribution and use in source and binary forms, with or without 6132399Sgrehan * modification, are permitted provided that the following conditions 7132399Sgrehan * are met: 8132399Sgrehan * 9132399Sgrehan * 1. Redistributions of source code must retain the above copyright 10132399Sgrehan * notice, this list of conditions and the following disclaimer. 11132399Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 12132399Sgrehan * notice, this list of conditions and the following disclaimer in the 13132399Sgrehan * documentation and/or other materials provided with the distribution. 14132399Sgrehan * 15132399Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16132399Sgrehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17132399Sgrehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18132399Sgrehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19132399Sgrehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20132399Sgrehan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21132399Sgrehan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22132399Sgrehan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23132399Sgrehan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24132399Sgrehan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25132399Sgrehan */ 26132399Sgrehan 27132399Sgrehan#include <sys/cdefs.h> 28132399Sgrehan__FBSDID("$FreeBSD$"); 29132399Sgrehan 30132399Sgrehan#include <sys/param.h> 31132399Sgrehan#include <sys/ucontext.h> 32132399Sgrehan#include <signal.h> 33132399Sgrehan#include <stdlib.h> 34132399Sgrehan#include <strings.h> 35132399Sgrehan 36132399Sgrehantypedef void (*handler_t)(uint32_t, uint32_t, uint32_t); 37132399Sgrehan 38132399Sgrehan/* Prototypes */ 39132399Sgrehanstatic void ctx_wrapper(ucontext_t *ucp, handler_t func, uint32_t sig, 40132399Sgrehan uint32_t sig_si, uint32_t sig_uc); 41132399Sgrehan 42132399Sgrehan__weak_reference(__signalcontext, signalcontext); 43132399Sgrehan 44132399Sgrehanint 45132399Sgrehan__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func) 46132399Sgrehan{ 47132399Sgrehan siginfo_t *sig_si; 48132399Sgrehan ucontext_t *sig_uc; 49132399Sgrehan uint32_t sp; 50132399Sgrehan 51132399Sgrehan /* Bail out if we don't have a valid ucontext pointer. */ 52132399Sgrehan if (ucp == NULL) 53132399Sgrehan abort(); 54132399Sgrehan 55132399Sgrehan /* 56132399Sgrehan * Build a 16-byte-aligned signal frame 57132399Sgrehan */ 58132399Sgrehan sp = (ucp->uc_mcontext.mc_gpr[1] - sizeof(ucontext_t)) & ~15UL; 59132399Sgrehan sig_uc = (ucontext_t *)sp; 60132399Sgrehan bcopy(ucp, sig_uc, sizeof(*sig_uc)); 61132399Sgrehan sp = (sp - sizeof(siginfo_t)) & ~15UL; 62132399Sgrehan sig_si = (siginfo_t *)sp; 63132399Sgrehan bzero(sig_si, sizeof(*sig_si)); 64132399Sgrehan sig_si->si_signo = sig; 65132399Sgrehan 66132399Sgrehan /* 67132399Sgrehan * Subtract 8 bytes from stack to allow for frameptr 68132399Sgrehan */ 69132399Sgrehan sp -= 2*sizeof(uint32_t); 70132399Sgrehan sp &= ~15UL; 71132399Sgrehan 72132399Sgrehan /* 73132399Sgrehan * Setup the ucontext of the signal handler. 74132399Sgrehan */ 75132399Sgrehan bzero(&ucp->uc_mcontext, sizeof(ucp->uc_mcontext)); 76132399Sgrehan ucp->uc_link = sig_uc; 77132399Sgrehan sigdelset(&ucp->uc_sigmask, sig); 78132399Sgrehan 79132399Sgrehan ucp->uc_mcontext.mc_vers = _MC_VERSION; 80132399Sgrehan ucp->uc_mcontext.mc_len = sizeof(struct __mcontext); 81132399Sgrehan ucp->uc_mcontext.mc_srr0 = (uint32_t) ctx_wrapper; 82132399Sgrehan ucp->uc_mcontext.mc_gpr[1] = (uint32_t) sp; 83132399Sgrehan ucp->uc_mcontext.mc_gpr[3] = (uint32_t) func; 84132399Sgrehan ucp->uc_mcontext.mc_gpr[4] = (uint32_t) sig; 85132399Sgrehan ucp->uc_mcontext.mc_gpr[5] = (uint32_t) sig_si; 86132399Sgrehan ucp->uc_mcontext.mc_gpr[6] = (uint32_t) sig_uc; 87132399Sgrehan 88132399Sgrehan return (0); 89132399Sgrehan} 90132399Sgrehan 91132399Sgrehanstatic void 92132399Sgrehanctx_wrapper(ucontext_t *ucp, handler_t func, uint32_t sig, uint32_t sig_si, 93132399Sgrehan uint32_t sig_uc) 94132399Sgrehan{ 95132399Sgrehan 96132399Sgrehan (*func)(sig, sig_si, sig_uc); 97132399Sgrehan if (ucp->uc_link == NULL) 98132399Sgrehan exit(0); 99132399Sgrehan setcontext((const ucontext_t *)ucp->uc_link); 100132399Sgrehan /* should never get here */ 101132399Sgrehan abort(); 102132399Sgrehan /* NOTREACHED */ 103132399Sgrehan} 104