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