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

📄 fbt.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 3 页
字号:
			cmn_err(CE_NOTE, "cannot instrument %s: "			    "save not in first basic block", name);			continue;		}		if (instr == limit) {			if (!have_ctf)				continue;			is_leaf = 1;			if (!estimate)				fbt_leaf_functions++;			canpatch = fbt_canpatch_retl;			patch = fbt_patch_retl;		} else {			canpatch = fbt_canpatch_return;			patch = fbt_patch_return;		}		if (!have_ctf && !is_leaf) {			/*			 * Before we assume that this isn't something tricky,			 * look for other saves.  If we find them, there are			 * multiple entry points here (or something), and we'll			 * leave it alone.			 */			while (++instr < limit) {				if (FBT_IS_SAVE(*instr))					break;			}			if (instr != limit)				continue;		}		instr = base;		if (estimate) {			tramp.fbtt_next = (uintptr_t)faketramp;			tramp.fbtt_limit = tramp.fbtt_next + sizeof (faketramp);			(void) fbt_patch_entry(instr, FBT_ESTIMATE_ID,			    &tramp, nargs);			fbt_size += tramp.fbtt_next - (uintptr_t)faketramp;		} else {			fbt = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP);			fbt->fbtp_name = name;			fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,			    name, FBT_ENTRY, 1, fbt);			fbt->fbtp_patchval = FBT_BAA(instr, tramp.fbtt_va);			if (!fbt_patch_entry(instr, fbt->fbtp_id,			    &tramp, nargs)) {				cmn_err(CE_WARN, "unexpectedly short FBT table "				    "in module %s (sym %d of %d)", modname,				    i, nsyms);				break;			}			fbt->fbtp_patchpoint =			    (uint32_t *)((uintptr_t)mp->textwin +			    ((uintptr_t)instr - (uintptr_t)mp->text));			fbt->fbtp_savedval = *instr;			fbt->fbtp_ctl = ctl;			fbt->fbtp_loadcnt = ctl->mod_loadcnt;			fbt->fbtp_primary = primary;			fbt->fbtp_symndx = i;			mp->fbt_nentries++;		}		retfbt = NULL;again:		if (++instr == limit)			continue;		offset = (uintptr_t)instr - (uintptr_t)base;		if (!(*canpatch)(instr, offset))			goto again;		if (estimate) {			tramp.fbtt_next = (uintptr_t)faketramp;			tramp.fbtt_limit = tramp.fbtt_next + sizeof (faketramp);			(void) (*patch)(instr, base, limit,			    offset, FBT_ESTIMATE_ID, &tramp);			fbt_size += tramp.fbtt_next - (uintptr_t)faketramp;			goto again;		}		fbt = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP);		fbt->fbtp_name = name;		if (retfbt == NULL) {			fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,			    name, FBT_RETURN, 1, fbt);		} else {			retfbt->fbtp_next = fbt;			fbt->fbtp_id = retfbt->fbtp_id;		}		fbt->fbtp_return = 1;		retfbt = fbt;		if ((fbt->fbtp_patchval = (*patch)(instr, base, limit, offset,		    fbt->fbtp_id, &tramp)) == FBT_ILLTRAP) {			cmn_err(CE_WARN, "unexpectedly short FBT table "			    "in module %s (sym %d of %d)", modname, i, nsyms);			break;		}		fbt->fbtp_patchpoint = (uint32_t *)((uintptr_t)mp->textwin +		    ((uintptr_t)instr - (uintptr_t)mp->text));		fbt->fbtp_savedval = *instr;		fbt->fbtp_ctl = ctl;		fbt->fbtp_loadcnt = ctl->mod_loadcnt;		fbt->fbtp_primary = primary;		fbt->fbtp_symndx = i;		mp->fbt_nentries++;		goto again;	}	if (estimate) {		/*		 * Slosh on another entry's worth...		 */		fbt_size += FBT_ENT_MAXSIZE;		mp->fbt_size = fbt_size;		mp->fbt_tab = kobj_texthole_alloc(mp->text, fbt_size);		if (mp->fbt_tab == NULL) {			cmn_err(CE_WARN, "couldn't allocate FBT table "			    "for module %s", modname);		} else {			estimate = 0;			goto forreal;		}	} else {		fbt_trampoline_unmap();	}error:	if (fp != NULL)		ctf_close(fp);}/*ARGSUSED*/static voidfbt_destroy(void *arg, dtrace_id_t id, void *parg){	fbt_probe_t *fbt = parg, *next;	struct modctl *ctl = fbt->fbtp_ctl;	do {		if (ctl != NULL && ctl->mod_loadcnt == fbt->fbtp_loadcnt) {			if ((ctl->mod_loadcnt == fbt->fbtp_loadcnt &&			    ctl->mod_loaded) || fbt->fbtp_primary) {				((struct module *)				    (ctl->mod_mp))->fbt_nentries--;			}		}		next = fbt->fbtp_next;		kmem_free(fbt, sizeof (fbt_probe_t));		fbt = next;	} while (fbt != NULL);}/*ARGSUSED*/static voidfbt_enable(void *arg, dtrace_id_t id, void *parg){	fbt_probe_t *fbt = parg, *f;	struct modctl *ctl = fbt->fbtp_ctl;	ctl->mod_nenabled++;	for (f = fbt; f != NULL; f = f->fbtp_next) {		if (f->fbtp_patchpoint == NULL) {			/*			 * Due to a shortened FBT table, this entry was never			 * completed; refuse to enable it.			 */			if (fbt_verbose) {				cmn_err(CE_NOTE, "fbt is failing for probe %s "				    "(short FBT table in %s)",				    fbt->fbtp_name, ctl->mod_modname);			}			return;		}	}	/*	 * If this module has disappeared since we discovered its probes,	 * refuse to enable it.	 */	if (!fbt->fbtp_primary && !ctl->mod_loaded) {		if (fbt_verbose) {			cmn_err(CE_NOTE, "fbt is failing for probe %s "			    "(module %s unloaded)",			    fbt->fbtp_name, ctl->mod_modname);		}		return;	}	/*	 * Now check that our modctl has the expected load count.  If it	 * doesn't, this module must have been unloaded and reloaded -- and	 * we're not going to touch it.	 */	if (ctl->mod_loadcnt != fbt->fbtp_loadcnt) {		if (fbt_verbose) {			cmn_err(CE_NOTE, "fbt is failing for probe %s "			    "(module %s reloaded)",			    fbt->fbtp_name, ctl->mod_modname);		}		return;	}	for (; fbt != NULL; fbt = fbt->fbtp_next)		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;}/*ARGSUSED*/static voidfbt_disable(void *arg, dtrace_id_t id, void *parg){	fbt_probe_t *fbt = parg, *f;	struct modctl *ctl = fbt->fbtp_ctl;	ASSERT(ctl->mod_nenabled > 0);	ctl->mod_nenabled--;	for (f = fbt; f != NULL; f = f->fbtp_next) {		if (f->fbtp_patchpoint == NULL)			return;	}	if ((!fbt->fbtp_primary && !ctl->mod_loaded) ||	    (ctl->mod_loadcnt != fbt->fbtp_loadcnt))		return;	for (; fbt != NULL; fbt = fbt->fbtp_next)		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;}/*ARGSUSED*/static voidfbt_suspend(void *arg, dtrace_id_t id, void *parg){	fbt_probe_t *fbt = parg;	struct modctl *ctl = fbt->fbtp_ctl;	if (!fbt->fbtp_primary && !ctl->mod_loaded)		return;	if (ctl->mod_loadcnt != fbt->fbtp_loadcnt)		return;	ASSERT(ctl->mod_nenabled > 0);	for (; fbt != NULL; fbt = fbt->fbtp_next)		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;}/*ARGSUSED*/static voidfbt_resume(void *arg, dtrace_id_t id, void *parg){	fbt_probe_t *fbt = parg;	struct modctl *ctl = fbt->fbtp_ctl;	if (!fbt->fbtp_primary && !ctl->mod_loaded)		return;	if (ctl->mod_loadcnt != fbt->fbtp_loadcnt)		return;	ASSERT(ctl->mod_nenabled > 0);	for (; fbt != NULL; fbt = fbt->fbtp_next)		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;}/*ARGSUSED*/static voidfbt_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc){	fbt_probe_t *fbt = parg;	struct modctl *ctl = fbt->fbtp_ctl;	struct module *mp = ctl->mod_mp;	ctf_file_t *fp = NULL, *pfp;	ctf_funcinfo_t f;	int error;	ctf_id_t argv[32], type;	int argc = sizeof (argv) / sizeof (ctf_id_t);	const char *parent;	if (!ctl->mod_loaded || (ctl->mod_loadcnt != fbt->fbtp_loadcnt))		goto err;	if (fbt->fbtp_return && desc->dtargd_ndx == 0) {		(void) strcpy(desc->dtargd_native, "int");		return;	}	if ((fp = ctf_modopen(mp, &error)) == NULL) {		/*		 * We have no CTF information for this module -- and therefore		 * no args[] information.		 */		goto err;	}	/*	 * If we have a parent container, we must manually import it.	 */	if ((parent = ctf_parent_name(fp)) != NULL) {		struct modctl *mod;		/*		 * We must iterate over all modules to find the module that		 * is our parent.		 */		for (mod = &modules; mod != NULL; mod = mod->mod_next) {			if (strcmp(mod->mod_filename, parent) == 0)				break;		}		if (mod == NULL)			goto err;		if ((pfp = ctf_modopen(mod->mod_mp, &error)) == NULL)			goto err;		if (ctf_import(fp, pfp) != 0) {			ctf_close(pfp);			goto err;		}		ctf_close(pfp);	}	if (ctf_func_info(fp, fbt->fbtp_symndx, &f) == CTF_ERR)		goto err;	if (fbt->fbtp_return) {		if (desc->dtargd_ndx > 1)			goto err;		ASSERT(desc->dtargd_ndx == 1);		type = f.ctc_return;	} else {		if (desc->dtargd_ndx + 1 > f.ctc_argc)			goto err;		if (ctf_func_args(fp, fbt->fbtp_symndx, argc, argv) == CTF_ERR)			goto err;		type = argv[desc->dtargd_ndx];	}	if (ctf_type_name(fp, type, desc->dtargd_native,	    DTRACE_ARGTYPELEN) != NULL) {		ctf_close(fp);		return;	}err:	if (fp != NULL)		ctf_close(fp);	desc->dtargd_ndx = DTRACE_ARGNONE;}static dtrace_pattr_t fbt_attr = {{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },};static dtrace_pops_t fbt_pops = {	NULL,	fbt_provide_module,	fbt_enable,	fbt_disable,	fbt_suspend,	fbt_resume,	fbt_getargdesc,	NULL,	NULL,	fbt_destroy};static intfbt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd){	switch (cmd) {	case DDI_ATTACH:		break;	case DDI_RESUME:		return (DDI_SUCCESS);	default:		return (DDI_FAILURE);	}	if (ddi_create_minor_node(devi, "fbt", S_IFCHR, 0,	    DDI_PSEUDO, NULL) == DDI_FAILURE ||	    dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_KERNEL, 0,	    &fbt_pops, NULL, &fbt_id) != 0) {		ddi_remove_minor_node(devi, NULL);		return (DDI_FAILURE);	}	ddi_report_dev(devi);	fbt_devi = devi;	return (DDI_SUCCESS);}static intfbt_detach(dev_info_t *devi, ddi_detach_cmd_t cmd){	switch (cmd) {	case DDI_DETACH:		break;	case DDI_SUSPEND:		return (DDI_SUCCESS);	default:		return (DDI_FAILURE);	}	if (dtrace_unregister(fbt_id) != 0)		return (DDI_FAILURE);	ddi_remove_minor_node(devi, NULL);	return (DDI_SUCCESS);}/*ARGSUSED*/static intfbt_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result){	int error;	switch (infocmd) {	case DDI_INFO_DEVT2DEVINFO:		*result = (void *)fbt_devi;		error = DDI_SUCCESS;		break;	case DDI_INFO_DEVT2INSTANCE:		*result = (void *)0;		error = DDI_SUCCESS;		break;	default:		error = DDI_FAILURE;	}	return (error);}/*ARGSUSED*/static intfbt_open(dev_t *devp, int flag, int otyp, cred_t *cred_p){	return (0);}static struct cb_ops fbt_cb_ops = {	fbt_open,		/* open */	nodev,			/* close */	nulldev,		/* strategy */	nulldev,		/* print */	nodev,			/* dump */	nodev,			/* read */	nodev,			/* write */	nodev,			/* ioctl */	nodev,			/* devmap */	nodev,			/* mmap */	nodev,			/* segmap */	nochpoll,		/* poll */	ddi_prop_op,		/* cb_prop_op */	0,			/* streamtab  */	D_NEW | D_MP		/* Driver compatibility flag */};static struct dev_ops fbt_ops = {	DEVO_REV,		/* devo_rev */	0,			/* refcnt */	fbt_info,		/* get_dev_info */	nulldev,		/* identify */	nulldev,		/* probe */	fbt_attach,		/* attach */	fbt_detach,		/* detach */	nodev,			/* reset */	&fbt_cb_ops,		/* driver operations */	NULL,			/* bus operations */	nodev			/* dev power */};/* * Module linkage information for the kernel. */static struct modldrv modldrv = {	&mod_driverops,		/* module type (this is a pseudo driver) */	"Function Boundary Tracing",	/* name of module */	&fbt_ops,		/* driver ops */};static struct modlinkage modlinkage = {	MODREV_1,	(void *)&modldrv,	NULL};int_init(void){	return (mod_install(&modlinkage));}int_info(struct modinfo *modinfop){	return (mod_info(&modlinkage, modinfop));}int_fini(void){	return (mod_remove(&modlinkage));}

⌨️ 快捷键说明

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