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

📄 fasttrap.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 5 页
字号:
static void *fasttrap_meta_provide(void *arg, dtrace_helper_provdesc_t *dhpv, pid_t pid){	fasttrap_provider_t *provider;	/*	 * A 32-bit unsigned integer (like a pid for example) can be	 * expressed in 10 or fewer decimal digits. Make sure that we'll	 * have enough space for the provider name.	 */	if (strlen(dhpv->dthpv_provname) + 10 >=	    sizeof (provider->ftp_name)) {		cmn_err(CE_WARN, "failed to instantiate provider %s: "		    "name too long to accomodate pid", dhpv->dthpv_provname);		return (NULL);	}	/*	 * Don't let folks spoof the true pid provider.	 */	if (strcmp(dhpv->dthpv_provname, FASTTRAP_PID_NAME) == 0) {		cmn_err(CE_WARN, "failed to instantiate provider %s: "		    "%s is an invalid name", dhpv->dthpv_provname,		    FASTTRAP_PID_NAME);		return (NULL);	}	/*	 * The highest stability class that fasttrap supports is ISA; cap	 * the stability of the new provider accordingly.	 */	if (dhpv->dthpv_pattr.dtpa_provider.dtat_class >= DTRACE_CLASS_COMMON)		dhpv->dthpv_pattr.dtpa_provider.dtat_class = DTRACE_CLASS_ISA;	if (dhpv->dthpv_pattr.dtpa_mod.dtat_class >= DTRACE_CLASS_COMMON)		dhpv->dthpv_pattr.dtpa_mod.dtat_class = DTRACE_CLASS_ISA;	if (dhpv->dthpv_pattr.dtpa_func.dtat_class >= DTRACE_CLASS_COMMON)		dhpv->dthpv_pattr.dtpa_func.dtat_class = DTRACE_CLASS_ISA;	if (dhpv->dthpv_pattr.dtpa_name.dtat_class >= DTRACE_CLASS_COMMON)		dhpv->dthpv_pattr.dtpa_name.dtat_class = DTRACE_CLASS_ISA;	if (dhpv->dthpv_pattr.dtpa_args.dtat_class >= DTRACE_CLASS_COMMON)		dhpv->dthpv_pattr.dtpa_args.dtat_class = DTRACE_CLASS_ISA;	if ((provider = fasttrap_provider_lookup(pid, dhpv->dthpv_provname,	    &dhpv->dthpv_pattr)) == NULL) {		cmn_err(CE_WARN, "failed to instantiate provider %s for "		    "process %u",  dhpv->dthpv_provname, (uint_t)pid);		return (NULL);	}	/*	 * We elevate the consumer count here to ensure that this provider	 * isn't removed until after the meta provider has been told to	 * remove it.	 */	provider->ftp_ccount++;	mutex_exit(&provider->ftp_mtx);	return (provider);}/*ARGSUSED*/static voidfasttrap_meta_create_probe(void *arg, void *parg,    dtrace_helper_probedesc_t *dhpb){	fasttrap_provider_t *provider = parg;	fasttrap_probe_t *pp;	fasttrap_tracepoint_t *tp;	size_t size;	int i;	mutex_enter(&provider->ftp_mtx);	if (dtrace_probe_lookup(provider->ftp_provid, dhpb->dthpb_mod,	    dhpb->dthpb_func, dhpb->dthpb_name) != 0) {		mutex_exit(&provider->ftp_mtx);		return;	}	atomic_add_32(&fasttrap_total, dhpb->dthpb_noffs);	if (fasttrap_total > fasttrap_max) {		atomic_add_32(&fasttrap_total, -dhpb->dthpb_noffs);		mutex_exit(&provider->ftp_mtx);		return;	}	size = sizeof (fasttrap_probe_t) +	    sizeof (pp->ftp_tps[0]) * (dhpb->dthpb_noffs - 1);	pp = kmem_zalloc(size, KM_SLEEP);	pp->ftp_prov = provider;	pp->ftp_pid = provider->ftp_pid;	pp->ftp_ntps = dhpb->dthpb_noffs;#ifdef __sparc	pp->ftp_type = DTFTP_POST_OFFSETS;#else	pp->ftp_type = DTFTP_OFFSETS;#endif	pp->ftp_nargs = dhpb->dthpb_xargc;	pp->ftp_xtypes = dhpb->dthpb_xtypes;	pp->ftp_ntypes = dhpb->dthpb_ntypes;	for (i = 0; i < pp->ftp_ntps; i++) {		tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), KM_SLEEP);		tp->ftt_prov = provider;		tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_offs[i];		tp->ftt_pid = provider->ftp_pid;		pp->ftp_tps[i].fit_tp = tp;		pp->ftp_tps[i].fit_id.fti_probe = pp;	}	/*	 * If the arguments are shuffled around we set the argument remapping	 * table. Later, when the probe fires, we only remap the arguments	 * if the table is non-NULL.	 */	for (i = 0; i < dhpb->dthpb_xargc; i++) {		if (dhpb->dthpb_args[i] != i) {			pp->ftp_argmap = dhpb->dthpb_args;			break;		}	}	/*	 * The probe is fully constructed -- register it with DTrace.	 */	pp->ftp_id = dtrace_probe_create(provider->ftp_provid, dhpb->dthpb_mod,	    dhpb->dthpb_func, dhpb->dthpb_name, FASTTRAP_OFFSET_AFRAMES, pp);	mutex_exit(&provider->ftp_mtx);}/*ARGSUSED*/static voidfasttrap_meta_remove(void *arg, dtrace_helper_provdesc_t *dhpv, pid_t pid){	fasttrap_provider_t *provider;	if ((provider = fasttrap_provider_lookup(pid,	    dhpv->dthpv_provname, NULL)) != NULL) {		/*		 * Drop the consumer count now that we're done with this		 * provider. If there are no other consumers retire it now.		 */		if (--provider->ftp_ccount == 0)			fasttrap_provider_retire(provider);		else			mutex_exit(&provider->ftp_mtx);	}}static dtrace_mops_t fasttrap_mops = {	fasttrap_meta_create_probe,	fasttrap_meta_provide,	fasttrap_meta_remove};/*ARGSUSED*/static intfasttrap_open(dev_t *devp, int flag, int otyp, cred_t *cred_p){	return (0);}/*ARGSUSED*/static intfasttrap_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv){	if (!dtrace_attached())		return (EAGAIN);	if (cmd == FASTTRAPIOC_MAKEPROBE) {		fasttrap_probe_spec_t *uprobe = (void *)arg;		fasttrap_probe_spec_t *probe;		uint64_t noffs;		size_t size;		int ret;		char *c;		if (copyin(&uprobe->ftps_noffs, &noffs,		    sizeof (uprobe->ftps_noffs)))			return (EFAULT);		/*		 * Probes must have at least one tracepoint.		 */		if (noffs == 0)			return (EINVAL);		size = sizeof (fasttrap_probe_spec_t) +		    sizeof (probe->ftps_offs[0]) * (noffs - 1);		if (size > 1024 * 1024)			return (ENOMEM);		probe = kmem_alloc(size, KM_SLEEP);		if (copyin(uprobe, probe, size) != 0) {			kmem_free(probe, size);			return (EFAULT);		}		/*		 * Verify that the function and module strings contain no		 * funny characters.		 */		for (c = &probe->ftps_func[0]; *c != '\0'; c++) {			if (*c < 0x20 || 0x7f <= *c) {				ret = EINVAL;				goto err;			}		}		for (c = &probe->ftps_mod[0]; *c != '\0'; c++) {			if (*c < 0x20 || 0x7f <= *c) {				ret = EINVAL;				goto err;			}		}		if (!PRIV_POLICY_CHOICE(cr, PRIV_ALL, B_FALSE)) {			proc_t *p;			pid_t pid = probe->ftps_pid;			mutex_enter(&pidlock);			/*			 * Report an error if the process doesn't exist			 * or is actively being birthed.			 */			if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {				mutex_exit(&pidlock);				return (ESRCH);			}			mutex_enter(&p->p_lock);			mutex_exit(&pidlock);			if ((ret = priv_proc_cred_perm(cr, p, NULL,			    VREAD | VWRITE)) != 0) {				mutex_exit(&p->p_lock);				return (ret);			}			mutex_exit(&p->p_lock);		}		ret = fasttrap_add_probe(probe);err:		kmem_free(probe, size);		return (ret);	} else if (cmd == FASTTRAPIOC_GETINSTR) {		fasttrap_instr_query_t instr;		fasttrap_tracepoint_t *tp;		uint_t index;		int ret;		if (copyin((void *)arg, &instr, sizeof (instr)) != 0)			return (EFAULT);		if (!PRIV_POLICY_CHOICE(cr, PRIV_ALL, B_FALSE)) {			proc_t *p;			pid_t pid = instr.ftiq_pid;			mutex_enter(&pidlock);			/*			 * Report an error if the process doesn't exist			 * or is actively being birthed.			 */			if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {				mutex_exit(&pidlock);				return (ESRCH);			}			mutex_enter(&p->p_lock);			mutex_exit(&pidlock);			if ((ret = priv_proc_cred_perm(cr, p, NULL,			    VREAD)) != 0) {				mutex_exit(&p->p_lock);				return (ret);			}			mutex_exit(&p->p_lock);		}		index = FASTTRAP_TPOINTS_INDEX(instr.ftiq_pid, instr.ftiq_pc);		mutex_enter(&fasttrap_tpoints.fth_table[index].ftb_mtx);		tp = fasttrap_tpoints.fth_table[index].ftb_data;		while (tp != NULL) {			if (instr.ftiq_pid == tp->ftt_pid &&			    instr.ftiq_pc == tp->ftt_pc &&			    !tp->ftt_prov->ftp_defunct)				break;			tp = tp->ftt_next;		}		if (tp == NULL) {			mutex_exit(&fasttrap_tpoints.fth_table[index].ftb_mtx);			return (ENOENT);		}		bcopy(&tp->ftt_instr, &instr.ftiq_instr,		    sizeof (instr.ftiq_instr));		mutex_exit(&fasttrap_tpoints.fth_table[index].ftb_mtx);		if (copyout(&instr, (void *)arg, sizeof (instr)) != 0)			return (EFAULT);		return (0);	}	return (EINVAL);}static struct cb_ops fasttrap_cb_ops = {	fasttrap_open,		/* open */	nodev,			/* close */	nulldev,		/* strategy */	nulldev,		/* print */	nodev,			/* dump */	nodev,			/* read */	nodev,			/* write */	fasttrap_ioctl,		/* ioctl */	nodev,			/* devmap */	nodev,			/* mmap */	nodev,			/* segmap */	nochpoll,		/* poll */	ddi_prop_op,		/* cb_prop_op */	0,			/* streamtab  */	D_NEW | D_MP		/* Driver compatibility flag */};/*ARGSUSED*/static intfasttrap_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result){	int error;	switch (infocmd) {	case DDI_INFO_DEVT2DEVINFO:		*result = (void *)fasttrap_devi;		error = DDI_SUCCESS;		break;	case DDI_INFO_DEVT2INSTANCE:		*result = (void *)0;		error = DDI_SUCCESS;		break;	default:		error = DDI_FAILURE;	}	return (error);}static intfasttrap_attach(dev_info_t *devi, ddi_attach_cmd_t cmd){	ulong_t nent;	switch (cmd) {	case DDI_ATTACH:		break;	case DDI_RESUME:		return (DDI_SUCCESS);	default:		return (DDI_FAILURE);	}	if (ddi_create_minor_node(devi, "fasttrap", S_IFCHR, 0,	    DDI_PSEUDO, NULL) == DDI_FAILURE ||	    dtrace_register("fasttrap", &fasttrap_attr, DTRACE_PRIV_USER, 0,	    &fasttrap_pops, NULL, &fasttrap_id) != 0) {		ddi_remove_minor_node(devi, NULL);		return (DDI_FAILURE);	}	ddi_report_dev(devi);	fasttrap_devi = devi;	/*	 * Install our hooks into fork(2), exec(2), and exit(2).	 */	dtrace_fasttrap_fork_ptr = &fasttrap_fork;	dtrace_fasttrap_exit_ptr = &fasttrap_exec_exit;	dtrace_fasttrap_exec_ptr = &fasttrap_exec_exit;	fasttrap_max = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,	    "fasttrap-max-probes", FASTTRAP_MAX_DEFAULT);	fasttrap_total = 0;	/*	 * Conjure up the tracepoints hashtable...	 */	nent = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,	    "fasttrap-hash-size", FASTTRAP_TPOINTS_DEFAULT_SIZE);	if (nent <= 0 || nent > 0x1000000)		nent = FASTTRAP_TPOINTS_DEFAULT_SIZE;	if ((nent & (nent - 1)) == 0)		fasttrap_tpoints.fth_nent = nent;	else		fasttrap_tpoints.fth_nent = 1 << fasttrap_highbit(nent);	ASSERT(fasttrap_tpoints.fth_nent > 0);	fasttrap_tpoints.fth_mask = fasttrap_tpoints.fth_nent - 1;	fasttrap_tpoints.fth_table = kmem_zalloc(fasttrap_tpoints.fth_nent *	    sizeof (fasttrap_bucket_t), KM_SLEEP);	/*	 * ... and the providers hash table.	 */	nent = FASTTRAP_PROVIDERS_DEFAULT_SIZE;	if ((nent & (nent - 1)) == 0)		fasttrap_provs.fth_nent = nent;	else		fasttrap_provs.fth_nent = 1 << fasttrap_highbit(nent);	ASSERT(fasttrap_provs.fth_nent > 0);	fasttrap_provs.fth_mask = fasttrap_provs.fth_nent - 1;	fasttrap_provs.fth_table = kmem_zalloc(fasttrap_provs.fth_nent *	    sizeof (fasttrap_bucket_t), KM_SLEEP);	(void) dtrace_meta_register("fasttrap", &fasttrap_mops, NULL,	    &fasttrap_meta_id);	return (DDI_SUCCESS);}static intfasttrap_detach(dev_info_t *devi, ddi_detach_cmd_t cmd){	int i, fail = 0;	timeout_id_t tmp;	switch (cmd) {	case DDI_DETACH:		break;	case DDI_SUSPEND:		return (DDI_SUCCESS);	default:		return (DDI_FAILURE);	}	/*	 * Unregister the meta-provider to make sure no new fasttrap-	 * managed providers come along while we're trying to close up	 * shop. If we fail to detach, we'll need to re-register as a	 * meta-provider. We can fail to unregister as a meta-provider	 * if providers we manage still exist.	 */	if (fasttrap_meta_id != DTRACE_METAPROVNONE &&	    dtrace_meta_unregister(fasttrap_meta_id) != 0)		return (DDI_FAILURE);	/*	 * Prevent any new timeouts from running by setting fasttrap_timeout	 * to a non-zero value, and wait for the current timeout to complete.	 */	mutex_enter(&fasttrap_cleanup_mtx);	fasttrap_cleanup_work = 0;	while (fasttrap_timeout != (timeout_id_t)1) {		tmp = fasttrap_timeout;		fasttrap_timeout = (timeout_id_t)1;		if (tmp != 0) {			mutex_exit(&fasttrap_cleanup_mtx);			(void) untimeout(tmp);			mutex_enter(&fasttrap_cleanup_mtx);		}	}	fasttrap_cleanup_work = 0;	mutex_exit(&fasttrap_cleanup_mtx);	/*	 * Iterate over all of our providers. If there's still a process	 * that corresponds to that pid, fail to detach.	 */	for (i = 0; i < fasttrap_provs.fth_nent; i++) {		fasttrap_provider_t **fpp, *fp;		fasttrap_bucket_t *bucket = &fasttrap_provs.fth_table[i];

⌨️ 快捷键说明

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