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