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