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 }