Ejemplo n.º 1
0
/*
 * Return a boolean value indicating if two types are compatible integers or
 * floating-pointer values.  This function returns true if the two types are
 * the same, or if they have the same ASCII name and encoding properties.
 * This function could be extended to test for compatibility for other kinds.
 */
int
ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
    ctf_file_t *rfp, ctf_id_t rtype)
{
	const ctf_type_t *ltp, *rtp;
	ctf_encoding_t le, re;
	ctf_arinfo_t la, ra;
	uint_t lkind, rkind;

	if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
		return (1);

	ltype = ctf_type_resolve(lfp, ltype);
	lkind = ctf_type_kind(lfp, ltype);

	rtype = ctf_type_resolve(rfp, rtype);
	rkind = ctf_type_kind(rfp, rtype);

	if (lkind != rkind ||
	    (ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL ||
	    (rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL ||
	    strcmp(ctf_strptr(lfp, ltp->ctt_name),
	    ctf_strptr(rfp, rtp->ctt_name)) != 0)
		return (0);

	switch (lkind) {
	case CTF_K_INTEGER:
	case CTF_K_FLOAT:
		return (ctf_type_encoding(lfp, ltype, &le) == 0 &&
		    ctf_type_encoding(rfp, rtype, &re) == 0 &&
		    bcmp(&le, &re, sizeof (ctf_encoding_t)) == 0);
	case CTF_K_POINTER:
		return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype),
		    rfp, ctf_type_reference(rfp, rtype)));
	case CTF_K_ARRAY:
		return (ctf_array_info(lfp, ltype, &la) == 0 &&
		    ctf_array_info(rfp, rtype, &ra) == 0 &&
		    la.ctr_nelems == ra.ctr_nelems && ctf_type_compat(
		    lfp, la.ctr_contents, rfp, ra.ctr_contents) &&
		    ctf_type_compat(lfp, la.ctr_index, rfp, ra.ctr_index));
	case CTF_K_STRUCT:
	case CTF_K_UNION:
		return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype));
	case CTF_K_ENUM:
	case CTF_K_FORWARD:
		return (1); /* no other checks required for these type kinds */
	default:
		return (0); /* should not get here since we did a resolve */
	}
}
Ejemplo n.º 2
0
int
mdb_ctf_type_resolve(mdb_ctf_id_t mid, mdb_ctf_id_t *outp)
{
	ctf_id_t id;
	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)∣

	if ((id = ctf_type_resolve(idp->mci_fp, idp->mci_id)) == CTF_ERR) {
		if (outp)
			mdb_ctf_type_invalidate(outp);
		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
	}

	if (ctf_type_kind(idp->mci_fp, id) == CTF_K_FORWARD) {
		char name[MDB_SYM_NAMLEN];
		mdb_ctf_id_t lookup_id;

		if (ctf_type_name(idp->mci_fp, id, name, sizeof (name)) !=
		    NULL &&
		    mdb_ctf_lookup_by_name(name, &lookup_id) == 0 &&
		    outp != NULL) {
			*outp = lookup_id;
			return (0);
		}
	}

	if (outp != NULL)
		set_ctf_id(outp, idp->mci_fp, id);

	return (0);
}
Ejemplo n.º 3
0
dt_ident_t *
dt_xlator_ident(dt_xlator_t *dxp, ctf_file_t *ctfp, ctf_id_t type)
{
	if (ctf_type_kind(ctfp, ctf_type_resolve(ctfp, type)) == CTF_K_POINTER)
		return (&dxp->dx_ptrid);
	else
		return (&dxp->dx_souid);
}
Ejemplo n.º 4
0
int
mdb_ctf_type_kind(mdb_ctf_id_t id)
{
	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
	int ret;

	if ((ret = ctf_type_kind(idp->mci_fp, idp->mci_id)) == CTF_ERR)
		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));

	return (ret);
}
Ejemplo n.º 5
0
void
check_sym(ctf_file_t *ctfp, symtab_sym_t *ss)
{
	int rettype = ctf_type_kind(ctfp, ss->ss_finfo.ctc_return);
	int start_index = 0;

	if (ss->ss_finfo.ctc_argc == 0) /* No arguments, no point */
		return;

	if (((rettype == CTF_K_STRUCT) || (rettype == CTF_K_UNION)) &&
	    ctf_type_size(ctfp, ss->ss_finfo.ctc_return) > 16)
		start_index = 1;

	if (saveargs_has_args(ss->ss_data, ss->ss_sym.st_size,
	    ss->ss_finfo.ctc_argc, start_index) != SAVEARGS_NO_ARGS)
		printf("%s has %d saved args\n", ss->ss_name,
		    ss->ss_finfo.ctc_argc);
}
Ejemplo n.º 6
0
ctf_id_t
ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name)
{
	ctf_hash_t *hp = &fp->ctf_enums;
	ctf_helem_t *hep = NULL;
	ctf_dtdef_t *dtd;
	ctf_id_t type;

	if (name != NULL)
		hep = ctf_hash_lookup(hp, fp, name, strlen(name));

	if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
		dtd = ctf_dtd_lookup(fp, type = hep->h_type);
	else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
		return (CTF_ERR); /* errno is set for us */

	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, flag, 0);
	dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int;

	return (type);
}
Ejemplo n.º 7
0
/*ARGSUSED*/
static int
obj_lookup(void *data, const mdb_map_t *mp, const char *name)
{
	tnarg_t *tnp = data;
	ctf_file_t *fp;
	ctf_id_t id;

	if ((fp = mdb_tgt_name_to_ctf(tnp->tn_tgt, name)) != NULL &&
	    (id = ctf_lookup_by_name(fp, tnp->tn_name)) != CTF_ERR) {
		tnp->tn_fp = fp;
		tnp->tn_id = id;

		/*
		 * We may have found a forward declaration.  If we did, we'll
		 * note the ID and file pointer, but we'll keep searching in
		 * an attempt to find the real thing.  If we found something
		 * real (i.e. not a forward), we stop the iteration.
		 */
		return (ctf_type_kind(fp, id) == CTF_K_FORWARD ? 0 : -1);
	}

	return (0);
}
Ejemplo n.º 8
0
/*
 * The ctf_add_type routine is used to copy a type from a source CTF container
 * to a dynamic destination container.  This routine operates recursively by
 * following the source type's links and embedded member types.  If the
 * destination container already contains a named type which has the same
 * attributes, then we succeed and return this type but no changes occur.
 */
ctf_id_t
ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
{
	ctf_id_t dst_type = CTF_ERR;
	uint_t dst_kind = CTF_K_UNKNOWN;

	const ctf_type_t *tp;
	const char *name;
	uint_t kind, flag, vlen;

	ctf_bundle_t src, dst;
	ctf_encoding_t src_en, dst_en;
	ctf_arinfo_t src_ar, dst_ar;

	ctf_dtdef_t *dtd;
	ctf_funcinfo_t ctc;
	ssize_t size;

	ctf_hash_t *hp;
	ctf_helem_t *hep;

	if (dst_fp == src_fp)
		return (src_type);

	if (!(dst_fp->ctf_flags & LCTF_RDWR))
		return (ctf_set_errno(dst_fp, ECTF_RDONLY));

	if ((tp = ctf_lookup_by_id(&src_fp, src_type)) == NULL)
		return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));

	name = ctf_strptr(src_fp, tp->ctt_name);
	kind = LCTF_INFO_KIND(src_fp, tp->ctt_info);
	flag = LCTF_INFO_ROOT(src_fp, tp->ctt_info);
	vlen = LCTF_INFO_VLEN(src_fp, tp->ctt_info);

	switch (kind) {
	case CTF_K_STRUCT:
		hp = &dst_fp->ctf_structs;
		break;
	case CTF_K_UNION:
		hp = &dst_fp->ctf_unions;
		break;
	case CTF_K_ENUM:
		hp = &dst_fp->ctf_enums;
		break;
	default:
		hp = &dst_fp->ctf_names;
		break;
	}

	/*
	 * If the source type has a name and is a root type (visible at the
	 * top-level scope), lookup the name in the destination container and
	 * verify that it is of the same kind before we do anything else.
	 */
	if ((flag & CTF_ADD_ROOT) && name[0] != '\0' &&
	    (hep = ctf_hash_lookup(hp, dst_fp, name, strlen(name))) != NULL) {
		dst_type = (ctf_id_t)hep->h_type;
		dst_kind = ctf_type_kind(dst_fp, dst_type);
	}

	/*
	 * If an identically named dst_type exists, fail with ECTF_CONFLICT
	 * unless dst_type is a forward declaration and src_type is a struct,
	 * union, or enum (i.e. the definition of the previous forward decl).
	 */
	if (dst_type != CTF_ERR && dst_kind != kind) {
		if (dst_kind != CTF_K_FORWARD || (kind != CTF_K_ENUM &&
		    kind != CTF_K_STRUCT && kind != CTF_K_UNION))
			return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
		else
			dst_type = CTF_ERR;
	}

	/*
	 * If the non-empty name was not found in the appropriate hash, search
	 * the list of pending dynamic definitions that are not yet committed.
	 * If a matching name and kind are found, assume this is the type that
	 * we are looking for.  This is necessary to permit ctf_add_type() to
	 * operate recursively on entities such as a struct that contains a
	 * pointer member that refers to the same struct type.
	 *
	 * In the case of integer and floating point types, we match using the
	 * type encoding as well - else we may incorrectly return a bitfield
	 * type, for instance.
	 */
	if (dst_type == CTF_ERR && name[0] != '\0') {
		for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL &&
		    CTF_TYPE_TO_INDEX(dtd->dtd_type) > dst_fp->ctf_dtoldid;
		    dtd = ctf_list_prev(dtd)) {
			if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) != kind ||
			    dtd->dtd_name == NULL ||
			    strcmp(dtd->dtd_name, name) != 0)
				continue;
			if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT) {
				if (ctf_type_encoding(src_fp, src_type,
				    &src_en) != 0)
					continue;
				if (bcmp(&src_en, &dtd->dtd_u.dtu_enc,
				    sizeof (ctf_encoding_t)) != 0)
					continue;
			}
			return (dtd->dtd_type);
		}
	}

	src.ctb_file = src_fp;
	src.ctb_type = src_type;
	src.ctb_dtd = NULL;

	dst.ctb_file = dst_fp;
	dst.ctb_type = dst_type;
	dst.ctb_dtd = NULL;

	/*
	 * Now perform kind-specific processing.  If dst_type is CTF_ERR, then
	 * we add a new type with the same properties as src_type to dst_fp.
	 * If dst_type is not CTF_ERR, then we verify that dst_type has the
	 * same attributes as src_type.  We recurse for embedded references.
	 */
	switch (kind) {
	case CTF_K_INTEGER:
	case CTF_K_FLOAT:
		if (ctf_type_encoding(src_fp, src_type, &src_en) != 0)
			return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));

		if (dst_type != CTF_ERR) {
			if (ctf_type_encoding(dst_fp, dst_type, &dst_en) != 0)
				return (CTF_ERR); /* errno is set for us */

			if (bcmp(&src_en, &dst_en, sizeof (ctf_encoding_t)))
				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));

		} else if (kind == CTF_K_INTEGER) {
			dst_type = ctf_add_integer(dst_fp, flag, name, &src_en);
		} else
			dst_type = ctf_add_float(dst_fp, flag, name, &src_en);
		break;

	case CTF_K_POINTER:
	case CTF_K_VOLATILE:
	case CTF_K_CONST:
	case CTF_K_RESTRICT:
		src_type = ctf_type_reference(src_fp, src_type);
		src_type = ctf_add_type(dst_fp, src_fp, src_type);

		if (src_type == CTF_ERR)
			return (CTF_ERR); /* errno is set for us */

		dst_type = ctf_add_reftype(dst_fp, flag, src_type, kind);
		break;

	case CTF_K_ARRAY:
		if (ctf_array_info(src_fp, src_type, &src_ar) == CTF_ERR)
			return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));

		src_ar.ctr_contents =
		    ctf_add_type(dst_fp, src_fp, src_ar.ctr_contents);
		src_ar.ctr_index =
		    ctf_add_type(dst_fp, src_fp, src_ar.ctr_index);
		src_ar.ctr_nelems = src_ar.ctr_nelems;

		if (src_ar.ctr_contents == CTF_ERR ||
		    src_ar.ctr_index == CTF_ERR)
			return (CTF_ERR); /* errno is set for us */

		if (dst_type != CTF_ERR) {
			if (ctf_array_info(dst_fp, dst_type, &dst_ar) != 0)
				return (CTF_ERR); /* errno is set for us */

			if (bcmp(&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))
				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
		} else
			dst_type = ctf_add_array(dst_fp, flag, &src_ar);
		break;

	case CTF_K_FUNCTION:
		ctc.ctc_return = ctf_add_type(dst_fp, src_fp, tp->ctt_type);
		ctc.ctc_argc = 0;
		ctc.ctc_flags = 0;

		if (ctc.ctc_return == CTF_ERR)
			return (CTF_ERR); /* errno is set for us */

		dst_type = ctf_add_function(dst_fp, flag, &ctc, NULL);
		break;

	case CTF_K_STRUCT:
	case CTF_K_UNION: {
		ctf_dmdef_t *dmd;
		int errs = 0;

		/*
		 * Technically to match a struct or union we need to check both
		 * ways (src members vs. dst, dst members vs. src) but we make
		 * this more optimal by only checking src vs. dst and comparing
		 * the total size of the structure (which we must do anyway)
		 * which covers the possibility of dst members not in src.
		 * This optimization can be defeated for unions, but is so
		 * pathological as to render it irrelevant for our purposes.
		 */
		if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) {
			if (ctf_type_size(src_fp, src_type) !=
			    ctf_type_size(dst_fp, dst_type))
				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));

			if (ctf_member_iter(src_fp, src_type, membcmp, &dst))
				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));

			break;
		}

		/*
		 * Unlike the other cases, copying structs and unions is done
		 * manually so as to avoid repeated lookups in ctf_add_member
		 * and to ensure the exact same member offsets as in src_type.
		 */
		dst_type = ctf_add_generic(dst_fp, flag, name, &dtd);
		if (dst_type == CTF_ERR)
			return (CTF_ERR); /* errno is set for us */

		dst.ctb_type = dst_type;
		dst.ctb_dtd = dtd;

		if (ctf_member_iter(src_fp, src_type, membadd, &dst) != 0)
			errs++; /* increment errs and fail at bottom of case */

		if ((size = ctf_type_size(src_fp, src_type)) > CTF_MAX_SIZE) {
			dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
			dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
			dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
		} else
			dtd->dtd_data.ctt_size = (ushort_t)size;

		dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, vlen);

		/*
		 * Make a final pass through the members changing each dmd_type
		 * (a src_fp type) to an equivalent type in dst_fp.  We pass
		 * through all members, leaving any that fail set to CTF_ERR.
		 */
		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
		    dmd != NULL; dmd = ctf_list_next(dmd)) {
			if ((dmd->dmd_type = ctf_add_type(dst_fp, src_fp,
			    dmd->dmd_type)) == CTF_ERR)
				errs++;
		}

		if (errs)
			return (CTF_ERR); /* errno is set for us */

		/*
		 * Now that we know that we can't fail, we go through and bump
		 * all the reference counts on the member types.
		 */
		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
		    dmd != NULL; dmd = ctf_list_next(dmd))
			ctf_ref_inc(dst_fp, dmd->dmd_type);
		break;
	}

	case CTF_K_ENUM:
		if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) {
			if (ctf_enum_iter(src_fp, src_type, enumcmp, &dst) ||
			    ctf_enum_iter(dst_fp, dst_type, enumcmp, &src))
				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
		} else {
			dst_type = ctf_add_enum(dst_fp, flag, name);
			if ((dst.ctb_type = dst_type) == CTF_ERR ||
			    ctf_enum_iter(src_fp, src_type, enumadd, &dst))
				return (CTF_ERR); /* errno is set for us */
		}
		break;

	case CTF_K_FORWARD:
		if (dst_type == CTF_ERR) {
			dst_type = ctf_add_forward(dst_fp,
			    flag, name, CTF_K_STRUCT); /* assume STRUCT */
		}
		break;

	case CTF_K_TYPEDEF:
		src_type = ctf_type_reference(src_fp, src_type);
		src_type = ctf_add_type(dst_fp, src_fp, src_type);

		if (src_type == CTF_ERR)
			return (CTF_ERR); /* errno is set for us */

		/*
		 * If dst_type is not CTF_ERR at this point, we should check if
		 * ctf_type_reference(dst_fp, dst_type) != src_type and if so
		 * fail with ECTF_CONFLICT.  However, this causes problems with
		 * <sys/types.h> typedefs that vary based on things like if
		 * _ILP32x then pid_t is int otherwise long.  We therefore omit
		 * this check and assume that if the identically named typedef
		 * already exists in dst_fp, it is correct or equivalent.
		 */
		if (dst_type == CTF_ERR) {
			dst_type = ctf_add_typedef(dst_fp, flag,
			    name, src_type);
		}
		break;

	default:
		return (ctf_set_errno(dst_fp, ECTF_CORRUPT));
	}

	return (dst_type);
}
Ejemplo n.º 9
0
int
dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
    dtrace_typeinfo_t *tip)
{
	dtrace_typeinfo_t ti;
	dt_module_t *dmp;
	int found = 0;
	ctf_id_t id;
	uint_t n, i;
	int justone;
	ctf_file_t *fp;
	char *buf, *p, *q;

	uint_t mask = 0; /* mask of dt_module flags to match */
	uint_t bits = 0; /* flag bits that must be present */

	if (object != DTRACE_OBJ_EVERY &&
	    object != DTRACE_OBJ_KMODS &&
	    object != DTRACE_OBJ_UMODS) {
		if ((dmp = dt_module_from_object(dtp, object)) == NULL)
			return (-1); /* dt_errno is set for us */

		if (dt_module_load(dtp, dmp) == -1)
			return (-1); /* dt_errno is set for us */
		n = 1;
		justone = 1;
	} else {
		if (object == DTRACE_OBJ_KMODS)
			mask = bits = DT_DM_KERNEL;
		else if (object == DTRACE_OBJ_UMODS)
			mask = DT_DM_KERNEL;

		dmp = dt_list_next(&dtp->dt_modlist);
		n = dtp->dt_nmods;
		justone = 0;
	}

	if (tip == NULL)
		tip = &ti;

	for (; n > 0; n--, dmp = dt_list_next(dmp)) {
		if ((dmp->dm_flags & mask) != bits)
			continue; /* failed to match required attributes */

		/*
		 * If we can't load the CTF container, continue on to the next
		 * module.  If our search was scoped to only one module then
		 * return immediately leaving dt_errno unmodified.
		 */
		if (dt_module_hasctf(dtp, dmp) == 0) {
			if (justone)
				return (-1);
			continue;
		}

		/*
		 * Look up the type in the module's CTF container.  If our
		 * match is a forward declaration tag, save this choice in
		 * 'tip' and keep going in the hope that we will locate the
		 * underlying structure definition.  Otherwise just return.
		 */
		if (dmp->dm_pid == 0) {
			id = ctf_lookup_by_name(dmp->dm_ctfp, name);
			fp = dmp->dm_ctfp;
		} else {
			if ((p = strchr(name, '`')) != NULL) {
				buf = strdup(name);
				if (buf == NULL)
					return (dt_set_errno(dtp, EDT_NOMEM));
				p = strchr(buf, '`');
				if ((q = strchr(p + 1, '`')) != NULL)
					p = q;
				*p = '\0';
				fp = dt_module_getctflib(dtp, dmp, buf);
				if (fp == NULL || (id = ctf_lookup_by_name(fp,
				    p + 1)) == CTF_ERR)
					id = CTF_ERR;
				free(buf);
			} else {
				for (i = 0; i < dmp->dm_nctflibs; i++) {
					fp = dmp->dm_libctfp[i];
					id = ctf_lookup_by_name(fp, name);
					if (id != CTF_ERR)
						break;
				}
			}
		}
		if (id != CTF_ERR) {
			tip->dtt_object = dmp->dm_name;
			tip->dtt_ctfp = fp;
			tip->dtt_type = id;
			if (ctf_type_kind(fp, ctf_type_resolve(fp, id)) !=
			    CTF_K_FORWARD)
				return (0);

			found++;
		}
	}

	if (found == 0)
		return (dt_set_errno(dtp, EDT_NOTYPE));

	return (0);
}
Ejemplo n.º 10
0
dt_xlator_t *
dt_xlator_create(dtrace_hdl_t *dtp,
    const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst,
    const char *name, dt_node_t *members, dt_node_t *nodes)
{
	dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t));
	dtrace_typeinfo_t ptr = *dst;
	dt_xlator_t **map;
	dt_node_t *dnp;
	uint_t kind;

	if (dxp == NULL)
		return (NULL);

	dxp->dx_hdl = dtp;
	dxp->dx_id = dtp->dt_xlatorid++;
	dxp->dx_gen = dtp->dt_gen;
	dxp->dx_arg = -1;

	if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) {
		dt_free(dtp, dxp);
		return (NULL);
	}

	dt_list_append(&dtp->dt_xlators, dxp);
	bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id);
	dt_free(dtp, dtp->dt_xlatormap);
	dtp->dt_xlatormap = map;
	dtp->dt_xlatormap[dxp->dx_id] = dxp;

	if (dt_type_pointer(&ptr) == -1) {
		ptr.dtt_ctfp = NULL;
		ptr.dtt_type = CTF_ERR;
	}

	dxp->dx_ident = dt_ident_create(name ? name : "T",
	    DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0,
	    _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);

	if (dxp->dx_ident == NULL)
		goto err; /* no memory for identifier */

	dxp->dx_ident->di_ctfp = src->dtt_ctfp;
	dxp->dx_ident->di_type = src->dtt_type;

	/*
	 * If an input parameter name is given, this is a static translator
	 * definition: create an idhash and identifier for the parameter.
	 */
	if (name != NULL) {
		dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0);

		if (dxp->dx_locals == NULL)
			goto err; /* no memory for identifier hash */

		dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident);
	}

	dxp->dx_souid.di_name = "translator";
	dxp->dx_souid.di_kind = DT_IDENT_XLSOU;
	dxp->dx_souid.di_flags = DT_IDFLG_REF;
	dxp->dx_souid.di_id = dxp->dx_id;
	dxp->dx_souid.di_attr = _dtrace_defattr;
	dxp->dx_souid.di_ops = &dt_idops_thaw;
	dxp->dx_souid.di_data = dxp;
	dxp->dx_souid.di_ctfp = dst->dtt_ctfp;
	dxp->dx_souid.di_type = dst->dtt_type;
	dxp->dx_souid.di_gen = dtp->dt_gen;

	dxp->dx_ptrid.di_name = "translator";
	dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR;
	dxp->dx_ptrid.di_flags = DT_IDFLG_REF;
	dxp->dx_ptrid.di_id = dxp->dx_id;
	dxp->dx_ptrid.di_attr = _dtrace_defattr;
	dxp->dx_ptrid.di_ops = &dt_idops_thaw;
	dxp->dx_ptrid.di_data = dxp;
	dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp;
	dxp->dx_ptrid.di_type = ptr.dtt_type;
	dxp->dx_ptrid.di_gen = dtp->dt_gen;

	/*
	 * If a deferred pragma is pending on the keyword "translator", run all
	 * the deferred pragmas on dx_souid and then copy results to dx_ptrid.
	 * See the code in dt_pragma.c for details on deferred ident pragmas.
	 */
	if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL &&
	    dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) {
		dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid);
		dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr;
		dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers;
	}

	dxp->dx_src_ctfp = src->dtt_ctfp;
	dxp->dx_src_type = src->dtt_type;
	dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type);

	dxp->dx_dst_ctfp = dst->dtt_ctfp;
	dxp->dx_dst_type = dst->dtt_type;
	dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type);

	kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base);
	assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION);

	/*
	 * If no input parameter is given, we're making a dynamic translator:
	 * create member nodes for every member of the output type.  Otherwise
	 * retain the member and allocation node lists presented by the parser.
	 */
	if (name == NULL) {
		if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base,
		    dt_xlator_create_member, dxp) != 0)
			goto err;
	} else {
		dxp->dx_members = members;
		dxp->dx_nodes = nodes;
	}

	/*
	 * Assign member IDs to each member and allocate space for DIFOs
	 * if and when this translator is eventually compiled.
	 */
	for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
		dnp->dn_membxlator = dxp;
		dnp->dn_membid = dxp->dx_nmembers++;
	}

	dxp->dx_membdif = dt_zalloc(dtp,
	    sizeof (dtrace_difo_t *) * dxp->dx_nmembers);

	if (dxp->dx_membdif == NULL) {
		dxp->dx_nmembers = 0;
		goto err;
	}

	return (dxp);

err:
	dt_xlator_destroy(dtp, dxp);
	return (NULL);
}
Ejemplo n.º 11
0
/*
 * Read arguments from the frame indicated by regs into args, return the
 * number of arguments successfully read
 */
static int
read_args(struct ps_prochandle *P, uintptr_t fp, uintptr_t pc, prgreg_t *args,
    size_t argsize)
{
	GElf_Sym sym;
	ctf_file_t *ctfp = NULL;
	ctf_funcinfo_t finfo;
	prsyminfo_t si = {0};
	uint8_t ins[SAVEARGS_INSN_SEQ_LEN];
	size_t insnsize;
	int argc = 0;
	int rettype = 0;
	int start_index = 0;
	int args_style = 0;
	int i;
	ctf_id_t args_types[5];

	if (Pxlookup_by_addr(P, pc, NULL, 0, &sym, &si) != 0)
		return (0);

	if ((ctfp = Paddr_to_ctf(P, pc)) == NULL)
		return (0);

	if (ctf_func_info(ctfp, si.prs_id, &finfo) == CTF_ERR)
		return (0);

	argc = finfo.ctc_argc;

	if (argc == 0)
		return (0);

	rettype = ctf_type_kind(ctfp, finfo.ctc_return);

	/*
	 * If the function returns a structure or union greater than 16 bytes
	 * in size %rdi contains the address in which to store the return
	 * value rather than for an argument.
	 */
	if (((rettype == CTF_K_STRUCT) || (rettype == CTF_K_UNION)) &&
	    ctf_type_size(ctfp, finfo.ctc_return) > 16)
		start_index = 1;
	else
		start_index = 0;

	/*
	 * If any of the first 5 arguments are a structure less than 16 bytes
	 * in size, it will be passed spread across two argument registers,
	 * and we will not cope.
	 */
	if (ctf_func_args(ctfp, si.prs_id, 5, args_types) == CTF_ERR)
		return (0);

	for (i = 0; i < MIN(5, finfo.ctc_argc); i++) {
		int t = ctf_type_kind(ctfp, args_types[i]);

		if (((t == CTF_K_STRUCT) || (t == CTF_K_UNION)) &&
		    ctf_type_size(ctfp, args_types[i]) <= 16)
			return (0);
	}

	/*
	 * The number of instructions to search for argument saving is limited
	 * such that only instructions prior to %pc are considered and we
	 * never read arguments from a function where the saving code has not
	 * in fact yet executed.
	 */
	insnsize = MIN(MIN(sym.st_size, SAVEARGS_INSN_SEQ_LEN),
	    pc - sym.st_value);

	if (Pread(P, ins, insnsize, sym.st_value) != insnsize)
		return (0);

	if ((argc != 0) &&
	    ((args_style = saveargs_has_args(ins, insnsize, argc,
	    start_index)) != SAVEARGS_NO_ARGS)) {
		int regargs = MIN((6 - start_index), argc);
		size_t size = regargs * sizeof (long);
		int i;

		/*
		 * If Studio pushed a structure return address as an argument,
		 * we need to read one more argument than actually exists (the
		 * addr) to make everything line up.
		 */
		if (args_style == SAVEARGS_STRUCT_ARGS)
			size += sizeof (long);

		if (Pread(P, args, size, (fp - size)) != size)
			return (0);

		for (i = 0; i < (regargs / 2); i++) {
			prgreg_t t = args[i];

			args[i] = args[regargs - i - 1];
			args[regargs - i - 1] = t;
		}

		if (argc > regargs) {
			size = MIN((argc - regargs) * sizeof (long),
			    argsize - (regargs * sizeof (long)));

			if (Pread(P, &args[regargs], size, fp +
			    (sizeof (uintptr_t) * 2)) != size)
				return (6);
		}

		return (argc);
	} else {
		return (0);
	}
}
Ejemplo n.º 12
0
uintptr_t
la_i86_pltenter(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcookie,
	uintptr_t *defcookie, La_i86_regs *regset, uint_t *sb_flags)
#endif
{
	char		*defname = (char *)(*defcookie);
	char		*refname = (char *)(*refcookie);
	sigset_t	omask;
#if	!defined(_LP64)
	char const	*sym_name = (char const *)symp->st_name;
#endif

	char		buf[256];
	GElf_Sym	sym;
	prsyminfo_t	si;
	ctf_file_t	*ctfp;
	ctf_funcinfo_t	finfo;
	int		argc;
	ctf_id_t	argt[NUM_ARGS];
	ulong_t		argv[NUM_ARGS];
	int		i;
	char		*sep = "";
	ctf_id_t	type, rtype;
	int		kind;

	abilock(&omask);

	if (pidout)
		(void) fprintf(ABISTREAM, "%7u:", (unsigned int)getpid());

	if ((ctfp = Pname_to_ctf(proc_hdl, defname)) == NULL)
		goto fail;

	if (Pxlookup_by_name(proc_hdl, PR_LMID_EVERY, defname, sym_name,
	    &sym, &si) != 0)
		goto fail;

	if (ctf_func_info(ctfp, si.prs_id, &finfo) == CTF_ERR)
		goto fail;

	(void) type_name(ctfp, finfo.ctc_return, buf, sizeof (buf));
	(void) fprintf(ABISTREAM, "-> %-8s -> %8s:%s %s(",
	    refname, defname, buf, sym_name);

	/*
	 * According to bug in la_pltexit(), it can't return
	 * if the type is just a struct/union.  So, if the return
	 * type is a struct/union, la_pltexit() should be off.
	 */
	rtype = ctf_type_resolve(ctfp, finfo.ctc_return);
	type = ctf_type_reference(ctfp, rtype);
	rtype = ctf_type_resolve(ctfp, type);
	kind = ctf_type_kind(ctfp, rtype);
	if ((kind == CTF_K_STRUCT || kind == CTF_K_UNION) &&
	    strpbrk(buf, "*") == NULL)
		*sb_flags |= LA_SYMB_NOPLTEXIT;

	argc = MIN(sizeof (argt) / sizeof (argt[0]), finfo.ctc_argc);
	(void) ctf_func_args(ctfp, si.prs_id, argc, argt);

	argv[0] = GETARG0(regset);
	if (argc > 1)
		argv[1] = GETARG1(regset);
	if (argc > 2)
		argv[2] = GETARG2(regset);
	if (argc > 3)
		argv[3] = GETARG3(regset);
	if (argc > 4)
		argv[4] = GETARG4(regset);
	if (argc > 5)
		argv[5] = GETARG5(regset);
	if (argc > 6) {
		for (i = 6; i < argc; i++)
			argv[i] = GETARG_6NUP(i, regset);
	}

	for (i = 0; i < argc; i++) {
		(void) type_name(ctfp, argt[i], buf, sizeof (buf));
		(void) fprintf(ABISTREAM, "%s%s = ", sep, buf);
		rtype = ctf_type_resolve(ctfp, argt[i]);
		type = ctf_type_reference(ctfp, rtype);
		rtype = ctf_type_resolve(ctfp, type);
		kind = ctf_type_kind(ctfp, rtype);
		if (kind == CTF_K_STRUCT || kind == CTF_K_UNION)
			(void) fprintf(ABISTREAM, "0x%p", (void *)argv[i]);
		else
			print_value(ctfp, argt[i], argv[i]);
		sep = ", ";
	}

	if (finfo.ctc_flags & CTF_FUNC_VARARG)
		(void) fprintf(ABISTREAM, "%s...", sep);
	else if (argc == 0)
		(void) fprintf(ABISTREAM, "void");

	if ((*sb_flags & LA_SYMB_NOPLTEXIT) != 0)
		(void) fprintf(ABISTREAM, ") ** ST\n");
	else
		(void) fprintf(ABISTREAM, ")\n");

	if (verbose_list != NULL &&
	    check_intlist(verbose_list, sym_name) != 0) {
		for (i = 0; i < argc; i++) {
			(void) type_name(ctfp, argt[i], buf, sizeof (buf));
			(void) fprintf(ABISTREAM, "\targ%d = (%s) ", i, buf);
			print_value(ctfp, argt[i], argv[i]);
			(void) fprintf(ABISTREAM, "\n");
		}
		if ((*sb_flags & LA_SYMB_NOPLTEXIT) != 0) {
			if (kind == CTF_K_STRUCT)
				(void) fprintf(ABISTREAM,
				    "\treturn = (struct), apptrace "
				    "will not trace the return\n");
			else
				(void) fprintf(ABISTREAM,
				    "\treturn = (union), apptrace "
				    "will not trace the return\n");
		}
	}

	(void) fflush(ABISTREAM);
	abiunlock(&omask);
	return (symp->st_value);

fail:
	(void) fprintf(ABISTREAM,
	    "-> %-8s -> %8s:%s(0x%lx, 0x%lx, 0x%lx) ** NR\n",
	    refname, defname, sym_name,
	    (ulong_t)GETARG0(regset),
	    (ulong_t)GETARG1(regset),
	    (ulong_t)GETARG2(regset));

	*sb_flags |= LA_SYMB_NOPLTEXIT;
	(void) fflush(ABISTREAM);
	abiunlock(&omask);
	return (symp->st_value);
}
Ejemplo n.º 13
0
/*
 * Begin a macro.
 *
 * Once we figure out the type of the thing that we're supposed to dump (struct,
 * union, or enum), we select the proper type-specific ops-vector for dumping.
 */
static int
fth_section_init(char *fullname)
{
	ctf_id_t ltid = 0, tid;
	char *curtype, *lpart, *part, *npart;
	int lkind = 0, kind;

	curtype = xstrdup(fullname);
	lpart = NULL;
	part = strtok(fullname, ".");

	/*
	 * First figure out what sort of type we're looking at.  Life would be
	 * simple if we were only going to get type names, but it's not - we
	 * could also get `type.member'.  In that case, we need to figure out
	 * (and dump) the type of `member' instead.
	 */
	for (;;) {
		if (lpart == NULL) {
			/* First part - the struct name */
			if ((tid = find_type(part)) == CTF_ERR ||
			    (tid = ctf_type_resolve(ctf, tid)) == CTF_ERR ||
			    (kind = ctf_type_kind(ctf, tid)) == CTF_ERR) {
				free(curtype);
				return (parse_warn("Couldn't find %s: %s",
				    part, ctf_errmsg(ctf_errno(ctf))));
			}
		} else {
			/* Second (or more) part - the member name */
			if (lkind != CTF_K_STRUCT && lkind != CTF_K_UNION) {
				free(curtype);
				return (parse_warn("%s isn't a struct/union",
				    lpart));
			}

			if ((tid = find_member(ltid, part)) <= 0) {
				free(curtype);
				return (parse_warn("%s isn't a member of %s",
				    part, lpart));
			}

			if ((kind = ctf_type_kind(ctf, tid)) == CTF_ERR) {
				free(curtype);
				return (parse_warn("Can't get kind for %s",
				    part));
			}
		}

		/*
		 * Stop if there aren't any more parts.  We use `npart' here
		 * because we don't want to clobber part - we need it later.
		 */
		if ((npart = strtok(NULL, ".")) == NULL)
			break;

		lpart = part;
		ltid = tid;
		lkind = kind;

		part = npart;
	}

	/*
	 * Pick the right ops vector for dumping.
	 */
	switch (kind) {
	case CTF_K_STRUCT:
	case CTF_K_UNION:
		fth_type_ops = &fth_struct_ops;
		break;

	case CTF_K_ENUM:
		fth_type_ops = &fth_enum_ops;
		break;

	default:
		fth_type_ops = &fth_null_ops;
		free(curtype);
		return (parse_warn("%s isn't a struct, union, or enum", part));
	}

	fth_curtype = curtype;

	return (fth_type_ops->fto_header(tid));
}
Ejemplo n.º 14
0
/*
 * Convert a string type name with an optional leading object specifier into
 * the corresponding CTF file container and type ID.  If an error occurs, we
 * print an appropriate message and return NULL.
 */
static ctf_file_t *
name_to_type(mdb_tgt_t *t, const char *cname, ctf_id_t *idp)
{
	const char *object = MDB_TGT_OBJ_EXEC;
	ctf_file_t *fp = NULL;
	ctf_id_t id;
	tnarg_t arg;
	char *p, *s;
	char buf[MDB_SYM_NAMLEN];
	char *name = &buf[0];

	(void) mdb_snprintf(buf, sizeof (buf), "%s", cname);

	if ((p = strrsplit(name, '`')) != NULL) {
		/*
		 * We need to shuffle things around a little to support
		 * type names of the form "struct module`name".
		 */
		if ((s = strsplit(name, ' ')) != NULL) {
			bcopy(cname + (s - name), name, (p - s) - 1);
			name[(p - s) - 1] = '\0';
			bcopy(cname, name + (p - s), s - name);
			p = name + (p - s);
		}
		if (*name != '\0')
			object = name;
		name = p;
	}

	/*
	 * Attempt to look up the name in the primary object file.  If this
	 * fails and the name was unscoped, search all remaining object files.
	 * Finally, search the synthetic types.
	 */
	if (((fp = mdb_tgt_name_to_ctf(t, object)) == NULL ||
	    (id = ctf_lookup_by_name(fp, name)) == CTF_ERR ||
	    ctf_type_kind(fp, id) == CTF_K_FORWARD) &&
	    object == MDB_TGT_OBJ_EXEC) {

		arg.tn_tgt = t;
		arg.tn_name = name;
		arg.tn_fp = NULL;
		arg.tn_id = CTF_ERR;

		(void) mdb_tgt_object_iter(t, obj_lookup, &arg);

		if (arg.tn_id != CTF_ERR) {
			fp = arg.tn_fp;
			id = arg.tn_id;
		} else if (mdb.m_synth != NULL) {
			if ((id = ctf_lookup_by_name(mdb.m_synth,
			    name)) != CTF_ERR)
				fp = mdb.m_synth;
		}
	}

	if (fp == NULL)
		return (NULL); /* errno is set for us */

	if (id == CTF_ERR) {
		(void) set_errno(ctf_to_errno(ctf_errno(fp)));
		return (NULL);
	}

	*idp = id;
	return (fp);
}
Ejemplo n.º 15
0
static int
ctfdump_types_cb(ctf_id_t id, boolean_t root, void *arg)
{
	int kind, i, count;
	ctf_id_t ref;
	char name[512], ienc[128];
	const char *encn;
	ctf_funcinfo_t ctc;
	ctf_arinfo_t ar;
	ctf_encoding_t cte;
	ssize_t size;

	if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR)
		ctfdump_fatal("encountered malformed ctf, type %s does not "
		    "have a kind: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));

	if (ctf_type_name(g_fp, id, name, sizeof (name)) == NULL) {
		if (ctf_errno(g_fp) != ECTF_NOPARENT)
			ctfdump_fatal("type %lu missing name: %s\n", id,
			    ctf_errmsg(ctf_errno(g_fp)));
		(void) snprintf(name, sizeof (name), "(unknown %s)",
		    ctf_kind_name(g_fp, kind));
	}

	g_stats.cs_ntypes[kind]++;
	if (root == B_TRUE)
		ctfdump_printf(CTFDUMP_TYPES, "  <%lu> ", id);
	else
		ctfdump_printf(CTFDUMP_TYPES, "  [%lu] ", id);

	switch (kind) {
	case CTF_K_UNKNOWN:
		break;
	case CTF_K_INTEGER:
		if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR)
			ctfdump_fatal("failed to get encoding information "
			    "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		ctfdump_intenc_name(&cte, ienc, sizeof (ienc));
		ctfdump_printf(CTFDUMP_TYPES,
		    "%s encoding=%s offset=%u bits=%u",
		    name, ienc, cte.cte_offset, cte.cte_bits);
		break;
	case CTF_K_FLOAT:
		if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR)
			ctfdump_fatal("failed to get encoding information "
			    "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		if (cte.cte_format < 1 || cte.cte_format > 12)
			encn = "unknown";
		else
			encn = ctfdump_fpenc[cte.cte_format];
		ctfdump_printf(CTFDUMP_TYPES, "%s encoding=%s offset=%u "
		    "bits=%u", name, encn, cte.cte_offset, cte.cte_bits);
		break;
	case CTF_K_POINTER:
		if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
			ctfdump_fatal("failed to get reference type for %s: "
			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name,
		    ref);
		break;
	case CTF_K_ARRAY:
		if (ctf_array_info(g_fp, id, &ar) == CTF_ERR)
			ctfdump_fatal("failed to get array information for "
			    "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		ctfdump_printf(CTFDUMP_TYPES, "%s contents: %lu, index: %lu",
		    name, ar.ctr_contents, ar.ctr_index);
		break;
	case CTF_K_FUNCTION:
		if (ctf_func_info_by_id(g_fp, id, &ctc) == CTF_ERR)
			ctfdump_fatal("failed to get function info for %s: "
			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		if (ctc.ctc_argc > 0) {
			ctfdump_fargs_grow(ctc.ctc_argc);
			if (ctf_func_args_by_id(g_fp, id, g_nfargc, g_fargc) ==
			    CTF_ERR)
				ctfdump_fatal("failed to get function "
				    "arguments for %s: %s\n", name,
				    ctf_errmsg(ctf_errno(g_fp)));
		}
		ctfdump_printf(CTFDUMP_TYPES,
		    "%s returns: %lu args: (", name, ctc.ctc_return);
		for (i = 0; i < ctc.ctc_argc; i++) {
			ctfdump_printf(CTFDUMP_TYPES, "%lu%s", g_fargc[i],
			    i + 1 == ctc.ctc_argc ? "" : ", ");
		}
		if (ctc.ctc_flags & CTF_FUNC_VARARG)
			ctfdump_printf(CTFDUMP_TYPES, "%s...",
			    ctc.ctc_argc == 0 ? "" : ", ");
		ctfdump_printf(CTFDUMP_TYPES, ")");
		break;
	case CTF_K_STRUCT:
	case CTF_K_UNION:
		size = ctf_type_size(g_fp, id);
		if (size == CTF_ERR)
			ctfdump_fatal("failed to get size of %s: %s\n", name,
			    ctf_errmsg(ctf_errno(g_fp)));
		ctfdump_printf(CTFDUMP_TYPES, "%s (%d bytes)\n", name, size);
		count = 0;
		if (ctf_member_iter(g_fp, id, ctfdump_member_cb, &count) != 0)
			ctfdump_fatal("failed to iterate members of %s: %s\n",
			    name, ctf_errmsg(ctf_errno(g_fp)));
		if (kind == CTF_K_STRUCT) {
			g_stats.cs_nsmembs += count;
			g_stats.cs_nsmax = MAX(count, g_stats.cs_nsmax);
			g_stats.cs_structsz += size;
			g_stats.cs_sszmax = MAX(size, g_stats.cs_sszmax);
		} else {
			g_stats.cs_numembs += count;
			g_stats.cs_numax = MAX(count, g_stats.cs_numax);
			g_stats.cs_unionsz += size;
			g_stats.cs_uszmax = MAX(count, g_stats.cs_uszmax);
		}
		break;
	case CTF_K_ENUM:
		ctfdump_printf(CTFDUMP_TYPES, "%s\n", name);
		count = 0;
		if (ctf_enum_iter(g_fp, id, ctfdump_enum_cb, &count) != 0)
			ctfdump_fatal("failed to iterate enumerators of %s: "
			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		g_stats.cs_nemembs += count;
		g_stats.cs_nemax = MAX(g_stats.cs_nemax, count);
		break;
	case CTF_K_FORWARD:
		ctfdump_printf(CTFDUMP_TYPES, "forward %s\n", name);
		break;
	case CTF_K_TYPEDEF:
		if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
			ctfdump_fatal("failed to get reference type for %s: "
			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		ctfdump_printf(CTFDUMP_TYPES, "typedef %s refers to %lu", name,
		    ref);
		break;
	case CTF_K_VOLATILE:
		if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
			ctfdump_fatal("failed to get reference type for %s: "
			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name,
		    ref);
		break;
	case CTF_K_CONST:
		if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
			ctfdump_fatal("failed to get reference type for %s: "
			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name,
		    ref);
		break;
	case CTF_K_RESTRICT:
		if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
			ctfdump_fatal("failed to get reference type for %s: "
			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name,
		    ref);
		break;
	default:
		ctfdump_fatal("encountered unknown kind for type %s: %d\n",
		    name, kind);
	}

	ctfdump_printf(CTFDUMP_TYPES, "\n");

	return (0);
}
Ejemplo n.º 16
0
dt_xlator_t *
dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
{
	ctf_file_t *src_ctfp = src->dn_ctfp;
	ctf_id_t src_type = src->dn_type;
	ctf_id_t src_base = ctf_type_resolve(src_ctfp, src_type);

	ctf_file_t *dst_ctfp = dst->dn_ctfp;
	ctf_id_t dst_type = dst->dn_type;
	ctf_id_t dst_base = ctf_type_resolve(dst_ctfp, dst_type);
	uint_t dst_kind = ctf_type_kind(dst_ctfp, dst_base);

	int ptr = dst_kind == CTF_K_POINTER;
	dtrace_typeinfo_t src_dtt, dst_dtt;
	dt_node_t xn = { 0 };
	dt_xlator_t *dxp = NULL;

	if (src_base == CTF_ERR || dst_base == CTF_ERR)
		return (NULL); /* fail if these are unresolvable types */

	/*
	 * Translators are always defined using a struct or union type, so if
	 * we are attempting to translate to type "T *", we internally look
	 * for a translation to type "T" by following the pointer reference.
	 */
	if (ptr) {
		dst_type = ctf_type_reference(dst_ctfp, dst_type);
		dst_base = ctf_type_resolve(dst_ctfp, dst_type);
		dst_kind = ctf_type_kind(dst_ctfp, dst_base);
	}

	if (dst_kind != CTF_K_UNION && dst_kind != CTF_K_STRUCT)
		return (NULL); /* fail if the output isn't a struct or union */

	/*
	 * In order to find a matching translator, we iterate over the set of
	 * available translators in three passes.  First, we look for a
	 * translation from the exact source type to the resolved destination.
	 * Second, we look for a translation from the resolved source type to
	 * the resolved destination.  Third, we look for a translation from a
	 * compatible source type (using the same rules as parameter formals)
	 * to the resolved destination.  If all passes fail, return NULL.
	 */
	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
	    dxp = dt_list_next(dxp)) {
		if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_type,
		    src_ctfp, src_type) &&
		    ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
		    dst_ctfp, dst_base))
			goto out;
	}

	if (flags & DT_XLATE_EXACT)
		goto out; /* skip remaining passes if exact match required */

	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
	    dxp = dt_list_next(dxp)) {
		if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_base,
		    src_ctfp, src_type) &&
		    ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
		    dst_ctfp, dst_base))
			goto out;
	}

	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
	    dxp = dt_list_next(dxp)) {
		dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type);
		if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
		    dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
			goto out;
	}

out:
	if (ptr && dxp != NULL && dxp->dx_ptrid.di_type == CTF_ERR)
		return (NULL);	/* no translation available to pointer type */

	if (dxp != NULL || !(flags & DT_XLATE_EXTERN) ||
	    dtp->dt_xlatemode == DT_XL_STATIC)
		return (dxp);	/* we succeeded or not allowed to extern */

	/*
	 * If we get here, then we didn't find an existing translator, but the
	 * caller and xlatemode permit us to create an extern to a dynamic one.
	 */
	src_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, src_ctfp)->dm_name;
	src_dtt.dtt_ctfp = src_ctfp;
	src_dtt.dtt_type = src_type;

	dst_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, dst_ctfp)->dm_name;
	dst_dtt.dtt_ctfp = dst_ctfp;
	dst_dtt.dtt_type = dst_type;

	return (dt_xlator_create(dtp, &src_dtt, &dst_dtt, NULL, NULL, NULL));
}
Ejemplo n.º 17
0
static void
ctfsrc_type(ctf_id_t id, const char *name)
{
	char refname[MAX_NAMELEN];
	ctf_id_t ref;
	ssize_t size;
	int kind;

	if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR) {
		ctfdump_fatal("encountered malformed ctf, type %s does not "
		    "have a kind: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
	}

	switch (kind) {
	case CTF_K_STRUCT:
	case CTF_K_UNION:
		/*
		 * Delay printing anonymous SOUs; a later typedef will usually
		 * pick them up.
		 */
		if (is_anon_refname(name))
			break;

		if ((size = ctf_type_size(g_fp, id)) == CTF_ERR) {
			ctfdump_fatal("failed to get size of %s: %s\n", name,
			    ctf_errmsg(ctf_errno(g_fp)));
		}

		(void) printf("%s { /* 0x%x bytes */\n", name, size);

		if (ctf_member_iter(g_fp, id, ctfsrc_member_cb, NULL) != 0) {
			ctfdump_fatal("failed to iterate members of %s: %s\n",
			    name, ctf_errmsg(ctf_errno(g_fp)));
		}

		(void) printf("};\n\n");
		break;
	case CTF_K_ENUM:
		/*
		 * This will throw away any anon enum that isn't followed by a
		 * typedef...
		 */
		if (is_anon_refname(name))
			break;

		(void) printf("%s {\n", name);

		if (ctf_enum_iter(g_fp, id, ctfsrc_enum_cb, NULL) != 0) {
			ctfdump_fatal("failed to iterate enumerators of %s: "
			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		}

		(void) printf("};\n\n");
		break;
	case CTF_K_TYPEDEF:
		ctfsrc_refname(id, refname, sizeof (refname));

		if (!is_anon_refname(refname)) {
			(void) ctf_type_cname(g_fp,
			    ctf_type_reference(g_fp, id), refname,
			    sizeof (refname), name);

			(void) printf("typedef %s;\n\n", refname);
			break;
		}

		ref = ctf_type_reference(g_fp, id);

		if (ctf_type_kind(g_fp, ref) == CTF_K_ENUM) {
			(void) printf("typedef enum {\n");

			if (ctf_enum_iter(g_fp, ref,
			    ctfsrc_enum_cb, NULL) != 0) {
				ctfdump_fatal("failed to iterate enumerators "
				    "of %s: %s\n", refname,
				    ctf_errmsg(ctf_errno(g_fp)));
			}

			(void) printf("} %s;\n\n", name);
		} else {
			if ((size = ctf_type_size(g_fp, ref)) == CTF_ERR) {
				ctfdump_fatal("failed to get size of %s: %s\n",
				    refname, ctf_errmsg(ctf_errno(g_fp)));
			}

			(void) printf("typedef %s{ /* 0x%zx bytes */\n",
			    refname, size);

			if (ctf_member_iter(g_fp, ref,
			    ctfsrc_member_cb, NULL) != 0) {
				ctfdump_fatal("failed to iterate members "
				    "of %s: %s\n", refname,
				    ctf_errmsg(ctf_errno(g_fp)));
			}

			(void) printf("} %s;\n\n", name);
		}

		break;
	case CTF_K_FORWARD:
		(void) printf("%s;\n\n", name);
		break;
	case CTF_K_UNKNOWN:
	case CTF_K_INTEGER:
	case CTF_K_FLOAT:
	case CTF_K_POINTER:
	case CTF_K_ARRAY:
	case CTF_K_FUNCTION:
	case CTF_K_VOLATILE:
	case CTF_K_CONST:
	case CTF_K_RESTRICT:
		break;
	default:
		ctfdump_fatal("encountered unknown kind for type %s: %d\n",
		    name, kind);
		break;
	}
}