void getucontext32(struct lwp *l, ucontext32_t *ucp) { struct proc *p = l->l_proc; KASSERT(mutex_owned(p->p_lock)); ucp->uc_flags = 0; ucp->uc_link = (uint32_t)(intptr_t)l->l_ctxlink; ucp->uc_sigmask = l->l_sigmask; ucp->uc_flags |= _UC_SIGMASK; /* * The (unsupplied) definition of the `current execution stack' * in the System V Interface Definition appears to allow returning * the main context stack. */ if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) { ucp->uc_stack.ss_sp = USRSTACK32; ucp->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize); ucp->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */ } else { /* Simply copy alternate signal execution stack. */ ucp->uc_stack.ss_sp = (uint32_t)(intptr_t)l->l_sigstk.ss_sp; ucp->uc_stack.ss_size = l->l_sigstk.ss_size; ucp->uc_stack.ss_flags = l->l_sigstk.ss_flags; } ucp->uc_flags |= _UC_STACK; mutex_exit(p->p_lock); cpu_getmcontext32(l, &ucp->uc_mcontext, &ucp->uc_flags); mutex_enter(p->p_lock); }
static void netbsd32_sendsig_siginfo(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; int sig = ksi->ksi_signo; ucontext32_t uc; struct sparc32_sigframe_siginfo *fp; siginfo32_t si32; netbsd32_intptr_t catcher; struct trapframe64 *tf = l->l_md.md_tf; struct rwindow32 *oldsp, *newsp; register32_t sp; int ucsz, error; /* Need to attempt to zero extend this 32-bit pointer */ oldsp = (struct rwindow32*)(u_long)(u_int)tf->tf_out[6]; /* Do we need to jump onto the signal stack? */ onstack = (l->l_sigstk.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 sparc32_sigframe_siginfo *) ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else fp = (struct sparc32_sigframe_siginfo *)oldsp; fp = (struct sparc32_sigframe_siginfo*)((u_long)(fp - 1) & ~7); /* * Build the signal context to be used by sigreturn. */ memset(&uc, 0, sizeof uc); uc.uc_flags = _UC_SIGMASK | ((l->l_sigstk.ss_flags & SS_ONSTACK) ? _UC_SETSTACK : _UC_CLRSTACK); uc.uc_sigmask = *mask; uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink; sendsig_reset(l, sig); /* * Now copy the stack contents out to user space. * We 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. * Since we're calling the handler directly, allocate a full size * C stack frame. */ mutex_exit(p->p_lock); cpu_getmcontext32(l, &uc.uc_mcontext, &uc.uc_flags); netbsd32_si_to_si32(&si32, (const siginfo_t *)&ksi->ksi_info); ucsz = (int)(intptr_t)&uc.__uc_pad - (int)(intptr_t)&uc; newsp = (struct rwindow32*)((intptr_t)fp - sizeof(struct frame32)); sp = NETBSD32PTR32I(oldsp); error = (copyout(&si32, &fp->sf_si, sizeof si32) || copyout(&uc, &fp->sf_uc, ucsz) || copyout(&sp, &newsp->rw_in[6], sizeof(sp))); mutex_enter(p->p_lock); if (error) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(l, SIGILL); /* NOTREACHED */ } switch (ps->sa_sigdesc[sig].sd_vers) { default: /* Unsupported trampoline version; kill the process. */ sigexit(l, SIGILL); case 2: /* * Arrange to continue execution at the user's handler. * It needs a new stack pointer, a return address and * three arguments: (signo, siginfo *, ucontext *). */ catcher = (intptr_t)SIGACTION(p, sig).sa_handler; tf->tf_pc = catcher; tf->tf_npc = catcher + 4; tf->tf_out[0] = sig; tf->tf_out[1] = (intptr_t)&fp->sf_si; tf->tf_out[2] = (intptr_t)&fp->sf_uc; tf->tf_out[6] = (intptr_t)newsp; tf->tf_out[7] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp - 8; break; } /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; }
static void netbsd32_sendsig_siginfo(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, error; int sig = ksi->ksi_signo; struct netbsd32_sigframe_siginfo *fp, frame; sig_t catcher = SIGACTION(p, sig).sa_handler; struct trapframe *tf = l->l_md.md_regs; /* Do we need to jump onto the signal stack? */ onstack = (l->l_sigstk.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 netbsd32_sigframe_siginfo *) ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else fp = (struct netbsd32_sigframe_siginfo *)tf->tf_rsp; fp--; /* Build stack frame for signal trampoline. */ switch (ps->sa_sigdesc[sig].sd_vers) { case 0: /* handled by sendsig_sigcontext */ case 1: /* handled by sendsig_sigcontext */ default: /* unknown version */ printf("nsendsig: bad version %d\n", ps->sa_sigdesc[sig].sd_vers); sigexit(l, SIGILL); case 2: break; } frame.sf_ra = (uint32_t)(uintptr_t)ps->sa_sigdesc[sig].sd_tramp; frame.sf_signum = sig; frame.sf_sip = (uint32_t)(uintptr_t)&fp->sf_si; frame.sf_ucp = (uint32_t)(uintptr_t)&fp->sf_uc; netbsd32_si_to_si32(&frame.sf_si, (const siginfo_t *)&ksi->ksi_info); frame.sf_uc.uc_flags = _UC_SIGMASK; frame.sf_uc.uc_sigmask = *mask; frame.sf_uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink; frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) ? _UC_SETSTACK : _UC_CLRSTACK; memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); sendsig_reset(l, sig); mutex_exit(p->p_lock); cpu_getmcontext32(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); 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_ds = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_fs = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_gs = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_rip = (uint64_t)catcher; tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL); tf->tf_rflags &= ~PSL_CLEARSIG; tf->tf_rsp = (uint64_t)fp; tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL); /* Ensure FP state is reset, if FP is used. */ l->l_md.md_flags &= ~MDL_USEDFPU; /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; if ((vaddr_t)catcher >= VM_MAXUSER_ADDRESS32) { /* * process has given an invalid address for the * handler. Stop it, but do not do it before so * we can return the right info to userland (or in core dump) */ sigexit(l, SIGILL); /* NOTREACHED */ } }