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 + -
显示快捷键?