static void fasttrap_sigsegv(proc_t *p, kthread_t *t, uintptr_t addr) { #if defined(sun) sigqueue_t *sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); sqp->sq_info.si_signo = SIGSEGV; sqp->sq_info.si_code = SEGV_MAPERR; sqp->sq_info.si_addr = (caddr_t)addr; mutex_enter(&p->p_lock); sigaddqa(p, t, sqp); mutex_exit(&p->p_lock); if (t != NULL) aston(t); #else ksiginfo_t *ksi = kmem_zalloc(sizeof (ksiginfo_t), KM_SLEEP); ksiginfo_init(ksi); ksi->ksi_signo = SIGSEGV; ksi->ksi_code = SEGV_MAPERR; ksi->ksi_addr = (caddr_t)addr; (void) tdksignal(t, SIGSEGV, ksi); #endif }
void dtrace_pid_probe(struct regs *rp) { krwlock_t *rwp = &CPU->cpu_ft_lock; uint32_t instr; /* * This trap should only be invoked if there's a corresponding * enabled dtrace probe. If there isn't, send SIGILL as though * the process had executed an invalid trap instruction. */ rw_enter(rwp, RW_READER); if (dtrace_pid_probe_ptr != NULL && (*dtrace_pid_probe_ptr)(rp) == 0) { rw_exit(rwp); return; } rw_exit(rwp); /* * It is possible that we were preempted after entering the kernel, * and the tracepoint was removed. If it appears that the process hit * our reserved trap instruction, we call send SIGILL just as though * the user had executed an unused trap instruction. */ if (fuword32((void *)rp->r_pc, &instr) != 0 || instr == FASTTRAP_INSTR) { sigqueue_t *sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); proc_t *p = curproc; sqp->sq_info.si_signo = SIGILL; sqp->sq_info.si_code = ILL_ILLTRP; sqp->sq_info.si_addr = (caddr_t)rp->r_pc; sqp->sq_info.si_trapno = 0x38; mutex_enter(&p->p_lock); sigaddqa(p, curthread, sqp); mutex_exit(&p->p_lock); aston(curthread); } }
/* * Handle a watchpoint that occurs while doing copyin() * or copyout() in a system call. * Return non-zero if the fault or signal is cleared * by a debugger while the lwp is stopped. */ static int sys_watchpoint(caddr_t addr, int watchcode, int ta) { extern greg_t getuserpc(void); /* XXX header file */ k_sigset_t smask; register proc_t *p = ttoproc(curthread); register klwp_t *lwp = ttolwp(curthread); register sigqueue_t *sqp; int rval; /* assert no locks are held */ /* ASSERT(curthread->t_nlocks == 0); */ sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); sqp->sq_info.si_signo = SIGTRAP; sqp->sq_info.si_code = watchcode; sqp->sq_info.si_addr = addr; sqp->sq_info.si_trapafter = ta; sqp->sq_info.si_pc = (caddr_t)getuserpc(); mutex_enter(&p->p_lock); /* this will be tested and cleared by the caller */ lwp->lwp_sysabort = 0; if (prismember(&p->p_fltmask, FLTWATCH)) { lwp->lwp_curflt = (uchar_t)FLTWATCH; lwp->lwp_siginfo = sqp->sq_info; stop(PR_FAULTED, FLTWATCH); if (lwp->lwp_curflt == 0) { mutex_exit(&p->p_lock); kmem_free(sqp, sizeof (sigqueue_t)); return (1); } lwp->lwp_curflt = 0; } /* * post the SIGTRAP signal. * Block all other signals so we only stop showing SIGTRAP. */ if (signal_is_blocked(curthread, SIGTRAP) || sigismember(&p->p_ignore, SIGTRAP)) { /* SIGTRAP is blocked or ignored, forget the rest. */ mutex_exit(&p->p_lock); kmem_free(sqp, sizeof (sigqueue_t)); return (0); } sigdelq(p, curthread, SIGTRAP); sigaddqa(p, curthread, sqp); schedctl_finish_sigblock(curthread); smask = curthread->t_hold; sigfillset(&curthread->t_hold); sigdiffset(&curthread->t_hold, &cantmask); sigdelset(&curthread->t_hold, SIGTRAP); mutex_exit(&p->p_lock); rval = ((ISSIG_FAST(curthread, lwp, p, FORREAL))? 0 : 1); /* restore the original signal mask */ mutex_enter(&p->p_lock); curthread->t_hold = smask; mutex_exit(&p->p_lock); return (rval); }