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

📄 fasttrap_isa.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 3 页
字号:
					    FASTTRAP_REX_B(rex));					rm = 0;				} else {					tp->ftt_ripmode = FASTTRAP_RIP_2 |					    (FASTTRAP_RIP_X *					    FASTTRAP_REX_B(rex));					rm = 1;				}				tp->ftt_modrm = tp->ftt_instr[rmindex];				tp->ftt_instr[rmindex] =				    FASTTRAP_MODRM(2, reg, rm);			}		}	}#endif	return (0);}intfasttrap_tracepoint_install(proc_t *p, fasttrap_tracepoint_t *tp){	fasttrap_instr_t instr = FASTTRAP_INSTR;	if (fasttrap_uwrite(p, &instr, 1, tp->ftt_pc) != 0)		return (-1);	return (0);}intfasttrap_tracepoint_remove(proc_t *p, fasttrap_tracepoint_t *tp){	uint8_t instr;	/*	 * Distinguish between read or write failures and a changed	 * instruction.	 */	if (fasttrap_uread(p, &instr, 1, tp->ftt_pc) != 0)		return (0);	if (instr != FASTTRAP_INSTR)		return (0);	if (fasttrap_uwrite(p, &tp->ftt_instr[0], 1, tp->ftt_pc) != 0)		return (-1);	return (0);}static uintptr_tfasttrap_fulword_noerr(const void *uaddr){	uintptr_t ret;	if (fasttrap_fulword(uaddr, &ret) == 0)		return (ret);	return (0);}static uint32_tfasttrap_fuword32_noerr(const void *uaddr){	uint32_t ret;	if (fasttrap_fuword32(uaddr, &ret) == 0)		return (ret);	return (0);}/*ARGSUSED*/intfasttrap_probe(struct regs *rp){#ifdef __amd64	proc_t *p = curproc;#endif	uintptr_t s0, s1, s2, s3, s4;#ifdef __amd64	if (p->p_model == DATAMODEL_LP64) {		uintptr_t *stack = (uintptr_t *)rp->r_sp;		s0 = fasttrap_fulword_noerr(&stack[1]);		s1 = fasttrap_fulword_noerr(&stack[2]);		s2 = fasttrap_fulword_noerr(&stack[3]);		s3 = fasttrap_fulword_noerr(&stack[4]);		s4 = fasttrap_fulword_noerr(&stack[5]);	} else {#endif		uint32_t *stack = (uint32_t *)rp->r_sp;		s0 = fasttrap_fuword32_noerr(&stack[1]);		s1 = fasttrap_fuword32_noerr(&stack[2]);		s2 = fasttrap_fuword32_noerr(&stack[3]);		s3 = fasttrap_fuword32_noerr(&stack[4]);		s4 = fasttrap_fuword32_noerr(&stack[5]);#ifdef __amd64	}#endif	dtrace_probe(fasttrap_probe_id, s0, s1, s2, s3, s4);	return (0);}static voidfasttrap_return_common(struct regs *rp, uintptr_t pc, pid_t pid,    uintptr_t new_pc){	fasttrap_tracepoint_t *tp;	fasttrap_bucket_t *bucket;	fasttrap_id_t *id;	kmutex_t *pid_mtx;	pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock;	mutex_enter(pid_mtx);	bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];	for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {		if (pid == tp->ftt_pid && pc == tp->ftt_pc &&		    !tp->ftt_prov->ftp_defunct)			break;	}	/*	 * Don't sweat it if we can't find the tracepoint again; unlike	 * when we're in fasttrap_pid_probe(), finding the tracepoint here	 * is not essential to the correct execution of the process.	 */	if (tp == NULL) {		mutex_exit(pid_mtx);		return;	}	for (id = tp->ftt_retids; id != NULL; id = id->fti_next) {		/*		 * If there's a branch that could act as a return site, we		 * need to trace it, and check here if the program counter is		 * external to the function.		 */		if (new_pc - id->fti_probe->ftp_faddr <		    id->fti_probe->ftp_fsize)			continue;		dtrace_probe(id->fti_probe->ftp_id,		    pc - id->fti_probe->ftp_faddr,		    rp->r_r0, rp->r_r1, 0, 0);	}	mutex_exit(pid_mtx);}static voidfasttrap_sigsegv(proc_t *p, kthread_t *t, uintptr_t addr){	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);}#ifdef __amd64static voidfasttrap_usdt_args64(fasttrap_probe_t *probe, struct regs *rp, int argc,    uintptr_t *argv){	int i, x, cap = MIN(argc, probe->ftp_nargs);	uintptr_t *stack = (uintptr_t *)rp->r_sp;	for (i = 0; i < cap; i++) {		x = probe->ftp_argmap[i];		if (x < 6)			argv[i] = (&rp->r_rdi)[x];		else			argv[i] = fasttrap_fulword_noerr(&stack[x]);	}	for (; i < argc; i++) {		argv[i] = 0;	}}#endifstatic voidfasttrap_usdt_args32(fasttrap_probe_t *probe, struct regs *rp, int argc,    uint32_t *argv){	int i, x, cap = MIN(argc, probe->ftp_nargs);	uint32_t *stack = (uint32_t *)rp->r_sp;	for (i = 0; i < cap; i++) {		x = probe->ftp_argmap[i];		argv[i] = fasttrap_fuword32_noerr(&stack[x]);	}	for (; i < argc; i++) {		argv[i] = 0;	}}intfasttrap_pid_probe(struct regs *rp){	proc_t *p = curproc;	uintptr_t pc = rp->r_pc - 1, new_pc = 0;	fasttrap_bucket_t *bucket;	kmutex_t *pid_mtx;	fasttrap_tracepoint_t *tp, tp_local;	pid_t pid;	dtrace_icookie_t cookie;	/*	 * It's possible that a user (in a veritable orgy of bad planning)	 * could redirect this thread's flow of control before it reached the	 * return probe fasttrap. In this case we need to kill the process	 * since it's in a unrecoverable state.	 */	if (curthread->t_dtrace_step) {		ASSERT(curthread->t_dtrace_on);		fasttrap_sigtrap(p, curthread, pc);		return (0);	}	/*	 * Clear all user tracing flags.	 */	curthread->t_dtrace_ft = 0;	curthread->t_dtrace_pc = 0;	curthread->t_dtrace_npc = 0;	curthread->t_dtrace_scrpc = 0;	curthread->t_dtrace_astpc = 0;#ifdef __amd64	curthread->t_dtrace_regv = 0;#endif	/*	 * Treat a child created by a call to vfork(2) as if it were its	 * parent. We know that there's only one thread of control in such a	 * process: this one.	 */	while (p->p_flag & SVFORK) {		p = p->p_parent;	}	pid = p->p_pid;	pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock;	mutex_enter(pid_mtx);	bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];	/*	 * Lookup the tracepoint that the process just hit.	 */	for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {		if (pid == tp->ftt_pid && pc == tp->ftt_pc &&		    !tp->ftt_prov->ftp_defunct)			break;	}	/*	 * If we couldn't find a matching tracepoint, either a tracepoint has	 * been inserted without using the pid<pid> ioctl interface (see	 * fasttrap_ioctl), or somehow we have mislaid this tracepoint.	 */	if (tp == NULL) {		mutex_exit(pid_mtx);		return (-1);	}	/*	 * Set the program counter to the address of the traced instruction	 * so that it looks right in ustack() output.	 */	rp->r_pc = pc;	if (tp->ftt_ids != NULL) {		fasttrap_id_t *id;#ifdef __amd64		if (p->p_model == DATAMODEL_LP64) {			for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {				fasttrap_probe_t *probe = id->fti_probe;				if (probe->ftp_type == DTFTP_ENTRY) {					/*					 * We note that this was an entry					 * probe to help ustack() find the					 * first caller.					 */					cookie = dtrace_interrupt_disable();					DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY);					dtrace_probe(probe->ftp_id, rp->r_rdi,					    rp->r_rsi, rp->r_rdx, rp->r_rcx,					    rp->r_r8);					DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY);					dtrace_interrupt_enable(cookie);				} else if (probe->ftp_argmap == NULL) {					dtrace_probe(probe->ftp_id, rp->r_rdi,					    rp->r_rsi, rp->r_rdx, rp->r_rcx,					    rp->r_r8);				} else {					uintptr_t t[5];					fasttrap_usdt_args64(probe, rp,					    sizeof (t) / sizeof (t[0]), t);					dtrace_probe(probe->ftp_id, t[0], t[1],					    t[2], t[3], t[4]);				}			}		} else {#endif			uintptr_t s0, s1, s2, s3, s4, s5;			uint32_t *stack = (uint32_t *)rp->r_sp;			/*			 * In 32-bit mode, all arguments are passed on the			 * stack. If this is a function entry probe, we need			 * to skip the first entry on the stack as it			 * represents the return address rather than a			 * parameter to the function.			 */			s0 = fasttrap_fuword32_noerr(&stack[0]);			s1 = fasttrap_fuword32_noerr(&stack[1]);			s2 = fasttrap_fuword32_noerr(&stack[2]);			s3 = fasttrap_fuword32_noerr(&stack[3]);			s4 = fasttrap_fuword32_noerr(&stack[4]);			s5 = fasttrap_fuword32_noerr(&stack[5]);			for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {				fasttrap_probe_t *probe = id->fti_probe;				if (probe->ftp_type == DTFTP_ENTRY) {					/*					 * We note that this was an entry					 * probe to help ustack() find the					 * first caller.					 */					cookie = dtrace_interrupt_disable();					DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY);					dtrace_probe(probe->ftp_id, s1, s2,					    s3, s4, s5);					DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY);					dtrace_interrupt_enable(cookie);				} else if (probe->ftp_argmap == NULL) {					dtrace_probe(probe->ftp_id, s0, s1,					    s2, s3, s4);				} else {					uint32_t t[5];					fasttrap_usdt_args32(probe, rp,					    sizeof (t) / sizeof (t[0]), t);					dtrace_probe(probe->ftp_id, t[0], t[1],					    t[2], t[3], t[4]);				}			}#ifdef __amd64		}#endif	}	/*	 * We're about to do a bunch of work so we cache a local copy of	 * the tracepoint to emulate the instruction, and then find the	 * tracepoint again later if we need to light up any return probes.	 */	tp_local = *tp;	mutex_exit(pid_mtx);	tp = &tp_local;	/*	 * Set the program counter to appear as though the traced instruction	 * had completely executed. This ensures that fasttrap_getreg() will	 * report the expected value for REG_RIP.	 */	rp->r_pc = pc + tp->ftt_size;	switch (tp->ftt_type) {	case FASTTRAP_T_RET:	case FASTTRAP_T_RET16:	{		uintptr_t dst;		uintptr_t addr;		int ret;		/*		 * We have to emulate _every_ facet of the behavior of a ret		 * instruction including what happens if the load from %esp		 * fails; in that case, we send a SIGSEGV.		 */#ifdef __amd64		if (p->p_model == DATAMODEL_NATIVE) {#endif			ret = fasttrap_fulword((void *)rp->r_sp, &dst);			addr = rp->r_sp + sizeof (uintptr_t);#ifdef __amd64		} else {			uint32_t dst32;			ret = fasttrap_fuword32((void *)rp->r_sp, &dst32);			dst = dst32;			addr = rp->r_sp + sizeof (uint32_t);		}#endif		if (ret == -1) {			fasttrap_sigsegv(p, curthread, rp->r_sp);			new_pc = pc;			break;		}		if (tp->ftt_type == FASTTRAP_T_RET16)			addr += tp->ftt_dest;		rp->r_sp = addr;		new_pc = dst;		break;	}	case FASTTRAP_T_JCC:	{		uint_t taken;		switch (tp->ftt_code) {		case FASTTRAP_JO:			taken = (rp->r_ps & FASTTRAP_EFLAGS_OF) != 0;			break;		case FASTTRAP_JNO:			taken = (rp->r_ps & FASTTRAP_EFLAGS_OF) == 0;			break;		case FASTTRAP_JB:			taken = (rp->r_ps & FASTTRAP_EFLAGS_CF) != 0;			break;		case FASTTRAP_JAE:			taken = (rp->r_ps & FASTTRAP_EFLAGS_CF) == 0;			break;		case FASTTRAP_JE:			taken = (rp->r_ps & FASTTRAP_EFLAGS_ZF) != 0;			break;		case FASTTRAP_JNE:			taken = (rp->r_ps & FASTTRAP_EFLAGS_ZF) == 0;			break;		case FASTTRAP_JBE:			taken = (rp->r_ps & FASTTRAP_EFLAGS_CF) != 0 ||			    (rp->r_ps & FASTTRAP_EFLAGS_ZF) != 0;			break;		case FASTTRAP_JA:			taken = (rp->r_ps & FASTTRAP_EFLAGS_CF) == 0 &&			    (rp->r_ps & FASTTRAP_EFLAGS_ZF) == 0;			break;		case FASTTRAP_JS:			taken = (rp->r_ps & FASTTRAP_EFLAGS_SF) != 0;			break;		case FASTTRAP_JNS:			taken = (rp->r_ps & FASTTRAP_EFLAGS_SF) == 0;			break;		case FASTTRAP_JP:			taken = (rp->r_ps & FASTTRAP_EFLAGS_PF) != 0;			break;		case FASTTRAP_JNP:			taken = (rp->r_ps & FASTTRAP_EFLAGS_PF) == 0;			break;		case FASTTRAP_JL:			taken = ((rp->r_ps & FASTTRAP_EFLAGS_SF) == 0) !=			    ((rp->r_ps & FASTTRAP_EFLAGS_OF) == 0);			break;		case FASTTRAP_JGE:			taken = ((rp->r_ps & FASTTRAP_EFLAGS_SF) == 0) ==			    ((rp->r_ps & FASTTRAP_EFLAGS_OF) == 0);			break;		case FASTTRAP_JLE:			taken = (rp->r_ps & FASTTRAP_EFLAGS_ZF) != 0 ||			    ((rp->r_ps & FASTTRAP_EFLAGS_SF) == 0) !=			    ((rp->r_ps & FASTTRAP_EFLAGS_OF) == 0);			break;		case FASTTRAP_JG:			taken = (rp->r_ps & FASTTRAP_EFLAGS_ZF) == 0 &&			    ((rp->r_ps & FASTTRAP_EFLAGS_SF) == 0) ==			    ((rp->r_ps & FASTTRAP_EFLAGS_OF) == 0);			break;		}		if (taken)			new_pc = tp->ftt_dest;		else			new_pc = pc + tp->ftt_size;		break;	}	case FASTTRAP_T_LOOP:	{

⌨️ 快捷键说明

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