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

📄 dt_ident.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright 2005 Sun Microsystems, Inc.  All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident	"@(#)dt_ident.c	1.8	04/11/13 SMI"#include <sys/sysmacros.h>#include <strings.h>#include <stdlib.h>#include <alloca.h>#include <assert.h>#include <errno.h>#include <ctype.h>#include <sys/procfs_isa.h>#include <limits.h>#include <dt_ident.h>#include <dt_parser.h>#include <dt_provider.h>#include <dt_strtab.h>#include <dt_impl.h>/* * Common code for cooking an identifier that uses a typed signature list (we * use this for associative arrays and functions).  If the argument list is * of the same length and types, then return the return type.  Otherwise * print an appropriate compiler error message and abort the compile. */static voiddt_idcook_sign(dt_node_t *dnp, dt_ident_t *idp,    int argc, dt_node_t *args, const char *prefix, const char *suffix){	dt_idsig_t *isp = idp->di_data;	int i, compat, mismatch, arglimit;	char n1[DT_TYPE_NAMELEN];	char n2[DT_TYPE_NAMELEN];	if (isp->dis_varargs >= 0) {		mismatch = argc < isp->dis_varargs;		arglimit = isp->dis_varargs;	} else {		mismatch = argc != isp->dis_argc;		arglimit = isp->dis_argc;	}	if (mismatch) {		xyerror(D_PROTO_LEN, "%s%s%s prototype mismatch: %d arg%s"		    "passed, %d expected\n", prefix, idp->di_name, suffix, argc,		    argc == 1 ? " " : "s ", arglimit);	}	for (i = 0; i < arglimit; i++, args = args->dn_list) {		if (isp->dis_args[i].dn_ctfp != NULL)			compat = dt_node_is_argcompat(&isp->dis_args[i], args);		else			compat = 1; /* "@" matches any type */		if (!compat) {			xyerror(D_PROTO_ARG,			    "%s%s%s argument #%d is incompatible with "			    "prototype:\n\tprototype: %s\n\t argument: %s\n",			    prefix, idp->di_name, suffix, i + 1,			    dt_node_type_name(&isp->dis_args[i], n1,			    sizeof (n1)),			    dt_node_type_name(args, n2, sizeof (n2)));		}	}	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);}/* * Cook an associative array identifier.  If this is the first time we are * cooking this array, create its signature based on the argument list. * Otherwise validate the argument list against the existing signature. */static voiddt_idcook_assc(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args){	if (idp->di_data == NULL) {		dt_idsig_t *isp = idp->di_data = malloc(sizeof (dt_idsig_t));		char n[DT_TYPE_NAMELEN];		int i;		if (isp == NULL)			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);		isp->dis_varargs = -1;		isp->dis_argc = argc;		isp->dis_args = NULL;		if (argc != 0 && (isp->dis_args = calloc(argc,		    sizeof (dt_node_t))) == NULL) {			idp->di_data = NULL;			free(isp);			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);		}		/*		 * If this identifier has not been explicitly declared earlier,		 * set the identifier's base type to be our special type <DYN>.		 * If this ident is an aggregation, it will remain as is.  If		 * this ident is an associative array, it will be reassigned		 * based on the result type of the first assignment statement.		 */		if (!(idp->di_flags & DT_IDFLG_DECL)) {			idp->di_ctfp = DT_DYN_CTFP(yypcb->pcb_hdl);			idp->di_type = DT_DYN_TYPE(yypcb->pcb_hdl);		}		for (i = 0; i < argc; i++, args = args->dn_list) {			if (dt_node_is_dynamic(args) || dt_node_is_void(args)) {				xyerror(D_KEY_TYPE, "%s expression may not be "				    "used as %s index: key #%d\n",				    dt_node_type_name(args, n, sizeof (n)),				    dt_idkind_name(idp->di_kind), i + 1);			}			dt_node_type_propagate(args, &isp->dis_args[i]);			isp->dis_args[i].dn_list = &isp->dis_args[i + 1];		}		if (argc != 0)			isp->dis_args[argc - 1].dn_list = NULL;		dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);	} else {		dt_idcook_sign(dnp, idp, argc, args,		    idp->di_kind == DT_IDENT_AGG ? "@" : "", "[ ]");	}}/* * Cook a function call.  If this is the first time we are cooking this * identifier, create its type signature based on predefined prototype stored * in di_iarg.  We then validate the argument list against this signature. */static voiddt_idcook_func(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args){	if (idp->di_data == NULL) {		dtrace_hdl_t *dtp = yypcb->pcb_hdl;		dtrace_typeinfo_t dtt;		dt_idsig_t *isp;		char *s, *p1, *p2;		int i = 0;		assert(idp->di_iarg != NULL);		s = alloca(strlen(idp->di_iarg) + 1);		(void) strcpy(s, idp->di_iarg);		if ((p2 = strrchr(s, ')')) != NULL)			*p2 = '\0'; /* mark end of parameter list string */		if ((p1 = strchr(s, '(')) != NULL)			*p1++ = '\0'; /* mark end of return type string */		if (p1 == NULL || p2 == NULL) {			xyerror(D_UNKNOWN, "internal error: malformed entry "			    "for built-in function %s\n", idp->di_name);		}		for (p2 = p1; *p2 != '\0'; p2++) {			if (!isspace(*p2)) {				i++;				break;			}		}		for (p2 = strchr(p2, ','); p2++ != NULL; i++)			p2 = strchr(p2, ',');		/*		 * We first allocate a new ident signature structure with the		 * appropriate number of argument entries, and then look up		 * the return type and store its CTF data in di_ctfp/type.		 */		if ((isp = idp->di_data = malloc(sizeof (dt_idsig_t))) == NULL)			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);		isp->dis_varargs = -1;		isp->dis_argc = i;		isp->dis_args = NULL;		if (i != 0 && (isp->dis_args = calloc(i,		    sizeof (dt_node_t))) == NULL) {			idp->di_data = NULL;			free(isp);			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);		}		if (dt_type_lookup(s, &dtt) == -1) {			xyerror(D_UNKNOWN, "failed to resolve type of %s (%s):"			    " %s\n", idp->di_name, s,			    dtrace_errmsg(dtp, dtrace_errno(dtp)));		}		if (idp->di_kind == DT_IDENT_AGGFUNC) {			idp->di_ctfp = DT_DYN_CTFP(dtp);			idp->di_type = DT_DYN_TYPE(dtp);		} else {			idp->di_ctfp = dtt.dtt_ctfp;			idp->di_type = dtt.dtt_type;		}		/*		 * For each comma-delimited parameter in the prototype string,		 * we look up the corresponding type and store its CTF data in		 * the corresponding location in dis_args[].  We also recognize		 * the special type string "@" to indicate that the specified		 * parameter may be a D expression of *any* type (represented		 * as a dis_args[] element with ctfp = NULL, type == CTF_ERR).		 * If a varargs "..." is present, we record the argument index		 * in dis_varargs for the benefit of dt_idcook_sign(), above.		 */		for (i = 0; i < isp->dis_argc; i++, p1 = p2) {			while (isspace(*p1))				p1++; /* skip leading whitespace */			if ((p2 = strchr(p1, ',')) == NULL)				p2 = p1 + strlen(p1);			else				*p2++ = '\0';			if (strcmp(p1, "@") == 0 || strcmp(p1, "...") == 0) {				isp->dis_args[i].dn_ctfp = NULL;				isp->dis_args[i].dn_type = CTF_ERR;				if (*p1 == '.')					isp->dis_varargs = i;				continue;			}			if (dt_type_lookup(p1, &dtt) == -1) {				xyerror(D_UNKNOWN, "failed to resolve type of "				    "%s arg#%d (%s): %s\n", idp->di_name, i + 1,				    p1, dtrace_errmsg(dtp, dtrace_errno(dtp)));			}			dt_node_type_assign(&isp->dis_args[i],			    dtt.dtt_ctfp, dtt.dtt_type);		}	}	dt_idcook_sign(dnp, idp, argc, args, "", "( )");}/* * Cook a reference to the dynamically typed args[] array.  We verify that the * reference is using a single integer constant, and then return the type found * at the corresponding location in yypcb->pcb_pargv[]. */static voiddt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap){	char n[DT_TYPE_NAMELEN];	dt_ident_t *xidp;	dtrace_hdl_t *dtp = yypcb->pcb_hdl;	dt_arg_t *argp;	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, n, sizeof (n)));	}	if (yypcb->pcb_pdesc == NULL) {		xyerror(D_ARGS_NONE, "%s[ ] may not be referenced outside "		    "of a probe clause\n", idp->di_name);	}	if (yypcb->pcb_pargs == NULL) {		if (yypcb->pcb_nprobes > 1) {			xyerror(D_ARGS_MULTI, "%s[ ] may not be referenced "			    "because probe description %s matches more than "			    "one probe\n", idp->di_name,			    dtrace_desc2str(yypcb->pcb_pdesc, n, sizeof (n)));		}		xyerror(D_ARGS_NONE, "no %s[ ] are available for probe %s\n",		    idp->di_name, dtrace_desc2str(yypcb->pcb_pdesc,		    n, sizeof (n)));	}	for (argp = yypcb->pcb_pargs; argp != NULL; argp = argp->da_next) {		if (argp->da_ndx == ap->dn_value)			break;	}	if (((ap->dn_flags & DT_NF_SIGNED) && (int64_t)ap->dn_value < 0) ||	    argp == NULL) {		xyerror(D_ARGS_IDX, "index %lld is out of range for probe %s "		    "%s[ ]\n", (longlong_t)ap->dn_value,		    dtrace_desc2str(yypcb->pcb_pdesc,		    n, sizeof (n)), idp->di_name);	}	if ((xidp = argp->da_xlator) != NULL) {		/*		 * If we have an argument translator, we need to transform the		 * ident for the node based on the ident of the translator.		 * We perform just enough transformation such that the node		 * appears to be a translator when looked at as a translator,		 * but not so much that it doesn't look like an array when it		 * needs to be viewed as an array.		 */		idp->di_kind = xidp->di_kind;		idp->di_data = xidp->di_data;		idp->di_ctfp = xidp->di_ctfp;		idp->di_type = xidp->di_type;		dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));	} else {		idp->di_kind = DT_IDENT_ARRAY;		idp->di_data = NULL;		idp->di_ctfp = DT_DYN_CTFP(yypcb->pcb_hdl);		idp->di_type = DT_DYN_TYPE(yypcb->pcb_hdl);		dt_node_type_assign(dnp, argp->da_ctfp, argp->da_type);	}}static voiddt_idcook_regs(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap){	dtrace_typeinfo_t dtt;	dtrace_hdl_t *dtp = yypcb->pcb_hdl;	char n[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, n, sizeof (n)));	}	if ((ap->dn_flags & DT_NF_SIGNED) && (int64_t)ap->dn_value < 0) {		xyerror(D_REGS_IDX, "index %lld is out of range for array %s\n",		    (longlong_t)ap->dn_value, idp->di_name);	}	if (dt_type_lookup("uint64_t", &dtt) == -1) {		xyerror(D_UNKNOWN, "failed to resolve type of %s: %s\n",		    idp->di_name, dtrace_errmsg(dtp, dtrace_errno(dtp)));	}	idp->di_ctfp = dtt.dtt_ctfp;	idp->di_type = dtt.dtt_type;	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);}/*ARGSUSED*/static voiddt_idcook_type(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args){	if (idp->di_type == CTF_ERR) {		dtrace_hdl_t *dtp = yypcb->pcb_hdl;		dtrace_typeinfo_t dtt;		if (dt_type_lookup(idp->di_iarg, &dtt) == -1) {			xyerror(D_UNKNOWN,			    "failed to resolve type %s for identifier %s: %s\n",			    (const char *)idp->di_iarg, idp->di_name,			    dtrace_errmsg(dtp, dtrace_errno(dtp)));		}		idp->di_ctfp = dtt.dtt_ctfp;		idp->di_type = dtt.dtt_type;	}	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);}/*ARGSUSED*/static voiddt_idcook_thaw(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args){	if (idp->di_ctfp != NULL && idp->di_type != CTF_ERR)		dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);}/*ARGSUSED*/static dt_ident_t *dt_idctor_default(dt_node_t *dnp, int argc, dt_node_t *ap){	return (dnp->dn_ident);}static dt_ident_t *dt_idctor_args(dt_node_t *dnp, int argc, dt_node_t *ap){	dt_ident_t *idp = dnp->dn_ident;	char n[DT_TYPE_NAMELEN], *name;	int len;	/*	 * The args[] array is special because two identifiers with different	 * indices will have different ident attributes.  To support this,	 * we create an ident for each index.  The di_data field of the "args"	 * ident in the hash points to a list of indexed idents; each of the	 * indexed args[] idents has DT_IDFLG_ARGNDX set in its di_flags field.	 */	if (idp->di_flags & DT_IDFLG_ARGNDX)		return (idp);	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, n, sizeof (n)));	}	if (ap->dn_value > UCHAR_MAX) {		xyerror(D_ARGS_IDX, "index %lld is out of range for probe %s "		    "%s[ ]\n", (longlong_t)ap->dn_value,		    dtrace_desc2str(yypcb->pcb_pdesc,		    n, sizeof (n)), idp->di_name);	}	len = strlen(idp->di_name) + 1;	for (idp = idp->di_data; idp != NULL; idp = idp->di_next) {		if (idp->di_name[len] == ap->dn_value)			return (idp);	}	/*	 * We need to create a new ident using the existing one as a template.	 */	idp = dnp->dn_ident;	if ((name = malloc(strlen(idp->di_name) + 2)) == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);	(void) strcpy(name, idp->di_name);	name[len] = ap->dn_value;	idp = dt_ident_create(NULL, idp->di_kind, idp->di_flags, idp->di_id,	    idp->di_attr, idp->di_vers, idp->di_ops, idp->di_iarg,	    idp->di_gen);	idp->di_next = dnp->dn_ident->di_data;	dnp->dn_ident->di_data = idp;	idp->di_flags |= DT_IDFLG_ARGNDX;	idp->di_name = name;	return (idp);}static voiddt_iddtor_sign(dt_ident_t *idp)

⌨️ 快捷键说明

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