1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 /*
  27  * Copyright (c) 2013 by Delphix. All rights reserved.
  28  * Copyright (c) 2013 Joyent, Inc. All rights reserved.
  29  */
  30 
  31 #include <strings.h>
  32 #include <assert.h>
  33 
  34 #include <dt_xlator.h>
  35 #include <dt_parser.h>
  36 #include <dt_grammar.h>
  37 #include <dt_module.h>
  38 #include <dt_impl.h>
  39 
  40 /*
  41  * Create a member node corresponding to one of the output members of a dynamic
  42  * translator.  We set the member's dn_membexpr to a DT_NODE_XLATOR node that
  43  * has dn_op set to DT_TOK_XLATE and refers back to the translator itself.  The
  44  * code generator will then use this as the indicator for dynamic translation.
  45  */
  46 /*ARGSUSED*/
  47 static int
  48 dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
  49 {
  50         dt_xlator_t *dxp = arg;
  51         dtrace_hdl_t *dtp = dxp->dx_hdl;
  52         dt_node_t *enp, *mnp;
  53         ctf_file_t *ctfp;
  54 
  55         if ((enp = dt_node_xalloc(dtp, DT_NODE_XLATOR)) == NULL)
  56                 return (dt_set_errno(dtp, EDT_NOMEM));
  57 
  58         enp->dn_link = dxp->dx_nodes;
  59         dxp->dx_nodes = enp;
  60 
  61         if ((mnp = dt_node_xalloc(dtp, DT_NODE_MEMBER)) == NULL)
  62                 return (dt_set_errno(dtp, EDT_NOMEM));
  63 
  64         mnp->dn_link = dxp->dx_nodes;
  65         dxp->dx_nodes = mnp;
  66 
  67         /*
  68          * For the member expression, we use a DT_NODE_XLATOR/TOK_XLATE whose
  69          * xlator refers back to the translator and whose dn_xmember refers to
  70          * the current member.  These refs will be used by dt_cg.c and dt_as.c.
  71          */
  72         enp->dn_op = DT_TOK_XLATE;
  73         enp->dn_xlator = dxp;
  74         enp->dn_xmember = mnp;
  75         /*
  76          * XXX: Is it ok for the CTF of the type to not be from the dst ctf?
  77          *
  78          * I suspect it's actually unnecessary, but I'm also unclear on
  79          * dynamic translators
  80          */
  81         dt_resolve_forward_decl(&ctfp, &type);
  82         dt_node_type_assign(enp, ctfp, type, B_FALSE);
  83 
  84         /*
  85          * For the member itself, we use a DT_NODE_MEMBER as usual with the
  86          * appropriate name, output type, and member expression set to 'enp'.
  87          */
  88         if (dxp->dx_members != NULL) {
  89                 assert(enp->dn_link->dn_kind == DT_NODE_MEMBER);
  90                 enp->dn_link->dn_list = mnp;
  91         } else
  92                 dxp->dx_members = mnp;
  93 
  94         mnp->dn_membname = strdup(name);
  95         mnp->dn_membexpr = enp;
  96         dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type, B_FALSE);
  97 
  98         if (mnp->dn_membname == NULL)
  99                 return (dt_set_errno(dtp, EDT_NOMEM));
 100 
 101         return (0);
 102 }
 103 
 104 dt_xlator_t *
 105 dt_xlator_create(dtrace_hdl_t *dtp,
 106     const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst,
 107     const char *name, dt_node_t *members, dt_node_t *nodes)
 108 {
 109         dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t));
 110         dtrace_typeinfo_t ptr = *dst;
 111         dt_xlator_t **map;
 112         dt_node_t *dnp;
 113         uint_t kind;
 114 
 115         if (dxp == NULL)
 116                 return (NULL);
 117 
 118         dxp->dx_hdl = dtp;
 119         dxp->dx_id = dtp->dt_xlatorid++;
 120         dxp->dx_gen = dtp->dt_gen;
 121         dxp->dx_arg = -1;
 122 
 123         if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) {
 124                 dt_free(dtp, dxp);
 125                 return (NULL);
 126         }
 127 
 128         dt_list_append(&dtp->dt_xlators, dxp);
 129         bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id);
 130         dt_free(dtp, dtp->dt_xlatormap);
 131         dtp->dt_xlatormap = map;
 132         dtp->dt_xlatormap[dxp->dx_id] = dxp;
 133 
 134         if (dt_type_pointer(&ptr) == -1) {
 135                 ptr.dtt_ctfp = NULL;
 136                 ptr.dtt_type = CTF_ERR;
 137         }
 138 
 139         dxp->dx_ident = dt_ident_create(name ? name : "T",
 140             DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0,
 141             _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);
 142 
 143         if (dxp->dx_ident == NULL)
 144                 goto err; /* no memory for identifier */
 145 
 146         dxp->dx_ident->di_ctfp = src->dtt_ctfp;
 147         dxp->dx_ident->di_type = src->dtt_type;
 148 
 149         /*
 150          * If an input parameter name is given, this is a static translator
 151          * definition: create an idhash and identifier for the parameter.
 152          */
 153         if (name != NULL) {
 154                 dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0);
 155 
 156                 if (dxp->dx_locals == NULL)
 157                         goto err; /* no memory for identifier hash */
 158 
 159                 dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident);
 160         }
 161 
 162         dxp->dx_souid.di_name = "translator";
 163         dxp->dx_souid.di_kind = DT_IDENT_XLSOU;
 164         dxp->dx_souid.di_flags = DT_IDFLG_REF;
 165         dxp->dx_souid.di_id = dxp->dx_id;
 166         dxp->dx_souid.di_attr = _dtrace_defattr;
 167         dxp->dx_souid.di_ops = &dt_idops_thaw;
 168         dxp->dx_souid.di_data = dxp;
 169         dxp->dx_souid.di_ctfp = dst->dtt_ctfp;
 170         dxp->dx_souid.di_type = dst->dtt_type;
 171         dxp->dx_souid.di_gen = dtp->dt_gen;
 172 
 173         dxp->dx_ptrid.di_name = "translator";
 174         dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR;
 175         dxp->dx_ptrid.di_flags = DT_IDFLG_REF;
 176         dxp->dx_ptrid.di_id = dxp->dx_id;
 177         dxp->dx_ptrid.di_attr = _dtrace_defattr;
 178         dxp->dx_ptrid.di_ops = &dt_idops_thaw;
 179         dxp->dx_ptrid.di_data = dxp;
 180         dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp;
 181         dxp->dx_ptrid.di_type = ptr.dtt_type;
 182         dxp->dx_ptrid.di_gen = dtp->dt_gen;
 183 
 184         /*
 185          * If a deferred pragma is pending on the keyword "translator", run all
 186          * the deferred pragmas on dx_souid and then copy results to dx_ptrid.
 187          * See the code in dt_pragma.c for details on deferred ident pragmas.
 188          */
 189         if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL &&
 190             dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) {
 191                 dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid);
 192                 dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr;
 193                 dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers;
 194         }
 195 
 196         dxp->dx_src_ctfp = src->dtt_ctfp;
 197         dxp->dx_src_type = src->dtt_type;
 198         dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type);
 199 
 200         dxp->dx_dst_ctfp = dst->dtt_ctfp;
 201         dxp->dx_dst_type = dst->dtt_type;
 202         dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type);
 203 
 204         kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base);
 205         assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION);
 206 
 207         /*
 208          * If no input parameter is given, we're making a dynamic translator:
 209          * create member nodes for every member of the output type.  Otherwise
 210          * retain the member and allocation node lists presented by the parser.
 211          */
 212         if (name == NULL) {
 213                 if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base,
 214                     dt_xlator_create_member, dxp) != 0)
 215                         goto err;
 216         } else {
 217                 dxp->dx_members = members;
 218                 dxp->dx_nodes = nodes;
 219         }
 220 
 221         /*
 222          * Assign member IDs to each member and allocate space for DIFOs
 223          * if and when this translator is eventually compiled.
 224          */
 225         for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
 226                 dnp->dn_membxlator = dxp;
 227                 dnp->dn_membid = dxp->dx_nmembers++;
 228         }
 229 
 230         dxp->dx_membdif = dt_zalloc(dtp,
 231             sizeof (dtrace_difo_t *) * dxp->dx_nmembers);
 232 
 233         if (dxp->dx_membdif == NULL) {
 234                 dxp->dx_nmembers = 0;
 235                 goto err;
 236         }
 237 
 238         return (dxp);
 239 
 240 err:
 241         dt_xlator_destroy(dtp, dxp);
 242         return (NULL);
 243 }
 244 
 245 void
 246 dt_xlator_destroy(dtrace_hdl_t *dtp, dt_xlator_t *dxp)
 247 {
 248         uint_t i;
 249 
 250         dt_node_link_free(&dxp->dx_nodes);
 251 
 252         if (dxp->dx_locals != NULL)
 253                 dt_idhash_destroy(dxp->dx_locals);
 254         else if (dxp->dx_ident != NULL)
 255                 dt_ident_destroy(dxp->dx_ident);
 256 
 257         for (i = 0; i < dxp->dx_nmembers; i++)
 258                 dt_difo_free(dtp, dxp->dx_membdif[i]);
 259 
 260         dt_free(dtp, dxp->dx_membdif);
 261         dt_list_delete(&dtp->dt_xlators, dxp);
 262         dt_free(dtp, dxp);
 263 }
 264 
 265 dt_xlator_t *
 266 dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
 267 {
 268         ctf_file_t *src_ctfp = src->dn_ctfp;
 269         ctf_id_t src_type = src->dn_type;
 270         ctf_id_t src_base = ctf_type_resolve(src_ctfp, src_type);
 271 
 272         ctf_file_t *dst_ctfp = dst->dn_ctfp;
 273         ctf_id_t dst_type = dst->dn_type;
 274         ctf_id_t dst_base = ctf_type_resolve(dst_ctfp, dst_type);
 275         uint_t dst_kind = ctf_type_kind(dst_ctfp, dst_base);
 276 
 277         int ptr = dst_kind == CTF_K_POINTER;
 278         dtrace_typeinfo_t src_dtt, dst_dtt;
 279         dt_node_t xn = { 0 };
 280         dt_xlator_t *dxp = NULL;
 281 
 282         if (src_base == CTF_ERR || dst_base == CTF_ERR)
 283                 return (NULL); /* fail if these are unresolvable types */
 284 
 285         /*
 286          * Translators are always defined using a struct or union type, so if
 287          * we are attempting to translate to type "T *", we internally look
 288          * for a translation to type "T" by following the pointer reference.
 289          */
 290         if (ptr) {
 291                 dst_type = ctf_type_reference(dst_ctfp, dst_type);
 292                 dst_base = ctf_type_resolve(dst_ctfp, dst_type);
 293                 dst_kind = ctf_type_kind(dst_ctfp, dst_base);
 294         }
 295 
 296         if (dst_kind != CTF_K_UNION && dst_kind != CTF_K_STRUCT)
 297                 return (NULL); /* fail if the output isn't a struct or union */
 298 
 299         /*
 300          * In order to find a matching translator, we iterate over the set of
 301          * available translators in three passes.  First, we look for a
 302          * translation from the exact source type to the resolved destination.
 303          * Second, we look for a translation from the resolved source type to
 304          * the resolved destination.  Third, we look for a translation from a
 305          * compatible source type (using the same rules as parameter formals)
 306          * to the resolved destination.  If all passes fail, return NULL.
 307          */
 308         for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
 309             dxp = dt_list_next(dxp)) {
 310                 if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_type,
 311                     src_ctfp, src_type) &&
 312                     ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
 313                     dst_ctfp, dst_base))
 314                         goto out;
 315         }
 316 
 317         if (flags & DT_XLATE_EXACT)
 318                 goto out; /* skip remaining passes if exact match required */
 319 
 320         for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
 321             dxp = dt_list_next(dxp)) {
 322                 if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_base,
 323                     src_ctfp, src_type) &&
 324                     ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
 325                     dst_ctfp, dst_base))
 326                         goto out;
 327         }
 328 
 329         for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
 330             dxp = dt_list_next(dxp)) {
 331                 dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type,
 332                     B_FALSE);
 333                 if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
 334                     dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
 335                         goto out;
 336         }
 337 
 338 out:
 339         if (ptr && dxp != NULL && dxp->dx_ptrid.di_type == CTF_ERR)
 340                 return (NULL);  /* no translation available to pointer type */
 341 
 342         if (dxp != NULL || !(flags & DT_XLATE_EXTERN) ||
 343             dtp->dt_xlatemode == DT_XL_STATIC)
 344                 return (dxp);   /* we succeeded or not allowed to extern */
 345 
 346         /*
 347          * If we get here, then we didn't find an existing translator, but the
 348          * caller and xlatemode permit us to create an extern to a dynamic one.
 349          */
 350         src_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, src_ctfp)->dm_name;
 351         src_dtt.dtt_ctfp = src_ctfp;
 352         src_dtt.dtt_type = src_type;
 353 
 354         dst_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, dst_ctfp)->dm_name;
 355         dst_dtt.dtt_ctfp = dst_ctfp;
 356         dst_dtt.dtt_type = dst_type;
 357 
 358         return (dt_xlator_create(dtp, &src_dtt, &dst_dtt, NULL, NULL, NULL));
 359 }
 360 
 361 dt_xlator_t *
 362 dt_xlator_lookup_id(dtrace_hdl_t *dtp, id_t id)
 363 {
 364         assert(id >= 0 && id < dtp->dt_xlatorid);
 365         return (dtp->dt_xlatormap[id]);
 366 }
 367 
 368 dt_ident_t *
 369 dt_xlator_ident(dt_xlator_t *dxp, ctf_file_t *ctfp, ctf_id_t type)
 370 {
 371         if (ctf_type_kind(ctfp, ctf_type_resolve(ctfp, type)) == CTF_K_POINTER)
 372                 return (&dxp->dx_ptrid);
 373         else
 374                 return (&dxp->dx_souid);
 375 }
 376 
 377 dt_node_t *
 378 dt_xlator_member(dt_xlator_t *dxp, const char *name)
 379 {
 380         dt_node_t *dnp;
 381 
 382         for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
 383                 if (strcmp(dnp->dn_membname, name) == 0)
 384                         return (dnp);
 385         }
 386 
 387         return (NULL);
 388 }
 389 
 390 int
 391 dt_xlator_dynamic(const dt_xlator_t *dxp)
 392 {
 393         return (dxp->dx_locals == NULL);
 394 }