dt_xlator.c revision 303975
129415Sjmg/* 2119853Scg * CDDL HEADER START 339899Sluigi * 429415Sjmg * The contents of this file are subject to the terms of the 529415Sjmg * Common Development and Distribution License, Version 1.0 only 629415Sjmg * (the "License"). You may not use this file except in compliance 729415Sjmg * with the License. 850723Scg * 950723Scg * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1029415Sjmg * or http://www.opensolaris.org/os/licensing. 1129415Sjmg * See the License for the specific language governing permissions 1230869Sjmg * and limitations under the License. 1330869Sjmg * 1430869Sjmg * When distributing Covered Code, include this CDDL HEADER in each 1530869Sjmg * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1650723Scg * If applicable, add the following below this CDDL HEADER, with the 1750723Scg * fields enclosed by brackets "[]" replaced with your own identifying 1830869Sjmg * information: Portions Copyright [yyyy] [name of copyright owner] 1950723Scg * 2050723Scg * CDDL HEADER END 2150723Scg */ 2250723Scg/* 2350723Scg * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 2450723Scg * Use is subject to license terms. 2550723Scg */ 2650723Scg/* 2750723Scg * Copyright (c) 2013 by Delphix. All rights reserved. 2850723Scg * Copyright (c) 2013 Joyent, Inc. All rights reserved. 2950723Scg */ 3029415Sjmg 3129415Sjmg#include <strings.h> 3253465Scg#include <assert.h> 3329415Sjmg 3453465Scg#include <dt_xlator.h> 3553553Stanimura#include <dt_parser.h> 3629415Sjmg#include <dt_grammar.h> 37110499Snyan#include <dt_module.h> 38110499Snyan#include <dt_impl.h> 3970134Scg 4070134Scg/* 4182180Scg * Create a member node corresponding to one of the output members of a dynamic 4282180Scg * translator. We set the member's dn_membexpr to a DT_NODE_XLATOR node that 4367803Scg * has dn_op set to DT_TOK_XLATE and refers back to the translator itself. The 4455706Scg * code generator will then use this as the indicator for dynamic translation. 4555254Scg */ 4667803Scg/*ARGSUSED*/ 4750723Scgstatic int 4850723Scgdt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg) 4964881Scg{ 5050723Scg dt_xlator_t *dxp = arg; 5174763Scg dtrace_hdl_t *dtp = dxp->dx_hdl; 5229415Sjmg dt_node_t *enp, *mnp; 5367803Scg 5464881Scg if ((enp = dt_node_xalloc(dtp, DT_NODE_XLATOR)) == NULL) 5550723Scg return (dt_set_errno(dtp, EDT_NOMEM)); 5664881Scg 5750723Scg enp->dn_link = dxp->dx_nodes; 5874763Scg dxp->dx_nodes = enp; 5929415Sjmg 6064881Scg if ((mnp = dt_node_xalloc(dtp, DT_NODE_MEMBER)) == NULL) 6164881Scg return (dt_set_errno(dtp, EDT_NOMEM)); 6264881Scg 6364881Scg mnp->dn_link = dxp->dx_nodes; 6464881Scg dxp->dx_nodes = mnp; 6564881Scg 6654462Scg /* 6774763Scg * For the member expression, we use a DT_NODE_XLATOR/TOK_XLATE whose 6854462Scg * xlator refers back to the translator and whose dn_xmember refers to 6950723Scg * the current member. These refs will be used by dt_cg.c and dt_as.c. 7029415Sjmg */ 7150723Scg enp->dn_op = DT_TOK_XLATE; 7250723Scg enp->dn_xlator = dxp; 7374763Scg enp->dn_xmember = mnp; 7474763Scg dt_node_type_assign(enp, dxp->dx_dst_ctfp, type, B_FALSE); 7567803Scg 7667803Scg /* 7750723Scg * For the member itself, we use a DT_NODE_MEMBER as usual with the 7829415Sjmg * appropriate name, output type, and member expression set to 'enp'. 7950723Scg */ 8050723Scg if (dxp->dx_members != NULL) { 8150723Scg assert(enp->dn_link->dn_kind == DT_NODE_MEMBER); 8254462Scg enp->dn_link->dn_list = mnp; 8354462Scg } else 8465644Scg dxp->dx_members = mnp; 8555706Scg 8629415Sjmg mnp->dn_membname = strdup(name); 8784111Scg mnp->dn_membexpr = enp; 8850723Scg dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type, B_FALSE); 8950723Scg 9070291Scg if (mnp->dn_membname == NULL) 9150723Scg return (dt_set_errno(dtp, EDT_NOMEM)); 9274763Scg 9350723Scg return (0); 9450723Scg} 9584111Scg 9674763Scgdt_xlator_t * 9774763Scgdt_xlator_create(dtrace_hdl_t *dtp, 9850723Scg const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst, 9950723Scg const char *name, dt_node_t *members, dt_node_t *nodes) 10050723Scg{ 10167803Scg dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t)); 10250723Scg dtrace_typeinfo_t ptr = *dst; 10350723Scg dt_xlator_t **map; 10450723Scg dt_node_t *dnp; 10550723Scg uint_t kind; 10654462Scg 10729415Sjmg if (dxp == NULL) 10850723Scg return (NULL); 10984111Scg 11050723Scg dxp->dx_hdl = dtp; 11129415Sjmg dxp->dx_id = dtp->dt_xlatorid++; 11250723Scg dxp->dx_gen = dtp->dt_gen; 11329415Sjmg dxp->dx_arg = -1; 11450723Scg 11550723Scg if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) { 11650723Scg dt_free(dtp, dxp); 11750723Scg return (NULL); 11829415Sjmg } 11929415Sjmg 12084111Scg dt_list_append(&dtp->dt_xlators, dxp); 12184111Scg bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id); 12284111Scg dt_free(dtp, dtp->dt_xlatormap); 12384111Scg dtp->dt_xlatormap = map; 12484111Scg dtp->dt_xlatormap[dxp->dx_id] = dxp; 12584111Scg 12684111Scg if (dt_type_pointer(&ptr) == -1) { 127129180Struckman ptr.dtt_ctfp = NULL; 128129180Struckman ptr.dtt_type = CTF_ERR; 129129180Struckman } 130129180Struckman 131129180Struckman dxp->dx_ident = dt_ident_create(name ? name : "T", 132129180Struckman DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0, 13384111Scg _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen); 13484111Scg 13584111Scg if (dxp->dx_ident == NULL) 13684111Scg goto err; /* no memory for identifier */ 13784111Scg 13829415Sjmg dxp->dx_ident->di_ctfp = src->dtt_ctfp; 13950723Scg dxp->dx_ident->di_type = src->dtt_type; 14029415Sjmg 14167803Scg /* 14250723Scg * If an input parameter name is given, this is a static translator 14329415Sjmg * definition: create an idhash and identifier for the parameter. 14450723Scg */ 14550723Scg if (name != NULL) { 14650723Scg dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0); 147108064Ssemenu 14829415Sjmg if (dxp->dx_locals == NULL) 14929415Sjmg goto err; /* no memory for identifier hash */ 15029415Sjmg 15150723Scg dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident); 15229415Sjmg } 15350723Scg 15450723Scg dxp->dx_souid.di_name = "translator"; 15529415Sjmg dxp->dx_souid.di_kind = DT_IDENT_XLSOU; 15650723Scg dxp->dx_souid.di_flags = DT_IDFLG_REF; 15750723Scg dxp->dx_souid.di_id = dxp->dx_id; 15850723Scg dxp->dx_souid.di_attr = _dtrace_defattr; 15950723Scg dxp->dx_souid.di_ops = &dt_idops_thaw; 16029415Sjmg dxp->dx_souid.di_data = dxp; 16129415Sjmg dxp->dx_souid.di_ctfp = dst->dtt_ctfp; 16250723Scg dxp->dx_souid.di_type = dst->dtt_type; 16350723Scg dxp->dx_souid.di_gen = dtp->dt_gen; 16429415Sjmg 16550723Scg dxp->dx_ptrid.di_name = "translator"; 16629415Sjmg dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR; 16750723Scg dxp->dx_ptrid.di_flags = DT_IDFLG_REF; 16870134Scg dxp->dx_ptrid.di_id = dxp->dx_id; 16970134Scg dxp->dx_ptrid.di_attr = _dtrace_defattr; 17070134Scg dxp->dx_ptrid.di_ops = &dt_idops_thaw; 17170134Scg dxp->dx_ptrid.di_data = dxp; 17270134Scg dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp; 17350723Scg dxp->dx_ptrid.di_type = ptr.dtt_type; 17450723Scg dxp->dx_ptrid.di_gen = dtp->dt_gen; 17579116Sgreen 17683366Sjulian /* 17774797Scg * If a deferred pragma is pending on the keyword "translator", run all 17879090Sgreen * the deferred pragmas on dx_souid and then copy results to dx_ptrid. 17950723Scg * See the code in dt_pragma.c for details on deferred ident pragmas. 18050723Scg */ 18129415Sjmg if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL && 18250723Scg dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) { 18350723Scg dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid); 18450723Scg dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr; 18550723Scg dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers; 18650723Scg } 18750723Scg 18850723Scg dxp->dx_src_ctfp = src->dtt_ctfp; 18950723Scg dxp->dx_src_type = src->dtt_type; 19029415Sjmg dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type); 19167803Scg 19250723Scg dxp->dx_dst_ctfp = dst->dtt_ctfp; 19350723Scg dxp->dx_dst_type = dst->dtt_type; 19450723Scg dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type); 19550723Scg 19650723Scg kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base); 19750723Scg assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION); 19850723Scg 19950723Scg /* 20050723Scg * If no input parameter is given, we're making a dynamic translator: 20150723Scg * create member nodes for every member of the output type. Otherwise 20267803Scg * retain the member and allocation node lists presented by the parser. 20329415Sjmg */ 20450723Scg if (name == NULL) { 20550723Scg if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base, 20650723Scg dt_xlator_create_member, dxp) != 0) 20784111Scg goto err; 20884111Scg } else { 20950723Scg dxp->dx_members = members; 21050723Scg dxp->dx_nodes = nodes; 21150723Scg } 21284111Scg 21384111Scg /* 21450723Scg * Assign member IDs to each member and allocate space for DIFOs 21584111Scg * if and when this translator is eventually compiled. 21684111Scg */ 21784111Scg for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) { 21884111Scg dnp->dn_membxlator = dxp; 21984111Scg dnp->dn_membid = dxp->dx_nmembers++; 22084111Scg } 22184111Scg 22284111Scg dxp->dx_membdif = dt_zalloc(dtp, 22384111Scg sizeof (dtrace_difo_t *) * dxp->dx_nmembers); 22450723Scg 22529415Sjmg if (dxp->dx_membdif == NULL) { 22650723Scg dxp->dx_nmembers = 0; 22750723Scg goto err; 22850723Scg } 22950723Scg 23050723Scg return (dxp); 23150723Scg 23250723Scgerr: 23374763Scg dt_xlator_destroy(dtp, dxp); 23450723Scg return (NULL); 23550723Scg} 23650723Scg 23750723Scgvoid 23874763Scgdt_xlator_destroy(dtrace_hdl_t *dtp, dt_xlator_t *dxp) 23950723Scg{ 24031361Sjmg uint_t i; 24150723Scg 24250723Scg dt_node_link_free(&dxp->dx_nodes); 24350723Scg 24450723Scg if (dxp->dx_locals != NULL) 24529415Sjmg dt_idhash_destroy(dxp->dx_locals); 24674763Scg else if (dxp->dx_ident != NULL) 24750723Scg dt_ident_destroy(dxp->dx_ident); 24850723Scg 24950723Scg for (i = 0; i < dxp->dx_nmembers; i++) 25050723Scg dt_difo_free(dtp, dxp->dx_membdif[i]); 25174763Scg 25229415Sjmg dt_free(dtp, dxp->dx_membdif); 25350723Scg dt_list_delete(&dtp->dt_xlators, dxp); 25450723Scg dt_free(dtp, dxp); 25529415Sjmg} 25650723Scg 25750723Scgdt_xlator_t * 25850723Scgdt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags) 25950723Scg{ 26029415Sjmg ctf_file_t *src_ctfp = src->dn_ctfp; 26150723Scg ctf_id_t src_type = src->dn_type; 26250723Scg ctf_id_t src_base = ctf_type_resolve(src_ctfp, src_type); 26350723Scg 26450723Scg ctf_file_t *dst_ctfp = dst->dn_ctfp; 26550723Scg ctf_id_t dst_type = dst->dn_type; 26650723Scg ctf_id_t dst_base = ctf_type_resolve(dst_ctfp, dst_type); 26750723Scg uint_t dst_kind = ctf_type_kind(dst_ctfp, dst_base); 26850723Scg 26929415Sjmg int ptr = dst_kind == CTF_K_POINTER; 27050723Scg dtrace_typeinfo_t src_dtt, dst_dtt; 27150723Scg dt_node_t xn = { 0 }; 27229415Sjmg dt_xlator_t *dxp = NULL; 27374763Scg 27474763Scg if (src_base == CTF_ERR || dst_base == CTF_ERR) 275129180Struckman return (NULL); /* fail if these are unresolvable types */ 27650723Scg 27750723Scg /* 27850723Scg * Translators are always defined using a struct or union type, so if 27974763Scg * we are attempting to translate to type "T *", we internally look 28074763Scg * for a translation to type "T" by following the pointer reference. 28150723Scg */ 28289774Sscottl if (ptr) { 28350723Scg dst_type = ctf_type_reference(dst_ctfp, dst_type); 28450723Scg dst_base = ctf_type_resolve(dst_ctfp, dst_type); 28550723Scg dst_kind = ctf_type_kind(dst_ctfp, dst_base); 28629415Sjmg } 28729415Sjmg 28867803Scg if (dst_kind != CTF_K_UNION && dst_kind != CTF_K_STRUCT) 28967803Scg return (NULL); /* fail if the output isn't a struct or union */ 29067803Scg 29167803Scg /* 29267803Scg * In order to find a matching translator, we iterate over the set of 29367803Scg * available translators in three passes. First, we look for a 29467803Scg * translation from the exact source type to the resolved destination. 29567803Scg * Second, we look for a translation from the resolved source type to 29667803Scg * the resolved destination. Third, we look for a translation from a 29767803Scg * compatible source type (using the same rules as parameter formals) 29867803Scg * to the resolved destination. If all passes fail, return NULL. 29967803Scg */ 30067803Scg for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL; 30167803Scg dxp = dt_list_next(dxp)) { 30267803Scg if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_type, 30367803Scg src_ctfp, src_type) && 30467803Scg ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base, 30567803Scg dst_ctfp, dst_base)) 30667803Scg goto out; 30767803Scg } 30867803Scg 309100953Ssobomax if (flags & DT_XLATE_EXACT) 31067803Scg goto out; /* skip remaining passes if exact match required */ 31167803Scg 31267803Scg for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL; 31374763Scg dxp = dt_list_next(dxp)) { 31467803Scg if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_base, 31567803Scg src_ctfp, src_type) && 31667803Scg ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base, 31767803Scg dst_ctfp, dst_base)) 31867803Scg goto out; 319100953Ssobomax } 32067803Scg 32167803Scg for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL; 32267803Scg dxp = dt_list_next(dxp)) { 323100953Ssobomax dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type, 32467803Scg B_FALSE); 32567803Scg if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base, 32667803Scg dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn)) 32767803Scg goto out; 32867803Scg } 32967803Scg 33067803Scgout: 33167803Scg if (ptr && dxp != NULL && dxp->dx_ptrid.di_type == CTF_ERR) 33267803Scg return (NULL); /* no translation available to pointer type */ 33367803Scg 334130472Sjosef if (dxp != NULL || !(flags & DT_XLATE_EXTERN) || 335130472Sjosef dtp->dt_xlatemode == DT_XL_STATIC) 336130472Sjosef return (dxp); /* we succeeded or not allowed to extern */ 337130472Sjosef 338130472Sjosef /* 339130472Sjosef * If we get here, then we didn't find an existing translator, but the 340130472Sjosef * caller and xlatemode permit us to create an extern to a dynamic one. 341130472Sjosef */ 342130472Sjosef src_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, src_ctfp)->dm_name; 343130472Sjosef src_dtt.dtt_ctfp = src_ctfp; 344130472Sjosef src_dtt.dtt_type = src_type; 345130472Sjosef 346130472Sjosef dst_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, dst_ctfp)->dm_name; 34774763Scg dst_dtt.dtt_ctfp = dst_ctfp; 34867803Scg dst_dtt.dtt_type = dst_type; 34967803Scg 35067803Scg return (dt_xlator_create(dtp, &src_dtt, &dst_dtt, NULL, NULL, NULL)); 35167803Scg} 35267803Scg 35367803Scgdt_xlator_t * 35467803Scgdt_xlator_lookup_id(dtrace_hdl_t *dtp, id_t id) 35567803Scg{ 356130472Sjosef assert(id >= 0 && id < dtp->dt_xlatorid); 357130472Sjosef return (dtp->dt_xlatormap[id]); 35867803Scg} 35967803Scg 36067803Scgdt_ident_t * 36168376Scgdt_xlator_ident(dt_xlator_t *dxp, ctf_file_t *ctfp, ctf_id_t type) 36267803Scg{ 36367803Scg if (ctf_type_kind(ctfp, ctf_type_resolve(ctfp, type)) == CTF_K_POINTER) 36467803Scg return (&dxp->dx_ptrid); 36567803Scg else 36667803Scg return (&dxp->dx_souid); 36767803Scg} 36867803Scg 36967803Scgdt_node_t * 37067803Scgdt_xlator_member(dt_xlator_t *dxp, const char *name) 37167803Scg{ 37274763Scg dt_node_t *dnp; 37367803Scg 37467803Scg for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) { 37567803Scg if (strcmp(dnp->dn_membname, name) == 0) 37667803Scg return (dnp); 37767803Scg } 37867803Scg 37967803Scg return (NULL); 38067803Scg} 38167803Scg 38267803Scgint 38367803Scgdt_xlator_dynamic(const dt_xlator_t *dxp) 38467803Scg{ 38567803Scg return (dxp->dx_locals == NULL); 38667803Scg} 38767803Scg