1d915a14eSPedro F. Giffuni /*- 2d915a14eSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3d915a14eSPedro F. Giffuni * 4840b91ccSNathan Whitehorn * Copyright (c) 2004 Marcel Moolenaar, Peter Grehan 5840b91ccSNathan Whitehorn * All rights reserved. 6840b91ccSNathan Whitehorn * 7840b91ccSNathan Whitehorn * Redistribution and use in source and binary forms, with or without 8840b91ccSNathan Whitehorn * modification, are permitted provided that the following conditions 9840b91ccSNathan Whitehorn * are met: 10840b91ccSNathan Whitehorn * 11840b91ccSNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 12840b91ccSNathan Whitehorn * notice, this list of conditions and the following disclaimer. 13840b91ccSNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 14840b91ccSNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 15840b91ccSNathan Whitehorn * documentation and/or other materials provided with the distribution. 16840b91ccSNathan Whitehorn * 17840b91ccSNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18840b91ccSNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19840b91ccSNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20840b91ccSNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21840b91ccSNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22840b91ccSNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23840b91ccSNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24840b91ccSNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25840b91ccSNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26840b91ccSNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27840b91ccSNathan Whitehorn */ 28840b91ccSNathan Whitehorn 29840b91ccSNathan Whitehorn #include <sys/cdefs.h> 30840b91ccSNathan Whitehorn __FBSDID("$FreeBSD$"); 31840b91ccSNathan Whitehorn 32840b91ccSNathan Whitehorn #include <sys/param.h> 33840b91ccSNathan Whitehorn #include <sys/ucontext.h> 34840b91ccSNathan Whitehorn #include <signal.h> 35840b91ccSNathan Whitehorn #include <stdlib.h> 36840b91ccSNathan Whitehorn #include <strings.h> 37840b91ccSNathan Whitehorn 38840b91ccSNathan Whitehorn typedef void (*handler_t)(uint32_t, uint32_t, uint32_t); 39840b91ccSNathan Whitehorn 40840b91ccSNathan Whitehorn /* Prototypes */ 41840b91ccSNathan Whitehorn static void ctx_wrapper(ucontext_t *ucp, handler_t func, uint32_t sig, 42840b91ccSNathan Whitehorn uint32_t sig_si, uint32_t sig_uc); 43840b91ccSNathan Whitehorn 44840b91ccSNathan Whitehorn __weak_reference(__signalcontext, signalcontext); 45840b91ccSNathan Whitehorn 46840b91ccSNathan Whitehorn int 47840b91ccSNathan Whitehorn __signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func) 48840b91ccSNathan Whitehorn { 49840b91ccSNathan Whitehorn siginfo_t *sig_si; 50840b91ccSNathan Whitehorn ucontext_t *sig_uc; 51840b91ccSNathan Whitehorn uintptr_t sp; 52840b91ccSNathan Whitehorn 53840b91ccSNathan Whitehorn /* Bail out if we don't have a valid ucontext pointer. */ 54840b91ccSNathan Whitehorn if (ucp == NULL) 55840b91ccSNathan Whitehorn abort(); 56840b91ccSNathan Whitehorn 57840b91ccSNathan Whitehorn /* 58840b91ccSNathan Whitehorn * Build a 16-byte-aligned signal frame 59840b91ccSNathan Whitehorn */ 60840b91ccSNathan Whitehorn sp = (ucp->uc_mcontext.mc_gpr[1] - sizeof(ucontext_t)) & ~15UL; 61840b91ccSNathan Whitehorn sig_uc = (ucontext_t *)sp; 62840b91ccSNathan Whitehorn bcopy(ucp, sig_uc, sizeof(*sig_uc)); 63840b91ccSNathan Whitehorn sp = (sp - sizeof(siginfo_t)) & ~15UL; 64840b91ccSNathan Whitehorn sig_si = (siginfo_t *)sp; 65840b91ccSNathan Whitehorn bzero(sig_si, sizeof(*sig_si)); 66840b91ccSNathan Whitehorn sig_si->si_signo = sig; 67840b91ccSNathan Whitehorn 68840b91ccSNathan Whitehorn /* 69840b91ccSNathan Whitehorn * Subtract 48 bytes from stack to allow for frameptr 70840b91ccSNathan Whitehorn */ 71840b91ccSNathan Whitehorn sp -= 6*sizeof(uint64_t); 72840b91ccSNathan Whitehorn sp &= ~15UL; 73840b91ccSNathan Whitehorn 74840b91ccSNathan Whitehorn /* 75840b91ccSNathan Whitehorn * Setup the ucontext of the signal handler. 76840b91ccSNathan Whitehorn */ 77840b91ccSNathan Whitehorn bzero(&ucp->uc_mcontext, sizeof(ucp->uc_mcontext)); 78840b91ccSNathan Whitehorn ucp->uc_link = sig_uc; 79840b91ccSNathan Whitehorn sigdelset(&ucp->uc_sigmask, sig); 80840b91ccSNathan Whitehorn 81840b91ccSNathan Whitehorn ucp->uc_mcontext.mc_vers = _MC_VERSION; 82840b91ccSNathan Whitehorn ucp->uc_mcontext.mc_len = sizeof(struct __mcontext); 83840b91ccSNathan Whitehorn ucp->uc_mcontext.mc_srr0 = (uint64_t) ctx_wrapper; 84840b91ccSNathan Whitehorn ucp->uc_mcontext.mc_gpr[1] = (uint64_t) sp; 85840b91ccSNathan Whitehorn ucp->uc_mcontext.mc_gpr[3] = (uint64_t) func; 86840b91ccSNathan Whitehorn ucp->uc_mcontext.mc_gpr[4] = (uint64_t) sig; 87840b91ccSNathan Whitehorn ucp->uc_mcontext.mc_gpr[5] = (uint64_t) sig_si; 88840b91ccSNathan Whitehorn ucp->uc_mcontext.mc_gpr[6] = (uint64_t) sig_uc; 89840b91ccSNathan Whitehorn 90840b91ccSNathan Whitehorn return (0); 91840b91ccSNathan Whitehorn } 92840b91ccSNathan Whitehorn 93840b91ccSNathan Whitehorn static void 94840b91ccSNathan Whitehorn ctx_wrapper(ucontext_t *ucp, handler_t func, uint32_t sig, uint32_t sig_si, 95840b91ccSNathan Whitehorn uint32_t sig_uc) 96840b91ccSNathan Whitehorn { 97840b91ccSNathan Whitehorn 98840b91ccSNathan Whitehorn (*func)(sig, sig_si, sig_uc); 99840b91ccSNathan Whitehorn if (ucp->uc_link == NULL) 100840b91ccSNathan Whitehorn exit(0); 101840b91ccSNathan Whitehorn setcontext((const ucontext_t *)ucp->uc_link); 102840b91ccSNathan Whitehorn /* should never get here */ 103840b91ccSNathan Whitehorn abort(); 104840b91ccSNathan Whitehorn /* NOTREACHED */ 105840b91ccSNathan Whitehorn } 106