Example #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 */
	}
}
Example #2
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));
}