dt_cc.c
来自「Sun Solaris 10 中的 DTrace 组件的源代码。请参看: htt」· C语言 代码 · 共 2,025 行 · 第 1/4 页
C
2,025 行
if (dnp->dn_aggfun->dn_args != NULL) { dt_cg(yypcb, dnp->dn_aggfun->dn_args); ap->dtad_difo = dt_as(yypcb); } if (fid->di_id == DTRACEAGG_LQUANTIZE) { /* * For linear quantization, we have between two and three * arguments: * * arg1 => Base value * arg2 => Limit value * arg3 => Quantization level step size (defaults to 1) */ dt_node_t *arg1 = dnp->dn_aggfun->dn_args->dn_list; dt_node_t *arg2 = arg1->dn_list; dt_node_t *arg3 = arg2->dn_list; uint64_t nlevels, step = 1; int64_t baseval, limitval; if (arg1->dn_kind != DT_NODE_INT) { dnerror(arg1, D_LQUANT_BASETYPE, "lquantize( ) " "argument #1 must be an integer constant\n"); } baseval = (int64_t)arg1->dn_value; if (baseval < INT32_MIN || baseval > INT32_MAX) { dnerror(arg1, D_LQUANT_BASEVAL, "lquantize( ) " "argument #1 must be a 32-bit quantity\n"); } if (arg2->dn_kind != DT_NODE_INT) { dnerror(arg2, D_LQUANT_LIMTYPE, "lquantize( ) " "argument #2 must be an integer constant\n"); } limitval = (int64_t)arg2->dn_value; if (limitval < INT32_MIN || limitval > INT32_MAX) { dnerror(arg2, D_LQUANT_LIMVAL, "lquantize( ) " "argument #2 must be a 32-bit quantity\n"); } if (limitval < baseval) { dnerror(dnp, D_LQUANT_MISMATCH, "lquantize( ) base (argument #1) must be less " "than limit (argument #2)\n"); } if (arg3 != NULL) { if (!dt_node_is_posconst(arg3)) { dnerror(arg3, D_LQUANT_STEPTYPE, "lquantize( ) " "argument #3 must be a non-zero positive " "integer constant\n"); } if ((step = arg3->dn_value) > UINT16_MAX) { dnerror(arg3, D_LQUANT_STEPVAL, "lquantize( ) " "argument #3 must be a 16-bit quantity\n"); } } nlevels = (limitval - baseval) / step; if (nlevels == 0) { dnerror(dnp, D_LQUANT_STEPLARGE, "lquantize( ) step (argument #3) too large: must " "have at least one quantization level\n"); } if (nlevels > UINT16_MAX) { dnerror(dnp, D_LQUANT_STEPSMALL, "lquantize( ) step " "(argument #3) too small: number of quantization " "levels must be a 16-bit quantity\n"); } ap->dtad_arg = (step << DTRACE_LQUANTIZE_STEPSHIFT) | (nlevels << DTRACE_LQUANTIZE_LEVELSHIFT) | ((baseval << DTRACE_LQUANTIZE_BASESHIFT) & DTRACE_LQUANTIZE_BASEMASK); }}static voiddt_compile_one_clause(dtrace_hdl_t *dtp, dt_node_t *cnp, dt_node_t *pnp){ dtrace_ecbdesc_t *edp; dtrace_stmtdesc_t *sdp; dt_node_t *dnp; yylineno = pnp->dn_line; dt_setcontext(dtp, pnp->dn_desc); (void) dt_node_cook(cnp, DT_IDFLG_REF); if (DT_TREEDUMP_PASS(dtp, 2)) dt_node_printr(cnp, stderr, 0); if ((edp = dtrace_ecbdesc_create(dtp, pnp->dn_desc)) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); assert(yypcb->pcb_ecbdesc == NULL); yypcb->pcb_ecbdesc = edp; if (cnp->dn_pred != NULL) { dt_cg(yypcb, cnp->dn_pred); edp->dted_pred.dtpdd_difo = dt_as(yypcb); } if (cnp->dn_acts == NULL) { dt_stmt_append(dt_stmt_create(dtp, edp, cnp->dn_ctxattr, _dtrace_defattr), cnp); } for (dnp = cnp->dn_acts; dnp != NULL; dnp = dnp->dn_list) { assert(yypcb->pcb_stmt == NULL); sdp = dt_stmt_create(dtp, edp, cnp->dn_ctxattr, cnp->dn_attr); switch (dnp->dn_kind) { case DT_NODE_DEXPR: if (dnp->dn_expr->dn_kind == DT_NODE_AGG) dt_compile_agg(dtp, dnp->dn_expr, sdp); else dt_compile_exp(dtp, dnp, sdp); break; case DT_NODE_DFUNC: dt_compile_fun(dtp, dnp, sdp); break; case DT_NODE_AGG: dt_compile_agg(dtp, dnp, sdp); break; default: dnerror(dnp, D_UNKNOWN, "internal error -- node kind " "%u is not a valid statement\n", dnp->dn_kind); } assert(yypcb->pcb_stmt == sdp); dt_stmt_append(sdp, dnp); } assert(yypcb->pcb_ecbdesc == edp); dtrace_ecbdesc_release(edp); dt_endcontext(dtp); yypcb->pcb_ecbdesc = NULL;}static voiddt_compile_clause(dtrace_hdl_t *dtp, dt_node_t *cnp){ dt_node_t *pnp; for (pnp = cnp->dn_pdescs; pnp != NULL; pnp = pnp->dn_list) dt_compile_one_clause(dtp, cnp, pnp);}voiddt_setcontext(dtrace_hdl_t *dtp, dtrace_probedesc_t *pdp){ dtrace_probedesc_t pd, mpd; uint_t n, narg; dtrace_id_t id = pdp->dtpd_id; dt_module_t *dmp = NULL; dt_provider_t *pvp = NULL; const dtrace_pattr_t *pap; dt_ident_t *idp; char attrstr[8]; dtrace_argdesc_t arg; /* * If the provider name ends with what could be interpreted as a * number, we assume that it's a pid and that we may need to * dynamically create those probes for that process. */ if (isdigit(pdp->dtpd_provider[strlen(pdp->dtpd_provider) - 1])) dt_pid_create_probes(pdp, dtp); /* * If the provider is specified and is not a glob-matching expression, * then attempt to discover the stability attributes of the specified * provider. If the provider is unspecified or this fails, we set the * provider attributes to a default set of Unstable attributes. We * then compute the clause stability by taking the minimum stability * and dependency class of all specified probe description members. */ if (pdp->dtpd_provider[0] != '\0' && !strisglob(pdp->dtpd_provider)) pvp = dt_provider_lookup(dtp, pdp->dtpd_provider); if (pvp != NULL) pap = &pvp->pv_desc.dtvd_attr; else pap = &dt_def_pattr; yypcb->pcb_attr = pap->dtpa_provider; if (pdp->dtpd_mod[0] != '\0' && !strisglob(pdp->dtpd_mod)) yypcb->pcb_attr = dt_attr_min(yypcb->pcb_attr, pap->dtpa_mod); if (pdp->dtpd_func[0] != '\0' && !strisglob(pdp->dtpd_func)) yypcb->pcb_attr = dt_attr_min(yypcb->pcb_attr, pap->dtpa_func); if (pdp->dtpd_name[0] != '\0' && !strisglob(pdp->dtpd_name)) yypcb->pcb_attr = dt_attr_min(yypcb->pcb_attr, pap->dtpa_name); /* * Convert the caller's partial probe description into a fully-formed * matching probe description by invoking DTRACEIOC_PROBEMATCH. We * select the module resulting from the first match. We do this at * most twice in order to determine if the description matches exactly * one probe, in which case the args[] array becomes valid for use. */ for (n = 0; n < 2; id = pd.dtpd_id + 1) { bcopy(pdp, &pd, sizeof (dtrace_probedesc_t)); pd.dtpd_id = id; if (dt_ioctl(dtp, DTRACEIOC_PROBEMATCH, &pd) == -1) { if (errno == ESRCH || errno == EBADF) break; /* no more matching probes */ xyerror(D_PDESC_GLOB, "probe description %s:%s:%s:%s " "contains too many glob meta-characters\n", pdp->dtpd_provider, pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name); } if (n < 1 && pd.dtpd_mod[0] != '\0' && (dmp = dt_module_create(dtp, pd.dtpd_mod)) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); if (n++ == 0) bcopy(&pd, &mpd, sizeof (dtrace_probedesc_t)); if (pdp->dtpd_id != 0) break; /* id was specified by caller */ } dt_dprintf("context %s:%s:%s:%s [%u] matched %u probes (mod %s) %s\n", pdp->dtpd_provider, pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name, pdp->dtpd_id, n, dmp == NULL ? "<exec>" : dmp->dm_name, dt_attr_str(yypcb->pcb_attr, attrstr, sizeof (attrstr))); if (n == 0 && !(yypcb->pcb_cflags & DTRACE_C_ZDEFS)) { xyerror(D_PDESC_ZERO, "probe description %s:%s:%s:%s does not " "match any probes\n", pdp->dtpd_provider, pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name); } /* * Reset the stability attributes of D global variables that vary * based on the attributes of the provider and context itself. */ if ((idp = dt_idhash_lookup(dtp->dt_globals, "probeprov")) != NULL) idp->di_attr = pap->dtpa_provider; if ((idp = dt_idhash_lookup(dtp->dt_globals, "probemod")) != NULL) idp->di_attr = pap->dtpa_mod; if ((idp = dt_idhash_lookup(dtp->dt_globals, "probefunc")) != NULL) idp->di_attr = pap->dtpa_func; if ((idp = dt_idhash_lookup(dtp->dt_globals, "probename")) != NULL) idp->di_attr = pap->dtpa_name; if ((idp = dt_idhash_lookup(dtp->dt_globals, "args")) != NULL) idp->di_attr = pap->dtpa_args; /* * Save the number of matching probes associated with the current * probe description, and free any arguments from any previous context. */ yypcb->pcb_pdesc = pdp; yypcb->pcb_nprobes = n; while (yypcb->pcb_pargs != NULL) { dt_arg_t *old = yypcb->pcb_pargs; yypcb->pcb_pargs = old->da_next; free(old); } /* * There are two conditions under which we query for the type and * mapping of the args[] array: * * (1) Exactly one probe is matched. * * (2) Multiple probes are matched, but all of the following are true: * * (a) The Arguments Data stability of the provider is at least * Evolving. * * (b) All of the Name stability components that are at least * Evolving have been explicitly specified. * * (c) No Evolving Name stability component has been specified * using globbing. * * As this implies, providers that provide Evolving or better Arguments * Data stability are required to guarantee that all probes that have * like Evolving or better Name stability components have identical * argument types and mappings. */ if (n != 1) { if (pap->dtpa_args.dtat_data < DTRACE_STABILITY_EVOLVING) return; if ((pap->dtpa_mod.dtat_name >= DTRACE_STABILITY_EVOLVING) && (pdp->dtpd_mod[0] == '\0' || strisglob(pdp->dtpd_mod))) return; if ((pap->dtpa_func.dtat_name >= DTRACE_STABILITY_EVOLVING) && (pdp->dtpd_func[0] == '\0' || strisglob(pdp->dtpd_func))) return; if ((pap->dtpa_name.dtat_name >= DTRACE_STABILITY_EVOLVING) && (pdp->dtpd_name[0] == '\0' || strisglob(pdp->dtpd_name))) return; } /* * We need to explicitly query for the types and mappings of the * arguments. */ bzero(&arg, sizeof (arg)); arg.dtargd_id = mpd.dtpd_id; for (narg = 0; ; narg++) { dt_arg_t *argp; dtrace_typeinfo_t ntv, xlt; dt_node_t sn, dn; dt_xlator_t *dxp; int identical; arg.dtargd_ndx = narg; if (dt_ioctl(dtp, DTRACEIOC_PROBEARG, &arg) == -1) { xyerror(D_UNKNOWN, "failed to get argument for " "probe %d: %s\n", pd.dtpd_id, strerror(errno)); } if (arg.dtargd_ndx == DTRACE_ARGNONE) break; if ((argp = malloc(sizeof (dt_arg_t))) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); bzero(argp, sizeof (dt_arg_t)); argp->da_ndx = narg; argp->da_mapping = arg.dtargd_mapping; argp->da_next = yypcb->pcb_pargs; yypcb->pcb_pargs = argp; identical = (strcmp(arg.dtargd_native, arg.dtargd_xlate) == 0);retry: if (dt_type_lookup(arg.dtargd_native, &ntv) == -1) { /* * There are conditions (especially with function * pointers) where dt_type_lookup() will fail to find * the proper name. We have an incredibly naive * heuristic to detect this case, and fall back to * "void *". */ if (strstr(arg.dtargd_native, "(*)") != NULL) { (void) strcpy(arg.dtargd_native, "void *"); goto retry; } /* * Unfortunately, a condition can arise when we cannot * look up the valid type of a function argument: if * an argument is of a pointer type when the pointer * type only exists in the child container and the * base type only exists in the parent, we will be * unable to lookup the type. Ultimately, this * situation needs to be rectified in * dt_type_lookup(); for now, we just fall back to * "void *" for these types -- forcing the user to * explicitly cast to the true type as required. */ if (strstr(arg.dtargd_native, "*") != NULL) { (void) strcpy(arg.dtargd_native, "void *"); goto retry; } xyerror(D_UNKNOWN, "failed to resolve native argument" " type \"%s\" (arg#%d): %s", arg.dtargd_native, narg, dtrace_errmsg(dtp, dtrace_errno(dtp))); } argp->da_type = ntv.dtt_type; argp->da_ctfp = ntv.dtt_ctfp; /* * If there's no translated type or it's identical to the * native type, we can skip the translation portion. */ if (identical || arg.dtargd_xlate[0] == '\0') continue; if (dt_type_lookup(arg.dtargd_xlate, &xlt) == -1) { xyerror(D_UNKNOWN, "failed to resolve translated " "argument type \"%s\" (arg#%d): %s", arg.dtargd_xlate, narg, dtrace_errmsg(dtp, dtrace_errno(dtp))); } /* * If the types are the same, we don't have to worry about * a translator. */ if (ctf_type_cmp(ntv.dtt_ctfp, ntv.dtt_type, xlt.dtt_ctfp, xlt.dtt_type) == 0) continue; bzero(&sn, sizeof (sn)); dt_node_type_assign(&sn, ntv.dtt_ctfp, ntv.dtt_type); bzero(&dn, sizeof (dn)); dt_node_type_assign(&dn, xlt.dtt_ctfp, xlt.dtt_type); dxp = dt_xlator_lookup(dtp, &sn, &dn, DT_XLATE_FUZZY); if (dxp == NULL) { xyerror(D_UNKNOWN, "cannot translate arg#%d " "from \"%s\" to \"%s\"", argp->da_ndx, arg.dtargd_native, arg.dtargd_xlate); } argp->da_xlator = dt_xlator_ident(dxp, xlt.dtt_ctfp, xlt.dtt_type); }}/* * Reset context-dependent variables and state at the end of cooking a D probe * definition clause. This ensures that external declarations between clauses * do not reference any stale context-dependent data from the previous clause. */voiddt_endcontext(dtrace_hdl_t *dtp){ static const char *const cvars[] = { "probeprov", "probemod", "probefunc", "probename", "args", NULL }; dt_ident_t *idp; int i; for (i = 0; cvars[i] != NULL; i++) { if ((idp = dt_idhash_lookup(dtp->dt_globals, cvars[i])) != NULL) idp->di_attr = _dtrace_defattr; } yypcb->pcb_pdesc = NULL; yypcb->pcb_nprobes = 0; while (yypcb->pcb_pargs != NULL) { dt_arg_t *old = yypcb->pcb_pargs; yypcb->pcb_pargs = old->da_next; free(old); }}static voiddt_reduce_ident(dt_idhash_t *dhp, dt_ident_t *idp, dtrace_hdl_t *dtp){ if (idp->di_vers != 0 && idp->di_vers > dtp->dt_vmax) dt_idhash_delete(dhp, idp);}/* * When dtrace_setopt() is called for "version", it calls dt_reduce() to remove * any identifiers or translators that have been previously defined as bound to * a version greater than the specified version. Therefore, in our current * version implementation, establishing a binding is a one-way transformation. * In addition, no versioning is currently provided for types as our .d library * files do not define any types and we reserve prefixes DTRACE_ and dtrace_ * for our exclusive use. If required, type versioning will require more work. */intdt_reduce(dtrace_hdl_t *dtp, dt_version_t v){ char s[DT_VERSION_STRMAX]; dt_xlator_t *dxp, *nxp; if (v > dtp->dt_vmax) return (dt_set_errno(dtp, EDT_VERSREDUCED)); else if (v == dtp->dt_vmax) return (0); /* no reduction necessary */ dt_dprintf("reducing api version to %s\n", dt_version_num2str(v, s, sizeof (s))); dtp->dt_vmax = v; for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL; dxp = nxp) { nxp = dt_list_next(dxp); if ((dxp->dx_souid.di_vers != 0 && dxp->dx_souid.di_vers > v) || (dxp->dx_ptrid.di_vers != 0 && dxp->dx_ptrid.di_vers > v)) dt_list_delete(&dtp->dt_xlators, dxp); } dt_idhash_iter(dtp->dt_macros, (dt_idhash_f *)dt_reduce_ident, dtp); dt_idhash_iter(dtp->dt_aggs, (dt_idhash_f *)dt_reduce_ident, dtp); dt_idhash_iter(dtp->dt_globals, (dt_idhash_f *)dt_reduce_ident, dtp); dt_idhash_iter(dtp->dt_tls, (dt_idhash_f *)dt_reduce_ident, dtp); return (0);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?