xref: /freebsd/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.c (revision a8c03de86d91378df9f7ae751d629f74f932b2e2)
16ff6d951SJohn Birrell /*
26ff6d951SJohn Birrell  * CDDL HEADER START
36ff6d951SJohn Birrell  *
46ff6d951SJohn Birrell  * The contents of this file are subject to the terms of the
56ff6d951SJohn Birrell  * Common Development and Distribution License, Version 1.0 only
66ff6d951SJohn Birrell  * (the "License").  You may not use this file except in compliance
76ff6d951SJohn Birrell  * with the License.
86ff6d951SJohn Birrell  *
96ff6d951SJohn Birrell  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
106ff6d951SJohn Birrell  * or http://www.opensolaris.org/os/licensing.
116ff6d951SJohn Birrell  * See the License for the specific language governing permissions
126ff6d951SJohn Birrell  * and limitations under the License.
136ff6d951SJohn Birrell  *
146ff6d951SJohn Birrell  * When distributing Covered Code, include this CDDL HEADER in each
156ff6d951SJohn Birrell  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
166ff6d951SJohn Birrell  * If applicable, add the following below this CDDL HEADER, with the
176ff6d951SJohn Birrell  * fields enclosed by brackets "[]" replaced with your own identifying
186ff6d951SJohn Birrell  * information: Portions Copyright [yyyy] [name of copyright owner]
196ff6d951SJohn Birrell  *
206ff6d951SJohn Birrell  * CDDL HEADER END
216ff6d951SJohn Birrell  */
226ff6d951SJohn Birrell /*
236ff6d951SJohn Birrell  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
246ff6d951SJohn Birrell  * Use is subject to license terms.
256ff6d951SJohn Birrell  */
268e648814SRui Paulo /*
278e648814SRui Paulo  * Copyright (c) 2013 by Delphix. All rights reserved.
288e648814SRui Paulo  * Copyright (c) 2013 Joyent, Inc. All rights reserved.
298e648814SRui Paulo  */
306ff6d951SJohn Birrell 
316ff6d951SJohn Birrell #include <strings.h>
326ff6d951SJohn Birrell #include <assert.h>
336ff6d951SJohn Birrell 
346ff6d951SJohn Birrell #include <dt_xlator.h>
356ff6d951SJohn Birrell #include <dt_parser.h>
366ff6d951SJohn Birrell #include <dt_grammar.h>
376ff6d951SJohn Birrell #include <dt_module.h>
386ff6d951SJohn Birrell #include <dt_impl.h>
396ff6d951SJohn Birrell 
406ff6d951SJohn Birrell /*
416ff6d951SJohn Birrell  * Create a member node corresponding to one of the output members of a dynamic
426ff6d951SJohn Birrell  * translator.  We set the member's dn_membexpr to a DT_NODE_XLATOR node that
436ff6d951SJohn Birrell  * has dn_op set to DT_TOK_XLATE and refers back to the translator itself.  The
446ff6d951SJohn Birrell  * code generator will then use this as the indicator for dynamic translation.
456ff6d951SJohn Birrell  */
466ff6d951SJohn Birrell /*ARGSUSED*/
476ff6d951SJohn Birrell static int
dt_xlator_create_member(const char * name,ctf_id_t type,ulong_t off,void * arg)486ff6d951SJohn Birrell dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
496ff6d951SJohn Birrell {
506ff6d951SJohn Birrell 	dt_xlator_t *dxp = arg;
516ff6d951SJohn Birrell 	dtrace_hdl_t *dtp = dxp->dx_hdl;
526ff6d951SJohn Birrell 	dt_node_t *enp, *mnp;
536ff6d951SJohn Birrell 
546ff6d951SJohn Birrell 	if ((enp = dt_node_xalloc(dtp, DT_NODE_XLATOR)) == NULL)
556ff6d951SJohn Birrell 		return (dt_set_errno(dtp, EDT_NOMEM));
566ff6d951SJohn Birrell 
576ff6d951SJohn Birrell 	enp->dn_link = dxp->dx_nodes;
586ff6d951SJohn Birrell 	dxp->dx_nodes = enp;
596ff6d951SJohn Birrell 
606ff6d951SJohn Birrell 	if ((mnp = dt_node_xalloc(dtp, DT_NODE_MEMBER)) == NULL)
616ff6d951SJohn Birrell 		return (dt_set_errno(dtp, EDT_NOMEM));
626ff6d951SJohn Birrell 
636ff6d951SJohn Birrell 	mnp->dn_link = dxp->dx_nodes;
646ff6d951SJohn Birrell 	dxp->dx_nodes = mnp;
656ff6d951SJohn Birrell 
666ff6d951SJohn Birrell 	/*
676ff6d951SJohn Birrell 	 * For the member expression, we use a DT_NODE_XLATOR/TOK_XLATE whose
686ff6d951SJohn Birrell 	 * xlator refers back to the translator and whose dn_xmember refers to
696ff6d951SJohn Birrell 	 * the current member.  These refs will be used by dt_cg.c and dt_as.c.
706ff6d951SJohn Birrell 	 */
716ff6d951SJohn Birrell 	enp->dn_op = DT_TOK_XLATE;
726ff6d951SJohn Birrell 	enp->dn_xlator = dxp;
736ff6d951SJohn Birrell 	enp->dn_xmember = mnp;
748e648814SRui Paulo 	dt_node_type_assign(enp, dxp->dx_dst_ctfp, type, B_FALSE);
756ff6d951SJohn Birrell 
766ff6d951SJohn Birrell 	/*
776ff6d951SJohn Birrell 	 * For the member itself, we use a DT_NODE_MEMBER as usual with the
786ff6d951SJohn Birrell 	 * appropriate name, output type, and member expression set to 'enp'.
796ff6d951SJohn Birrell 	 */
806ff6d951SJohn Birrell 	if (dxp->dx_members != NULL) {
816ff6d951SJohn Birrell 		assert(enp->dn_link->dn_kind == DT_NODE_MEMBER);
826ff6d951SJohn Birrell 		enp->dn_link->dn_list = mnp;
836ff6d951SJohn Birrell 	} else
846ff6d951SJohn Birrell 		dxp->dx_members = mnp;
856ff6d951SJohn Birrell 
866ff6d951SJohn Birrell 	mnp->dn_membname = strdup(name);
876ff6d951SJohn Birrell 	mnp->dn_membexpr = enp;
888e648814SRui Paulo 	dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type, B_FALSE);
896ff6d951SJohn Birrell 
906ff6d951SJohn Birrell 	if (mnp->dn_membname == NULL)
916ff6d951SJohn Birrell 		return (dt_set_errno(dtp, EDT_NOMEM));
926ff6d951SJohn Birrell 
936ff6d951SJohn Birrell 	return (0);
946ff6d951SJohn Birrell }
956ff6d951SJohn Birrell 
966ff6d951SJohn Birrell 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)976ff6d951SJohn Birrell dt_xlator_create(dtrace_hdl_t *dtp,
986ff6d951SJohn Birrell     const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst,
996ff6d951SJohn Birrell     const char *name, dt_node_t *members, dt_node_t *nodes)
1006ff6d951SJohn Birrell {
1016ff6d951SJohn Birrell 	dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t));
1026ff6d951SJohn Birrell 	dtrace_typeinfo_t ptr = *dst;
1036ff6d951SJohn Birrell 	dt_xlator_t **map;
1046ff6d951SJohn Birrell 	dt_node_t *dnp;
1056ff6d951SJohn Birrell 	uint_t kind;
1066ff6d951SJohn Birrell 
1076ff6d951SJohn Birrell 	if (dxp == NULL)
1086ff6d951SJohn Birrell 		return (NULL);
1096ff6d951SJohn Birrell 
1106ff6d951SJohn Birrell 	dxp->dx_hdl = dtp;
1116ff6d951SJohn Birrell 	dxp->dx_id = dtp->dt_xlatorid++;
1126ff6d951SJohn Birrell 	dxp->dx_gen = dtp->dt_gen;
1136ff6d951SJohn Birrell 	dxp->dx_arg = -1;
1146ff6d951SJohn Birrell 
1156ff6d951SJohn Birrell 	if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) {
1166ff6d951SJohn Birrell 		dt_free(dtp, dxp);
1176ff6d951SJohn Birrell 		return (NULL);
1186ff6d951SJohn Birrell 	}
1196ff6d951SJohn Birrell 
1206ff6d951SJohn Birrell 	dt_list_append(&dtp->dt_xlators, dxp);
1216ff6d951SJohn Birrell 	bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id);
1226ff6d951SJohn Birrell 	dt_free(dtp, dtp->dt_xlatormap);
1236ff6d951SJohn Birrell 	dtp->dt_xlatormap = map;
1246ff6d951SJohn Birrell 	dtp->dt_xlatormap[dxp->dx_id] = dxp;
1256ff6d951SJohn Birrell 
1266ff6d951SJohn Birrell 	if (dt_type_pointer(&ptr) == -1) {
1276ff6d951SJohn Birrell 		ptr.dtt_ctfp = NULL;
1286ff6d951SJohn Birrell 		ptr.dtt_type = CTF_ERR;
1296ff6d951SJohn Birrell 	}
1306ff6d951SJohn Birrell 
1316ff6d951SJohn Birrell 	dxp->dx_ident = dt_ident_create(name ? name : "T",
1326ff6d951SJohn Birrell 	    DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0,
1336ff6d951SJohn Birrell 	    _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);
1346ff6d951SJohn Birrell 
1356ff6d951SJohn Birrell 	if (dxp->dx_ident == NULL)
1366ff6d951SJohn Birrell 		goto err; /* no memory for identifier */
1376ff6d951SJohn Birrell 
1386ff6d951SJohn Birrell 	dxp->dx_ident->di_ctfp = src->dtt_ctfp;
1396ff6d951SJohn Birrell 	dxp->dx_ident->di_type = src->dtt_type;
1406ff6d951SJohn Birrell 
1416ff6d951SJohn Birrell 	/*
1426ff6d951SJohn Birrell 	 * If an input parameter name is given, this is a static translator
1436ff6d951SJohn Birrell 	 * definition: create an idhash and identifier for the parameter.
1446ff6d951SJohn Birrell 	 */
1456ff6d951SJohn Birrell 	if (name != NULL) {
1466ff6d951SJohn Birrell 		dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0);
1476ff6d951SJohn Birrell 
1486ff6d951SJohn Birrell 		if (dxp->dx_locals == NULL)
1496ff6d951SJohn Birrell 			goto err; /* no memory for identifier hash */
1506ff6d951SJohn Birrell 
1516ff6d951SJohn Birrell 		dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident);
1526ff6d951SJohn Birrell 	}
1536ff6d951SJohn Birrell 
1546ff6d951SJohn Birrell 	dxp->dx_souid.di_name = "translator";
1556ff6d951SJohn Birrell 	dxp->dx_souid.di_kind = DT_IDENT_XLSOU;
1566ff6d951SJohn Birrell 	dxp->dx_souid.di_flags = DT_IDFLG_REF;
1576ff6d951SJohn Birrell 	dxp->dx_souid.di_id = dxp->dx_id;
1586ff6d951SJohn Birrell 	dxp->dx_souid.di_attr = _dtrace_defattr;
1596ff6d951SJohn Birrell 	dxp->dx_souid.di_ops = &dt_idops_thaw;
1606ff6d951SJohn Birrell 	dxp->dx_souid.di_data = dxp;
1616ff6d951SJohn Birrell 	dxp->dx_souid.di_ctfp = dst->dtt_ctfp;
1626ff6d951SJohn Birrell 	dxp->dx_souid.di_type = dst->dtt_type;
1636ff6d951SJohn Birrell 	dxp->dx_souid.di_gen = dtp->dt_gen;
1646ff6d951SJohn Birrell 
1656ff6d951SJohn Birrell 	dxp->dx_ptrid.di_name = "translator";
1666ff6d951SJohn Birrell 	dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR;
1676ff6d951SJohn Birrell 	dxp->dx_ptrid.di_flags = DT_IDFLG_REF;
1686ff6d951SJohn Birrell 	dxp->dx_ptrid.di_id = dxp->dx_id;
1696ff6d951SJohn Birrell 	dxp->dx_ptrid.di_attr = _dtrace_defattr;
1706ff6d951SJohn Birrell 	dxp->dx_ptrid.di_ops = &dt_idops_thaw;
1716ff6d951SJohn Birrell 	dxp->dx_ptrid.di_data = dxp;
1726ff6d951SJohn Birrell 	dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp;
1736ff6d951SJohn Birrell 	dxp->dx_ptrid.di_type = ptr.dtt_type;
1746ff6d951SJohn Birrell 	dxp->dx_ptrid.di_gen = dtp->dt_gen;
1756ff6d951SJohn Birrell 
1766ff6d951SJohn Birrell 	/*
1776ff6d951SJohn Birrell 	 * If a deferred pragma is pending on the keyword "translator", run all
1786ff6d951SJohn Birrell 	 * the deferred pragmas on dx_souid and then copy results to dx_ptrid.
1796ff6d951SJohn Birrell 	 * See the code in dt_pragma.c for details on deferred ident pragmas.
1806ff6d951SJohn Birrell 	 */
1816ff6d951SJohn Birrell 	if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL &&
1826ff6d951SJohn Birrell 	    dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) {
1836ff6d951SJohn Birrell 		dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid);
1846ff6d951SJohn Birrell 		dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr;
1856ff6d951SJohn Birrell 		dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers;
1866ff6d951SJohn Birrell 	}
1876ff6d951SJohn Birrell 
1886ff6d951SJohn Birrell 	dxp->dx_src_ctfp = src->dtt_ctfp;
1896ff6d951SJohn Birrell 	dxp->dx_src_type = src->dtt_type;
1906ff6d951SJohn Birrell 	dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type);
1916ff6d951SJohn Birrell 
1926ff6d951SJohn Birrell 	dxp->dx_dst_ctfp = dst->dtt_ctfp;
1936ff6d951SJohn Birrell 	dxp->dx_dst_type = dst->dtt_type;
1946ff6d951SJohn Birrell 	dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type);
1956ff6d951SJohn Birrell 
1966ff6d951SJohn Birrell 	kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base);
1976ff6d951SJohn Birrell 	assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION);
1986ff6d951SJohn Birrell 
1996ff6d951SJohn Birrell 	/*
2006ff6d951SJohn Birrell 	 * If no input parameter is given, we're making a dynamic translator:
2016ff6d951SJohn Birrell 	 * create member nodes for every member of the output type.  Otherwise
2026ff6d951SJohn Birrell 	 * retain the member and allocation node lists presented by the parser.
2036ff6d951SJohn Birrell 	 */
2046ff6d951SJohn Birrell 	if (name == NULL) {
2056ff6d951SJohn Birrell 		if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base,
2066ff6d951SJohn Birrell 		    dt_xlator_create_member, dxp) != 0)
2076ff6d951SJohn Birrell 			goto err;
2086ff6d951SJohn Birrell 	} else {
2096ff6d951SJohn Birrell 		dxp->dx_members = members;
2106ff6d951SJohn Birrell 		dxp->dx_nodes = nodes;
2116ff6d951SJohn Birrell 	}
2126ff6d951SJohn Birrell 
2136ff6d951SJohn Birrell 	/*
2146ff6d951SJohn Birrell 	 * Assign member IDs to each member and allocate space for DIFOs
2156ff6d951SJohn Birrell 	 * if and when this translator is eventually compiled.
2166ff6d951SJohn Birrell 	 */
2176ff6d951SJohn Birrell 	for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
2186ff6d951SJohn Birrell 		dnp->dn_membxlator = dxp;
2196ff6d951SJohn Birrell 		dnp->dn_membid = dxp->dx_nmembers++;
2206ff6d951SJohn Birrell 	}
2216ff6d951SJohn Birrell 
2226ff6d951SJohn Birrell 	dxp->dx_membdif = dt_zalloc(dtp,
2236ff6d951SJohn Birrell 	    sizeof (dtrace_difo_t *) * dxp->dx_nmembers);
2246ff6d951SJohn Birrell 
2256ff6d951SJohn Birrell 	if (dxp->dx_membdif == NULL) {
2266ff6d951SJohn Birrell 		dxp->dx_nmembers = 0;
2276ff6d951SJohn Birrell 		goto err;
2286ff6d951SJohn Birrell 	}
2296ff6d951SJohn Birrell 
2306ff6d951SJohn Birrell 	return (dxp);
2316ff6d951SJohn Birrell 
2326ff6d951SJohn Birrell err:
2336ff6d951SJohn Birrell 	dt_xlator_destroy(dtp, dxp);
2346ff6d951SJohn Birrell 	return (NULL);
2356ff6d951SJohn Birrell }
2366ff6d951SJohn Birrell 
2376ff6d951SJohn Birrell void
dt_xlator_destroy(dtrace_hdl_t * dtp,dt_xlator_t * dxp)2386ff6d951SJohn Birrell dt_xlator_destroy(dtrace_hdl_t *dtp, dt_xlator_t *dxp)
2396ff6d951SJohn Birrell {
2406ff6d951SJohn Birrell 	uint_t i;
2416ff6d951SJohn Birrell 
2426ff6d951SJohn Birrell 	dt_node_link_free(&dxp->dx_nodes);
2436ff6d951SJohn Birrell 
2446ff6d951SJohn Birrell 	if (dxp->dx_locals != NULL)
2456ff6d951SJohn Birrell 		dt_idhash_destroy(dxp->dx_locals);
2466ff6d951SJohn Birrell 	else if (dxp->dx_ident != NULL)
2476ff6d951SJohn Birrell 		dt_ident_destroy(dxp->dx_ident);
2486ff6d951SJohn Birrell 
2496ff6d951SJohn Birrell 	for (i = 0; i < dxp->dx_nmembers; i++)
2506ff6d951SJohn Birrell 		dt_difo_free(dtp, dxp->dx_membdif[i]);
2516ff6d951SJohn Birrell 
2526ff6d951SJohn Birrell 	dt_free(dtp, dxp->dx_membdif);
2536ff6d951SJohn Birrell 	dt_list_delete(&dtp->dt_xlators, dxp);
2546ff6d951SJohn Birrell 	dt_free(dtp, dxp);
2556ff6d951SJohn Birrell }
2566ff6d951SJohn Birrell 
2576ff6d951SJohn Birrell dt_xlator_t *
dt_xlator_lookup(dtrace_hdl_t * dtp,dt_node_t * src,dt_node_t * dst,int flags)2586ff6d951SJohn Birrell dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
2596ff6d951SJohn Birrell {
2606ff6d951SJohn Birrell 	ctf_file_t *src_ctfp = src->dn_ctfp;
2616ff6d951SJohn Birrell 	ctf_id_t src_type = src->dn_type;
2626ff6d951SJohn Birrell 	ctf_id_t src_base = ctf_type_resolve(src_ctfp, src_type);
2636ff6d951SJohn Birrell 
2646ff6d951SJohn Birrell 	ctf_file_t *dst_ctfp = dst->dn_ctfp;
2656ff6d951SJohn Birrell 	ctf_id_t dst_type = dst->dn_type;
2666ff6d951SJohn Birrell 	ctf_id_t dst_base = ctf_type_resolve(dst_ctfp, dst_type);
2676ff6d951SJohn Birrell 	uint_t dst_kind = ctf_type_kind(dst_ctfp, dst_base);
2686ff6d951SJohn Birrell 
2696ff6d951SJohn Birrell 	int ptr = dst_kind == CTF_K_POINTER;
2706ff6d951SJohn Birrell 	dtrace_typeinfo_t src_dtt, dst_dtt;
2716ff6d951SJohn Birrell 	dt_node_t xn = { 0 };
2726ff6d951SJohn Birrell 	dt_xlator_t *dxp = NULL;
2736ff6d951SJohn Birrell 
2746ff6d951SJohn Birrell 	if (src_base == CTF_ERR || dst_base == CTF_ERR)
2756ff6d951SJohn Birrell 		return (NULL); /* fail if these are unresolvable types */
2766ff6d951SJohn Birrell 
2776ff6d951SJohn Birrell 	/*
2786ff6d951SJohn Birrell 	 * Translators are always defined using a struct or union type, so if
2796ff6d951SJohn Birrell 	 * we are attempting to translate to type "T *", we internally look
2806ff6d951SJohn Birrell 	 * for a translation to type "T" by following the pointer reference.
2816ff6d951SJohn Birrell 	 */
2826ff6d951SJohn Birrell 	if (ptr) {
2836ff6d951SJohn Birrell 		dst_type = ctf_type_reference(dst_ctfp, dst_type);
2846ff6d951SJohn Birrell 		dst_base = ctf_type_resolve(dst_ctfp, dst_type);
2856ff6d951SJohn Birrell 		dst_kind = ctf_type_kind(dst_ctfp, dst_base);
2866ff6d951SJohn Birrell 	}
2876ff6d951SJohn Birrell 
2886ff6d951SJohn Birrell 	if (dst_kind != CTF_K_UNION && dst_kind != CTF_K_STRUCT)
2896ff6d951SJohn Birrell 		return (NULL); /* fail if the output isn't a struct or union */
2906ff6d951SJohn Birrell 
2916ff6d951SJohn Birrell 	/*
2926ff6d951SJohn Birrell 	 * In order to find a matching translator, we iterate over the set of
2936ff6d951SJohn Birrell 	 * available translators in three passes.  First, we look for a
2946ff6d951SJohn Birrell 	 * translation from the exact source type to the resolved destination.
2956ff6d951SJohn Birrell 	 * Second, we look for a translation from the resolved source type to
2966ff6d951SJohn Birrell 	 * the resolved destination.  Third, we look for a translation from a
2976ff6d951SJohn Birrell 	 * compatible source type (using the same rules as parameter formals)
2986ff6d951SJohn Birrell 	 * to the resolved destination.  If all passes fail, return NULL.
2996ff6d951SJohn Birrell 	 */
3006ff6d951SJohn Birrell 	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
3016ff6d951SJohn Birrell 	    dxp = dt_list_next(dxp)) {
3026ff6d951SJohn Birrell 		if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_type,
3036ff6d951SJohn Birrell 		    src_ctfp, src_type) &&
3046ff6d951SJohn Birrell 		    ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
3056ff6d951SJohn Birrell 		    dst_ctfp, dst_base))
3066ff6d951SJohn Birrell 			goto out;
3076ff6d951SJohn Birrell 	}
3086ff6d951SJohn Birrell 
3096ff6d951SJohn Birrell 	if (flags & DT_XLATE_EXACT)
3106ff6d951SJohn Birrell 		goto out; /* skip remaining passes if exact match required */
3116ff6d951SJohn Birrell 
3126ff6d951SJohn Birrell 	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
3136ff6d951SJohn Birrell 	    dxp = dt_list_next(dxp)) {
3146ff6d951SJohn Birrell 		if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_base,
3156ff6d951SJohn Birrell 		    src_ctfp, src_type) &&
3166ff6d951SJohn Birrell 		    ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
3176ff6d951SJohn Birrell 		    dst_ctfp, dst_base))
3186ff6d951SJohn Birrell 			goto out;
3196ff6d951SJohn Birrell 	}
3206ff6d951SJohn Birrell 
3216ff6d951SJohn Birrell 	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
3226ff6d951SJohn Birrell 	    dxp = dt_list_next(dxp)) {
3238e648814SRui Paulo 		dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type,
3248e648814SRui Paulo 		    B_FALSE);
3256ff6d951SJohn Birrell 		if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
3266ff6d951SJohn Birrell 		    dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
3276ff6d951SJohn Birrell 			goto out;
3286ff6d951SJohn Birrell 	}
3296ff6d951SJohn Birrell 
3306ff6d951SJohn Birrell out:
3316ff6d951SJohn Birrell 	if (ptr && dxp != NULL && dxp->dx_ptrid.di_type == CTF_ERR)
3326ff6d951SJohn Birrell 		return (NULL);	/* no translation available to pointer type */
3336ff6d951SJohn Birrell 
3346ff6d951SJohn Birrell 	if (dxp != NULL || !(flags & DT_XLATE_EXTERN) ||
3356ff6d951SJohn Birrell 	    dtp->dt_xlatemode == DT_XL_STATIC)
3366ff6d951SJohn Birrell 		return (dxp);	/* we succeeded or not allowed to extern */
3376ff6d951SJohn Birrell 
3386ff6d951SJohn Birrell 	/*
3396ff6d951SJohn Birrell 	 * If we get here, then we didn't find an existing translator, but the
3406ff6d951SJohn Birrell 	 * caller and xlatemode permit us to create an extern to a dynamic one.
3416ff6d951SJohn Birrell 	 */
3426ff6d951SJohn Birrell 	src_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, src_ctfp)->dm_name;
3436ff6d951SJohn Birrell 	src_dtt.dtt_ctfp = src_ctfp;
3446ff6d951SJohn Birrell 	src_dtt.dtt_type = src_type;
3456ff6d951SJohn Birrell 
346*a8c03de8SConrad Meyer 	dst_dtt = (dtrace_typeinfo_t){
347*a8c03de8SConrad Meyer 		.dtt_object = dt_module_lookup_by_ctf(dtp, dst_ctfp)->dm_name,
348*a8c03de8SConrad Meyer 		.dtt_ctfp = dst_ctfp,
349*a8c03de8SConrad Meyer 		.dtt_type = dst_type,
350*a8c03de8SConrad Meyer 	};
3516ff6d951SJohn Birrell 
3526ff6d951SJohn Birrell 	return (dt_xlator_create(dtp, &src_dtt, &dst_dtt, NULL, NULL, NULL));
3536ff6d951SJohn Birrell }
3546ff6d951SJohn Birrell 
3556ff6d951SJohn Birrell dt_xlator_t *
dt_xlator_lookup_id(dtrace_hdl_t * dtp,id_t id)3566ff6d951SJohn Birrell dt_xlator_lookup_id(dtrace_hdl_t *dtp, id_t id)
3576ff6d951SJohn Birrell {
3586ff6d951SJohn Birrell 	assert(id >= 0 && id < dtp->dt_xlatorid);
3596ff6d951SJohn Birrell 	return (dtp->dt_xlatormap[id]);
3606ff6d951SJohn Birrell }
3616ff6d951SJohn Birrell 
3626ff6d951SJohn Birrell dt_ident_t *
dt_xlator_ident(dt_xlator_t * dxp,ctf_file_t * ctfp,ctf_id_t type)3636ff6d951SJohn Birrell dt_xlator_ident(dt_xlator_t *dxp, ctf_file_t *ctfp, ctf_id_t type)
3646ff6d951SJohn Birrell {
3656ff6d951SJohn Birrell 	if (ctf_type_kind(ctfp, ctf_type_resolve(ctfp, type)) == CTF_K_POINTER)
3666ff6d951SJohn Birrell 		return (&dxp->dx_ptrid);
3676ff6d951SJohn Birrell 	else
3686ff6d951SJohn Birrell 		return (&dxp->dx_souid);
3696ff6d951SJohn Birrell }
3706ff6d951SJohn Birrell 
3716ff6d951SJohn Birrell dt_node_t *
dt_xlator_member(dt_xlator_t * dxp,const char * name)3726ff6d951SJohn Birrell dt_xlator_member(dt_xlator_t *dxp, const char *name)
3736ff6d951SJohn Birrell {
3746ff6d951SJohn Birrell 	dt_node_t *dnp;
3756ff6d951SJohn Birrell 
3766ff6d951SJohn Birrell 	for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
3776ff6d951SJohn Birrell 		if (strcmp(dnp->dn_membname, name) == 0)
3786ff6d951SJohn Birrell 			return (dnp);
3796ff6d951SJohn Birrell 	}
3806ff6d951SJohn Birrell 
3816ff6d951SJohn Birrell 	return (NULL);
3826ff6d951SJohn Birrell }
3836ff6d951SJohn Birrell 
3846ff6d951SJohn Birrell int
dt_xlator_dynamic(const dt_xlator_t * dxp)3856ff6d951SJohn Birrell dt_xlator_dynamic(const dt_xlator_t *dxp)
3866ff6d951SJohn Birrell {
3876ff6d951SJohn Birrell 	return (dxp->dx_locals == NULL);
3886ff6d951SJohn Birrell }
389