コード例 #1
0
ファイル: sig_unix.cpp プロジェクト: cthulhuology/self
 bool SignalInterface::is_uplevel_trap(int code) { return code == ILL_TRAP_FAULT(ST_UpLevel); }
コード例 #2
0
ファイル: signal.c プロジェクト: andreiw/polaris
static void
ucbsigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp)
{
	struct sigcontext sc;
	int code;
	char *addr;
#ifdef NEVER
	int gwinswitch = 0;
#endif

	sc.sc_onstack = ((ucp->uc_stack.ss_flags & SS_ONSTACK) != 0);
	sc.sc_mask = set2mask(&ucp->uc_sigmask);

#if defined(__sparc)
	if (sig == SIGFPE && sip != NULL && SI_FROMKERNEL(sip) &&
	    (sip->si_code == FPE_INTDIV || sip->si_code == FPE_INTOVF)) {
		/*
		 * Hack to emulate the 4.x kernel behavior of incrementing
		 * the PC on integer divide by zero and integer overflow
		 * on sparc machines.  (5.x does not increment the PC.)
		 */
		ucp->uc_mcontext.gregs[REG_PC] =
		    ucp->uc_mcontext.gregs[REG_nPC];
		ucp->uc_mcontext.gregs[REG_nPC] += 4;
	}
	sc.sc_sp = ucp->uc_mcontext.gregs[REG_SP];
	sc.sc_pc = ucp->uc_mcontext.gregs[REG_PC];
	sc.sc_npc = ucp->uc_mcontext.gregs[REG_nPC];

	/* XX64 There is no REG_PSR for sparcv9, we map in REG_CCR for now */
#if defined(__sparcv9)
	sc.sc_psr = ucp->uc_mcontext.gregs[REG_CCR];
#else
	sc.sc_psr = ucp->uc_mcontext.gregs[REG_PSR];
#endif

	sc.sc_g1 = ucp->uc_mcontext.gregs[REG_G1];
	sc.sc_o0 = ucp->uc_mcontext.gregs[REG_O0];

	/*
	 * XXX - What a kludge!
	 * Store a pointer to the original ucontext_t in the sigcontext
	 * so that it's available to the sigcleanup call that needs to
	 * return from the signal handler.  Otherwise, vital information
	 * (e.g., the "out" registers) that's only saved in the
	 * ucontext_t isn't available to sigcleanup.
	 */
	sc.sc_wbcnt = (int)(sizeof (*ucp));
	sc.sc_spbuf[0] = (char *)(uintptr_t)sig;
	sc.sc_spbuf[1] = (char *)ucp;
#ifdef NEVER
	/*
	 * XXX - Sorry, we can never pass the saved register windows
	 * on in the sigcontext because we use that space to save the
	 * ucontext_t.
	 */
	if (ucp->uc_mcontext.gwins != (gwindows_t *)0) {
		int i, j;

		gwinswitch = 1;
		sc.sc_wbcnt = ucp->uc_mcontext.gwins->wbcnt;
		/* XXX - should use bcopy to move this in bulk */
		for (i = 0; i < ucp->uc_mcontext.gwins; i++) {
			sc.sc_spbuf[i] = ucp->uc_mcontext.gwins->spbuf[i];
			for (j = 0; j < 8; j++)
				sc.sc_wbuf[i][j] =
				    ucp->uc_mcontext.gwins->wbuf[i].rw_local[j];
			for (j = 0; j < 8; j++)
				sc.sc_wbuf[i][j+8] =
				    ucp->uc_mcontext.gwins->wbuf[i].rw_in[j];
		}
	}
#endif
#endif

	/*
	 * Translate signal codes from new to old.
	 * /usr/include/sys/siginfo.h contains new codes.
	 * /usr/ucbinclude/sys/signal.h contains old codes.
	 */
	code = 0;
	addr = SIG_NOADDR;
	if (sip != NULL && SI_FROMKERNEL(sip)) {
		addr = sip->si_addr;

		switch (sig) {
		case SIGILL:
			switch (sip->si_code) {
			case ILL_PRVOPC:
				code = ILL_PRIVINSTR_FAULT;
				break;
			case ILL_BADSTK:
				code = ILL_STACK;
				break;
			case ILL_ILLTRP:
				code = ILL_TRAP_FAULT(sip->si_trapno);
				break;
			default:
				code = ILL_ILLINSTR_FAULT;
				break;
			}
			break;

		case SIGEMT:
			code = EMT_TAG;
			break;

		case SIGFPE:
			switch (sip->si_code) {
			case FPE_INTDIV:
				code = FPE_INTDIV_TRAP;
				break;
			case FPE_INTOVF:
				code = FPE_INTOVF_TRAP;
				break;
			case FPE_FLTDIV:
				code = FPE_FLTDIV_TRAP;
				break;
			case FPE_FLTOVF:
				code = FPE_FLTOVF_TRAP;
				break;
			case FPE_FLTUND:
				code = FPE_FLTUND_TRAP;
				break;
			case FPE_FLTRES:
				code = FPE_FLTINEX_TRAP;
				break;
			default:
				code = FPE_FLTOPERR_TRAP;
				break;
			}
			break;

		case SIGBUS:
			switch (sip->si_code) {
			case BUS_ADRALN:
				code = BUS_ALIGN;
				break;
			case BUS_ADRERR:
				code = BUS_HWERR;
				break;
			default:	/* BUS_OBJERR */
				code = FC_MAKE_ERR(sip->si_errno);
				break;
			}
			break;

		case SIGSEGV:
			switch (sip->si_code) {
			case SEGV_MAPERR:
				code = SEGV_NOMAP;
				break;
			case SEGV_ACCERR:
				code = SEGV_PROT;
				break;
			default:
				code = FC_MAKE_ERR(sip->si_errno);
				break;
			}
			break;

		default:
			addr = SIG_NOADDR;
			break;
		}
	}

	(*_siguhandler[sig])(sig, code, &sc, addr);

	if (sc.sc_onstack)
		ucp->uc_stack.ss_flags |= SS_ONSTACK;
	else
		ucp->uc_stack.ss_flags &= ~SS_ONSTACK;
	mask2set(sc.sc_mask, &ucp->uc_sigmask);

#if defined(__sparc)
	ucp->uc_mcontext.gregs[REG_SP] = sc.sc_sp;
	ucp->uc_mcontext.gregs[REG_PC] = sc.sc_pc;
	ucp->uc_mcontext.gregs[REG_nPC] = sc.sc_npc;
#if defined(__sparcv9)
	ucp->uc_mcontext.gregs[REG_CCR] = sc.sc_psr;
#else
	ucp->uc_mcontext.gregs[REG_PSR] = sc.sc_psr;
#endif
	ucp->uc_mcontext.gregs[REG_G1] = sc.sc_g1;
	ucp->uc_mcontext.gregs[REG_O0] = sc.sc_o0;
#ifdef NEVER
	if (gwinswitch == 1) {
		int i, j;

		ucp->uc_mcontext.gwins->wbcnt = sc.sc_wbcnt;
		/* XXX - should use bcopy to move this in bulk */
		for (i = 0; i < sc.sc_wbcnt; i++) {
			ucp->uc_mcontext.gwins->spbuf[i] = sc.sc_spbuf[i];
			for (j = 0; j < 8; j++)
				ucp->uc_mcontext.gwins->wbuf[i].rw_local[j] =
				    sc.sc_wbuf[i][j];
			for (j = 0; j < 8; j++)
				ucp->uc_mcontext.gwins->wbuf[i].rw_in[j] =
				    sc.sc_wbuf[i][j+8];
		}
	}
#endif

	if (sig == SIGFPE) {
		if (ucp->uc_mcontext.fpregs.fpu_qcnt > 0) {
			ucp->uc_mcontext.fpregs.fpu_qcnt--;
			ucp->uc_mcontext.fpregs.fpu_q++;
		}
	}
#endif

	(void) setcontext(ucp);
}