Example #1
0
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
}
Example #2
0
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);
	}
}
Example #3
0
/*
 * 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);
}