1d915a14eSPedro F. Giffuni /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3d915a14eSPedro F. Giffuni *
44adc354cSDaniel Eischen * Copyright (c) 2003 Marcel Moolenaar
54adc354cSDaniel Eischen * All rights reserved.
64adc354cSDaniel Eischen *
74adc354cSDaniel Eischen * Redistribution and use in source and binary forms, with or without
84adc354cSDaniel Eischen * modification, are permitted provided that the following conditions
94adc354cSDaniel Eischen * are met:
104adc354cSDaniel Eischen *
114adc354cSDaniel Eischen * 1. Redistributions of source code must retain the above copyright
124adc354cSDaniel Eischen * notice, this list of conditions and the following disclaimer.
134adc354cSDaniel Eischen * 2. Redistributions in binary form must reproduce the above copyright
144adc354cSDaniel Eischen * notice, this list of conditions and the following disclaimer in the
154adc354cSDaniel Eischen * documentation and/or other materials provided with the distribution.
164adc354cSDaniel Eischen *
174adc354cSDaniel Eischen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
184adc354cSDaniel Eischen * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
194adc354cSDaniel Eischen * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
204adc354cSDaniel Eischen * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
214adc354cSDaniel Eischen * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
224adc354cSDaniel Eischen * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234adc354cSDaniel Eischen * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244adc354cSDaniel Eischen * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254adc354cSDaniel Eischen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
264adc354cSDaniel Eischen * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274adc354cSDaniel Eischen */
284adc354cSDaniel Eischen
294adc354cSDaniel Eischen #include <sys/types.h>
304adc354cSDaniel Eischen #include <sys/ucontext.h>
314adc354cSDaniel Eischen #include <signal.h>
324adc354cSDaniel Eischen #include <stdlib.h>
334adc354cSDaniel Eischen #include <strings.h>
344adc354cSDaniel Eischen
354adc354cSDaniel Eischen typedef void (*handler_t)(uint64_t, uint64_t, uint64_t);
364adc354cSDaniel Eischen
374adc354cSDaniel Eischen /* Prototypes */
3837260333SPeter Wemm static void sigctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args);
394adc354cSDaniel Eischen
404adc354cSDaniel Eischen __weak_reference(__signalcontext, signalcontext);
414adc354cSDaniel Eischen
424adc354cSDaniel Eischen int
__signalcontext(ucontext_t * ucp,int sig,__sighandler_t * func)434adc354cSDaniel Eischen __signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
444adc354cSDaniel Eischen {
454adc354cSDaniel Eischen uint64_t *args;
464adc354cSDaniel Eischen siginfo_t *sig_si;
474adc354cSDaniel Eischen ucontext_t *sig_uc;
484adc354cSDaniel Eischen uint64_t sp;
494adc354cSDaniel Eischen
504adc354cSDaniel Eischen /* Bail out if we don't have a valid ucontext pointer. */
514adc354cSDaniel Eischen if (ucp == NULL)
524adc354cSDaniel Eischen abort();
534adc354cSDaniel Eischen
544adc354cSDaniel Eischen /*
554adc354cSDaniel Eischen * Build a signal frame and copy the arguments of signal handler
5637260333SPeter Wemm * 'func' onto the stack and do the funky stack alignment.
5737260333SPeter Wemm * This means that we need an 8-byte-odd alignment since the ABI expects
5837260333SPeter Wemm * the return address to be pushed, thus breaking the 16 byte alignment.
594adc354cSDaniel Eischen */
602ff285bfSDavid Xu sp = (ucp->uc_mcontext.mc_rsp - 128 - sizeof(ucontext_t)) & ~15UL;
614adc354cSDaniel Eischen sig_uc = (ucontext_t *)sp;
624adc354cSDaniel Eischen bcopy(ucp, sig_uc, sizeof(*sig_uc));
634adc354cSDaniel Eischen sp = (sp - sizeof(siginfo_t)) & ~15UL;
644adc354cSDaniel Eischen sig_si = (siginfo_t *)sp;
654adc354cSDaniel Eischen bzero(sig_si, sizeof(*sig_si));
664adc354cSDaniel Eischen sig_si->si_signo = sig;
6737260333SPeter Wemm sp -= 3 * sizeof(uint64_t);
684adc354cSDaniel Eischen args = (uint64_t *)sp;
694adc354cSDaniel Eischen args[0] = sig;
704adc354cSDaniel Eischen args[1] = (intptr_t)sig_si;
714adc354cSDaniel Eischen args[2] = (intptr_t)sig_uc;
724adc354cSDaniel Eischen sp -= 16;
734adc354cSDaniel Eischen
744adc354cSDaniel Eischen /*
754adc354cSDaniel Eischen * Setup the ucontext of the signal handler.
764adc354cSDaniel Eischen */
774adc354cSDaniel Eischen bzero(&ucp->uc_mcontext, sizeof(ucp->uc_mcontext));
780187c8ffSDavid Xu ucp->uc_mcontext.mc_fpformat = _MC_FPFMT_NODEV;
790187c8ffSDavid Xu ucp->uc_mcontext.mc_ownedfp = _MC_FPOWNED_NONE;
804adc354cSDaniel Eischen ucp->uc_link = sig_uc;
814adc354cSDaniel Eischen sigdelset(&ucp->uc_sigmask, sig);
824adc354cSDaniel Eischen
834160fed5SDavid Xu ucp->uc_mcontext.mc_len = sizeof(mcontext_t);
844adc354cSDaniel Eischen ucp->uc_mcontext.mc_rdi = (register_t)ucp;
854adc354cSDaniel Eischen ucp->uc_mcontext.mc_rsi = (register_t)func;
864adc354cSDaniel Eischen ucp->uc_mcontext.mc_rdx = (register_t)args;
874adc354cSDaniel Eischen ucp->uc_mcontext.mc_rbp = (register_t)sp;
884adc354cSDaniel Eischen ucp->uc_mcontext.mc_rbx = (register_t)sp;
894adc354cSDaniel Eischen ucp->uc_mcontext.mc_rsp = (register_t)sp;
9037260333SPeter Wemm ucp->uc_mcontext.mc_rip = (register_t)sigctx_wrapper;
914adc354cSDaniel Eischen return (0);
924adc354cSDaniel Eischen }
934adc354cSDaniel Eischen
944adc354cSDaniel Eischen static void
sigctx_wrapper(ucontext_t * ucp,handler_t func,uint64_t * args)9537260333SPeter Wemm sigctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args)
964adc354cSDaniel Eischen {
974adc354cSDaniel Eischen
984adc354cSDaniel Eischen (*func)(args[0], args[1], args[2]);
994adc354cSDaniel Eischen if (ucp->uc_link == NULL)
1004adc354cSDaniel Eischen exit(0);
1014adc354cSDaniel Eischen setcontext((const ucontext_t *)ucp->uc_link);
1024adc354cSDaniel Eischen /* should never get here */
1034adc354cSDaniel Eischen abort();
1044adc354cSDaniel Eischen /* NOTREACHED */
1054adc354cSDaniel Eischen }
106