static int instr_seq_show(struct seq_file *seq, void *v)
{
	int	i;
	long	n = (long) v;
	int	target;
	instr_probe_t *fbt = NULL;
	unsigned long size;
	unsigned long offset;
	char	*modname = NULL;
	char	name[KSYM_NAME_LEN];
	const	char	*cp;

//printk("%s v=%p\n", __func__, v);
	if (n == 1) {
		seq_printf(seq, "# patchpoint opcode inslen modrm name\n");
		return 0;
	}
	if (n > num_probes)
		return 0;

	/***********************************************/
	/*   Find first probe.			       */
	/***********************************************/
	target = n;
	for (i = 0; target > 0 && i < instr_probetab_size; i++) {
		fbt = instr_probetab[i];
		if (fbt == NULL)
			continue;
		target--;
		while (target > 0 && fbt) {
			if ((fbt = fbt->insp_hashnext) == NULL)
				break;
			target--;
		}
	}
	if (fbt == NULL)
		return 0;

	cp = my_kallsyms_lookup((unsigned long) fbt->insp_patchpoint, 
		&size, &offset, &modname, name);
	seq_printf(seq, "%ld %p %02x %d %2d %s:%s\n", n-1, 
		fbt->insp_patchpoint,
		fbt->insp_savedval,
		fbt->insp_inslen,
		fbt->insp_modrm,
		modname ? modname : "kernel",
		cp ? cp : "NULL");
	return 0;
}
void
instr_provide_kernel(void)
{
	static struct module kern;
	int	n;
static	caddr_t ktext;
static	caddr_t ketext;
static int first_time = TRUE;
	caddr_t a, aend;
	char	name[KSYM_NAME_LEN];

	if (first_time) {
		first_time = FALSE;
		ktext = get_proc_addr("_text");
		if (ktext == NULL)
			ktext = get_proc_addr("_stext");
		ketext = get_proc_addr("_etext");
		my_kallsyms_lookup = get_proc_addr("kallsyms_lookup");
		}

	if (ktext == NULL) {
		printk("dtracedrv:instr_provide_kernel: Cannot find _text/_stext\n");
		return;
	}
	if (kern.name[0])
		return;

	strcpy(kern.name, "kernel");
	/***********************************************/
	/*   Walk   the  code  segment,  finding  the  */
	/*   symbols,  and  creating a probe for each  */
	/*   one.				       */
	/***********************************************/
	for (n = 0, a = ktext; my_kallsyms_lookup && a < ketext; ) {
		const char *cp;
		unsigned long size;
		unsigned long offset;
		char	*modname = NULL;

//printk("lookup %p kallsyms_lookup=%p\n", a, kallsyms_lookup);
		cp = my_kallsyms_lookup((unsigned long) a, &size, &offset, &modname, name);
if (cp && size == 0)
printk("instr_linux: size=0 %p %s\n", a, cp ? cp : "??");
/*		printk("a:%p cp:%s size:%lx offset:%lx\n", a, cp ? cp : "--undef--", size, offset);*/
		if (cp == NULL)
			aend = a + 4;
		else
			aend = a + (size - offset);

		/***********************************************/
		/*   If  this  function  is  toxic, we mustnt  */
		/*   touch it.				       */
		/***********************************************/
		if (cp && *cp && !is_toxic_func((unsigned long) a, cp)) {
			instr_provide_function(&kern, 
				(par_module_t *) &kern, //uck on the cast..we dont really need it
				"kernel", name, 
				a, a, aend, n);
		}
		a = aend;
		n++;
	}
}
示例#3
0
static int fbt_seq_show(struct seq_file *seq, void *v)
{
	int	i, s;
	int	n = (int) (long) v;
	int	target;
	fbt_probe_t *fbt = NULL;
	unsigned long size;
	unsigned long offset;
	char	*modname = NULL;
	char	name[KSYM_NAME_LEN];
	char	ibuf[64];
	char	*cp;

//printk("%s v=%p\n", __func__, v);
	if (n == 1) {
		seq_printf(seq, "# count patchpoint opcode inslen modrm name\n");
		return 0;
	}
	if (n > num_probes)
		return 0;

	/***********************************************/
	/*   Find  first  probe.  This  is incredibly  */
	/*   slow  and  inefficient, but we dont want  */
	/*   to waste memory keeping a list (an extra  */
	/*   ptr for each probe).		       */
	/***********************************************/
	target = n;
	for (i = 0; target > 0 && i < fbt_probetab_size; i++) {
		fbt = fbt_probetab[i];
		if (fbt == NULL)
			continue;
		target--;
		while (target > 0 && fbt) {
			if ((fbt = fbt->fbtp_hashnext) == NULL)
				break;
			target--;
		}
	}
	if (fbt == NULL)
		return 0;

	/***********************************************/
	/*   Dump the instruction so we can make sure  */
	/*   we  can  single  step them in the adjust  */
	/*   cpu code.				       */
	/*   When a module is loaded and we parse the  */
	/*   module,  this may include syms which may  */
	/*   get  unmapped  later  on.  So, trying to  */
	/*   access a patchpoint instruction can GPF.  */
	/*   We need to tread very carefully here not  */
	/*   to  GPF whilst catting /proc/dtrace/fbt.  */
	/*   We   actually   need  to  disable  these  */
	/*   probes.				       */
	/***********************************************/
//printk("fbtproc %p\n", fbt->fbtp_patchpoint);
	if (!validate_ptr(fbt->fbtp_patchpoint)) {
		s = 0xfff;
		strcpy(ibuf, "<unmapped>");
	} else {
		s = dtrace_instr_size((uchar_t *) fbt->fbtp_patchpoint);
		ibuf[0] = '\0';
		for (cp = ibuf, i = 0; i < s; i++) {
			snprintf(cp, sizeof ibuf - (cp - ibuf) - 3, "%02x ", 
				fbt->fbtp_patchpoint[i] & 0xff);
			cp += 3;
			}
	}
	cp = (char *) my_kallsyms_lookup((unsigned long) fbt->fbtp_patchpoint, 
		&size, &offset, &modname, name);
# if defined(__arm__)
	seq_printf(seq, "%d %04u%c %p %08x %d %2d %s:%s:%s %s\n", n-1, 
# else
	seq_printf(seq, "%d %04u%c %p %02x %d %2d %s:%s:%s %s\n", n-1, 
# endif
		fbt->fbtp_fired,
		fbt->fbtp_overrun ? '*' : ' ',
		fbt->fbtp_patchpoint,
		fbt->fbtp_savedval,
		fbt->fbtp_inslen,
		fbt->fbtp_modrm,
		modname ? modname : "kernel",
		cp ? cp : "NULL",
		fbt->fbtp_type ? "return" : "entry",
		ibuf);
	return 0;
}