dtrace_attribute_t dt_ident_cook(dt_node_t *dnp, dt_ident_t *idp, dt_node_t **pargp) { dtrace_attribute_t attr; dt_node_t *args, *argp; int argc = 0; attr = dt_node_list_cook(pargp, DT_IDFLG_REF); args = pargp ? *pargp : NULL; for (argp = args; argp != NULL; argp = argp->dn_list) argc++; idp->di_ops->di_cook(dnp, idp, argc, args); if (idp->di_flags & DT_IDFLG_USER) dnp->dn_flags |= DT_NF_USERLAND; return (dt_attr_min(attr, idp->di_attr)); }
dt_probe_t * dt_probe_info(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp, dtrace_probeinfo_t *pip) { int m_is_glob = pdp->dtpd_mod[0] == '\0' || strisglob(pdp->dtpd_mod); int f_is_glob = pdp->dtpd_func[0] == '\0' || strisglob(pdp->dtpd_func); int n_is_glob = pdp->dtpd_name[0] == '\0' || strisglob(pdp->dtpd_name); dt_probe_t *prp = NULL; const dtrace_pattr_t *pap; dt_provider_t *pvp; dt_ident_t *idp; /* * Attempt to lookup the probe in our existing cache for this provider. * If none is found and an explicit probe ID was specified, discover * that specific probe and cache its description and arguments. */ if ((pvp = dt_provider_lookup(dtp, pdp->dtpd_provider)) != NULL) { size_t keylen = dt_probe_keylen(pdp); char *key = dt_probe_key(pdp, alloca(keylen)); if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL) prp = idp->di_data; else if (pdp->dtpd_id != DTRACE_IDNONE) prp = dt_probe_discover(pvp, pdp); } /* * If no probe was found in our cache, convert the caller's partial * probe description into a fully-formed matching probe description by * iterating over up to at most two probes that match 'pdp'. We then * call dt_probe_discover() on the resulting probe identifier. */ if (prp == NULL) { dtrace_probedesc_t pd; int m; bzero(&pd, sizeof (pd)); pd.dtpd_id = DTRACE_IDNONE; /* * Call dtrace_probe_iter() to find matching probes. Our * dt_probe_desc() callback will produce the following results: * * m < 0 dtrace_probe_iter() found zero matches (or failed). * m > 0 dtrace_probe_iter() found more than one match. * m = 0 dtrace_probe_iter() found exactly one match. */ if ((m = dtrace_probe_iter(dtp, pdp, dt_probe_desc, &pd)) < 0) return (NULL); /* dt_errno is set for us */ if ((pvp = dt_provider_lookup(dtp, pd.dtpd_provider)) == NULL) return (NULL); /* dt_errno is set for us */ /* * If more than one probe was matched, then do not report probe * information if either of the following conditions is true: * * (a) The Arguments Data stability of the matched provider is * less than Evolving. * * (b) Any description component that is at least Evolving is * empty or is specified using a globbing expression. * * These conditions imply that providers that provide Evolving * or better Arguments Data stability must guarantee that all * probes with identical field names in a field of Evolving or * better Name stability have identical argument signatures. */ if (m > 0) { if (pvp->pv_desc.dtvd_attr.dtpa_args.dtat_data < DTRACE_STABILITY_EVOLVING) { (void) dt_set_errno(dtp, EDT_UNSTABLE); return (NULL); } if (pvp->pv_desc.dtvd_attr.dtpa_mod.dtat_name >= DTRACE_STABILITY_EVOLVING && m_is_glob) { (void) dt_set_errno(dtp, EDT_UNSTABLE); return (NULL); } if (pvp->pv_desc.dtvd_attr.dtpa_func.dtat_name >= DTRACE_STABILITY_EVOLVING && f_is_glob) { (void) dt_set_errno(dtp, EDT_UNSTABLE); return (NULL); } if (pvp->pv_desc.dtvd_attr.dtpa_name.dtat_name >= DTRACE_STABILITY_EVOLVING && n_is_glob) { (void) dt_set_errno(dtp, EDT_UNSTABLE); return (NULL); } } /* * If we matched a probe exported by dtrace(7D), then discover * the real attributes. Otherwise grab the static declaration. */ if (pd.dtpd_id != DTRACE_IDNONE) prp = dt_probe_discover(pvp, &pd); else prp = dt_probe_lookup(pvp, pd.dtpd_name); if (prp == NULL) return (NULL); /* dt_errno is set for us */ } assert(pvp != NULL && prp != NULL); /* * Compute the probe description attributes by taking the minimum of * the attributes of the specified fields. If no provider is specified * or a glob pattern is used for the provider, use Unstable attributes. */ if (pdp->dtpd_provider[0] == '\0' || strisglob(pdp->dtpd_provider)) pap = &_dtrace_prvdesc; else pap = &pvp->pv_desc.dtvd_attr; pip->dtp_attr = pap->dtpa_provider; if (!m_is_glob) pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_mod); if (!f_is_glob) pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_func); if (!n_is_glob) pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_name); pip->dtp_arga = pap->dtpa_args; pip->dtp_argv = prp->pr_argv; pip->dtp_argc = prp->pr_argc; return (prp); }
/*ARGSUSED*/ void dtrace_program_info(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_proginfo_t *pip) { dt_stmt_t *stp; dtrace_actdesc_t *ap; dtrace_ecbdesc_t *last = NULL; if (pip == NULL) return; bzero(pip, sizeof (dtrace_proginfo_t)); if (dt_list_next(&pgp->dp_stmts) != NULL) { pip->dpi_descattr = _dtrace_maxattr; pip->dpi_stmtattr = _dtrace_maxattr; } else { pip->dpi_descattr = _dtrace_defattr; pip->dpi_stmtattr = _dtrace_defattr; } for (stp = dt_list_next(&pgp->dp_stmts); stp; stp = dt_list_next(stp)) { dtrace_ecbdesc_t *edp = stp->ds_desc->dtsd_ecbdesc; if (edp == last) continue; last = edp; pip->dpi_descattr = dt_attr_min(stp->ds_desc->dtsd_descattr, pip->dpi_descattr); pip->dpi_stmtattr = dt_attr_min(stp->ds_desc->dtsd_stmtattr, pip->dpi_stmtattr); /* * If there aren't any actions, account for the fact that * recording the epid will generate a record. */ if (edp->dted_action == NULL) pip->dpi_recgens++; for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { if (ap->dtad_kind == DTRACEACT_SPECULATE) { pip->dpi_speculations++; continue; } if (DTRACEACT_ISAGG(ap->dtad_kind)) { pip->dpi_recgens -= ap->dtad_arg; pip->dpi_aggregates++; continue; } if (DTRACEACT_ISDESTRUCTIVE(ap->dtad_kind)) continue; if (ap->dtad_kind == DTRACEACT_DIFEXPR && ap->dtad_difo->dtdo_rtype.dtdt_kind == DIF_TYPE_CTF && ap->dtad_difo->dtdo_rtype.dtdt_size == 0) continue; pip->dpi_recgens++; } } }