示例#1
0
dt_ident_t *
dt_idhash_insert(dt_idhash_t *dhp, const char *name, ushort_t kind,
    ushort_t flags, uint_t id, dtrace_attribute_t attr, uint_t vers,
    const dt_idops_t *ops, void *iarg, ulong_t gen)
{
	dt_ident_t *idp;
	ulong_t h;

	if (dhp->dh_tmpl != NULL)
		dt_idhash_populate(dhp); /* fill hash w/ initial population */

	idp = dt_ident_create(name, kind, flags, id,
	    attr, vers, ops, iarg, gen);

	if (idp == NULL)
		return (NULL);

	h = dt_strtab_hash(name, NULL) % dhp->dh_hashsz;
	idp->di_next = dhp->dh_hash[h];

	dhp->dh_hash[h] = idp;
	dhp->dh_nelems++;

	if (dhp->dh_defer != NULL)
		dhp->dh_defer(dhp, idp);

	return (idp);
}
示例#2
0
/*
 * If a probe was discovered from the kernel, ask dtrace(7D) for a description
 * of each of its arguments, including native and translated types.
 */
static dt_probe_t *
dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
{
	dtrace_hdl_t *dtp = pvp->pv_hdl;
	char *name = dt_probe_key(pdp, alloca(dt_probe_keylen(pdp)));

	dt_node_t *xargs, *nargs;
	dt_ident_t *idp;
	dt_probe_t *prp;

	dtrace_typeinfo_t dtt;
	int i, nc, xc;

	int adc = _dtrace_argmax;
	dtrace_argdesc_t *adv = alloca(sizeof (dtrace_argdesc_t) * adc);
	dtrace_argdesc_t *adp = adv;

	assert(strcmp(pvp->pv_desc.dtvd_name, pdp->dtpd_provider) == 0);
	assert(pdp->dtpd_id != DTRACE_IDNONE);

	dt_dprintf("discovering probe %s:%s id=%d\n",
	    pvp->pv_desc.dtvd_name, name, pdp->dtpd_id);

	for (nc = -1, i = 0; i < adc; i++, adp++) {
		bzero(adp, sizeof (dtrace_argdesc_t));
		adp->dtargd_ndx = i;
		adp->dtargd_id = pdp->dtpd_id;

		if (dt_ioctl(dtp, DTRACEIOC_PROBEARG, adp) != 0) {
			(void) dt_set_errno(dtp, errno);
			return (NULL);
		}

		if (adp->dtargd_ndx == DTRACE_ARGNONE)
			break; /* all argument descs have been retrieved */

		nc = MAX(nc, adp->dtargd_mapping);
	}

	xc = i;
	nc++;

	/*
	 * The pid provider believes in giving the kernel a break. No reason to
	 * give the kernel all the ctf containers that we're keeping ourselves
	 * just to get it back from it. So if we're coming from a pid provider
	 * probe and the kernel gave us no argument information we'll get some
	 * here. If for some crazy reason the kernel knows about our userland
	 * types then we just ignore this.
	 */
	if (xc == 0 && nc == 0 &&
	    strncmp(pvp->pv_desc.dtvd_name, "pid", 3) == 0) {
		nc = adc;
		dt_pid_get_types(dtp, pdp, adv, &nc);
		xc = nc;
	}

	/*
	 * Now that we have discovered the number of native and translated
	 * arguments from the argument descriptions, allocate a new probe ident
	 * and corresponding dt_probe_t and hash it into the provider.
	 */
	xargs = dt_probe_alloc_args(pvp, xc);
	nargs = dt_probe_alloc_args(pvp, nc);

	if ((xc != 0 && xargs == NULL) || (nc != 0 && nargs == NULL))
		return (NULL); /* dt_errno is set for us */

	idp = dt_ident_create(name, DT_IDENT_PROBE,
	    DT_IDFLG_ORPHAN, pdp->dtpd_id, _dtrace_defattr, 0,
	    &dt_idops_probe, NULL, dtp->dt_gen);

	if (idp == NULL) {
		(void) dt_set_errno(dtp, EDT_NOMEM);
		return (NULL);
	}

	if ((prp = dt_probe_create(dtp, idp, 2,
	    nargs, nc, xargs, xc)) == NULL) {
		dt_ident_destroy(idp);
		return (NULL);
	}

	dt_probe_declare(pvp, prp);

	/*
	 * Once our new dt_probe_t is fully constructed, iterate over the
	 * cached argument descriptions and assign types to prp->pr_nargv[]
	 * and prp->pr_xargv[] and assign mappings to prp->pr_mapping[].
	 */
	for (adp = adv, i = 0; i < xc; i++, adp++) {
		if (dtrace_type_strcompile(dtp,
		    adp->dtargd_native, &dtt) != 0) {
			dt_dprintf("failed to resolve input type %s "
			    "for %s:%s arg #%d: %s\n", adp->dtargd_native,
			    pvp->pv_desc.dtvd_name, name, i + 1,
			    dtrace_errmsg(dtp, dtrace_errno(dtp)));

			dtt.dtt_object = NULL;
			dtt.dtt_ctfp = NULL;
			dtt.dtt_type = CTF_ERR;
		} else {
			dt_node_type_assign(prp->pr_nargv[adp->dtargd_mapping],
			    dtt.dtt_ctfp, dtt.dtt_type,
			    dtt.dtt_flags & DTT_FL_USER ? B_TRUE : B_FALSE);
		}

		if (dtt.dtt_type != CTF_ERR && (adp->dtargd_xlate[0] == '\0' ||
		    strcmp(adp->dtargd_native, adp->dtargd_xlate) == 0)) {
			dt_node_type_propagate(prp->pr_nargv[
			    adp->dtargd_mapping], prp->pr_xargv[i]);
		} else if (dtrace_type_strcompile(dtp,
		    adp->dtargd_xlate, &dtt) != 0) {
			dt_dprintf("failed to resolve output type %s "
			    "for %s:%s arg #%d: %s\n", adp->dtargd_xlate,
			    pvp->pv_desc.dtvd_name, name, i + 1,
			    dtrace_errmsg(dtp, dtrace_errno(dtp)));

			dtt.dtt_object = NULL;
			dtt.dtt_ctfp = NULL;
			dtt.dtt_type = CTF_ERR;
		} else {
			dt_node_type_assign(prp->pr_xargv[i],
			    dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
		}

		prp->pr_mapping[i] = adp->dtargd_mapping;
		prp->pr_argv[i] = dtt;
	}

	return (prp);
}
示例#3
0
dt_xlator_t *
dt_xlator_create(dtrace_hdl_t *dtp,
    const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst,
    const char *name, dt_node_t *members, dt_node_t *nodes)
{
	dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t));
	dtrace_typeinfo_t ptr = *dst;
	dt_xlator_t **map;
	dt_node_t *dnp;
	uint_t kind;

	if (dxp == NULL)
		return (NULL);

	dxp->dx_hdl = dtp;
	dxp->dx_id = dtp->dt_xlatorid++;
	dxp->dx_gen = dtp->dt_gen;
	dxp->dx_arg = -1;

	if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) {
		dt_free(dtp, dxp);
		return (NULL);
	}

	dt_list_append(&dtp->dt_xlators, dxp);
	bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id);
	dt_free(dtp, dtp->dt_xlatormap);
	dtp->dt_xlatormap = map;
	dtp->dt_xlatormap[dxp->dx_id] = dxp;

	if (dt_type_pointer(&ptr) == -1) {
		ptr.dtt_ctfp = NULL;
		ptr.dtt_type = CTF_ERR;
	}

	dxp->dx_ident = dt_ident_create(name ? name : "T",
	    DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0,
	    _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);

	if (dxp->dx_ident == NULL)
		goto err; /* no memory for identifier */

	dxp->dx_ident->di_ctfp = src->dtt_ctfp;
	dxp->dx_ident->di_type = src->dtt_type;

	/*
	 * If an input parameter name is given, this is a static translator
	 * definition: create an idhash and identifier for the parameter.
	 */
	if (name != NULL) {
		dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0);

		if (dxp->dx_locals == NULL)
			goto err; /* no memory for identifier hash */

		dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident);
	}

	dxp->dx_souid.di_name = "translator";
	dxp->dx_souid.di_kind = DT_IDENT_XLSOU;
	dxp->dx_souid.di_flags = DT_IDFLG_REF;
	dxp->dx_souid.di_id = dxp->dx_id;
	dxp->dx_souid.di_attr = _dtrace_defattr;
	dxp->dx_souid.di_ops = &dt_idops_thaw;
	dxp->dx_souid.di_data = dxp;
	dxp->dx_souid.di_ctfp = dst->dtt_ctfp;
	dxp->dx_souid.di_type = dst->dtt_type;
	dxp->dx_souid.di_gen = dtp->dt_gen;

	dxp->dx_ptrid.di_name = "translator";
	dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR;
	dxp->dx_ptrid.di_flags = DT_IDFLG_REF;
	dxp->dx_ptrid.di_id = dxp->dx_id;
	dxp->dx_ptrid.di_attr = _dtrace_defattr;
	dxp->dx_ptrid.di_ops = &dt_idops_thaw;
	dxp->dx_ptrid.di_data = dxp;
	dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp;
	dxp->dx_ptrid.di_type = ptr.dtt_type;
	dxp->dx_ptrid.di_gen = dtp->dt_gen;

	/*
	 * If a deferred pragma is pending on the keyword "translator", run all
	 * the deferred pragmas on dx_souid and then copy results to dx_ptrid.
	 * See the code in dt_pragma.c for details on deferred ident pragmas.
	 */
	if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL &&
	    dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) {
		dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid);
		dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr;
		dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers;
	}

	dxp->dx_src_ctfp = src->dtt_ctfp;
	dxp->dx_src_type = src->dtt_type;
	dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type);

	dxp->dx_dst_ctfp = dst->dtt_ctfp;
	dxp->dx_dst_type = dst->dtt_type;
	dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type);

	kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base);
	assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION);

	/*
	 * If no input parameter is given, we're making a dynamic translator:
	 * create member nodes for every member of the output type.  Otherwise
	 * retain the member and allocation node lists presented by the parser.
	 */
	if (name == NULL) {
		if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base,
		    dt_xlator_create_member, dxp) != 0)
			goto err;
	} else {
		dxp->dx_members = members;
		dxp->dx_nodes = nodes;
	}

	/*
	 * Assign member IDs to each member and allocate space for DIFOs
	 * if and when this translator is eventually compiled.
	 */
	for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
		dnp->dn_membxlator = dxp;
		dnp->dn_membid = dxp->dx_nmembers++;
	}

	dxp->dx_membdif = dt_zalloc(dtp,
	    sizeof (dtrace_difo_t *) * dxp->dx_nmembers);

	if (dxp->dx_membdif == NULL) {
		dxp->dx_nmembers = 0;
		goto err;
	}

	return (dxp);

err:
	dt_xlator_destroy(dtp, dxp);
	return (NULL);
}
示例#4
0
/*
 * Cook a reference to the dynamically typed args[] array.  We verify that the
 * reference is using a single integer constant, and then construct a new ident
 * representing the appropriate type or translation specifically for this node.
 */
static void
dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
{
	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
	dt_probe_t *prp = yypcb->pcb_probe;

	dt_node_t tag, *nnp, *xnp;
	dt_xlator_t *dxp;
	dt_ident_t *xidp;

	char n1[DT_TYPE_NAMELEN];
	char n2[DT_TYPE_NAMELEN];

	if (argc != 1) {
		xyerror(D_PROTO_LEN, "%s[ ] prototype mismatch: %d arg%s"
		    "passed, 1 expected\n", idp->di_name, argc,
		    argc == 1 ? " " : "s ");
	}

	if (ap->dn_kind != DT_NODE_INT) {
		xyerror(D_PROTO_ARG, "%s[ ] argument #1 is incompatible with "
		    "prototype:\n\tprototype: %s\n\t argument: %s\n",
		    idp->di_name, "integer constant",
		    dt_type_name(ap->dn_ctfp, ap->dn_type, n1, sizeof (n1)));
	}

	if (yypcb->pcb_pdesc == NULL) {
		xyerror(D_ARGS_NONE, "%s[ ] may not be referenced outside "
		    "of a probe clause\n", idp->di_name);
	}

	if (prp == NULL) {
		xyerror(D_ARGS_MULTI,
		    "%s[ ] may not be referenced because probe description %s "
		    "matches an unstable set of probes\n", idp->di_name,
		    dtrace_desc2str(yypcb->pcb_pdesc, n1, sizeof (n1)));
	}

	if (ap->dn_value >= prp->pr_argc) {
		xyerror(D_ARGS_IDX, "index %lld is out of range for %s %s[ ]\n",
		    (longlong_t)ap->dn_value, dtrace_desc2str(yypcb->pcb_pdesc,
		    n1, sizeof (n1)), idp->di_name);
	}

	/*
	 * Look up the native and translated argument types for the probe.
	 * If no translation is needed, these will be the same underlying node.
	 * If translation is needed, look up the appropriate translator.  Once
	 * we have the appropriate node, create a new dt_ident_t for this node,
	 * assign it the appropriate attributes, and set the type of 'dnp'.
	 */
	xnp = prp->pr_xargv[ap->dn_value];
	nnp = prp->pr_nargv[prp->pr_mapping[ap->dn_value]];

	if (xnp->dn_type == CTF_ERR) {
		xyerror(D_ARGS_TYPE, "failed to resolve translated type for "
		    "%s[%lld]\n", idp->di_name, (longlong_t)ap->dn_value);
	}

	if (nnp->dn_type == CTF_ERR) {
		xyerror(D_ARGS_TYPE, "failed to resolve native type for "
		    "%s[%lld]\n", idp->di_name, (longlong_t)ap->dn_value);
	}

	if (dtp->dt_xlatemode == DT_XL_STATIC && (
	    nnp == xnp || dt_node_is_argcompat(nnp, xnp))) {
		dnp->dn_ident = dt_ident_create(idp->di_name, idp->di_kind,
		    idp->di_flags | DT_IDFLG_ORPHAN, idp->di_id, idp->di_attr,
		    idp->di_vers, idp->di_ops, idp->di_iarg, idp->di_gen);

		if (dnp->dn_ident == NULL)
			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);

		dt_node_type_assign(dnp,
		    prp->pr_argv[ap->dn_value].dtt_ctfp,
		    prp->pr_argv[ap->dn_value].dtt_type);

	} else if ((dxp = dt_xlator_lookup(dtp,
	    nnp, xnp, DT_XLATE_FUZZY)) != NULL || (
	    dxp = dt_xlator_lookup(dtp, dt_probe_tag(prp, ap->dn_value, &tag),
	    xnp, DT_XLATE_EXACT | DT_XLATE_EXTERN)) != NULL) {

		xidp = dt_xlator_ident(dxp, xnp->dn_ctfp, xnp->dn_type);

		dnp->dn_ident = dt_ident_create(idp->di_name, xidp->di_kind,
		    xidp->di_flags | DT_IDFLG_ORPHAN, idp->di_id, idp->di_attr,
		    idp->di_vers, idp->di_ops, idp->di_iarg, idp->di_gen);

		if (dnp->dn_ident == NULL)
			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);

		if (dt_xlator_dynamic(dxp))
			dxp->dx_arg = (int)ap->dn_value;

		/*
		 * Propagate relevant members from the translator's internal
		 * dt_ident_t.  This code must be kept in sync with the state
		 * that is initialized for idents in dt_xlator_create().
		 */
		dnp->dn_ident->di_data = xidp->di_data;
		dnp->dn_ident->di_ctfp = xidp->di_ctfp;
		dnp->dn_ident->di_type = xidp->di_type;

		dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));

	} else {
		xyerror(D_ARGS_XLATOR, "translator for %s[%lld] from %s to %s "
		    "is not defined\n", idp->di_name, (longlong_t)ap->dn_value,
		    dt_node_type_name(nnp, n1, sizeof (n1)),
		    dt_node_type_name(xnp, n2, sizeof (n2)));
	}

	assert(dnp->dn_ident->di_flags & DT_IDFLG_ORPHAN);
	assert(dnp->dn_ident->di_id == idp->di_id);
}