signalcontext.c revision 285830
1228509Sjhb/* 2283927Sjhb * Copyright (c) 2003 Marcel Moolenaar 3228509Sjhb * All rights reserved. 4228509Sjhb * 5228509Sjhb * Redistribution and use in source and binary forms, with or without 6228509Sjhb * modification, are permitted provided that the following conditions 7228509Sjhb * are met: 8228509Sjhb * 9228509Sjhb * 1. Redistributions of source code must retain the above copyright 10228509Sjhb * notice, this list of conditions and the following disclaimer. 11228509Sjhb * 2. Redistributions in binary form must reproduce the above copyright 12228509Sjhb * notice, this list of conditions and the following disclaimer in the 13228509Sjhb * documentation and/or other materials provided with the distribution. 14228509Sjhb * 15228509Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16228509Sjhb * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17228509Sjhb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18228509Sjhb * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19228509Sjhb * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20228509Sjhb * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21228509Sjhb * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22228509Sjhb * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23228509Sjhb * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24228509Sjhb * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25228509Sjhb */ 26228509Sjhb 27228509Sjhb#include <sys/cdefs.h> 28228509Sjhb__FBSDID("$FreeBSD: releng/10.2/lib/libc/amd64/gen/signalcontext.c 132795 2004-07-28 13:08:24Z davidxu $"); 29228509Sjhb 30228509Sjhb#include <sys/types.h> 31228509Sjhb#include <sys/ucontext.h> 32228509Sjhb#include <signal.h> 33228620Sru#include <stdlib.h> 34228620Sru#include <strings.h> 35228509Sjhb 36228509Sjhbtypedef void (*handler_t)(uint64_t, uint64_t, uint64_t); 37228509Sjhb 38228509Sjhb/* Prototypes */ 39228509Sjhbstatic void sigctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args); 40228509Sjhb 41228509Sjhb__weak_reference(__signalcontext, signalcontext); 42228509Sjhb 43228509Sjhbint 44228620Sru__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func) 45228509Sjhb{ 46228620Sru uint64_t *args; 47228509Sjhb siginfo_t *sig_si; 48228509Sjhb ucontext_t *sig_uc; 49228509Sjhb uint64_t sp; 50228509Sjhb 51228509Sjhb /* Bail out if we don't have a valid ucontext pointer. */ 52228509Sjhb if (ucp == NULL) 53228509Sjhb abort(); 54228509Sjhb 55228509Sjhb /* 56228509Sjhb * Build a signal frame and copy the arguments of signal handler 57228509Sjhb * 'func' onto the stack and do the funky stack alignment. 58228509Sjhb * This means that we need an 8-byte-odd alignment since the ABI expects 59228620Sru * the return address to be pushed, thus breaking the 16 byte alignment. 60228509Sjhb */ 61228620Sru sp = (ucp->uc_mcontext.mc_rsp - 128 - sizeof(ucontext_t)) & ~15UL; 62228509Sjhb sig_uc = (ucontext_t *)sp; 63228509Sjhb bcopy(ucp, sig_uc, sizeof(*sig_uc)); 64228509Sjhb sp = (sp - sizeof(siginfo_t)) & ~15UL; 65228620Sru sig_si = (siginfo_t *)sp; 66228509Sjhb bzero(sig_si, sizeof(*sig_si)); 67228509Sjhb sig_si->si_signo = sig; 68228509Sjhb sp -= 3 * sizeof(uint64_t); 69228509Sjhb args = (uint64_t *)sp; 70228509Sjhb args[0] = sig; 71228509Sjhb args[1] = (intptr_t)sig_si; 72228509Sjhb args[2] = (intptr_t)sig_uc; 73228509Sjhb sp -= 16; 74228509Sjhb 75228509Sjhb /* 76228509Sjhb * Setup the ucontext of the signal handler. 77228509Sjhb */ 78228509Sjhb bzero(&ucp->uc_mcontext, sizeof(ucp->uc_mcontext)); 79228620Sru ucp->uc_mcontext.mc_fpformat = _MC_FPFMT_NODEV; 80228509Sjhb ucp->uc_mcontext.mc_ownedfp = _MC_FPOWNED_NONE; 81228620Sru ucp->uc_link = sig_uc; 82228509Sjhb sigdelset(&ucp->uc_sigmask, sig); 83228509Sjhb 84228509Sjhb ucp->uc_mcontext.mc_len = sizeof(mcontext_t); 85228509Sjhb ucp->uc_mcontext.mc_rdi = (register_t)ucp; 86228509Sjhb ucp->uc_mcontext.mc_rsi = (register_t)func; 87228509Sjhb ucp->uc_mcontext.mc_rdx = (register_t)args; 88228509Sjhb ucp->uc_mcontext.mc_rbp = (register_t)sp; 89228620Sru ucp->uc_mcontext.mc_rbx = (register_t)sp; 90228509Sjhb ucp->uc_mcontext.mc_rsp = (register_t)sp; 91228509Sjhb ucp->uc_mcontext.mc_rip = (register_t)sigctx_wrapper; 92228620Sru return (0); 93228509Sjhb} 94228509Sjhb 95228509Sjhbstatic void 96228509Sjhbsigctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args) 97228509Sjhb{ 98228620Sru 99228509Sjhb (*func)(args[0], args[1], args[2]); 100228509Sjhb if (ucp->uc_link == NULL) 101228509Sjhb exit(0); 102228620Sru setcontext((const ucontext_t *)ucp->uc_link); 103228509Sjhb /* should never get here */ 104228620Sru abort(); 105228509Sjhb /* NOTREACHED */ 106228509Sjhb} 107228509Sjhb