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 */
26*a386cc11SRobert Mustacchi /*
27*a386cc11SRobert Mustacchi * Copyright (c) 2013 by Delphix. All rights reserved.
28*a386cc11SRobert Mustacchi * Copyright (c) 2013 Joyent, Inc. All rights reserved.
29*a386cc11SRobert Mustacchi */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <strings.h>
321a7c1b72Smws #include <assert.h>
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #include <dt_xlator.h>
351a7c1b72Smws #include <dt_parser.h>
361a7c1b72Smws #include <dt_grammar.h>
371a7c1b72Smws #include <dt_module.h>
387c478bd9Sstevel@tonic-gate #include <dt_impl.h>
397c478bd9Sstevel@tonic-gate
401a7c1b72Smws /*
411a7c1b72Smws * Create a member node corresponding to one of the output members of a dynamic
421a7c1b72Smws * translator. We set the member's dn_membexpr to a DT_NODE_XLATOR node that
431a7c1b72Smws * has dn_op set to DT_TOK_XLATE and refers back to the translator itself. The
441a7c1b72Smws * code generator will then use this as the indicator for dynamic translation.
451a7c1b72Smws */
461a7c1b72Smws /*ARGSUSED*/
471a7c1b72Smws static int
dt_xlator_create_member(const char * name,ctf_id_t type,ulong_t off,void * arg)481a7c1b72Smws dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
491a7c1b72Smws {
501a7c1b72Smws dt_xlator_t *dxp = arg;
511a7c1b72Smws dtrace_hdl_t *dtp = dxp->dx_hdl;
521a7c1b72Smws dt_node_t *enp, *mnp;
531a7c1b72Smws
541a7c1b72Smws if ((enp = dt_node_xalloc(dtp, DT_NODE_XLATOR)) == NULL)
551a7c1b72Smws return (dt_set_errno(dtp, EDT_NOMEM));
561a7c1b72Smws
571a7c1b72Smws enp->dn_link = dxp->dx_nodes;
581a7c1b72Smws dxp->dx_nodes = enp;
591a7c1b72Smws
601a7c1b72Smws if ((mnp = dt_node_xalloc(dtp, DT_NODE_MEMBER)) == NULL)
611a7c1b72Smws return (dt_set_errno(dtp, EDT_NOMEM));
621a7c1b72Smws
631a7c1b72Smws mnp->dn_link = dxp->dx_nodes;
641a7c1b72Smws dxp->dx_nodes = mnp;
651a7c1b72Smws
661a7c1b72Smws /*
671a7c1b72Smws * For the member expression, we use a DT_NODE_XLATOR/TOK_XLATE whose
681a7c1b72Smws * xlator refers back to the translator and whose dn_xmember refers to
691a7c1b72Smws * the current member. These refs will be used by dt_cg.c and dt_as.c.
701a7c1b72Smws */
711a7c1b72Smws enp->dn_op = DT_TOK_XLATE;
721a7c1b72Smws enp->dn_xlator = dxp;
731a7c1b72Smws enp->dn_xmember = mnp;
74*a386cc11SRobert Mustacchi dt_node_type_assign(enp, dxp->dx_dst_ctfp, type, B_FALSE);
751a7c1b72Smws
761a7c1b72Smws /*
771a7c1b72Smws * For the member itself, we use a DT_NODE_MEMBER as usual with the
781a7c1b72Smws * appropriate name, output type, and member expression set to 'enp'.
791a7c1b72Smws */
801a7c1b72Smws if (dxp->dx_members != NULL) {
811a7c1b72Smws assert(enp->dn_link->dn_kind == DT_NODE_MEMBER);
821a7c1b72Smws enp->dn_link->dn_list = mnp;
831a7c1b72Smws } else
841a7c1b72Smws dxp->dx_members = mnp;
851a7c1b72Smws
861a7c1b72Smws mnp->dn_membname = strdup(name);
871a7c1b72Smws mnp->dn_membexpr = enp;
88*a386cc11SRobert Mustacchi dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type, B_FALSE);
891a7c1b72Smws
901a7c1b72Smws if (mnp->dn_membname == NULL)
911a7c1b72Smws return (dt_set_errno(dtp, EDT_NOMEM));
921a7c1b72Smws
931a7c1b72Smws return (0);
941a7c1b72Smws }
951a7c1b72Smws
967c478bd9Sstevel@tonic-gate 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)977c478bd9Sstevel@tonic-gate dt_xlator_create(dtrace_hdl_t *dtp,
987c478bd9Sstevel@tonic-gate const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst,
997c478bd9Sstevel@tonic-gate const char *name, dt_node_t *members, dt_node_t *nodes)
1007c478bd9Sstevel@tonic-gate {
1011a7c1b72Smws dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t));
1027c478bd9Sstevel@tonic-gate dtrace_typeinfo_t ptr = *dst;
1031a7c1b72Smws dt_xlator_t **map;
1041a7c1b72Smws dt_node_t *dnp;
1051a7c1b72Smws uint_t kind;
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate if (dxp == NULL)
1087c478bd9Sstevel@tonic-gate return (NULL);
1097c478bd9Sstevel@tonic-gate
1101a7c1b72Smws dxp->dx_hdl = dtp;
1111a7c1b72Smws dxp->dx_id = dtp->dt_xlatorid++;
1121a7c1b72Smws dxp->dx_gen = dtp->dt_gen;
1131a7c1b72Smws dxp->dx_arg = -1;
1141a7c1b72Smws
1151a7c1b72Smws if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) {
1161a7c1b72Smws dt_free(dtp, dxp);
1171a7c1b72Smws return (NULL);
1181a7c1b72Smws }
1191a7c1b72Smws
1201a7c1b72Smws dt_list_append(&dtp->dt_xlators, dxp);
1211a7c1b72Smws bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id);
1221a7c1b72Smws dt_free(dtp, dtp->dt_xlatormap);
1231a7c1b72Smws dtp->dt_xlatormap = map;
1241a7c1b72Smws dtp->dt_xlatormap[dxp->dx_id] = dxp;
1251a7c1b72Smws
1267c478bd9Sstevel@tonic-gate if (dt_type_pointer(&ptr) == -1) {
1277c478bd9Sstevel@tonic-gate ptr.dtt_ctfp = NULL;
1287c478bd9Sstevel@tonic-gate ptr.dtt_type = CTF_ERR;
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate
1311a7c1b72Smws dxp->dx_ident = dt_ident_create(name ? name : "T",
1321a7c1b72Smws DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0,
1331a7c1b72Smws _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate if (dxp->dx_ident == NULL)
1367c478bd9Sstevel@tonic-gate goto err; /* no memory for identifier */
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate dxp->dx_ident->di_ctfp = src->dtt_ctfp;
1397c478bd9Sstevel@tonic-gate dxp->dx_ident->di_type = src->dtt_type;
1407c478bd9Sstevel@tonic-gate
1411a7c1b72Smws /*
1421a7c1b72Smws * If an input parameter name is given, this is a static translator
1431a7c1b72Smws * definition: create an idhash and identifier for the parameter.
1441a7c1b72Smws */
1451a7c1b72Smws if (name != NULL) {
1461a7c1b72Smws dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0);
1471a7c1b72Smws
1481a7c1b72Smws if (dxp->dx_locals == NULL)
1491a7c1b72Smws goto err; /* no memory for identifier hash */
1501a7c1b72Smws
1511a7c1b72Smws dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident);
1521a7c1b72Smws }
1531a7c1b72Smws
1547c478bd9Sstevel@tonic-gate dxp->dx_souid.di_name = "translator";
1557c478bd9Sstevel@tonic-gate dxp->dx_souid.di_kind = DT_IDENT_XLSOU;
1567c478bd9Sstevel@tonic-gate dxp->dx_souid.di_flags = DT_IDFLG_REF;
1571a7c1b72Smws dxp->dx_souid.di_id = dxp->dx_id;
1587c478bd9Sstevel@tonic-gate dxp->dx_souid.di_attr = _dtrace_defattr;
1597c478bd9Sstevel@tonic-gate dxp->dx_souid.di_ops = &dt_idops_thaw;
1607c478bd9Sstevel@tonic-gate dxp->dx_souid.di_data = dxp;
1617c478bd9Sstevel@tonic-gate dxp->dx_souid.di_ctfp = dst->dtt_ctfp;
1627c478bd9Sstevel@tonic-gate dxp->dx_souid.di_type = dst->dtt_type;
1637c478bd9Sstevel@tonic-gate dxp->dx_souid.di_gen = dtp->dt_gen;
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_name = "translator";
1667c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR;
1677c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_flags = DT_IDFLG_REF;
1681a7c1b72Smws dxp->dx_ptrid.di_id = dxp->dx_id;
1697c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_attr = _dtrace_defattr;
1707c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_ops = &dt_idops_thaw;
1717c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_data = dxp;
1727c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp;
1737c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_type = ptr.dtt_type;
1747c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_gen = dtp->dt_gen;
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate /*
1777c478bd9Sstevel@tonic-gate * If a deferred pragma is pending on the keyword "translator", run all
1787c478bd9Sstevel@tonic-gate * the deferred pragmas on dx_souid and then copy results to dx_ptrid.
1797c478bd9Sstevel@tonic-gate * See the code in dt_pragma.c for details on deferred ident pragmas.
1807c478bd9Sstevel@tonic-gate */
1817c478bd9Sstevel@tonic-gate if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL &&
1827c478bd9Sstevel@tonic-gate dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) {
1837c478bd9Sstevel@tonic-gate dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid);
1847c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr;
1857c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers;
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate
1887c478bd9Sstevel@tonic-gate dxp->dx_src_ctfp = src->dtt_ctfp;
1897c478bd9Sstevel@tonic-gate dxp->dx_src_type = src->dtt_type;
1907c478bd9Sstevel@tonic-gate dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type);
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate dxp->dx_dst_ctfp = dst->dtt_ctfp;
1937c478bd9Sstevel@tonic-gate dxp->dx_dst_type = dst->dtt_type;
1947c478bd9Sstevel@tonic-gate dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type);
1957c478bd9Sstevel@tonic-gate
1961a7c1b72Smws kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base);
1971a7c1b72Smws assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION);
1981a7c1b72Smws
1991a7c1b72Smws /*
2001a7c1b72Smws * If no input parameter is given, we're making a dynamic translator:
2011a7c1b72Smws * create member nodes for every member of the output type. Otherwise
2021a7c1b72Smws * retain the member and allocation node lists presented by the parser.
2031a7c1b72Smws */
2041a7c1b72Smws if (name == NULL) {
2051a7c1b72Smws if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base,
2061a7c1b72Smws dt_xlator_create_member, dxp) != 0)
2071a7c1b72Smws goto err;
2081a7c1b72Smws } else {
2097c478bd9Sstevel@tonic-gate dxp->dx_members = members;
2107c478bd9Sstevel@tonic-gate dxp->dx_nodes = nodes;
2111a7c1b72Smws }
2121a7c1b72Smws
2131a7c1b72Smws /*
2141a7c1b72Smws * Assign member IDs to each member and allocate space for DIFOs
2151a7c1b72Smws * if and when this translator is eventually compiled.
2161a7c1b72Smws */
2171a7c1b72Smws for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
2181a7c1b72Smws dnp->dn_membxlator = dxp;
2191a7c1b72Smws dnp->dn_membid = dxp->dx_nmembers++;
2201a7c1b72Smws }
2211a7c1b72Smws
2221a7c1b72Smws dxp->dx_membdif = dt_zalloc(dtp,
2231a7c1b72Smws sizeof (dtrace_difo_t *) * dxp->dx_nmembers);
2241a7c1b72Smws
2251a7c1b72Smws if (dxp->dx_membdif == NULL) {
2261a7c1b72Smws dxp->dx_nmembers = 0;
2271a7c1b72Smws goto err;
2281a7c1b72Smws }
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate return (dxp);
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate err:
2337c478bd9Sstevel@tonic-gate dt_xlator_destroy(dtp, dxp);
2347c478bd9Sstevel@tonic-gate return (NULL);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate void
dt_xlator_destroy(dtrace_hdl_t * dtp,dt_xlator_t * dxp)2387c478bd9Sstevel@tonic-gate dt_xlator_destroy(dtrace_hdl_t *dtp, dt_xlator_t *dxp)
2397c478bd9Sstevel@tonic-gate {
2401a7c1b72Smws uint_t i;
2411a7c1b72Smws
2427c478bd9Sstevel@tonic-gate dt_node_link_free(&dxp->dx_nodes);
2431a7c1b72Smws
2441a7c1b72Smws if (dxp->dx_locals != NULL)
2457c478bd9Sstevel@tonic-gate dt_idhash_destroy(dxp->dx_locals);
2461a7c1b72Smws else if (dxp->dx_ident != NULL)
2471a7c1b72Smws dt_ident_destroy(dxp->dx_ident);
2481a7c1b72Smws
2491a7c1b72Smws for (i = 0; i < dxp->dx_nmembers; i++)
2501a7c1b72Smws dt_difo_free(dtp, dxp->dx_membdif[i]);
2511a7c1b72Smws
2521a7c1b72Smws dt_free(dtp, dxp->dx_membdif);
2537c478bd9Sstevel@tonic-gate dt_list_delete(&dtp->dt_xlators, dxp);
2541a7c1b72Smws dt_free(dtp, dxp);
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate dt_xlator_t *
dt_xlator_lookup(dtrace_hdl_t * dtp,dt_node_t * src,dt_node_t * dst,int flags)2581a7c1b72Smws dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
2597c478bd9Sstevel@tonic-gate {
2607c478bd9Sstevel@tonic-gate ctf_file_t *src_ctfp = src->dn_ctfp;
2617c478bd9Sstevel@tonic-gate ctf_id_t src_type = src->dn_type;
2627c478bd9Sstevel@tonic-gate ctf_id_t src_base = ctf_type_resolve(src_ctfp, src_type);
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate ctf_file_t *dst_ctfp = dst->dn_ctfp;
2657c478bd9Sstevel@tonic-gate ctf_id_t dst_type = dst->dn_type;
2667c478bd9Sstevel@tonic-gate ctf_id_t dst_base = ctf_type_resolve(dst_ctfp, dst_type);
2671a7c1b72Smws uint_t dst_kind = ctf_type_kind(dst_ctfp, dst_base);
2687c478bd9Sstevel@tonic-gate
2691a7c1b72Smws int ptr = dst_kind == CTF_K_POINTER;
2701a7c1b72Smws dtrace_typeinfo_t src_dtt, dst_dtt;
2717c478bd9Sstevel@tonic-gate dt_node_t xn = { 0 };
2721a7c1b72Smws dt_xlator_t *dxp = NULL;
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate if (src_base == CTF_ERR || dst_base == CTF_ERR)
2757c478bd9Sstevel@tonic-gate return (NULL); /* fail if these are unresolvable types */
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate /*
2787c478bd9Sstevel@tonic-gate * Translators are always defined using a struct or union type, so if
2797c478bd9Sstevel@tonic-gate * we are attempting to translate to type "T *", we internally look
2807c478bd9Sstevel@tonic-gate * for a translation to type "T" by following the pointer reference.
2817c478bd9Sstevel@tonic-gate */
2827c478bd9Sstevel@tonic-gate if (ptr) {
2837c478bd9Sstevel@tonic-gate dst_type = ctf_type_reference(dst_ctfp, dst_type);
2847c478bd9Sstevel@tonic-gate dst_base = ctf_type_resolve(dst_ctfp, dst_type);
2851a7c1b72Smws dst_kind = ctf_type_kind(dst_ctfp, dst_base);
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate
2881a7c1b72Smws if (dst_kind != CTF_K_UNION && dst_kind != CTF_K_STRUCT)
2891a7c1b72Smws return (NULL); /* fail if the output isn't a struct or union */
2901a7c1b72Smws
2917c478bd9Sstevel@tonic-gate /*
2927c478bd9Sstevel@tonic-gate * In order to find a matching translator, we iterate over the set of
2937c478bd9Sstevel@tonic-gate * available translators in three passes. First, we look for a
2947c478bd9Sstevel@tonic-gate * translation from the exact source type to the resolved destination.
2957c478bd9Sstevel@tonic-gate * Second, we look for a translation from the resolved source type to
2967c478bd9Sstevel@tonic-gate * the resolved destination. Third, we look for a translation from a
2977c478bd9Sstevel@tonic-gate * compatible source type (using the same rules as parameter formals)
2987c478bd9Sstevel@tonic-gate * to the resolved destination. If all passes fail, return NULL.
2997c478bd9Sstevel@tonic-gate */
3007c478bd9Sstevel@tonic-gate for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
3017c478bd9Sstevel@tonic-gate dxp = dt_list_next(dxp)) {
3027c478bd9Sstevel@tonic-gate if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_type,
3037c478bd9Sstevel@tonic-gate src_ctfp, src_type) &&
3047c478bd9Sstevel@tonic-gate ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
3057c478bd9Sstevel@tonic-gate dst_ctfp, dst_base))
3067c478bd9Sstevel@tonic-gate goto out;
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate
3091a7c1b72Smws if (flags & DT_XLATE_EXACT)
3107c478bd9Sstevel@tonic-gate goto out; /* skip remaining passes if exact match required */
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
3137c478bd9Sstevel@tonic-gate dxp = dt_list_next(dxp)) {
3147c478bd9Sstevel@tonic-gate if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_base,
3157c478bd9Sstevel@tonic-gate src_ctfp, src_type) &&
3167c478bd9Sstevel@tonic-gate ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
3177c478bd9Sstevel@tonic-gate dst_ctfp, dst_base))
3187c478bd9Sstevel@tonic-gate goto out;
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
3227c478bd9Sstevel@tonic-gate dxp = dt_list_next(dxp)) {
323*a386cc11SRobert Mustacchi dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type,
324*a386cc11SRobert Mustacchi B_FALSE);
3257c478bd9Sstevel@tonic-gate if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
3267c478bd9Sstevel@tonic-gate dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
3277c478bd9Sstevel@tonic-gate goto out;
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate out:
3317c478bd9Sstevel@tonic-gate if (ptr && dxp != NULL && dxp->dx_ptrid.di_type == CTF_ERR)
3327c478bd9Sstevel@tonic-gate return (NULL); /* no translation available to pointer type */
3337c478bd9Sstevel@tonic-gate
3341a7c1b72Smws if (dxp != NULL || !(flags & DT_XLATE_EXTERN) ||
3351a7c1b72Smws dtp->dt_xlatemode == DT_XL_STATIC)
3361a7c1b72Smws return (dxp); /* we succeeded or not allowed to extern */
3371a7c1b72Smws
3381a7c1b72Smws /*
3391a7c1b72Smws * If we get here, then we didn't find an existing translator, but the
3401a7c1b72Smws * caller and xlatemode permit us to create an extern to a dynamic one.
3411a7c1b72Smws */
3421a7c1b72Smws src_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, src_ctfp)->dm_name;
3431a7c1b72Smws src_dtt.dtt_ctfp = src_ctfp;
3441a7c1b72Smws src_dtt.dtt_type = src_type;
3451a7c1b72Smws
3461a7c1b72Smws dst_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, dst_ctfp)->dm_name;
3471a7c1b72Smws dst_dtt.dtt_ctfp = dst_ctfp;
3481a7c1b72Smws dst_dtt.dtt_type = dst_type;
3491a7c1b72Smws
3501a7c1b72Smws return (dt_xlator_create(dtp, &src_dtt, &dst_dtt, NULL, NULL, NULL));
3511a7c1b72Smws }
3521a7c1b72Smws
3531a7c1b72Smws dt_xlator_t *
dt_xlator_lookup_id(dtrace_hdl_t * dtp,id_t id)3541a7c1b72Smws dt_xlator_lookup_id(dtrace_hdl_t *dtp, id_t id)
3551a7c1b72Smws {
3561a7c1b72Smws assert(id >= 0 && id < dtp->dt_xlatorid);
3571a7c1b72Smws return (dtp->dt_xlatormap[id]);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate dt_ident_t *
dt_xlator_ident(dt_xlator_t * dxp,ctf_file_t * ctfp,ctf_id_t type)3617c478bd9Sstevel@tonic-gate dt_xlator_ident(dt_xlator_t *dxp, ctf_file_t *ctfp, ctf_id_t type)
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate if (ctf_type_kind(ctfp, ctf_type_resolve(ctfp, type)) == CTF_K_POINTER)
3647c478bd9Sstevel@tonic-gate return (&dxp->dx_ptrid);
3657c478bd9Sstevel@tonic-gate else
3667c478bd9Sstevel@tonic-gate return (&dxp->dx_souid);
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate dt_node_t *
dt_xlator_member(dt_xlator_t * dxp,const char * name)3707c478bd9Sstevel@tonic-gate dt_xlator_member(dt_xlator_t *dxp, const char *name)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate dt_node_t *dnp;
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
3757c478bd9Sstevel@tonic-gate if (strcmp(dnp->dn_membname, name) == 0)
3767c478bd9Sstevel@tonic-gate return (dnp);
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate return (NULL);
3807c478bd9Sstevel@tonic-gate }
3811a7c1b72Smws
3821a7c1b72Smws int
dt_xlator_dynamic(const dt_xlator_t * dxp)3831a7c1b72Smws dt_xlator_dynamic(const dt_xlator_t *dxp)
3841a7c1b72Smws {
3851a7c1b72Smws return (dxp->dx_locals == NULL);
3861a7c1b72Smws }
387