static void linux_rt_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct trapframe *tf; struct linux_rt_sigframe *fp, frame; int onstack, error; int sig = ksi->ksi_signo; sig_t catcher = SIGACTION(p, sig).sa_handler; struct sigaltstack *sas = &l->l_sigstk; tf = l->l_md.md_regs; /* Do we need to jump onto the signal stack? */ onstack = (sas->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; /* Allocate space for the signal handler context. */ if (onstack) fp = (struct linux_rt_sigframe *)((char *)sas->ss_sp + sas->ss_size); else fp = (struct linux_rt_sigframe *)tf->tf_esp; fp--; DPRINTF(("rt: onstack = %d, fp = %p sig = %d eip = 0x%x cr2 = 0x%x\n", onstack, fp, sig, tf->tf_eip, ((struct pcb *)lwp_getpcb(l))->pcb_cr2)); /* Build stack frame for signal trampoline. */ frame.sf_handler = catcher; frame.sf_sig = native_to_linux_signo[sig]; frame.sf_sip = &fp->sf_si; frame.sf_ucp = &fp->sf_uc; /* * XXX: the following code assumes that the constants for * siginfo are the same between linux and NetBSD. */ native_to_linux_siginfo(&frame.sf_si, &ksi->ksi_info); /* Save register context. */ linux_save_ucontext(l, tf, mask, sas, &frame.sf_uc); 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 */ } /* * Build context to run handler in. */ tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_eip = ((int)p->p_sigctx.ps_sigcode) + (linux_rt_sigcode - linux_sigcode); tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); tf->tf_eflags &= ~PSL_CLEARSIG; tf->tf_esp = (int)fp; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); /* Remember that we're now on the signal stack. */ if (onstack) sas->ss_flags |= SS_ONSTACK; }
static void linux_rt_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct trapframe *tf; struct linux_rt_sigframe *fp, frame; int onstack, error; linux_siginfo_t *lsi; int sig = ksi->ksi_signo; sig_t catcher = SIGACTION(p, sig).sa_handler; struct sigaltstack *sas = &l->l_sigstk; tf = l->l_md.md_regs; /* Do we need to jump onto the signal stack? */ onstack = (sas->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; /* Allocate space for the signal handler context. */ if (onstack) fp = (struct linux_rt_sigframe *)((char *)sas->ss_sp + sas->ss_size); else fp = (struct linux_rt_sigframe *)tf->tf_esp; fp--; DPRINTF(("rt: onstack = %d, fp = %p sig = %d eip = 0x%x cr2 = 0x%x\n", onstack, fp, sig, tf->tf_eip, l->l_addr->u_pcb.pcb_cr2)); /* Build stack frame for signal trampoline. */ frame.sf_handler = catcher; frame.sf_sig = native_to_linux_signo[sig]; frame.sf_sip = &fp->sf_si; frame.sf_ucp = &fp->sf_uc; /* * XXX: the following code assumes that the constants for * siginfo are the same between linux and NetBSD. */ (void)memset(lsi = &frame.sf_si, 0, sizeof(frame.sf_si)); lsi->lsi_errno = native_to_linux_errno[ksi->ksi_errno]; lsi->lsi_code = ksi->ksi_code; switch (lsi->lsi_signo = frame.sf_sig) { case LINUX_SIGILL: case LINUX_SIGFPE: case LINUX_SIGSEGV: case LINUX_SIGBUS: case LINUX_SIGTRAP: lsi->lsi_addr = ksi->ksi_addr; break; case LINUX_SIGCHLD: lsi->lsi_uid = ksi->ksi_uid; lsi->lsi_pid = ksi->ksi_pid; lsi->lsi_utime = ksi->ksi_utime; lsi->lsi_stime = ksi->ksi_stime; /* XXX is that right? */ lsi->lsi_status = WEXITSTATUS(ksi->ksi_status); break; case LINUX_SIGIO: lsi->lsi_band = ksi->ksi_band; lsi->lsi_fd = ksi->ksi_fd; break; default: lsi->lsi_uid = ksi->ksi_uid; lsi->lsi_pid = ksi->ksi_pid; if (lsi->lsi_signo == LINUX_SIGALRM || lsi->lsi_signo >= LINUX_SIGRTMIN) lsi->lsi_value.sival_ptr = ksi->ksi_value.sival_ptr; break; } /* Save register context. */ linux_save_ucontext(l, tf, mask, sas, &frame.sf_uc); 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 */ } /* * Build context to run handler in. */ tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_eip = ((int)p->p_sigctx.ps_sigcode) + (linux_rt_sigcode - linux_sigcode); tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); tf->tf_eflags &= ~PSL_CLEARSIG; tf->tf_esp = (int)fp; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); /* Remember that we're now on the signal stack. */ if (onstack) sas->ss_flags |= SS_ONSTACK; }