int darwin_sys_sigprocmask(struct lwp *l, const struct darwin_sys_sigprocmask_args *uap, register_t *retval) { /* { syscallarg(int) how; syscallarg(sigset13_t *) set; syscallarg(sigset13_t *) oset; } */ int error; sigset13_t kdset; sigset_t kbset, kboset; if (SCARG(uap, set) != NULL) { error = copyin(SCARG(uap, set), &kdset, sizeof(kdset)); if (error != 0) return error; native_sigset13_to_sigset(&kdset, &kbset); error = sigprocmask1(l, SCARG(uap, how), &kbset, &kboset); } else error = sigprocmask1(l, SCARG(uap, how), NULL, &kboset); if (SCARG(uap, oset) == NULL || error != 0) return error; native_sigset_to_sigset13(&kboset, &kdset); return copyout(&kdset, SCARG(uap, oset), sizeof(kdset)); }
void native_sigaction_to_sigaction13(const struct sigaction *sa, struct sigaction13 *osa) { osa->osa_handler = sa->sa_handler; native_sigset_to_sigset13(&sa->sa_mask, &osa->osa_mask); osa->osa_flags = sa->sa_flags; }
int compat_13_sys_sigpending(struct lwp *l, const void *v, register_t *retval) { sigset13_t ess; sigset_t bss; sigpending1(l, &bss); native_sigset_to_sigset13(&bss, &ess); *retval = ess; return (0); }
int ultrix_sys_sigvec(struct lwp *l, const struct ultrix_sys_sigvec_args *uap, register_t *retval) { struct sigvec nsv, osv; struct sigaction nsa, osa; int error; if (SCARG(uap, nsv)) { error = copyin(SCARG(uap, nsv), &nsv, sizeof(nsv)); if (error) return error; nsa.sa_handler = nsv.sv_handler; #if 0 /* documentation */ /* ONSTACK is identical */ nsa.sa_flags = nsv.sv_flags & ULTRIX_SV_ONSTACK; if ((nsv.sv_flags & ULTRIX_SV_OLDSIG) /* old signal() - always restart */ || (!(nsv.sv_flags & ULTRIX_SV_INTERRUPT)) /* inverted meaning (same bit) */ ) nsa.sa_flags |= SA_RESTART; #else /* optimized - assuming ULTRIX_SV_OLDSIG=>!ULTRIX_SV_INTERRUPT */ nsa.sa_flags = nsv.sv_flags & ~ULTRIX_SV_OLDSIG; nsa.sa_flags ^= SA_RESTART; #endif native_sigset13_to_sigset(&nsv.sv_mask, &nsa.sa_mask); } error = sigaction1(l, SCARG(uap, signum), SCARG(uap, nsv) ? &nsa : 0, SCARG(uap, osv) ? &osa : 0, NULL, 0); if (error) return error; if (SCARG(uap, osv)) { osv.sv_handler = osa.sa_handler; osv.sv_flags = osa.sa_flags ^ SA_RESTART; osv.sv_flags &= (ULTRIX_SV_ONSTACK | ULTRIX_SV_INTERRUPT); native_sigset_to_sigset13(&osa.sa_mask, &osv.sv_mask); error = copyout(&osv, SCARG(uap, osv), sizeof(osv)); if (error) return error; } return 0; }
int compat_13_netbsd32_sigprocmask(struct lwp *l, const struct compat_13_netbsd32_sigprocmask_args *uap, register_t *retval) { /* { syscallarg(int) how; syscallarg(int) mask; } */ sigset13_t ness, oess; sigset_t nbss, obss; int error; ness = SCARG(uap, mask); native_sigset13_to_sigset(&ness, &nbss); error = sigprocmask1(l, SCARG(uap, how), &nbss, &obss); if (error) return (error); native_sigset_to_sigset13(&obss, &oess); *retval = oess; return (0); }
static vaddr_t setupstack_oldsigcontext(const ksiginfo_t *ksi, const sigset_t *mask, int vers, struct lwp *l, struct trapframe *tf, vaddr_t sp, int onstack, vaddr_t handler) { struct sigcontext sigctx; struct otrampframe tramp; sigctx.sc_pc = tf->pc; sigctx.sc_ps = tf->psl; sigctx.sc_ap = tf->ap; sigctx.sc_fp = tf->fp; sigctx.sc_sp = tf->sp; sigctx.sc_onstack = onstack ? SS_ONSTACK : 0; sigctx.sc_mask = *mask; sp -= sizeof(struct sigcontext); #if defined(COMPAT_13) || defined(COMPAT_ULTRIX) native_sigset_to_sigset13(mask, &sigctx.__sc_mask13); #endif tramp.sig = ksi->ksi_signo; tramp.code = (register_t)ksi->ksi_addr; /* Set up positions for structs on stack */ tramp.scp = sp; /* r0..r5 are saved by the popr in the sigcode snippet but we need to zero them anyway. */ tramp.r0 = tramp.r1 = tramp.r2 = tramp.r3 = tramp.r4 = tramp.r5 = 0; tramp.pc = (register_t)handler; tramp.arg = sp; /* Point stack pointer at pc in trampoline. */ sp =- 8; if (copyout(&tramp, (caddr_t)tramp.scp - sizeof(tramp), sizeof(tramp)) != 0 || copyout(&sigctx, (caddr_t)tramp.scp, sizeof(sigctx)) != 0) return 0; return sp; }
int darwin_sys_sigaction(struct lwp *l, const struct darwin_sys_sigaction_args *uap, register_t *retval) { /* { syscallarg(int) signum; syscallarg(struct darwin___sigaction *) nsa; syscallarg(struct sigaction13 *) osa; } */ struct darwin___sigaction dsa; struct sigaction nsa, osa; struct sigaction13 sa13; int error; if ((error = copyin(SCARG(uap, nsa), &dsa, sizeof(dsa))) != 0) return error; nsa.sa_handler = dsa.darwin_sa_handler.__sa_handler; native_sigset13_to_sigset(&dsa.darwin_sa_mask, &nsa.sa_mask); if (dsa.darwin_sa_flags & ~DARWIN_SA_ALLBITS) { DPRINTF(("darwin_sys_sigaction: ignoring bits (flags = %x)\n", dsa.darwin_sa_flags)); } nsa.sa_flags = dsa.darwin_sa_flags & DARWIN_SA_ALLBITS; error = sigaction1(l, SCARG(uap, signum), &nsa, &osa, dsa.darwin_sa_tramp, 1); if (error != 0) return error; if (SCARG(uap, osa) == NULL) return 0; /* XXX: The returned structure has a different type to that supplied */ sa13.osa_handler = osa.sa_handler; sa13.osa_mask = osa.sa_mask.__bits[0]; native_sigset_to_sigset13(&osa.sa_mask, &sa13.osa_mask); sa13.osa_flags = osa.sa_flags; return copyout(&sa13, SCARG(uap, osa), sizeof(sa13)); }
int compat_13_sys_sigprocmask(struct lwp *l, const struct compat_13_sys_sigprocmask_args *uap, register_t *retval) { /* { syscallarg(int) how; syscallarg(int) mask; } */ struct proc *p = l->l_proc; sigset13_t ness, oess; sigset_t nbss, obss; int error; ness = SCARG(uap, mask); native_sigset13_to_sigset(&ness, &nbss); mutex_enter(p->p_lock); error = sigprocmask1(l, SCARG(uap, how), &nbss, &obss); mutex_exit(p->p_lock); if (error) return (error); native_sigset_to_sigset13(&obss, &oess); *retval = oess; return (0); }
/* * Send a signal to process. */ void sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *returnmask) { int sig = ksi->ksi_signo; struct lwp * const l = curlwp; struct proc * const p = l->l_proc; struct sigacts * const ps = p->p_sigacts; struct pcb * const pcb = lwp_getpcb(l); int onstack, error; struct sigcontext *scp = getframe(l, sig, &onstack); struct sigcontext ksc; struct trapframe * const tf = l->l_md.md_utf; sig_t catcher = SIGACTION(p, sig).sa_handler; #if !defined(__mips_o32) if (p->p_md.md_abi != _MIPS_BSD_API_O32) sigexit(l, SIGILL); #endif scp--; #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) || ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) printf("sendsig(%d): sig %d ssp %p scp %p\n", p->p_pid, sig, &onstack, scp); #endif /* Build stack frame for signal trampoline. */ ksc.sc_pc = tf->tf_regs[_R_PC]; ksc.mullo = tf->tf_regs[_R_MULLO]; ksc.mulhi = tf->tf_regs[_R_MULHI]; /* Save register context. */ ksc.sc_regs[_R_ZERO] = 0xACEDBADE; /* magic number */ #if defined(__mips_o32) memcpy(&ksc.sc_regs[1], &tf->tf_regs[1], sizeof(ksc.sc_regs) - sizeof(ksc.sc_regs[0])); #else for (size_t i = 1; i < 32; i++) ksc.sc_regs[i] = tf->tf_regs[i]; #endif /* Save the FP state, if necessary, then copy it. */ ksc.sc_fpused = fpu_used_p(); #if !defined(NOFPU) if (ksc.sc_fpused) { /* if FPU has current state, save it first */ fpu_save(); } #endif *(struct fpreg *)ksc.sc_fpregs = *(struct fpreg *)&pcb->pcb_fpregs; /* Save signal stack. */ ksc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; /* Save signal mask. */ ksc.sc_mask = *returnmask; #if defined(COMPAT_13) || defined(COMPAT_ULTRIX) /* * XXX We always have to save an old style signal mask because * XXX we might be delivering a signal to a process which will * XXX escape from the signal in a non-standard way and invoke * XXX sigreturn() directly. */ native_sigset_to_sigset13(returnmask, &ksc.__sc_mask13); #endif sendsig_reset(l, sig); mutex_exit(p->p_lock); error = copyout(&ksc, (void *)scp, sizeof(ksc)); mutex_enter(p->p_lock); if (error != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) || ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) printf("sendsig(%d): copyout failed on sig %d\n", p->p_pid, sig); #endif sigexit(l, SIGILL); /* NOTREACHED */ } /* * Set up the registers to directly invoke the signal * handler. The return address will be set up to point * to the signal trampoline to bounce us back. */ tf->tf_regs[_R_A0] = sig; tf->tf_regs[_R_A1] = ksi->ksi_trap; tf->tf_regs[_R_A2] = (intptr_t)scp; tf->tf_regs[_R_A3] = (intptr_t)catcher; /* XXX ??? */ tf->tf_regs[_R_PC] = (intptr_t)catcher; tf->tf_regs[_R_T9] = (intptr_t)catcher; tf->tf_regs[_R_SP] = (intptr_t)scp; switch (ps->sa_sigdesc[sig].sd_vers) { case 0: /* legacy on-stack sigtramp */ tf->tf_regs[_R_RA] = (intptr_t)p->p_sigctx.ps_sigcode; break; #ifdef COMPAT_16 case 1: tf->tf_regs[_R_RA] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp; break; #endif default: /* Don't know what trampoline version; kill it. */ sigexit(l, SIGILL); } /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) || ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) printf("sendsig(%d): sig %d returns\n", p->p_pid, sig); #endif }
/* * Send an interrupt to process. */ void sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sigacts *ps = p->p_sigacts; struct frame *frame = (struct frame *)l->l_md.md_regs; int onstack; int sig = ksi->ksi_signo; u_long code = KSI_TRAPCODE(ksi); struct sigframe_sigcontext *fp = getframe(l, sig, &onstack), kf; sig_t catcher = SIGACTION(p, sig).sa_handler; short ft = frame->f_format; fp--; #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): sig %d ssp %p usp %p scp %p ft %d\n", p->p_pid, sig, &onstack, fp, &fp->sf_sc, ft); #endif /* Build stack frame for signal trampoline. */ switch (ps->sa_sigdesc[sig].sd_vers) { case 0: /* legacy on-stack sigtramp */ kf.sf_ra = (int)p->p_sigctx.ps_sigcode; break; case 1: kf.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp; break; default: /* Don't know what trampoline version; kill it. */ sigexit(l, SIGILL); } kf.sf_signum = sig; kf.sf_code = code; kf.sf_scp = &fp->sf_sc; /* * Save necessary hardware state. Currently this includes: * - general registers * - original exception frame (if not a "normal" frame) * - FP coprocessor state */ kf.sf_state.ss_flags = SS_USERREGS; memcpy(kf.sf_state.ss_frame.f_regs, frame->f_regs, sizeof(frame->f_regs)); if (ft >= FMT4) { #ifdef DEBUG if (ft > 15 || exframesize[ft] < 0) panic("sendsig: bogus frame type"); #endif kf.sf_state.ss_flags |= SS_RTEFRAME; kf.sf_state.ss_frame.f_format = frame->f_format; kf.sf_state.ss_frame.f_vector = frame->f_vector; memcpy(&kf.sf_state.ss_frame.F_u, &frame->F_u, (size_t) exframesize[ft]); /* * Leave an indicator that we need to clean up the kernel * stack. We do this by setting the "pad word" above the * hardware stack frame to the amount the stack must be * adjusted by. * * N.B. we increment rather than just set f_stackadj in * case we are called from syscall when processing a * sigreturn. In that case, f_stackadj may be non-zero. */ frame->f_stackadj += exframesize[ft]; frame->f_format = frame->f_vector = 0; #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sendsig(%d): copy out %d of frame %d\n", p->p_pid, exframesize[ft], ft); #endif } if (fputype) { kf.sf_state.ss_flags |= SS_FPSTATE; m68881_save(&kf.sf_state.ss_fpstate); } #ifdef DEBUG if ((sigdebug & SDB_FPSTATE) && *(char *)&kf.sf_state.ss_fpstate) printf("sendsig(%d): copy out FP state (%x) to %p\n", p->p_pid, *(u_int *)&kf.sf_state.ss_fpstate, &kf.sf_state.ss_fpstate); #endif /* Build the signal context to be used by sigreturn. */ kf.sf_sc.sc_sp = frame->f_regs[SP]; kf.sf_sc.sc_fp = frame->f_regs[A6]; kf.sf_sc.sc_ap = (int)&fp->sf_state; kf.sf_sc.sc_pc = frame->f_pc; kf.sf_sc.sc_ps = frame->f_sr; /* Save signal stack. */ kf.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; /* Save signal mask. */ kf.sf_sc.sc_mask = *mask; #ifdef COMPAT_13 /* * XXX We always have to save an old style signal mask because * XXX we might be delivering a signal to a process which will * XXX escape from the signal in a non-standard way and invoke * XXX sigreturn() directly. */ native_sigset_to_sigset13(mask, &kf.sf_sc.__sc_mask13); #endif if (copyout(&kf, fp, sizeof(kf)) != 0) { #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): copyout failed on sig %d\n", p->p_pid, sig); #endif /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(l, SIGILL); /* NOTREACHED */ } #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n", p->p_pid, sig, kf.sf_scp, fp, kf.sf_sc.sc_sp, kf.sf_sc.sc_ap); #endif buildcontext(l, catcher, fp); /* Remember that we're now on the signal stack. */ if (onstack) p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): sig %d returns\n", p->p_pid, sig); #endif }
void sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sigacts *ps = p->p_sigacts; int onstack, sig = ksi->ksi_signo; struct sigframe_sigcontext *fp, frame; struct trapframe *tf; sig_t catcher = SIGACTION(p, sig).sa_handler; tf = l->l_md.md_tf; fp = getframe(l, sig, &onstack), frame; fp--; #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig_sigcontext(%d): sig %d ssp %p usp %p\n", p->p_pid, sig, &onstack, fp); #endif /* Build stack frame for signal trampoline. */ frame.sf_sc.sc_pc = tf->tf_regs[FRAME_PC]; frame.sf_sc.sc_ps = tf->tf_regs[FRAME_PS]; /* Save register context. */ frametoreg(tf, (struct reg *)frame.sf_sc.sc_regs); frame.sf_sc.sc_regs[R_ZERO] = 0xACEDBADE; /* magic number */ frame.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp(); /* save the floating-point state, if necessary, then copy it. */ if (l->l_addr->u_pcb.pcb_fpcpu != NULL) fpusave_proc(l, 1); frame.sf_sc.sc_ownedfp = l->l_md.md_flags & MDP_FPUSED; memcpy((struct fpreg *)frame.sf_sc.sc_fpregs, &l->l_addr->u_pcb.pcb_fp, sizeof(struct fpreg)); frame.sf_sc.sc_fp_control = alpha_read_fp_c(l); memset(frame.sf_sc.sc_reserved, 0, sizeof frame.sf_sc.sc_reserved); memset(frame.sf_sc.sc_xxx, 0, sizeof frame.sf_sc.sc_xxx); /* XXX */ /* Save signal stack. */ frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; /* Save signal mask. */ frame.sf_sc.sc_mask = *mask; #ifdef COMPAT_13 /* * XXX We always have to save an old style signal mask because * XXX we might be delivering a signal to a process which will * XXX escape from the signal in a non-standard way and invoke * XXX sigreturn() directly. */ { /* Note: it's a long in the stack frame. */ sigset13_t mask13; native_sigset_to_sigset13(mask, &mask13); frame.sf_sc.__sc_mask13 = mask13; } #endif #ifdef COMPAT_OSF1 /* * XXX Create an OSF/1-style sigcontext and associated goo. */ #endif if (copyout(&frame, (caddr_t)fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig_sigcontext(%d): copyout failed on sig %d\n", p->p_pid, sig); #endif sigexit(l, SIGILL); /* NOTREACHED */ } #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sendsig_sigcontext(%d): sig %d usp %p code %x\n", p->p_pid, sig, fp, ksi->ksi_code); #endif /* * Set up the registers to directly invoke the signal handler. The * signal trampoline is then used to return from the signal. Note * the trampoline version numbers are coordinated with machine- * dependent code in libc. */ switch (ps->sa_sigdesc[sig].sd_vers) { case 0: /* legacy on-stack sigtramp */ buildcontext(l,(void *)catcher, (void *)p->p_sigctx.ps_sigcode, (void *)fp); break; case 1: buildcontext(l,(void *)catcher, (void *)ps->sa_sigdesc[sig].sd_tramp, (void *)fp); break; default: /* Don't know what trampoline version; kill it. */ sigexit(l, SIGILL); } /* sigcontext specific trap frame */ tf->tf_regs[FRAME_A0] = sig; /* tf->tf_regs[FRAME_A1] = ksi->ksi_code; */ tf->tf_regs[FRAME_A1] = KSI_TRAPCODE(ksi); tf->tf_regs[FRAME_A2] = (u_int64_t)&fp->sf_sc; /* Remember that we're now on the signal stack. */ if (onstack) p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid, tf->tf_regs[FRAME_PC], tf->tf_regs[FRAME_A3]); if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): sig %d returns\n", p->p_pid, sig); #endif }
/* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ void sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sigacts *ps = p->p_sigacts; struct reg *regs; int sig = ksi->ksi_signo; int onstack; struct sigframe *fp = getframe(l, sig, &onstack), frame; sig_t catcher = SIGACTION(p, sig).sa_handler; regs = l->l_md.md_regs; fp--; /* Build stack frame for signal trampoline. */ switch (ps->sa_sigdesc[sig].sd_vers) { case 0: frame.sf_ra = (int)p->p_sigctx.ps_sigcode; break; case 1: frame.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp; break; default: /* Don't know what trampoline version; kill it. */ sigexit(l, SIGILL); } frame.sf_signum = sig; frame.sf_code = ksi->ksi_trap; frame.sf_scp = &fp->sf_sc; /* Save the register context. */ frame.sf_sc.sc_fp = regs->r_fp; frame.sf_sc.sc_sp = regs->r_sp; frame.sf_sc.sc_pc = regs->r_pc; frame.sf_sc.sc_ps = regs->r_psr; frame.sf_sc.sc_sb = regs->r_sb; frame.sf_sc.sc_reg[REG_R7] = regs->r_r7; frame.sf_sc.sc_reg[REG_R6] = regs->r_r6; frame.sf_sc.sc_reg[REG_R5] = regs->r_r5; frame.sf_sc.sc_reg[REG_R4] = regs->r_r4; frame.sf_sc.sc_reg[REG_R3] = regs->r_r3; frame.sf_sc.sc_reg[REG_R2] = regs->r_r2; frame.sf_sc.sc_reg[REG_R1] = regs->r_r1; frame.sf_sc.sc_reg[REG_R0] = regs->r_r0; /* Save signal stack. */ frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; /* Save the signal mask. */ frame.sf_sc.sc_mask = *mask; #ifdef COMPAT_13 /* * XXX We always have to save an old style signal mask because * XXX we might be delivering a signal to a process which will * XXX escape from the signal in a non-standard way and invoke * XXX sigreturn() directly. */ native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13); #endif if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(l, SIGILL); /* NOTREACHED */ } /* * Build context to run handler in. We invoke the handler * directly, only returning via the trampoline. Note the * trampoline version numbers are coordinated with machine- * dependent code in libc. */ regs->r_sp = (int)fp; regs->r_pc = (int)catcher; /* Remember that we're now on the signal stack. */ if (onstack) p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; }
void sunos_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sunos_sigframe *fp; struct trapframe *tf; int addr, onstack, oldsp, newsp, error; int sig = ksi->ksi_signo; u_long code = ksi->ksi_code; sig_t catcher = SIGACTION(p, sig).sa_handler; struct sunos_sigframe sf; tf = l->l_md.md_tf; oldsp = tf->tf_out[6]; /* * Compute new user stack addresses, subtract off * one signal frame, and align. */ onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; if (onstack) fp = (struct sunos_sigframe *) ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else fp = (struct sunos_sigframe *)oldsp; fp = (struct sunos_sigframe *)((int)(fp - 1) & ~7); #ifdef DEBUG if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) printf("sendsig: %s[%d] sig %d newusp %p scp %p\n", p->p_comm, p->p_pid, sig, fp, &fp->sf_sc); #endif /* * Now set up the signal frame. We build it in kernel space * and then copy it out. We probably ought to just build it * directly in user space.... */ sf.sf_signo = sig; sf.sf_code = code; sf.sf_scp = &fp->sf_sc; sf.sf_addr = 0; /* XXX */ /* * Build the signal context to be used by sigreturn. */ sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask); sf.sf_sc.sc_sp = oldsp; sf.sf_sc.sc_pc = tf->tf_pc; sf.sf_sc.sc_npc = tf->tf_npc; sf.sf_sc.sc_psr = tf->tf_psr; sf.sf_sc.sc_g1 = tf->tf_global[1]; sf.sf_sc.sc_o0 = tf->tf_out[0]; /* * Put the stack in a consistent state before we whack away * at it. Note that write_user_windows may just dump the * registers into the pcb; we need them in the process's memory. * We also need to make sure that when we start the signal handler, * its %i6 (%fp), which is loaded from the newly allocated stack area, * joins seamlessly with the frame it was in when the signal occurred, * so that the debugger and _longjmp code can back up through it. */ sendsig_reset(l, sig); mutex_exit(p->p_lock); newsp = (int)fp - sizeof(struct rwindow); write_user_windows(); error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) || suword(&((struct rwindow *)newsp)->rw_in[6], oldsp)); mutex_enter(p->p_lock); if (error) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) printf("sendsig: window save or copyout error\n"); #endif sigexit(l, SIGILL); /* NOTREACHED */ } #ifdef DEBUG if (sunos_sigdebug & SDB_FOLLOW) printf("sendsig: %s[%d] sig %d scp %p\n", p->p_comm, p->p_pid, sig, &fp->sf_sc); #endif /* * Arrange to continue execution at the code copied out in exec(). * It needs the function to call in %g1, and a new stack pointer. */ addr = (int)catcher; /* user does his own trampolining */ tf->tf_pc = addr; tf->tf_npc = addr + 4; tf->tf_out[6] = newsp; /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; #ifdef DEBUG if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) printf("sendsig: about to return to catcher\n"); #endif }
void sunos32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) { int sig = ksi->ksi_signo; struct lwp *l = curlwp; /* XXX */ struct proc *p = l->l_proc; struct sunos32_sigframe *fp; struct trapframe64 *tf; struct rwindow32 *oldsp, *newsp; struct sunos32_sigframe sf; struct sunos32_sigcontext *scp; uint32_t addr, oldsp32; int onstack, error; sig_t catcher = SIGACTION(p, sig).sa_handler; tf = l->l_md.md_tf; /* Need to attempt to zero extend this 32-bit pointer */ oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6]; oldsp32 = (uint32_t)(u_long)oldsp; /* * Compute new user stack addresses, subtract off * one signal frame, and align. */ onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; if (onstack) fp = (struct sunos32_sigframe *) ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else fp = (struct sunos32_sigframe *)oldsp; fp = (struct sunos32_sigframe *)((u_long)(fp - 1) & ~7); #ifdef DEBUG sigpid = p->p_pid; if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { mutex_exit(p->p_lock); printf("sunos32_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n", p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp); #ifdef DDB if (sigdebug & SDB_DDB) Debugger(); #endif mutex_enter(p->p_lock); } #endif /* * Now set up the signal frame. We build it in kernel space * and then copy it out. We probably ought to just build it * directly in user space.... */ sf.sf_signo = sig; sf.sf_code = (uint32_t)ksi->ksi_trap; scp = &fp->sf_sc; if ((u_long)scp >= 0x100000000) printf("sunos32_sendsig: sf_scp overflow %p > 0x100000000\n", scp); sf.sf_scp = (uint32_t)(u_long)scp; sf.sf_addr = 0; /* XXX */ /* * Build the signal context to be used by sigreturn. */ sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask); sf.sf_sc.sc_sp = (u_int)(u_long)oldsp; sf.sf_sc.sc_pc = tf->tf_pc; sf.sf_sc.sc_npc = tf->tf_npc; sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */ sf.sf_sc.sc_g1 = tf->tf_global[1]; sf.sf_sc.sc_o0 = tf->tf_out[0]; /* * Put the stack in a consistent state before we whack away * at it. Note that write_user_windows may just dump the * registers into the pcb; we need them in the process's memory. * We also need to make sure that when we start the signal handler, * its %i6 (%fp), which is loaded from the newly allocated stack area, * joins seamlessly with the frame it was in when the signal occurred, * so that the debugger and _longjmp code can back up through it. */ sendsig_reset(l, sig); mutex_exit(p->p_lock); newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32)); write_user_windows(); #ifdef DEBUG if ((sigdebug & SDB_KSTACK)) printf("sunos32_sendsig: saving sf to %p, setting stack pointer %p to %p\n", fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp); #endif error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) || copyout((void *)&oldsp32, &(((struct rwindow32 *)newsp)->rw_in[6]), sizeof oldsp32)); mutex_enter(p->p_lock); if (error) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG mutex_exit(p->p_lock); if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sunos32_sendsig: window save or copyout error\n"); printf("sunos32_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig); #ifdef DDB if (sigdebug & SDB_DDB) Debugger(); #endif mutex_enter(p->p_lock); #endif sigexit(l, SIGILL); /* NOTREACHED */ } #ifdef DEBUG if ((sigdebug & SDB_FOLLOW)) { printf("sunos32_sendsig: %s[%d] sig %d scp %p\n", p->p_comm, p->p_pid, sig, &fp->sf_sc); } #endif /* * Arrange to continue execution at the code copied out in exec(). * It needs the function to call in %g1, and a new stack pointer. */ addr = (uint32_t)(u_long)catcher; /* user does his own trampolining */ tf->tf_pc = addr; tf->tf_npc = addr + 4; tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp; #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { mutex_exit(p->p_lock); printf("sunos32_sendsig: about to return to catcher %p thru %p\n", catcher, (void *)(u_long)addr); #ifdef DDB if (sigdebug & SDB_DDB) Debugger(); #endif mutex_enter(p->p_lock); } #endif }
/* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ void sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct pmap *pmap = vm_map_pmap(&p->p_vmspace->vm_map); int sel = pmap->pm_hiexec > I386_MAX_EXE_ADDR ? GUCODEBIG_SEL : GUCODE_SEL; struct sigacts *ps = p->p_sigacts; struct trapframe *tf = l->l_md.md_regs; int onstack, error; int sig = ksi->ksi_signo; u_long code = KSI_TRAPCODE(ksi); struct sigframe_sigcontext *fp = getframe(l, sig, &onstack), frame; sig_t catcher = SIGACTION(p, sig).sa_handler; fp--; /* Build stack frame for signal trampoline. */ switch (ps->sa_sigdesc[sig].sd_vers) { case 0: /* legacy on-stack sigtramp */ frame.sf_ra = (int)p->p_sigctx.ps_sigcode; break; case 1: frame.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp; break; default: /* Don't know what trampoline version; kill it. */ sigexit(l, SIGILL); } frame.sf_signum = sig; frame.sf_code = code; frame.sf_scp = &fp->sf_sc; /* Save register context. */ #ifdef VM86 if (tf->tf_eflags & PSL_VM) { frame.sf_sc.sc_gs = tf->tf_vm86_gs; frame.sf_sc.sc_fs = tf->tf_vm86_fs; frame.sf_sc.sc_es = tf->tf_vm86_es; frame.sf_sc.sc_ds = tf->tf_vm86_ds; frame.sf_sc.sc_eflags = get_vflags(l); (*p->p_emul->e_syscall_intern)(p); } else #endif { frame.sf_sc.sc_gs = tf->tf_gs; frame.sf_sc.sc_fs = tf->tf_fs; frame.sf_sc.sc_es = tf->tf_es; frame.sf_sc.sc_ds = tf->tf_ds; frame.sf_sc.sc_eflags = tf->tf_eflags; } frame.sf_sc.sc_edi = tf->tf_edi; frame.sf_sc.sc_esi = tf->tf_esi; frame.sf_sc.sc_ebp = tf->tf_ebp; frame.sf_sc.sc_ebx = tf->tf_ebx; frame.sf_sc.sc_edx = tf->tf_edx; frame.sf_sc.sc_ecx = tf->tf_ecx; frame.sf_sc.sc_eax = tf->tf_eax; frame.sf_sc.sc_eip = tf->tf_eip; frame.sf_sc.sc_cs = tf->tf_cs; frame.sf_sc.sc_esp = tf->tf_esp; frame.sf_sc.sc_ss = tf->tf_ss; frame.sf_sc.sc_trapno = tf->tf_trapno; frame.sf_sc.sc_err = tf->tf_err; /* Save signal stack. */ frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; /* Save signal mask. */ frame.sf_sc.sc_mask = *mask; #ifdef COMPAT_13 /* * XXX We always have to save an old style signal mask because * XXX we might be delivering a signal to a process which will * XXX escape from the signal in a non-standard way and invoke * XXX sigreturn() directly. */ native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13); #endif sendsig_reset(l, sig); mutex_exit(p->p_lock); error = copyout(&frame, fp, sizeof(frame)); mutex_enter(p->p_lock); if (error != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(l, SIGILL); /* NOTREACHED */ } int svufpu = l->l_md.md_flags & MDL_USEDFPU; buildcontext(l, sel, catcher, fp); l->l_md.md_flags |= svufpu; /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; }