1178479Sjb/* 2178479Sjb * CDDL HEADER START 3178479Sjb * 4178479Sjb * The contents of this file are subject to the terms of the 5178479Sjb * Common Development and Distribution License, Version 1.0 only 6178479Sjb * (the "License"). You may not use this file except in compliance 7178479Sjb * with the License. 8178479Sjb * 9178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10178479Sjb * or http://www.opensolaris.org/os/licensing. 11178479Sjb * See the License for the specific language governing permissions 12178479Sjb * and limitations under the License. 13178479Sjb * 14178479Sjb * When distributing Covered Code, include this CDDL HEADER in each 15178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16178479Sjb * If applicable, add the following below this CDDL HEADER, with the 17178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying 18178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 19178479Sjb * 20178479Sjb * CDDL HEADER END 21178479Sjb */ 22178479Sjb/* 23178479Sjb * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24178479Sjb * Use is subject to license terms. 25178479Sjb */ 26268578Srpaulo/* 27268578Srpaulo * Copyright (c) 2013 by Delphix. All rights reserved. 28268578Srpaulo * Copyright (c) 2013 Joyent, Inc. All rights reserved. 29268578Srpaulo */ 30178479Sjb 31178479Sjb#include <strings.h> 32178479Sjb#include <assert.h> 33178479Sjb 34178479Sjb#include <dt_xlator.h> 35178479Sjb#include <dt_parser.h> 36178479Sjb#include <dt_grammar.h> 37178479Sjb#include <dt_module.h> 38178479Sjb#include <dt_impl.h> 39178479Sjb 40178479Sjb/* 41178479Sjb * Create a member node corresponding to one of the output members of a dynamic 42178479Sjb * translator. We set the member's dn_membexpr to a DT_NODE_XLATOR node that 43178479Sjb * has dn_op set to DT_TOK_XLATE and refers back to the translator itself. The 44178479Sjb * code generator will then use this as the indicator for dynamic translation. 45178479Sjb */ 46178479Sjb/*ARGSUSED*/ 47178479Sjbstatic int 48178479Sjbdt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg) 49178479Sjb{ 50178479Sjb dt_xlator_t *dxp = arg; 51178479Sjb dtrace_hdl_t *dtp = dxp->dx_hdl; 52178479Sjb dt_node_t *enp, *mnp; 53178479Sjb 54178479Sjb if ((enp = dt_node_xalloc(dtp, DT_NODE_XLATOR)) == NULL) 55178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 56178479Sjb 57178479Sjb enp->dn_link = dxp->dx_nodes; 58178479Sjb dxp->dx_nodes = enp; 59178479Sjb 60178479Sjb if ((mnp = dt_node_xalloc(dtp, DT_NODE_MEMBER)) == NULL) 61178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 62178479Sjb 63178479Sjb mnp->dn_link = dxp->dx_nodes; 64178479Sjb dxp->dx_nodes = mnp; 65178479Sjb 66178479Sjb /* 67178479Sjb * For the member expression, we use a DT_NODE_XLATOR/TOK_XLATE whose 68178479Sjb * xlator refers back to the translator and whose dn_xmember refers to 69178479Sjb * the current member. These refs will be used by dt_cg.c and dt_as.c. 70178479Sjb */ 71178479Sjb enp->dn_op = DT_TOK_XLATE; 72178479Sjb enp->dn_xlator = dxp; 73178479Sjb enp->dn_xmember = mnp; 74268578Srpaulo dt_node_type_assign(enp, dxp->dx_dst_ctfp, type, B_FALSE); 75178479Sjb 76178479Sjb /* 77178479Sjb * For the member itself, we use a DT_NODE_MEMBER as usual with the 78178479Sjb * appropriate name, output type, and member expression set to 'enp'. 79178479Sjb */ 80178479Sjb if (dxp->dx_members != NULL) { 81178479Sjb assert(enp->dn_link->dn_kind == DT_NODE_MEMBER); 82178479Sjb enp->dn_link->dn_list = mnp; 83178479Sjb } else 84178479Sjb dxp->dx_members = mnp; 85178479Sjb 86178479Sjb mnp->dn_membname = strdup(name); 87178479Sjb mnp->dn_membexpr = enp; 88268578Srpaulo dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type, B_FALSE); 89178479Sjb 90178479Sjb if (mnp->dn_membname == NULL) 91178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 92178479Sjb 93178479Sjb return (0); 94178479Sjb} 95178479Sjb 96178479Sjbdt_xlator_t * 97178479Sjbdt_xlator_create(dtrace_hdl_t *dtp, 98178479Sjb const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst, 99178479Sjb const char *name, dt_node_t *members, dt_node_t *nodes) 100178479Sjb{ 101178479Sjb dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t)); 102178479Sjb dtrace_typeinfo_t ptr = *dst; 103178479Sjb dt_xlator_t **map; 104178479Sjb dt_node_t *dnp; 105178479Sjb uint_t kind; 106178479Sjb 107178479Sjb if (dxp == NULL) 108178479Sjb return (NULL); 109178479Sjb 110178479Sjb dxp->dx_hdl = dtp; 111178479Sjb dxp->dx_id = dtp->dt_xlatorid++; 112178479Sjb dxp->dx_gen = dtp->dt_gen; 113178479Sjb dxp->dx_arg = -1; 114178479Sjb 115178479Sjb if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) { 116178479Sjb dt_free(dtp, dxp); 117178479Sjb return (NULL); 118178479Sjb } 119178479Sjb 120178479Sjb dt_list_append(&dtp->dt_xlators, dxp); 121178479Sjb bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id); 122178479Sjb dt_free(dtp, dtp->dt_xlatormap); 123178479Sjb dtp->dt_xlatormap = map; 124178479Sjb dtp->dt_xlatormap[dxp->dx_id] = dxp; 125178479Sjb 126178479Sjb if (dt_type_pointer(&ptr) == -1) { 127178479Sjb ptr.dtt_ctfp = NULL; 128178479Sjb ptr.dtt_type = CTF_ERR; 129178479Sjb } 130178479Sjb 131178479Sjb dxp->dx_ident = dt_ident_create(name ? name : "T", 132178479Sjb DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0, 133178479Sjb _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen); 134178479Sjb 135178479Sjb if (dxp->dx_ident == NULL) 136178479Sjb goto err; /* no memory for identifier */ 137178479Sjb 138178479Sjb dxp->dx_ident->di_ctfp = src->dtt_ctfp; 139178479Sjb dxp->dx_ident->di_type = src->dtt_type; 140178479Sjb 141178479Sjb /* 142178479Sjb * If an input parameter name is given, this is a static translator 143178479Sjb * definition: create an idhash and identifier for the parameter. 144178479Sjb */ 145178479Sjb if (name != NULL) { 146178479Sjb dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0); 147178479Sjb 148178479Sjb if (dxp->dx_locals == NULL) 149178479Sjb goto err; /* no memory for identifier hash */ 150178479Sjb 151178479Sjb dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident); 152178479Sjb } 153178479Sjb 154178479Sjb dxp->dx_souid.di_name = "translator"; 155178479Sjb dxp->dx_souid.di_kind = DT_IDENT_XLSOU; 156178479Sjb dxp->dx_souid.di_flags = DT_IDFLG_REF; 157178479Sjb dxp->dx_souid.di_id = dxp->dx_id; 158178479Sjb dxp->dx_souid.di_attr = _dtrace_defattr; 159178479Sjb dxp->dx_souid.di_ops = &dt_idops_thaw; 160178479Sjb dxp->dx_souid.di_data = dxp; 161178479Sjb dxp->dx_souid.di_ctfp = dst->dtt_ctfp; 162178479Sjb dxp->dx_souid.di_type = dst->dtt_type; 163178479Sjb dxp->dx_souid.di_gen = dtp->dt_gen; 164178479Sjb 165178479Sjb dxp->dx_ptrid.di_name = "translator"; 166178479Sjb dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR; 167178479Sjb dxp->dx_ptrid.di_flags = DT_IDFLG_REF; 168178479Sjb dxp->dx_ptrid.di_id = dxp->dx_id; 169178479Sjb dxp->dx_ptrid.di_attr = _dtrace_defattr; 170178479Sjb dxp->dx_ptrid.di_ops = &dt_idops_thaw; 171178479Sjb dxp->dx_ptrid.di_data = dxp; 172178479Sjb dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp; 173178479Sjb dxp->dx_ptrid.di_type = ptr.dtt_type; 174178479Sjb dxp->dx_ptrid.di_gen = dtp->dt_gen; 175178479Sjb 176178479Sjb /* 177178479Sjb * If a deferred pragma is pending on the keyword "translator", run all 178178479Sjb * the deferred pragmas on dx_souid and then copy results to dx_ptrid. 179178479Sjb * See the code in dt_pragma.c for details on deferred ident pragmas. 180178479Sjb */ 181178479Sjb if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL && 182178479Sjb dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) { 183178479Sjb dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid); 184178479Sjb dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr; 185178479Sjb dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers; 186178479Sjb } 187178479Sjb 188178479Sjb dxp->dx_src_ctfp = src->dtt_ctfp; 189178479Sjb dxp->dx_src_type = src->dtt_type; 190178479Sjb dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type); 191178479Sjb 192178479Sjb dxp->dx_dst_ctfp = dst->dtt_ctfp; 193178479Sjb dxp->dx_dst_type = dst->dtt_type; 194178479Sjb dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type); 195178479Sjb 196178479Sjb kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base); 197178479Sjb assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION); 198178479Sjb 199178479Sjb /* 200178479Sjb * If no input parameter is given, we're making a dynamic translator: 201178479Sjb * create member nodes for every member of the output type. Otherwise 202178479Sjb * retain the member and allocation node lists presented by the parser. 203178479Sjb */ 204178479Sjb if (name == NULL) { 205178479Sjb if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base, 206178479Sjb dt_xlator_create_member, dxp) != 0) 207178479Sjb goto err; 208178479Sjb } else { 209178479Sjb dxp->dx_members = members; 210178479Sjb dxp->dx_nodes = nodes; 211178479Sjb } 212178479Sjb 213178479Sjb /* 214178479Sjb * Assign member IDs to each member and allocate space for DIFOs 215178479Sjb * if and when this translator is eventually compiled. 216178479Sjb */ 217178479Sjb for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) { 218178479Sjb dnp->dn_membxlator = dxp; 219178479Sjb dnp->dn_membid = dxp->dx_nmembers++; 220178479Sjb } 221178479Sjb 222178479Sjb dxp->dx_membdif = dt_zalloc(dtp, 223178479Sjb sizeof (dtrace_difo_t *) * dxp->dx_nmembers); 224178479Sjb 225178479Sjb if (dxp->dx_membdif == NULL) { 226178479Sjb dxp->dx_nmembers = 0; 227178479Sjb goto err; 228178479Sjb } 229178479Sjb 230178479Sjb return (dxp); 231178479Sjb 232178479Sjberr: 233178479Sjb dt_xlator_destroy(dtp, dxp); 234178479Sjb return (NULL); 235178479Sjb} 236178479Sjb 237178479Sjbvoid 238178479Sjbdt_xlator_destroy(dtrace_hdl_t *dtp, dt_xlator_t *dxp) 239178479Sjb{ 240178479Sjb uint_t i; 241178479Sjb 242178479Sjb dt_node_link_free(&dxp->dx_nodes); 243178479Sjb 244178479Sjb if (dxp->dx_locals != NULL) 245178479Sjb dt_idhash_destroy(dxp->dx_locals); 246178479Sjb else if (dxp->dx_ident != NULL) 247178479Sjb dt_ident_destroy(dxp->dx_ident); 248178479Sjb 249178479Sjb for (i = 0; i < dxp->dx_nmembers; i++) 250178479Sjb dt_difo_free(dtp, dxp->dx_membdif[i]); 251178479Sjb 252178479Sjb dt_free(dtp, dxp->dx_membdif); 253178479Sjb dt_list_delete(&dtp->dt_xlators, dxp); 254178479Sjb dt_free(dtp, dxp); 255178479Sjb} 256178479Sjb 257178479Sjbdt_xlator_t * 258178479Sjbdt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags) 259178479Sjb{ 260178479Sjb ctf_file_t *src_ctfp = src->dn_ctfp; 261178479Sjb ctf_id_t src_type = src->dn_type; 262178479Sjb ctf_id_t src_base = ctf_type_resolve(src_ctfp, src_type); 263178479Sjb 264178479Sjb ctf_file_t *dst_ctfp = dst->dn_ctfp; 265178479Sjb ctf_id_t dst_type = dst->dn_type; 266178479Sjb ctf_id_t dst_base = ctf_type_resolve(dst_ctfp, dst_type); 267178479Sjb uint_t dst_kind = ctf_type_kind(dst_ctfp, dst_base); 268178479Sjb 269178479Sjb int ptr = dst_kind == CTF_K_POINTER; 270178479Sjb dtrace_typeinfo_t src_dtt, dst_dtt; 271178479Sjb dt_node_t xn = { 0 }; 272178479Sjb dt_xlator_t *dxp = NULL; 273178479Sjb 274178479Sjb if (src_base == CTF_ERR || dst_base == CTF_ERR) 275178479Sjb return (NULL); /* fail if these are unresolvable types */ 276178479Sjb 277178479Sjb /* 278178479Sjb * Translators are always defined using a struct or union type, so if 279178479Sjb * we are attempting to translate to type "T *", we internally look 280178479Sjb * for a translation to type "T" by following the pointer reference. 281178479Sjb */ 282178479Sjb if (ptr) { 283178479Sjb dst_type = ctf_type_reference(dst_ctfp, dst_type); 284178479Sjb dst_base = ctf_type_resolve(dst_ctfp, dst_type); 285178479Sjb dst_kind = ctf_type_kind(dst_ctfp, dst_base); 286178479Sjb } 287178479Sjb 288178479Sjb if (dst_kind != CTF_K_UNION && dst_kind != CTF_K_STRUCT) 289178479Sjb return (NULL); /* fail if the output isn't a struct or union */ 290178479Sjb 291178479Sjb /* 292178479Sjb * In order to find a matching translator, we iterate over the set of 293178479Sjb * available translators in three passes. First, we look for a 294178479Sjb * translation from the exact source type to the resolved destination. 295178479Sjb * Second, we look for a translation from the resolved source type to 296178479Sjb * the resolved destination. Third, we look for a translation from a 297178479Sjb * compatible source type (using the same rules as parameter formals) 298178479Sjb * to the resolved destination. If all passes fail, return NULL. 299178479Sjb */ 300178479Sjb for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL; 301178479Sjb dxp = dt_list_next(dxp)) { 302178479Sjb if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_type, 303178479Sjb src_ctfp, src_type) && 304178479Sjb ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base, 305178479Sjb dst_ctfp, dst_base)) 306178479Sjb goto out; 307178479Sjb } 308178479Sjb 309178479Sjb if (flags & DT_XLATE_EXACT) 310178479Sjb goto out; /* skip remaining passes if exact match required */ 311178479Sjb 312178479Sjb for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL; 313178479Sjb dxp = dt_list_next(dxp)) { 314178479Sjb if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_base, 315178479Sjb src_ctfp, src_type) && 316178479Sjb ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base, 317178479Sjb dst_ctfp, dst_base)) 318178479Sjb goto out; 319178479Sjb } 320178479Sjb 321178479Sjb for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL; 322178479Sjb dxp = dt_list_next(dxp)) { 323268578Srpaulo dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type, 324268578Srpaulo B_FALSE); 325178479Sjb if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base, 326178479Sjb dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn)) 327178479Sjb goto out; 328178479Sjb } 329178479Sjb 330178479Sjbout: 331178479Sjb if (ptr && dxp != NULL && dxp->dx_ptrid.di_type == CTF_ERR) 332178479Sjb return (NULL); /* no translation available to pointer type */ 333178479Sjb 334178479Sjb if (dxp != NULL || !(flags & DT_XLATE_EXTERN) || 335178479Sjb dtp->dt_xlatemode == DT_XL_STATIC) 336178479Sjb return (dxp); /* we succeeded or not allowed to extern */ 337178479Sjb 338178479Sjb /* 339178479Sjb * If we get here, then we didn't find an existing translator, but the 340178479Sjb * caller and xlatemode permit us to create an extern to a dynamic one. 341178479Sjb */ 342178479Sjb src_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, src_ctfp)->dm_name; 343178479Sjb src_dtt.dtt_ctfp = src_ctfp; 344178479Sjb src_dtt.dtt_type = src_type; 345178479Sjb 346178479Sjb dst_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, dst_ctfp)->dm_name; 347178479Sjb dst_dtt.dtt_ctfp = dst_ctfp; 348178479Sjb dst_dtt.dtt_type = dst_type; 349178479Sjb 350178479Sjb return (dt_xlator_create(dtp, &src_dtt, &dst_dtt, NULL, NULL, NULL)); 351178479Sjb} 352178479Sjb 353178479Sjbdt_xlator_t * 354178479Sjbdt_xlator_lookup_id(dtrace_hdl_t *dtp, id_t id) 355178479Sjb{ 356178479Sjb assert(id >= 0 && id < dtp->dt_xlatorid); 357178479Sjb return (dtp->dt_xlatormap[id]); 358178479Sjb} 359178479Sjb 360178479Sjbdt_ident_t * 361178479Sjbdt_xlator_ident(dt_xlator_t *dxp, ctf_file_t *ctfp, ctf_id_t type) 362178479Sjb{ 363178479Sjb if (ctf_type_kind(ctfp, ctf_type_resolve(ctfp, type)) == CTF_K_POINTER) 364178479Sjb return (&dxp->dx_ptrid); 365178479Sjb else 366178479Sjb return (&dxp->dx_souid); 367178479Sjb} 368178479Sjb 369178479Sjbdt_node_t * 370178479Sjbdt_xlator_member(dt_xlator_t *dxp, const char *name) 371178479Sjb{ 372178479Sjb dt_node_t *dnp; 373178479Sjb 374178479Sjb for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) { 375178479Sjb if (strcmp(dnp->dn_membname, name) == 0) 376178479Sjb return (dnp); 377178479Sjb } 378178479Sjb 379178479Sjb return (NULL); 380178479Sjb} 381178479Sjb 382178479Sjbint 383178479Sjbdt_xlator_dynamic(const dt_xlator_t *dxp) 384178479Sjb{ 385178479Sjb return (dxp->dx_locals == NULL); 386178479Sjb} 387