17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <strings.h>
30*1a7c1b72Smws #include <assert.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <dt_xlator.h>
33*1a7c1b72Smws #include <dt_parser.h>
34*1a7c1b72Smws #include <dt_grammar.h>
35*1a7c1b72Smws #include <dt_module.h>
367c478bd9Sstevel@tonic-gate #include <dt_impl.h>
377c478bd9Sstevel@tonic-gate 
38*1a7c1b72Smws /*
39*1a7c1b72Smws  * Create a member node corresponding to one of the output members of a dynamic
40*1a7c1b72Smws  * translator.  We set the member's dn_membexpr to a DT_NODE_XLATOR node that
41*1a7c1b72Smws  * has dn_op set to DT_TOK_XLATE and refers back to the translator itself.  The
42*1a7c1b72Smws  * code generator will then use this as the indicator for dynamic translation.
43*1a7c1b72Smws  */
44*1a7c1b72Smws /*ARGSUSED*/
45*1a7c1b72Smws static int
46*1a7c1b72Smws dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
47*1a7c1b72Smws {
48*1a7c1b72Smws 	dt_xlator_t *dxp = arg;
49*1a7c1b72Smws 	dtrace_hdl_t *dtp = dxp->dx_hdl;
50*1a7c1b72Smws 	dt_node_t *enp, *mnp;
51*1a7c1b72Smws 
52*1a7c1b72Smws 	if ((enp = dt_node_xalloc(dtp, DT_NODE_XLATOR)) == NULL)
53*1a7c1b72Smws 		return (dt_set_errno(dtp, EDT_NOMEM));
54*1a7c1b72Smws 
55*1a7c1b72Smws 	enp->dn_link = dxp->dx_nodes;
56*1a7c1b72Smws 	dxp->dx_nodes = enp;
57*1a7c1b72Smws 
58*1a7c1b72Smws 	if ((mnp = dt_node_xalloc(dtp, DT_NODE_MEMBER)) == NULL)
59*1a7c1b72Smws 		return (dt_set_errno(dtp, EDT_NOMEM));
60*1a7c1b72Smws 
61*1a7c1b72Smws 	mnp->dn_link = dxp->dx_nodes;
62*1a7c1b72Smws 	dxp->dx_nodes = mnp;
63*1a7c1b72Smws 
64*1a7c1b72Smws 	/*
65*1a7c1b72Smws 	 * For the member expression, we use a DT_NODE_XLATOR/TOK_XLATE whose
66*1a7c1b72Smws 	 * xlator refers back to the translator and whose dn_xmember refers to
67*1a7c1b72Smws 	 * the current member.  These refs will be used by dt_cg.c and dt_as.c.
68*1a7c1b72Smws 	 */
69*1a7c1b72Smws 	enp->dn_op = DT_TOK_XLATE;
70*1a7c1b72Smws 	enp->dn_xlator = dxp;
71*1a7c1b72Smws 	enp->dn_xmember = mnp;
72*1a7c1b72Smws 	dt_node_type_assign(enp, dxp->dx_dst_ctfp, type);
73*1a7c1b72Smws 
74*1a7c1b72Smws 	/*
75*1a7c1b72Smws 	 * For the member itself, we use a DT_NODE_MEMBER as usual with the
76*1a7c1b72Smws 	 * appropriate name, output type, and member expression set to 'enp'.
77*1a7c1b72Smws 	 */
78*1a7c1b72Smws 	if (dxp->dx_members != NULL) {
79*1a7c1b72Smws 		assert(enp->dn_link->dn_kind == DT_NODE_MEMBER);
80*1a7c1b72Smws 		enp->dn_link->dn_list = mnp;
81*1a7c1b72Smws 	} else
82*1a7c1b72Smws 		dxp->dx_members = mnp;
83*1a7c1b72Smws 
84*1a7c1b72Smws 	mnp->dn_membname = strdup(name);
85*1a7c1b72Smws 	mnp->dn_membexpr = enp;
86*1a7c1b72Smws 	dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type);
87*1a7c1b72Smws 
88*1a7c1b72Smws 	if (mnp->dn_membname == NULL)
89*1a7c1b72Smws 		return (dt_set_errno(dtp, EDT_NOMEM));
90*1a7c1b72Smws 
91*1a7c1b72Smws 	return (0);
92*1a7c1b72Smws }
93*1a7c1b72Smws 
947c478bd9Sstevel@tonic-gate dt_xlator_t *
957c478bd9Sstevel@tonic-gate dt_xlator_create(dtrace_hdl_t *dtp,
967c478bd9Sstevel@tonic-gate     const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst,
977c478bd9Sstevel@tonic-gate     const char *name, dt_node_t *members, dt_node_t *nodes)
987c478bd9Sstevel@tonic-gate {
99*1a7c1b72Smws 	dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t));
1007c478bd9Sstevel@tonic-gate 	dtrace_typeinfo_t ptr = *dst;
101*1a7c1b72Smws 	dt_xlator_t **map;
102*1a7c1b72Smws 	dt_node_t *dnp;
103*1a7c1b72Smws 	uint_t kind;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	if (dxp == NULL)
1067c478bd9Sstevel@tonic-gate 		return (NULL);
1077c478bd9Sstevel@tonic-gate 
108*1a7c1b72Smws 	dxp->dx_hdl = dtp;
109*1a7c1b72Smws 	dxp->dx_id = dtp->dt_xlatorid++;
110*1a7c1b72Smws 	dxp->dx_gen = dtp->dt_gen;
111*1a7c1b72Smws 	dxp->dx_arg = -1;
112*1a7c1b72Smws 
113*1a7c1b72Smws 	if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) {
114*1a7c1b72Smws 		dt_free(dtp, dxp);
115*1a7c1b72Smws 		return (NULL);
1167c478bd9Sstevel@tonic-gate 	}
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	dt_list_append(&dtp->dt_xlators, dxp);
119*1a7c1b72Smws 	bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id);
120*1a7c1b72Smws 	dt_free(dtp, dtp->dt_xlatormap);
121*1a7c1b72Smws 	dtp->dt_xlatormap = map;
122*1a7c1b72Smws 	dtp->dt_xlatormap[dxp->dx_id] = dxp;
1237c478bd9Sstevel@tonic-gate 
124*1a7c1b72Smws 	if (dt_type_pointer(&ptr) == -1) {
125*1a7c1b72Smws 		ptr.dtt_ctfp = NULL;
126*1a7c1b72Smws 		ptr.dtt_type = CTF_ERR;
127*1a7c1b72Smws 	}
1287c478bd9Sstevel@tonic-gate 
129*1a7c1b72Smws 	dxp->dx_ident = dt_ident_create(name ? name : "T",
130*1a7c1b72Smws 	    DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0,
131*1a7c1b72Smws 	    _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	if (dxp->dx_ident == NULL)
1347c478bd9Sstevel@tonic-gate 		goto err; /* no memory for identifier */
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	dxp->dx_ident->di_ctfp = src->dtt_ctfp;
1377c478bd9Sstevel@tonic-gate 	dxp->dx_ident->di_type = src->dtt_type;
1387c478bd9Sstevel@tonic-gate 
139*1a7c1b72Smws 	/*
140*1a7c1b72Smws 	 * If an input parameter name is given, this is a static translator
141*1a7c1b72Smws 	 * definition: create an idhash and identifier for the parameter.
142*1a7c1b72Smws 	 */
143*1a7c1b72Smws 	if (name != NULL) {
144*1a7c1b72Smws 		dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0);
145*1a7c1b72Smws 
146*1a7c1b72Smws 		if (dxp->dx_locals == NULL)
147*1a7c1b72Smws 			goto err; /* no memory for identifier hash */
148*1a7c1b72Smws 
149*1a7c1b72Smws 		dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident);
150*1a7c1b72Smws 	}
151*1a7c1b72Smws 
1527c478bd9Sstevel@tonic-gate 	dxp->dx_souid.di_name = "translator";
1537c478bd9Sstevel@tonic-gate 	dxp->dx_souid.di_kind = DT_IDENT_XLSOU;
1547c478bd9Sstevel@tonic-gate 	dxp->dx_souid.di_flags = DT_IDFLG_REF;
155*1a7c1b72Smws 	dxp->dx_souid.di_id = dxp->dx_id;
1567c478bd9Sstevel@tonic-gate 	dxp->dx_souid.di_attr = _dtrace_defattr;
1577c478bd9Sstevel@tonic-gate 	dxp->dx_souid.di_ops = &dt_idops_thaw;
1587c478bd9Sstevel@tonic-gate 	dxp->dx_souid.di_data = dxp;
1597c478bd9Sstevel@tonic-gate 	dxp->dx_souid.di_ctfp = dst->dtt_ctfp;
1607c478bd9Sstevel@tonic-gate 	dxp->dx_souid.di_type = dst->dtt_type;
1617c478bd9Sstevel@tonic-gate 	dxp->dx_souid.di_gen = dtp->dt_gen;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	dxp->dx_ptrid.di_name = "translator";
1647c478bd9Sstevel@tonic-gate 	dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR;
1657c478bd9Sstevel@tonic-gate 	dxp->dx_ptrid.di_flags = DT_IDFLG_REF;
166*1a7c1b72Smws 	dxp->dx_ptrid.di_id = dxp->dx_id;
1677c478bd9Sstevel@tonic-gate 	dxp->dx_ptrid.di_attr = _dtrace_defattr;
1687c478bd9Sstevel@tonic-gate 	dxp->dx_ptrid.di_ops = &dt_idops_thaw;
1697c478bd9Sstevel@tonic-gate 	dxp->dx_ptrid.di_data = dxp;
1707c478bd9Sstevel@tonic-gate 	dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp;
1717c478bd9Sstevel@tonic-gate 	dxp->dx_ptrid.di_type = ptr.dtt_type;
1727c478bd9Sstevel@tonic-gate 	dxp->dx_ptrid.di_gen = dtp->dt_gen;
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	/*
1757c478bd9Sstevel@tonic-gate 	 * If a deferred pragma is pending on the keyword "translator", run all
1767c478bd9Sstevel@tonic-gate 	 * the deferred pragmas on dx_souid and then copy results to dx_ptrid.
1777c478bd9Sstevel@tonic-gate 	 * See the code in dt_pragma.c for details on deferred ident pragmas.
1787c478bd9Sstevel@tonic-gate 	 */
1797c478bd9Sstevel@tonic-gate 	if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL &&
1807c478bd9Sstevel@tonic-gate 	    dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) {
1817c478bd9Sstevel@tonic-gate 		dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid);
1827c478bd9Sstevel@tonic-gate 		dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr;
1837c478bd9Sstevel@tonic-gate 		dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers;
1847c478bd9Sstevel@tonic-gate 	}
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	dxp->dx_src_ctfp = src->dtt_ctfp;
1877c478bd9Sstevel@tonic-gate 	dxp->dx_src_type = src->dtt_type;
1887c478bd9Sstevel@tonic-gate 	dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type);
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	dxp->dx_dst_ctfp = dst->dtt_ctfp;
1917c478bd9Sstevel@tonic-gate 	dxp->dx_dst_type = dst->dtt_type;
1927c478bd9Sstevel@tonic-gate 	dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type);
1937c478bd9Sstevel@tonic-gate 
194*1a7c1b72Smws 	kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base);
195*1a7c1b72Smws 	assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION);
196*1a7c1b72Smws 
197*1a7c1b72Smws 	/*
198*1a7c1b72Smws 	 * If no input parameter is given, we're making a dynamic translator:
199*1a7c1b72Smws 	 * create member nodes for every member of the output type.  Otherwise
200*1a7c1b72Smws 	 * retain the member and allocation node lists presented by the parser.
201*1a7c1b72Smws 	 */
202*1a7c1b72Smws 	if (name == NULL) {
203*1a7c1b72Smws 		if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base,
204*1a7c1b72Smws 		    dt_xlator_create_member, dxp) != 0)
205*1a7c1b72Smws 			goto err;
206*1a7c1b72Smws 	} else {
207*1a7c1b72Smws 		dxp->dx_members = members;
208*1a7c1b72Smws 		dxp->dx_nodes = nodes;
209*1a7c1b72Smws 	}
210*1a7c1b72Smws 
211*1a7c1b72Smws 	/*
212*1a7c1b72Smws 	 * Assign member IDs to each member and allocate space for DIFOs
213*1a7c1b72Smws 	 * if and when this translator is eventually compiled.
214*1a7c1b72Smws 	 */
215*1a7c1b72Smws 	for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
216*1a7c1b72Smws 		dnp->dn_membxlator = dxp;
217*1a7c1b72Smws 		dnp->dn_membid = dxp->dx_nmembers++;
218*1a7c1b72Smws 	}
219*1a7c1b72Smws 
220*1a7c1b72Smws 	dxp->dx_membdif = dt_zalloc(dtp,
221*1a7c1b72Smws 	    sizeof (dtrace_difo_t *) * dxp->dx_nmembers);
222*1a7c1b72Smws 
223*1a7c1b72Smws 	if (dxp->dx_membdif == NULL) {
224*1a7c1b72Smws 		dxp->dx_nmembers = 0;
225*1a7c1b72Smws 		goto err;
226*1a7c1b72Smws 	}
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	return (dxp);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate err:
2317c478bd9Sstevel@tonic-gate 	dt_xlator_destroy(dtp, dxp);
2327c478bd9Sstevel@tonic-gate 	return (NULL);
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate void
2367c478bd9Sstevel@tonic-gate dt_xlator_destroy(dtrace_hdl_t *dtp, dt_xlator_t *dxp)
2377c478bd9Sstevel@tonic-gate {
238*1a7c1b72Smws 	uint_t i;
239*1a7c1b72Smws 
2407c478bd9Sstevel@tonic-gate 	dt_node_link_free(&dxp->dx_nodes);
241*1a7c1b72Smws 
242*1a7c1b72Smws 	if (dxp->dx_locals != NULL)
243*1a7c1b72Smws 		dt_idhash_destroy(dxp->dx_locals);
244*1a7c1b72Smws 	else if (dxp->dx_ident != NULL)
245*1a7c1b72Smws 		dt_ident_destroy(dxp->dx_ident);
246*1a7c1b72Smws 
247*1a7c1b72Smws 	for (i = 0; i < dxp->dx_nmembers; i++)
248*1a7c1b72Smws 		dt_difo_free(dtp, dxp->dx_membdif[i]);
249*1a7c1b72Smws 
250*1a7c1b72Smws 	dt_free(dtp, dxp->dx_membdif);
2517c478bd9Sstevel@tonic-gate 	dt_list_delete(&dtp->dt_xlators, dxp);
252*1a7c1b72Smws 	dt_free(dtp, dxp);
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate dt_xlator_t *
256*1a7c1b72Smws dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
2577c478bd9Sstevel@tonic-gate {
2587c478bd9Sstevel@tonic-gate 	ctf_file_t *src_ctfp = src->dn_ctfp;
2597c478bd9Sstevel@tonic-gate 	ctf_id_t src_type = src->dn_type;
2607c478bd9Sstevel@tonic-gate 	ctf_id_t src_base = ctf_type_resolve(src_ctfp, src_type);
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	ctf_file_t *dst_ctfp = dst->dn_ctfp;
2637c478bd9Sstevel@tonic-gate 	ctf_id_t dst_type = dst->dn_type;
2647c478bd9Sstevel@tonic-gate 	ctf_id_t dst_base = ctf_type_resolve(dst_ctfp, dst_type);
265*1a7c1b72Smws 	uint_t dst_kind = ctf_type_kind(dst_ctfp, dst_base);
2667c478bd9Sstevel@tonic-gate 
267*1a7c1b72Smws 	int ptr = dst_kind == CTF_K_POINTER;
268*1a7c1b72Smws 	dtrace_typeinfo_t src_dtt, dst_dtt;
2697c478bd9Sstevel@tonic-gate 	dt_node_t xn = { 0 };
270*1a7c1b72Smws 	dt_xlator_t *dxp = NULL;
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	if (src_base == CTF_ERR || dst_base == CTF_ERR)
2737c478bd9Sstevel@tonic-gate 		return (NULL); /* fail if these are unresolvable types */
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	/*
2767c478bd9Sstevel@tonic-gate 	 * Translators are always defined using a struct or union type, so if
2777c478bd9Sstevel@tonic-gate 	 * we are attempting to translate to type "T *", we internally look
2787c478bd9Sstevel@tonic-gate 	 * for a translation to type "T" by following the pointer reference.
2797c478bd9Sstevel@tonic-gate 	 */
2807c478bd9Sstevel@tonic-gate 	if (ptr) {
2817c478bd9Sstevel@tonic-gate 		dst_type = ctf_type_reference(dst_ctfp, dst_type);
2827c478bd9Sstevel@tonic-gate 		dst_base = ctf_type_resolve(dst_ctfp, dst_type);
283*1a7c1b72Smws 		dst_kind = ctf_type_kind(dst_ctfp, dst_base);
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate 
286*1a7c1b72Smws 	if (dst_kind != CTF_K_UNION && dst_kind != CTF_K_STRUCT)
287*1a7c1b72Smws 		return (NULL); /* fail if the output isn't a struct or union */
288*1a7c1b72Smws 
2897c478bd9Sstevel@tonic-gate 	/*
2907c478bd9Sstevel@tonic-gate 	 * In order to find a matching translator, we iterate over the set of
2917c478bd9Sstevel@tonic-gate 	 * available translators in three passes.  First, we look for a
2927c478bd9Sstevel@tonic-gate 	 * translation from the exact source type to the resolved destination.
2937c478bd9Sstevel@tonic-gate 	 * Second, we look for a translation from the resolved source type to
2947c478bd9Sstevel@tonic-gate 	 * the resolved destination.  Third, we look for a translation from a
2957c478bd9Sstevel@tonic-gate 	 * compatible source type (using the same rules as parameter formals)
2967c478bd9Sstevel@tonic-gate 	 * to the resolved destination.  If all passes fail, return NULL.
2977c478bd9Sstevel@tonic-gate 	 */
2987c478bd9Sstevel@tonic-gate 	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
2997c478bd9Sstevel@tonic-gate 	    dxp = dt_list_next(dxp)) {
3007c478bd9Sstevel@tonic-gate 		if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_type,
3017c478bd9Sstevel@tonic-gate 		    src_ctfp, src_type) &&
3027c478bd9Sstevel@tonic-gate 		    ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
3037c478bd9Sstevel@tonic-gate 		    dst_ctfp, dst_base))
3047c478bd9Sstevel@tonic-gate 			goto out;
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 
307*1a7c1b72Smws 	if (flags & DT_XLATE_EXACT)
3087c478bd9Sstevel@tonic-gate 		goto out; /* skip remaining passes if exact match required */
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
3117c478bd9Sstevel@tonic-gate 	    dxp = dt_list_next(dxp)) {
3127c478bd9Sstevel@tonic-gate 		if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_base,
3137c478bd9Sstevel@tonic-gate 		    src_ctfp, src_type) &&
3147c478bd9Sstevel@tonic-gate 		    ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
3157c478bd9Sstevel@tonic-gate 		    dst_ctfp, dst_base))
3167c478bd9Sstevel@tonic-gate 			goto out;
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
3207c478bd9Sstevel@tonic-gate 	    dxp = dt_list_next(dxp)) {
3217c478bd9Sstevel@tonic-gate 		dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type);
3227c478bd9Sstevel@tonic-gate 		if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
3237c478bd9Sstevel@tonic-gate 		    dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
3247c478bd9Sstevel@tonic-gate 			goto out;
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate out:
3287c478bd9Sstevel@tonic-gate 	if (ptr && dxp != NULL && dxp->dx_ptrid.di_type == CTF_ERR)
329*1a7c1b72Smws 		return (NULL);	/* no translation available to pointer type */
3307c478bd9Sstevel@tonic-gate 
331*1a7c1b72Smws 	if (dxp != NULL || !(flags & DT_XLATE_EXTERN) ||
332*1a7c1b72Smws 	    dtp->dt_xlatemode == DT_XL_STATIC)
333*1a7c1b72Smws 		return (dxp);	/* we succeeded or not allowed to extern */
334*1a7c1b72Smws 
335*1a7c1b72Smws 	/*
336*1a7c1b72Smws 	 * If we get here, then we didn't find an existing translator, but the
337*1a7c1b72Smws 	 * caller and xlatemode permit us to create an extern to a dynamic one.
338*1a7c1b72Smws 	 */
339*1a7c1b72Smws 	src_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, src_ctfp)->dm_name;
340*1a7c1b72Smws 	src_dtt.dtt_ctfp = src_ctfp;
341*1a7c1b72Smws 	src_dtt.dtt_type = src_type;
342*1a7c1b72Smws 
343*1a7c1b72Smws 	dst_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, dst_ctfp)->dm_name;
344*1a7c1b72Smws 	dst_dtt.dtt_ctfp = dst_ctfp;
345*1a7c1b72Smws 	dst_dtt.dtt_type = dst_type;
346*1a7c1b72Smws 
347*1a7c1b72Smws 	return (dt_xlator_create(dtp, &src_dtt, &dst_dtt, NULL, NULL, NULL));
348*1a7c1b72Smws }
349*1a7c1b72Smws 
350*1a7c1b72Smws dt_xlator_t *
351*1a7c1b72Smws dt_xlator_lookup_id(dtrace_hdl_t *dtp, id_t id)
352*1a7c1b72Smws {
353*1a7c1b72Smws 	assert(id >= 0 && id < dtp->dt_xlatorid);
354*1a7c1b72Smws 	return (dtp->dt_xlatormap[id]);
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate dt_ident_t *
3587c478bd9Sstevel@tonic-gate dt_xlator_ident(dt_xlator_t *dxp, ctf_file_t *ctfp, ctf_id_t type)
3597c478bd9Sstevel@tonic-gate {
3607c478bd9Sstevel@tonic-gate 	if (ctf_type_kind(ctfp, ctf_type_resolve(ctfp, type)) == CTF_K_POINTER)
3617c478bd9Sstevel@tonic-gate 		return (&dxp->dx_ptrid);
3627c478bd9Sstevel@tonic-gate 	else
3637c478bd9Sstevel@tonic-gate 		return (&dxp->dx_souid);
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate dt_node_t *
3677c478bd9Sstevel@tonic-gate dt_xlator_member(dt_xlator_t *dxp, const char *name)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate 	dt_node_t *dnp;
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
3727c478bd9Sstevel@tonic-gate 		if (strcmp(dnp->dn_membname, name) == 0)
3737c478bd9Sstevel@tonic-gate 			return (dnp);
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	return (NULL);
3777c478bd9Sstevel@tonic-gate }
378*1a7c1b72Smws 
379*1a7c1b72Smws int
380*1a7c1b72Smws dt_xlator_dynamic(const dt_xlator_t *dxp)
381*1a7c1b72Smws {
382*1a7c1b72Smws 	return (dxp->dx_locals == NULL);
383*1a7c1b72Smws }
384