示例#1
0
/*
 * 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 void
dt_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, iskey;

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

	iskey = idp->di_kind == DT_IDENT_ARRAY || idp->di_kind == DT_IDENT_AGG;

	if (isp->dis_varargs >= 0) {
		mismatch = argc < isp->dis_varargs;
		arglimit = isp->dis_varargs;
	} else if (isp->dis_optargs >= 0) {
		mismatch = (argc < isp->dis_optargs || argc > isp->dis_argc);
		arglimit = argc;
	} else {
		mismatch = argc != isp->dis_argc;
		arglimit = isp->dis_argc;
	}

	if (mismatch) {
		xyerror(D_PROTO_LEN, "%s%s%s prototype mismatch: %d %s%s"
		    "passed, %s%d expected\n", prefix, idp->di_name, suffix,
		    argc, iskey ? "key" : "arg", argc == 1 ? " " : "s ",
		    isp->dis_optargs >= 0 ? "at least " : "",
		    isp->dis_optargs >= 0 ? isp->dis_optargs : 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 %s #%d is incompatible with "
			    "prototype:\n\tprototype: %s\n\t%9s: %s\n",
			    prefix, idp->di_name, suffix,
			    iskey ? "key" : "argument", i + 1,
			    dt_node_type_name(&isp->dis_args[i], n1,
			    sizeof (n1)),
			    iskey ? "key" : "argument",
			    dt_node_type_name(args, n2, sizeof (n2)));
		}
	}

	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
}
示例#2
0
/*
 * 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 void
dt_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_optargs = -1;
		isp->dis_argc = argc;
		isp->dis_args = NULL;
		isp->dis_auxinfo = 0;

		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 ? "@" : "", "[ ]");
	}
}
示例#3
0
void
dt_dis(const dtrace_difo_t *dp, FILE *fp)
{
	static const struct opent {
		const char *op_name;
		void (*op_func)(const dtrace_difo_t *, const char *,
		    dif_instr_t, FILE *);
	} optab[] = {
		{ "(illegal opcode)", dt_dis_str },
		{ "or", dt_dis_log },		/* DIF_OP_OR */
		{ "xor", dt_dis_log },		/* DIF_OP_XOR */
		{ "and", dt_dis_log },		/* DIF_OP_AND */
		{ "sll", dt_dis_log },		/* DIF_OP_SLL */
		{ "srl", dt_dis_log },		/* DIF_OP_SRL */
		{ "sub", dt_dis_log },		/* DIF_OP_SUB */
		{ "add", dt_dis_log },		/* DIF_OP_ADD */
		{ "mul", dt_dis_log },		/* DIF_OP_MUL */
		{ "sdiv", dt_dis_log },		/* DIF_OP_SDIV */
		{ "udiv", dt_dis_log },		/* DIF_OP_UDIV */
		{ "srem", dt_dis_log },		/* DIF_OP_SREM */
		{ "urem", dt_dis_log },		/* DIF_OP_UREM */
		{ "not", dt_dis_r1rd },		/* DIF_OP_NOT */
		{ "mov", dt_dis_r1rd },		/* DIF_OP_MOV */
		{ "cmp", dt_dis_cmp },		/* DIF_OP_CMP */
		{ "tst", dt_dis_tst },		/* DIF_OP_TST */
		{ "ba", dt_dis_branch },	/* DIF_OP_BA */
		{ "be", dt_dis_branch },	/* DIF_OP_BE */
		{ "bne", dt_dis_branch },	/* DIF_OP_BNE */
		{ "bg", dt_dis_branch },	/* DIF_OP_BG */
		{ "bgu", dt_dis_branch },	/* DIF_OP_BGU */
		{ "bge", dt_dis_branch },	/* DIF_OP_BGE */
		{ "bgeu", dt_dis_branch },	/* DIF_OP_BGEU */
		{ "bl", dt_dis_branch },	/* DIF_OP_BL */
		{ "blu", dt_dis_branch },	/* DIF_OP_BLU */
		{ "ble", dt_dis_branch },	/* DIF_OP_BLE */
		{ "bleu", dt_dis_branch },	/* DIF_OP_BLEU */
		{ "ldsb", dt_dis_load },	/* DIF_OP_LDSB */
		{ "ldsh", dt_dis_load },	/* DIF_OP_LDSH */
		{ "ldsw", dt_dis_load },	/* DIF_OP_LDSW */
		{ "ldub", dt_dis_load },	/* DIF_OP_LDUB */
		{ "lduh", dt_dis_load },	/* DIF_OP_LDUH */
		{ "lduw", dt_dis_load },	/* DIF_OP_LDUW */
		{ "ldx", dt_dis_load },		/* DIF_OP_LDX */
		{ "ret", dt_dis_ret },		/* DIF_OP_RET */
		{ "nop", dt_dis_str },		/* DIF_OP_NOP */
		{ "setx", dt_dis_setx },	/* DIF_OP_SETX */
		{ "sets", dt_dis_sets },	/* DIF_OP_SETS */
		{ "scmp", dt_dis_cmp },		/* DIF_OP_SCMP */
		{ "ldga", dt_dis_lda },		/* DIF_OP_LDGA */
		{ "ldgs", dt_dis_ldv },		/* DIF_OP_LDGS */
		{ "stgs", dt_dis_stv },		/* DIF_OP_STGS */
		{ "ldta", dt_dis_lda },		/* DIF_OP_LDTA */
		{ "ldts", dt_dis_ldv },		/* DIF_OP_LDTS */
		{ "stts", dt_dis_stv },		/* DIF_OP_STTS */
		{ "sra", dt_dis_log },		/* DIF_OP_SRA */
		{ "call", dt_dis_call },	/* DIF_OP_CALL */
		{ "pushtr", dt_dis_pushts },	/* DIF_OP_PUSHTR */
		{ "pushtv", dt_dis_pushts },	/* DIF_OP_PUSHTV */
		{ "popts", dt_dis_str },	/* DIF_OP_POPTS */
		{ "flushts", dt_dis_str },	/* DIF_OP_FLUSHTS */
		{ "ldgaa", dt_dis_ldv },	/* DIF_OP_LDGAA */
		{ "ldtaa", dt_dis_ldv },	/* DIF_OP_LDTAA */
		{ "stgaa", dt_dis_stv },	/* DIF_OP_STGAA */
		{ "sttaa", dt_dis_stv },	/* DIF_OP_STTAA */
		{ "ldls", dt_dis_ldv },		/* DIF_OP_LDLS */
		{ "stls", dt_dis_stv },		/* DIF_OP_STLS */
		{ "allocs", dt_dis_r1rd },	/* DIF_OP_ALLOCS */
		{ "copys", dt_dis_log },	/* DIF_OP_COPYS */
		{ "stb", dt_dis_store },	/* DIF_OP_STB */
		{ "sth", dt_dis_store },	/* DIF_OP_STH */
		{ "stw", dt_dis_store },	/* DIF_OP_STW */
		{ "stx", dt_dis_store },	/* DIF_OP_STX */
		{ "uldsb", dt_dis_load },	/* DIF_OP_ULDSB */
		{ "uldsh", dt_dis_load },	/* DIF_OP_ULDSH */
		{ "uldsw", dt_dis_load },	/* DIF_OP_ULDSW */
		{ "uldub", dt_dis_load },	/* DIF_OP_ULDUB */
		{ "ulduh", dt_dis_load },	/* DIF_OP_ULDUH */
		{ "ulduw", dt_dis_load },	/* DIF_OP_ULDUW */
		{ "uldx", dt_dis_load },	/* DIF_OP_ULDX */
		{ "rldsb", dt_dis_load },	/* DIF_OP_RLDSB */
		{ "rldsh", dt_dis_load },	/* DIF_OP_RLDSH */
		{ "rldsw", dt_dis_load },	/* DIF_OP_RLDSW */
		{ "rldub", dt_dis_load },	/* DIF_OP_RLDUB */
		{ "rlduh", dt_dis_load },	/* DIF_OP_RLDUH */
		{ "rlduw", dt_dis_load },	/* DIF_OP_RLDUW */
		{ "rldx", dt_dis_load },	/* DIF_OP_RLDX */
		{ "xlate", dt_dis_xlate },	/* DIF_OP_XLATE */
		{ "xlarg", dt_dis_xlate },	/* DIF_OP_XLARG */
	};

	const struct opent *op;
	ulong_t i = 0;
	char type[DT_TYPE_NAMELEN];

	(void) fprintf(fp, "\nDIFO 0x%p returns %s\n", (void *)dp,
	    dt_dis_typestr(&dp->dtdo_rtype, type, sizeof (type)));

	(void) fprintf(fp, "%-3s %-8s    %s\n",
	    "OFF", "OPCODE", "INSTRUCTION");

	for (i = 0; i < dp->dtdo_len; i++) {
		dif_instr_t instr = dp->dtdo_buf[i];
		dif_instr_t opcode = DIF_INSTR_OP(instr);

		if (opcode >= sizeof (optab) / sizeof (optab[0]))
			opcode = 0; /* force invalid opcode message */

		op = &optab[opcode];
		(void) fprintf(fp, "%02lu: %08x    ", i, instr);
		op->op_func(dp, op->op_name, instr, fp);
		(void) fprintf(fp, "\n");
	}

	if (dp->dtdo_varlen != 0) {
		(void) fprintf(fp, "\n%-16s %-4s %-3s %-3s %-4s %s\n",
		    "NAME", "ID", "KND", "SCP", "FLAG", "TYPE");
	}

	for (i = 0; i < dp->dtdo_varlen; i++) {
		dtrace_difv_t *v = &dp->dtdo_vartab[i];
		char kind[4], scope[4], flags[16] = { 0 };

		switch (v->dtdv_kind) {
		case DIFV_KIND_ARRAY:
			(void) strcpy(kind, "arr");
			break;
		case DIFV_KIND_SCALAR:
			(void) strcpy(kind, "scl");
			break;
		default:
			(void) snprintf(kind, sizeof (kind),
			    "%u", v->dtdv_kind);
		}

		switch (v->dtdv_scope) {
		case DIFV_SCOPE_GLOBAL:
			(void) strcpy(scope, "glb");
			break;
		case DIFV_SCOPE_THREAD:
			(void) strcpy(scope, "tls");
			break;
		case DIFV_SCOPE_LOCAL:
			(void) strcpy(scope, "loc");
			break;
		default:
			(void) snprintf(scope, sizeof (scope),
			    "%u", v->dtdv_scope);
		}

		if (v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)) {
			(void) snprintf(flags, sizeof (flags), "/0x%x",
			    v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD));
		}

		if (v->dtdv_flags & DIFV_F_REF)
			(void) strcat(flags, "/r");
		if (v->dtdv_flags & DIFV_F_MOD)
			(void) strcat(flags, "/w");

		(void) fprintf(fp, "%-16s %-4x %-3s %-3s %-4s %s\n",
		    &dp->dtdo_strtab[v->dtdv_name],
		    v->dtdv_id, kind, scope, flags + 1,
		    dt_dis_typestr(&v->dtdv_type, type, sizeof (type)));
	}

	if (dp->dtdo_xlmlen != 0) {
		(void) fprintf(fp, "\n%-4s %-3s %-12s %s\n",
		    "XLID", "ARG", "MEMBER", "TYPE");
	}

	for (i = 0; i < dp->dtdo_xlmlen; i++) {
		dt_node_t *dnp = dp->dtdo_xlmtab[i];
		dt_xlator_t *dxp = dnp->dn_membexpr->dn_xlator;
		(void) fprintf(fp, "%-4u %-3d %-12s %s\n",
		    (uint_t)dxp->dx_id, dxp->dx_arg, dnp->dn_membname,
		    dt_node_type_name(dnp, type, sizeof (type)));
	}

	if (dp->dtdo_krelen != 0)
		dt_dis_rtab("KREL", dp, fp, dp->dtdo_kreltab, dp->dtdo_krelen);

	if (dp->dtdo_urelen != 0)
		dt_dis_rtab("UREL", dp, fp, dp->dtdo_ureltab, dp->dtdo_urelen);
}
示例#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);
}