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