⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fasttrap_isa.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 3 页
字号:
		return (0);	if (instr != FASTTRAP_INSTR && instr != BREAKPOINT_INSTR)		return (0);	if (fasttrap_uwrite(p, &tp->ftt_instr, 4, tp->ftt_pc) != 0)		return (-1);	return (0);}intfasttrap_tracepoint_init(proc_t *p, fasttrap_probe_t *probe,    fasttrap_tracepoint_t *tp, uintptr_t pc){	uint32_t instr;	int32_t disp;	/*	 * Read the instruction at the given address out of the process's	 * address space. We don't have to worry about a debugger	 * changing this instruction before we overwrite it with our trap	 * instruction since P_PR_LOCK is set.	 */	if (fasttrap_uread(p, &instr, 4, pc) != 0)		return (-1);	/*	 * Decode the instruction to fill in the probe flags. We can have	 * the process execute most instructions on its own using a pc/npc	 * trick, but pc-relative control transfer present a problem since	 * we're relocating the instruction. We emulate these instructions	 * in the kernel. We assume a default type and over-write that as	 * needed.	 *	 * pc-relative instructions must be emulated for correctness;	 * other instructions (which represent a large set of commonly traced	 * instructions) are emulated or otherwise optimized for performance.	 */	tp->ftt_type = FASTTRAP_T_COMMON;	if (OP(instr) == 1) {		/*		 * Call instructions.		 */		tp->ftt_type = FASTTRAP_T_CALL;		disp = DISP30(instr) << 2;		tp->ftt_dest = pc + (intptr_t)disp;	} else if (OP(instr) == 0) {		/*		 * Branch instructions.		 *		 * Unconditional branches need careful attention when they're		 * annulled: annulled unconditional branches never execute		 * the instruction in the delay slot.		 */		switch (OP2(instr)) {		case OP2_ILLTRAP:		case 0x7:			/*			 * The compiler may place an illtrap after a call to			 * a function that returns a structure. In the case of			 * a returned structure, the compiler places an illtrap			 * whose const22 field is the size of the returned			 * structure immediately following the delay slot of			 * the call. To stay out of the way, we refuse to			 * place tracepoints on top of illtrap instructions.			 *			 * This is one of the dumbest architectural decisions			 * I've ever had to work around.			 *			 * We also identify the only illegal op2 value (See			 * SPARC Architecture Manual Version 9, E.2 table 31).			 */			return (-1);		case OP2_BPcc:			if (COND(instr) == 8) {				tp->ftt_type = FASTTRAP_T_ALWAYS;			} else {				/*				 * Check for an illegal instruction.				 */				if (CC(instr) & 1)					return (-1);				tp->ftt_type = FASTTRAP_T_CCR;				tp->ftt_cc = CC(instr);				tp->ftt_code = COND(instr);			}			if (A(instr) != 0)				tp->ftt_flags |= FASTTRAP_F_ANNUL;			disp = DISP19(instr);			disp <<= 13;			disp >>= 11;			tp->ftt_dest = pc + (intptr_t)disp;			break;		case OP2_Bicc:			if (COND(instr) == 8) {				tp->ftt_type = FASTTRAP_T_ALWAYS;			} else {				tp->ftt_type = FASTTRAP_T_CCR;				tp->ftt_cc = 0;				tp->ftt_code = COND(instr);			}			if (A(instr) != 0)				tp->ftt_flags |= FASTTRAP_F_ANNUL;			disp = DISP22(instr);			disp <<= 10;			disp >>= 8;			tp->ftt_dest = pc + (intptr_t)disp;			break;		case OP2_BPr:			/*			 * Check for an illegal instruction.			 */			if ((RCOND(instr) & 3) == 0)				return (-1);			/*			 * It's a violation of the v8plus ABI to use a			 * register-predicated branch in a 32-bit app if			 * the register used is an %l or an %i (%gs and %os			 * are legit because they're not saved to the stack			 * in 32-bit words when we take a trap).			 */			if (p->p_model == DATAMODEL_ILP32 && RS1(instr) >= 16)				return (-1);			tp->ftt_type = FASTTRAP_T_REG;			if (A(instr) != 0)				tp->ftt_flags |= FASTTRAP_F_ANNUL;			disp = DISP16(instr);			disp <<= 16;			disp >>= 14;			tp->ftt_dest = pc + (intptr_t)disp;			tp->ftt_code = RCOND(instr);			break;		case OP2_SETHI:			tp->ftt_type = FASTTRAP_T_SETHI;			break;		case OP2_FBPfcc:			if (COND(instr) == 8) {				tp->ftt_type = FASTTRAP_T_ALWAYS;			} else {				tp->ftt_type = FASTTRAP_T_FCC;				tp->ftt_cc = CC(instr);				tp->ftt_code = COND(instr);			}			if (A(instr) != 0)				tp->ftt_flags |= FASTTRAP_F_ANNUL;			disp = DISP19(instr);			disp <<= 13;			disp >>= 11;			tp->ftt_dest = pc + (intptr_t)disp;			break;		case OP2_FBfcc:			if (COND(instr) == 8) {				tp->ftt_type = FASTTRAP_T_ALWAYS;			} else {				tp->ftt_type = FASTTRAP_T_FCC;				tp->ftt_cc = 0;				tp->ftt_code = COND(instr);			}			if (A(instr) != 0)				tp->ftt_flags |= FASTTRAP_F_ANNUL;			disp = DISP22(instr);			disp <<= 10;			disp >>= 8;			tp->ftt_dest = pc + (intptr_t)disp;			break;		}	} else if (OP(instr) == 2) {		switch (OP3(instr)) {		case OP3_RETURN:			tp->ftt_type = FASTTRAP_T_RETURN;			break;		case OP3_JMPL:			tp->ftt_type = FASTTRAP_T_JMPL;			break;		case OP3_RD:			if (RS1(instr) == 5)				tp->ftt_type = FASTTRAP_T_RDPC;			break;		case OP3_SAVE:			/*			 * We optimize for save instructions at function			 * entry; see the comment in fasttrap_pid_probe()			 * (near FASTTRAP_T_SAVE) for details.			 */			if (fasttrap_optimize_save != 0 &&			    probe->ftp_type == DTFTP_ENTRY &&			    I(instr) == 1 && RD(instr) == R_SP)				tp->ftt_type = FASTTRAP_T_SAVE;			break;		case OP3_RESTORE:			/*			 * We optimize restore instructions at function			 * return; see the comment in fasttrap_pid_probe()			 * (near FASTTRAP_T_RESTORE) for details.			 *			 * rd must be an %o or %g register.			 */			if ((RD(instr) & 0x10) == 0)				tp->ftt_type = FASTTRAP_T_RESTORE;			break;		case OP3_OR:			/*			 * A large proportion of instructions in the delay			 * slot of retl instructions are or's so we emulate			 * these downstairs as an optimization.			 */			tp->ftt_type = FASTTRAP_T_OR;			break;		case OP3_TCC:			/*			 * Breakpoint instructions are effectively position-			 * dependent since the debugger uses the %pc value			 * to lookup which breakpoint was executed. As a			 * result, we can't actually instrument breakpoints.			 */			if (SW_TRAP(instr) == ST_BREAKPOINT)				return (-1);			break;		case 0x19:		case 0x1d:		case 0x29:		case 0x33:		case 0x3f:			/*			 * Identify illegal instructions (See SPARC			 * Architecture Manual Version 9, E.2 table 32).			 */			return (-1);		}	} else if (OP(instr) == 3) {		uint32_t op3 = OP3(instr);		/*		 * Identify illegal instructions (See SPARC Architecture		 * Manual Version 9, E.2 table 33).		 */		if ((op3 & 0x28) == 0x28) {			if (op3 != OP3_PREFETCH && op3 != OP3_CASA &&			    op3 != OP3_PREFETCHA && op3 != OP3_CASXA)				return (-1);		} else {			if ((op3 & 0x0f) == 0x0c || (op3 & 0x3b) == 0x31)				return (-1);		}	}	tp->ftt_instr = instr;	return (0);}/*ARGSUSED*/uint64_tfasttrap_getarg(void *arg, dtrace_id_t id, void *parg, int argno, int aframes){	return (fasttrap_anarg(ttolwp(curthread)->lwp_regs, argno));}/*ARGSUSED*/uint64_tfasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,    int aframes){	return (fasttrap_anarg(ttolwp(curthread)->lwp_regs, argno));}static uint64_t fasttrap_getreg_fast_cnt;static uint64_t fasttrap_getreg_mpcb_cnt;static uint64_t fasttrap_getreg_slow_cnt;static ulong_tfasttrap_getreg(struct regs *rp, uint_t reg){	ulong_t value;	dtrace_icookie_t cookie;	struct machpcb *mpcb;	extern ulong_t dtrace_getreg_win(uint_t, uint_t);	/*	 * We have the %os and %gs in our struct regs, but if we need to	 * snag a %l or %i we need to go scrounging around in the process's	 * address space.	 */	if (reg == 0)		return (0);	if (reg < 16)		return ((&rp->r_g1)[reg - 1]);	/*	 * Before we look at the user's stack, we'll check the register	 * windows to see if the information we want is in there.	 */	cookie = dtrace_interrupt_disable();	if (dtrace_getotherwin() > 0) {		value = dtrace_getreg_win(reg, 1);		dtrace_interrupt_enable(cookie);		atomic_add_64(&fasttrap_getreg_fast_cnt, 1);		return (value);	}	dtrace_interrupt_enable(cookie);	/*	 * First check the machpcb structure to see if we've already read	 * in the register window we're looking for; if we haven't, (and	 * we probably haven't) try to copy in the value of the register.	 */	mpcb = (struct machpcb *)((caddr_t)rp - REGOFF);	if (get_udatamodel() == DATAMODEL_NATIVE) {		struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS);		if (mpcb->mpcb_wbcnt > 0) {			struct rwindow *rwin = (void *)mpcb->mpcb_wbuf;			int i = mpcb->mpcb_wbcnt;			do {				i--;				if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)					continue;				atomic_add_64(&fasttrap_getreg_mpcb_cnt, 1);				return (rwin[i].rw_local[reg - 16]);			} while (i > 0);		}		if (fasttrap_fulword(&fr->fr_local[reg - 16], &value) != 0)			goto err;	} else {		struct frame32 *fr = (struct frame32 *)(caddr32_t)rp->r_sp;		uint32_t *v32 = (uint32_t *)&value;		if (mpcb->mpcb_wbcnt > 0) {			struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf;			int i = mpcb->mpcb_wbcnt;			do {				i--;				if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)					continue;				atomic_add_64(&fasttrap_getreg_mpcb_cnt, 1);				return (rwin[i].rw_local[reg - 16]);			} while (i > 0);		}		if (fasttrap_fuword32(&fr->fr_local[reg - 16], &v32[1]) != 0)			goto err;		v32[0] = 0;	}	atomic_add_64(&fasttrap_getreg_slow_cnt, 1);	return (value);err:	/*	 * If the copy in failed, the process will be in a irrecoverable	 * state, and we have no choice but to kill it.	 */	psignal(ttoproc(curthread), SIGILL);	return (0);}static uint64_t fasttrap_putreg_fast_cnt;static uint64_t fasttrap_putreg_mpcb_cnt;static uint64_t fasttrap_putreg_slow_cnt;static voidfasttrap_putreg(struct regs *rp, uint_t reg, ulong_t value){	dtrace_icookie_t cookie;	struct machpcb *mpcb;	extern void dtrace_putreg_win(uint_t, ulong_t);	if (reg == 0)		return;	if (reg < 16) {		(&rp->r_g1)[reg - 1] = value;		return;	}	/*	 * If the user process is still using some register windows, we	 * can just place the value in the correct window.	 */	cookie = dtrace_interrupt_disable();	if (dtrace_getotherwin() > 0) {		dtrace_putreg_win(reg, value);		dtrace_interrupt_enable(cookie);		atomic_add_64(&fasttrap_putreg_fast_cnt, 1);		return;	}	dtrace_interrupt_enable(cookie);	/*	 * First see if there's a copy of the register window in the	 * machpcb structure that we can modify; if there isn't try to	 * copy out the value. If that fails, we try to create a new	 * register window in the machpcb structure. While this isn't	 * _precisely_ the intended use of the machpcb structure, it	 * can't cause any problems since we know at this point in the	 * code that all of the user's data have been flushed out of the	 * register file (since %otherwin is 0).	 */	mpcb = (struct machpcb *)((caddr_t)rp - REGOFF);	if (get_udatamodel() == DATAMODEL_NATIVE) {		struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS);		struct rwindow *rwin = (struct rwindow *)mpcb->mpcb_wbuf;		if (mpcb->mpcb_wbcnt > 0) {			int i = mpcb->mpcb_wbcnt;			do {				i--;				if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)					continue;				rwin[i].rw_local[reg - 16] = value;				atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);				return;			} while (i > 0);		}		if (fasttrap_sulword(&fr->fr_local[reg - 16], value) != 0) {			if (mpcb->mpcb_wbcnt >= MAXWIN || copyin(fr,			    &rwin[mpcb->mpcb_wbcnt], sizeof (*rwin)) != 0)				goto err;			rwin[mpcb->mpcb_wbcnt].rw_local[reg - 16] = value;			mpcb->mpcb_spbuf[mpcb->mpcb_wbcnt] = (caddr_t)rp->r_sp;			mpcb->mpcb_wbcnt++;			atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);			return;		}	} else {		struct frame32 *fr = (struct frame32 *)(caddr32_t)rp->r_sp;		struct rwindow32 *rwin = (struct rwindow32 *)mpcb->mpcb_wbuf;		uint32_t v32 = (uint32_t)value;		if (mpcb->mpcb_wbcnt > 0) {			int i = mpcb->mpcb_wbcnt;			do {				i--;				if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)					continue;				rwin[i].rw_local[reg - 16] = v32;				atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);				return;			} while (i > 0);		}		if (fasttrap_suword32(&fr->fr_local[reg - 16], v32) != 0) {			if (mpcb->mpcb_wbcnt >= MAXWIN || copyin(fr,			    &rwin[mpcb->mpcb_wbcnt], sizeof (*rwin)) != 0)				goto err;			rwin[mpcb->mpcb_wbcnt].rw_local[reg - 16] = v32;			mpcb->mpcb_spbuf[mpcb->mpcb_wbcnt] = (caddr_t)rp->r_sp;			mpcb->mpcb_wbcnt++;			atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);			return;		}	}	atomic_add_64(&fasttrap_putreg_slow_cnt, 1);	return;err:	/*	 * If we couldn't record this register's value, the process is in an	 * irrecoverable state and we have no choice but to euthanize it.	 */	psignal(ttoproc(curthread), SIGILL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -