void native_to_linux_sigaction(struct linux_sigaction *lsa, const struct sigaction *bsa) { lsa->linux_sa_handler = bsa->sa_handler; native_to_linux_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); #ifndef __alpha__ lsa->linux_sa_restorer = NULL; #endif }
static void linux_save_ucontext(struct lwp *l, struct trapframe *tf, const sigset_t *mask, struct sigaltstack *sas, struct linux_ucontext *uc) { uc->uc_flags = 0; uc->uc_link = NULL; native_to_linux_sigaltstack(&uc->uc_stack, sas); linux_save_sigcontext(l, tf, mask, &uc->uc_mcontext); native_to_linux_sigset(&uc->uc_sigmask, mask); (void)memset(&uc->uc_fpregs_mem, 0, sizeof(uc->uc_fpregs_mem)); }
void native_to_linux_old_extra_sigset(linux_old_sigset_t *lss, unsigned long *extra, const sigset_t *bss) { linux_sigset_t lsnew; native_to_linux_sigset(&lsnew, bss); /* convert new sigset to old sigset */ *lss = lsnew.sig[0]; if (extra) memcpy(extra, &lsnew.sig[1], sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); }
int linux_sys_rt_sigprocmask(struct lwp *l, const struct linux_sys_rt_sigprocmask_args *uap, register_t *retval) { /* { syscallarg(int) how; syscallarg(const linux_sigset_t *) set; syscallarg(linux_sigset_t *) oset; syscallarg(size_t) sigsetsize; } */ linux_sigset_t nlss, olss, *oset; const linux_sigset_t *set; struct proc *p = l->l_proc; sigset_t nbss, obss; int error, how; if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) return (EINVAL); switch (SCARG(uap, how)) { case LINUX_SIG_BLOCK: how = SIG_BLOCK; break; case LINUX_SIG_UNBLOCK: how = SIG_UNBLOCK; break; case LINUX_SIG_SETMASK: how = SIG_SETMASK; break; default: return (EINVAL); } set = SCARG(uap, set); oset = SCARG(uap, oset); if (set) { error = copyin(set, &nlss, sizeof(nlss)); if (error) return (error); linux_to_native_sigset(&nbss, &nlss); } mutex_enter(p->p_lock); error = sigprocmask1(l, how, set ? &nbss : NULL, oset ? &obss : NULL); mutex_exit(p->p_lock); if (!error && oset) { native_to_linux_sigset(&olss, &obss); error = copyout(&olss, oset, sizeof(olss)); } return (error); }
int linux_sys_rt_sigpending(struct lwp *l, const struct linux_sys_rt_sigpending_args *uap, register_t *retval) { /* { syscallarg(linux_sigset_t *) set; syscallarg(size_t) sigsetsize; } */ sigset_t bss; linux_sigset_t lss; if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) return (EINVAL); sigpending1(l, &bss); native_to_linux_sigset(&lss, &bss); return copyout(&lss, SCARG(uap, set), sizeof(lss)); }
void linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) { const int sig = ksi->ksi_signo; struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sigacts *ps = p->p_sigacts; struct linux_rt_sigframe *fp; struct frame *f; int i, onstack, error; struct linux_rt_sigframe sf; #ifdef DEBUG_LINUX printf("linux_sendsig()\n"); #endif /* DEBUG_LINUX */ f = (struct frame *)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) panic("linux_sendsig: onstack notyet"); else fp = (struct linux_rt_sigframe *)(u_int32_t)f->f_regs[_R_SP]; /* * Build stack frame for signal trampoline. */ memset(&sf, 0, sizeof sf); #if LINUX_SYS_rt_sigreturn > 127 #error LINUX_SYS_rt_sigreturn does not fit in a 16-bit opcode. #endif /* * This is the signal trampoline used by Linux, we don't use it, * but we set it up in case an application expects it to be there. * * mov r8, LINUX_SYS_rt_sigreturn * scall */ sf.lrs_code = (0x3008d733 | LINUX_SYS_rt_sigreturn << 20); /* * The user context. */ native_to_linux_sigset(&sf.lrs_uc.luc_sigmask, mask); sf.lrs_uc.luc_flags = 0; sf.lrs_uc.luc_link = NULL; /* This is used regardless of SA_ONSTACK in Linux AVR32. */ sf.lrs_uc.luc_stack.ss_sp = l->l_sigstk.ss_sp; sf.lrs_uc.luc_stack.ss_size = l->l_sigstk.ss_size; sf.lrs_uc.luc_stack.ss_flags = 0; if (l->l_sigstk.ss_flags & SS_ONSTACK) sf.lrs_uc.luc_stack.ss_flags |= LINUX_SS_ONSTACK; if (l->l_sigstk.ss_flags & SS_DISABLE) sf.lrs_uc.luc_stack.ss_flags |= LINUX_SS_DISABLE; memcpy(sf.lrs_uc.luc_mcontext.lsc_regs, f->f_regs, sizeof(sf.lrs_uc.luc_mcontext.lsc_regs)); sendsig_reset(l, sig); /* * Install the sigframe onto the stack. */ fp -= sizeof(struct linux_rt_sigframe); mutex_exit(p->p_lock); error = copyout(&sf, fp, sizeof(sf)); 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_LINUX printf("linux_sendsig: stack trashed\n"); #endif /* DEBUG_LINUX */ sigexit(l, SIGILL); /* NOTREACHED */ } #ifdef DEBUG_LINUX printf("sigcontext is at %p\n", &fp->lrs_sc); #endif /* DEBUG_LINUX */ /* Set up the registers to return to sigcode. */ f->f_regs[_R_SP] = (register_t)fp; f->f_regs[_R_R12] = native_to_linux_signo[sig]; f->f_regs[_R_R11] = 0; f->f_regs[_R_R10] = (register_t)&fp->lrs_uc; f->f_regs[_R_PC] = (register_t)SIGACTION(p, sig).sa_handler; #define RESTORER(p, sig) \ (p->p_sigacts->sa_sigdesc[(sig)].sd_tramp) if (ps->sa_sigdesc[sig].sd_vers != 0) f->f_regs[_R_LR] = (register_t)RESTORER(p, sig); else panic("linux_sendsig: SA_RESTORER"); /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; return; }
void setup_linux_rt_sigframe(struct trapframe *tf, const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct linux_rt_sigframe *sfp, sigframe; int onstack, error; int fsize, rndfsize; int sig = ksi->ksi_signo; extern char linux_rt_sigcode[], linux_rt_esigcode[]; /* 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. */ fsize = sizeof(struct linux_rt_sigframe); rndfsize = ((fsize + 15) / 16) * 16; if (onstack) sfp = (struct linux_rt_sigframe *) ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else sfp = (struct linux_rt_sigframe *)(alpha_pal_rdusp()); sfp = (struct linux_rt_sigframe *)((char *)sfp - rndfsize); #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && (p->p_pid == sigpid)) printf("linux_sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid, sig, &onstack, sfp); #endif /* DEBUG */ /* * Build the signal context to be used by sigreturn. */ memset(&sigframe.uc, 0, sizeof(struct linux_ucontext)); sigframe.uc.uc_mcontext.sc_onstack = onstack; /* Setup potentially partial signal mask in sc_mask. */ /* But get all of it in uc_sigmask */ native_to_linux_old_sigset(&sigframe.uc.uc_mcontext.sc_mask, mask); native_to_linux_sigset(&sigframe.uc.uc_sigmask, mask); sigframe.uc.uc_mcontext.sc_pc = tf->tf_regs[FRAME_PC]; sigframe.uc.uc_mcontext.sc_ps = ALPHA_PSL_USERMODE; frametoreg(tf, (struct reg *)sigframe.uc.uc_mcontext.sc_regs); sigframe.uc.uc_mcontext.sc_regs[R_SP] = alpha_pal_rdusp(); fpu_load(); alpha_pal_wrfen(1); sigframe.uc.uc_mcontext.sc_fpcr = alpha_read_fpcr(); sigframe.uc.uc_mcontext.sc_fp_control = alpha_read_fp_c(l); alpha_pal_wrfen(0); sigframe.uc.uc_mcontext.sc_traparg_a0 = tf->tf_regs[FRAME_A0]; sigframe.uc.uc_mcontext.sc_traparg_a1 = tf->tf_regs[FRAME_A1]; sigframe.uc.uc_mcontext.sc_traparg_a2 = tf->tf_regs[FRAME_A2]; native_to_linux_siginfo(&sigframe.info, &ksi->ksi_info); sendsig_reset(l, sig); mutex_exit(p->p_lock); error = copyout((void *)&sigframe, (void *)sfp, fsize); mutex_enter(p->p_lock); if (error != 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 */ } /* Pass pointers to siginfo and ucontext in the regs */ tf->tf_regs[FRAME_A1] = (unsigned long)&sfp->info; tf->tf_regs[FRAME_A2] = (unsigned long)&sfp->uc; /* Address of trampoline code. End up at this PC after mi_switch */ tf->tf_regs[FRAME_PC] = (u_int64_t)(p->p_psstrp - (linux_rt_esigcode - linux_rt_sigcode)); /* Adjust the stack */ alpha_pal_wrusp((unsigned long)sfp); /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; }
void linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) { const int sig = ksi->ksi_signo; struct lwp *l = curlwp; struct proc *p = l->l_proc; struct linux_sigframe *fp; struct frame *f; int i, onstack, error; sig_t catcher = SIGACTION(p, sig).sa_handler; struct linux_sigframe sf; #ifdef DEBUG_LINUX printf("linux_sendsig()\n"); #endif /* DEBUG_LINUX */ f = (struct frame *)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; /* * Signal stack is broken (see at the end of linux_sigreturn), so we do * not use it yet. XXX fix this. */ onstack=0; /* * Allocate space for the signal handler context. */ if (onstack) fp = (struct linux_sigframe *) ((uint8_t *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else /* cast for _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN case */ fp = (struct linux_sigframe *)(u_int32_t)f->f_regs[_R_SP]; /* * Build stack frame for signal trampoline. */ memset(&sf, 0, sizeof sf); /* * This is the signal trampoline used by Linux, we don't use it, * but we set it up in case an application expects it to be there */ sf.lsf_code[0] = 0x24020000; /* li v0, __NR_sigreturn */ sf.lsf_code[1] = 0x0000000c; /* syscall */ native_to_linux_sigset(&sf.lsf_mask, mask); for (i=0; i<32; i++) { sf.lsf_sc.lsc_regs[i] = f->f_regs[i]; } sf.lsf_sc.lsc_mdhi = f->f_regs[_R_MULHI]; sf.lsf_sc.lsc_mdlo = f->f_regs[_R_MULLO]; sf.lsf_sc.lsc_pc = f->f_regs[_R_PC]; sf.lsf_sc.lsc_status = f->f_regs[_R_SR]; sf.lsf_sc.lsc_cause = f->f_regs[_R_CAUSE]; sf.lsf_sc.lsc_badvaddr = f->f_regs[_R_BADVADDR]; sendsig_reset(l, sig); /* * Save signal stack. XXX broken */ /* kregs.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; */ /* * Install the sigframe onto the stack */ fp -= sizeof(struct linux_sigframe); mutex_exit(p->p_lock); error = copyout(&sf, fp, sizeof(sf)); 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_LINUX printf("linux_sendsig: stack trashed\n"); #endif /* DEBUG_LINUX */ sigexit(l, SIGILL); /* NOTREACHED */ } /* Set up the registers to return to sigcode. */ f->f_regs[_R_A0] = native_to_linux_signo[sig]; f->f_regs[_R_A1] = 0; f->f_regs[_R_A2] = (unsigned long)&fp->lsf_sc; #ifdef DEBUG_LINUX printf("sigcontext is at %p\n", &fp->lsf_sc); #endif /* DEBUG_LINUX */ f->f_regs[_R_SP] = (unsigned long)fp; /* Signal trampoline code is at base of user stack. */ f->f_regs[_R_RA] = (unsigned long)p->p_sigctx.ps_sigcode; f->f_regs[_R_T9] = (unsigned long)catcher; f->f_regs[_R_PC] = (unsigned long)catcher; /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; return; }
void linux_sendsig(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 linux_rt_sigframe *sfp, sigframe; struct linux__fpstate *fpsp, fpstate; struct fpreg fpregs; struct trapframe *tf = l->l_md.md_regs; sig_t catcher = SIGACTION(p, sig).sa_handler; linux_sigset_t lmask; char *sp; /* 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) sp = ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else sp = (char *)tf->tf_rsp - 128; /* * Save FPU state, if any */ if (l->l_md.md_flags & MDP_USEDFPU) { sp = (char *) (((long)sp - sizeof(struct linux__fpstate)) & ~0xfUL); fpsp = (struct linux__fpstate *)sp; } else fpsp = NULL; /* * Populate the rt_sigframe */ sp = (char *) ((((long)sp - sizeof(struct linux_rt_sigframe)) & ~0xfUL) - 8); sfp = (struct linux_rt_sigframe *)sp; bzero(&sigframe, sizeof(sigframe)); if (ps->sa_sigdesc[sig].sd_vers != 0) sigframe.pretcode = (char *)(u_long)ps->sa_sigdesc[sig].sd_tramp; else sigframe.pretcode = NULL; /* * The user context */ sigframe.uc.luc_flags = 0; sigframe.uc.luc_link = NULL; /* This is used regardless of SA_ONSTACK in Linux */ sigframe.uc.luc_stack.ss_sp = l->l_sigstk.ss_sp; sigframe.uc.luc_stack.ss_size = l->l_sigstk.ss_size; sigframe.uc.luc_stack.ss_flags = 0; if (l->l_sigstk.ss_flags & SS_ONSTACK) sigframe.uc.luc_stack.ss_flags |= LINUX_SS_ONSTACK; if (l->l_sigstk.ss_flags & SS_DISABLE) sigframe.uc.luc_stack.ss_flags |= LINUX_SS_DISABLE; sigframe.uc.luc_mcontext.r8 = tf->tf_r8; sigframe.uc.luc_mcontext.r9 = tf->tf_r9; sigframe.uc.luc_mcontext.r10 = tf->tf_r10; sigframe.uc.luc_mcontext.r11 = tf->tf_r11; sigframe.uc.luc_mcontext.r12 = tf->tf_r12; sigframe.uc.luc_mcontext.r13 = tf->tf_r13; sigframe.uc.luc_mcontext.r14 = tf->tf_r14; sigframe.uc.luc_mcontext.r15 = tf->tf_r15; sigframe.uc.luc_mcontext.rdi = tf->tf_rdi; sigframe.uc.luc_mcontext.rsi = tf->tf_rsi; sigframe.uc.luc_mcontext.rbp = tf->tf_rbp; sigframe.uc.luc_mcontext.rbx = tf->tf_rbx; sigframe.uc.luc_mcontext.rdx = tf->tf_rdx; sigframe.uc.luc_mcontext.rax = tf->tf_rax; sigframe.uc.luc_mcontext.rcx = tf->tf_rcx; sigframe.uc.luc_mcontext.rsp = tf->tf_rsp; sigframe.uc.luc_mcontext.rip = tf->tf_rip; sigframe.uc.luc_mcontext.eflags = tf->tf_rflags; sigframe.uc.luc_mcontext.cs = tf->tf_cs; sigframe.uc.luc_mcontext.gs = tf->tf_gs; sigframe.uc.luc_mcontext.fs = tf->tf_fs; sigframe.uc.luc_mcontext.err = tf->tf_err; sigframe.uc.luc_mcontext.trapno = tf->tf_trapno; native_to_linux_sigset(&lmask, mask); sigframe.uc.luc_mcontext.oldmask = lmask.sig[0]; sigframe.uc.luc_mcontext.cr2 = (long)l->l_addr->u_pcb.pcb_onfault; sigframe.uc.luc_mcontext.fpstate = fpsp; native_to_linux_sigset(&sigframe.uc.luc_sigmask, mask); /* * the siginfo structure */ sigframe.info.lsi_signo = native_to_linux_signo[sig]; sigframe.info.lsi_errno = native_to_linux_errno[ksi->ksi_errno]; sigframe.info.lsi_code = native_to_linux_si_code(ksi->ksi_code); /* XXX This is a rought conversion, taken from i386 code */ switch (sigframe.info.lsi_signo) { case LINUX_SIGILL: case LINUX_SIGFPE: case LINUX_SIGSEGV: case LINUX_SIGBUS: case LINUX_SIGTRAP: sigframe.info._sifields._sigfault._addr = ksi->ksi_addr; break; case LINUX_SIGCHLD: sigframe.info._sifields._sigchld._pid = ksi->ksi_pid; sigframe.info._sifields._sigchld._uid = ksi->ksi_uid; sigframe.info._sifields._sigchld._utime = ksi->ksi_utime; sigframe.info._sifields._sigchld._stime = ksi->ksi_stime; if (WCOREDUMP(ksi->ksi_status)) { sigframe.info.lsi_code = LINUX_CLD_DUMPED; sigframe.info._sifields._sigchld._status = _WSTATUS(ksi->ksi_status); } else if (_WSTATUS(ksi->ksi_status)) { sigframe.info.lsi_code = LINUX_CLD_KILLED; sigframe.info._sifields._sigchld._status = _WSTATUS(ksi->ksi_status); } else { sigframe.info.lsi_code = LINUX_CLD_EXITED; sigframe.info._sifields._sigchld._status = ((ksi->ksi_status & 0xff00U) >> 8); } break; case LINUX_SIGIO: sigframe.info._sifields._sigpoll._band = ksi->ksi_band; sigframe.info._sifields._sigpoll._fd = ksi->ksi_fd; break; default: sigframe.info._sifields._sigchld._pid = ksi->ksi_pid; sigframe.info._sifields._sigchld._uid = ksi->ksi_uid; if ((sigframe.info.lsi_signo == LINUX_SIGALRM) || (sigframe.info.lsi_signo >= LINUX_SIGRTMIN)) sigframe.info._sifields._timer._sigval.sival_ptr = ksi->ksi_value.sival_ptr; break; } sendsig_reset(l, sig); mutex_exit(p->p_lock); error = 0; /* * Save FPU state, if any */ if (fpsp != NULL) { (void)process_read_fpregs(l, &fpregs); bzero(&fpstate, sizeof(fpstate)); fpstate.cwd = fpregs.fp_fcw; fpstate.swd = fpregs.fp_fsw; fpstate.twd = fpregs.fp_ftw; fpstate.fop = fpregs.fp_fop; fpstate.rip = fpregs.fp_rip; fpstate.rdp = fpregs.fp_rdp; fpstate.mxcsr = fpregs.fp_mxcsr; fpstate.mxcsr_mask = fpregs.fp_mxcsr_mask; memcpy(&fpstate.st_space, &fpregs.fp_st, sizeof(fpstate.st_space)); memcpy(&fpstate.xmm_space, &fpregs.fp_xmm, sizeof(fpstate.xmm_space)); error = copyout(&fpstate, fpsp, sizeof(fpstate)); } if (error == 0) error = copyout(&sigframe, sp, sizeof(sigframe)); mutex_enter(p->p_lock); if (error != 0) { sigexit(l, SIGILL); return; } linux_buildcontext(l, catcher, sp); tf->tf_rdi = sigframe.info.lsi_signo; tf->tf_rax = 0; tf->tf_rsi = (long)&sfp->info; tf->tf_rdx = (long)&sfp->uc; /* * Remember we use signal stack */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; return; }