Deleted Added
full compact
dt_map.c (248708) dt_map.c (269524)
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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * Copyright (c) 2011 by Delphix. All rights reserved.
28 */
29
30#include <stdlib.h>
31#include <strings.h>
32#include <errno.h>
33#include <unistd.h>
34#include <assert.h>
35
36#include <dt_impl.h>
37#include <dt_printf.h>
38
39static int
40dt_strdata_add(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, void ***data, int *max)
41{
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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * Copyright (c) 2011 by Delphix. All rights reserved.
28 */
29
30#include <stdlib.h>
31#include <strings.h>
32#include <errno.h>
33#include <unistd.h>
34#include <assert.h>
35
36#include <dt_impl.h>
37#include <dt_printf.h>
38
39static int
40dt_strdata_add(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, void ***data, int *max)
41{
42 int maxformat;
42 int maxformat, rval;
43 dtrace_fmtdesc_t fmt;
44 void *result;
45
46 if (rec->dtrd_format == 0)
47 return (0);
48
49 if (rec->dtrd_format <= *max &&
50 (*data)[rec->dtrd_format - 1] != NULL) {
51 return (0);
52 }
53
54 bzero(&fmt, sizeof (fmt));
55 fmt.dtfd_format = rec->dtrd_format;
56 fmt.dtfd_string = NULL;
57 fmt.dtfd_length = 0;
58
59 if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1)
60 return (dt_set_errno(dtp, errno));
61
62 if ((fmt.dtfd_string = dt_alloc(dtp, fmt.dtfd_length)) == NULL)
63 return (dt_set_errno(dtp, EDT_NOMEM));
64
65 if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) {
43 dtrace_fmtdesc_t fmt;
44 void *result;
45
46 if (rec->dtrd_format == 0)
47 return (0);
48
49 if (rec->dtrd_format <= *max &&
50 (*data)[rec->dtrd_format - 1] != NULL) {
51 return (0);
52 }
53
54 bzero(&fmt, sizeof (fmt));
55 fmt.dtfd_format = rec->dtrd_format;
56 fmt.dtfd_string = NULL;
57 fmt.dtfd_length = 0;
58
59 if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1)
60 return (dt_set_errno(dtp, errno));
61
62 if ((fmt.dtfd_string = dt_alloc(dtp, fmt.dtfd_length)) == NULL)
63 return (dt_set_errno(dtp, EDT_NOMEM));
64
65 if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) {
66 rval = dt_set_errno(dtp, errno);
66 free(fmt.dtfd_string);
67 free(fmt.dtfd_string);
67 return (dt_set_errno(dtp, errno));
68 return (rval);
68 }
69
70 while (rec->dtrd_format > (maxformat = *max)) {
71 int new_max = maxformat ? (maxformat << 1) : 1;
72 size_t nsize = new_max * sizeof (void *);
73 size_t osize = maxformat * sizeof (void *);
74 void **new_data = dt_zalloc(dtp, nsize);
75
76 if (new_data == NULL) {
77 dt_free(dtp, fmt.dtfd_string);
78 return (dt_set_errno(dtp, EDT_NOMEM));
79 }
80
81 bcopy(*data, new_data, osize);
82 free(*data);
83
84 *data = new_data;
85 *max = new_max;
86 }
87
88 switch (rec->dtrd_action) {
89 case DTRACEACT_DIFEXPR:
90 result = fmt.dtfd_string;
91 break;
92 case DTRACEACT_PRINTA:
93 result = dtrace_printa_create(dtp, fmt.dtfd_string);
94 dt_free(dtp, fmt.dtfd_string);
95 break;
96 default:
97 result = dtrace_printf_create(dtp, fmt.dtfd_string);
98 dt_free(dtp, fmt.dtfd_string);
99 break;
100 }
101
102 if (result == NULL)
103 return (-1);
104
105 (*data)[rec->dtrd_format - 1] = result;
106
107 return (0);
108}
109
110static int
111dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
112{
113 dtrace_id_t max;
114 int rval, i;
115 dtrace_eprobedesc_t *enabled, *nenabled;
116 dtrace_probedesc_t *probe;
117
118 while (id >= (max = dtp->dt_maxprobe) || dtp->dt_pdesc == NULL) {
119 dtrace_id_t new_max = max ? (max << 1) : 1;
120 size_t nsize = new_max * sizeof (void *);
121 dtrace_probedesc_t **new_pdesc;
122 dtrace_eprobedesc_t **new_edesc;
123
124 if ((new_pdesc = malloc(nsize)) == NULL ||
125 (new_edesc = malloc(nsize)) == NULL) {
126 free(new_pdesc);
127 return (dt_set_errno(dtp, EDT_NOMEM));
128 }
129
130 bzero(new_pdesc, nsize);
131 bzero(new_edesc, nsize);
132
133 if (dtp->dt_pdesc != NULL) {
134 size_t osize = max * sizeof (void *);
135
136 bcopy(dtp->dt_pdesc, new_pdesc, osize);
137 free(dtp->dt_pdesc);
138
139 bcopy(dtp->dt_edesc, new_edesc, osize);
140 free(dtp->dt_edesc);
141 }
142
143 dtp->dt_pdesc = new_pdesc;
144 dtp->dt_edesc = new_edesc;
145 dtp->dt_maxprobe = new_max;
146 }
147
148 if (dtp->dt_pdesc[id] != NULL)
149 return (0);
150
151 if ((enabled = malloc(sizeof (dtrace_eprobedesc_t))) == NULL)
152 return (dt_set_errno(dtp, EDT_NOMEM));
153
154 bzero(enabled, sizeof (dtrace_eprobedesc_t));
155 enabled->dtepd_epid = id;
156 enabled->dtepd_nrecs = 1;
157
158#if defined(sun)
159 if (dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled) == -1) {
160#else
161 if (dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled) == -1) {
162#endif
163 rval = dt_set_errno(dtp, errno);
164 free(enabled);
165 return (rval);
166 }
167
168 if (DTRACE_SIZEOF_EPROBEDESC(enabled) != sizeof (*enabled)) {
169 /*
170 * There must be more than one action. Allocate the
171 * appropriate amount of space and try again.
172 */
173 if ((nenabled =
174 malloc(DTRACE_SIZEOF_EPROBEDESC(enabled))) != NULL)
175 bcopy(enabled, nenabled, sizeof (*enabled));
176
177 free(enabled);
178
179 if ((enabled = nenabled) == NULL)
180 return (dt_set_errno(dtp, EDT_NOMEM));
181
182#if defined(sun)
183 rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled);
184#else
185 rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled);
186#endif
187
188 if (rval == -1) {
189 rval = dt_set_errno(dtp, errno);
190 free(enabled);
191 return (rval);
192 }
193 }
194
195 if ((probe = malloc(sizeof (dtrace_probedesc_t))) == NULL) {
196 free(enabled);
197 return (dt_set_errno(dtp, EDT_NOMEM));
198 }
199
200 probe->dtpd_id = enabled->dtepd_probeid;
201
202 if (dt_ioctl(dtp, DTRACEIOC_PROBES, probe) == -1) {
203 rval = dt_set_errno(dtp, errno);
204 goto err;
205 }
206
207 for (i = 0; i < enabled->dtepd_nrecs; i++) {
208 dtrace_recdesc_t *rec = &enabled->dtepd_rec[i];
209
210 if (DTRACEACT_ISPRINTFLIKE(rec->dtrd_action)) {
211 if (dt_strdata_add(dtp, rec, &dtp->dt_formats,
212 &dtp->dt_maxformat) != 0) {
213 rval = -1;
214 goto err;
215 }
216 } else if (rec->dtrd_action == DTRACEACT_DIFEXPR) {
217 if (dt_strdata_add(dtp, rec,
218 (void ***)&dtp->dt_strdata,
219 &dtp->dt_maxstrdata) != 0) {
220 rval = -1;
221 goto err;
222 }
223 }
224
225 }
226
227 dtp->dt_pdesc[id] = probe;
228 dtp->dt_edesc[id] = enabled;
229
230 return (0);
231
232err:
233 /*
234 * If we failed, free our allocated probes. Note that if we failed
235 * while allocating formats, we aren't going to free formats that
236 * we have already allocated. This is okay; these formats are
237 * hanging off of dt_formats and will therefore not be leaked.
238 */
239 free(enabled);
240 free(probe);
241 return (rval);
242}
243
244int
245dt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid,
246 dtrace_eprobedesc_t **epdp, dtrace_probedesc_t **pdp)
247{
248 int rval;
249
250 if (epid >= dtp->dt_maxprobe || dtp->dt_pdesc[epid] == NULL) {
251 if ((rval = dt_epid_add(dtp, epid)) != 0)
252 return (rval);
253 }
254
255 assert(epid < dtp->dt_maxprobe);
256 assert(dtp->dt_edesc[epid] != NULL);
257 assert(dtp->dt_pdesc[epid] != NULL);
258 *epdp = dtp->dt_edesc[epid];
259 *pdp = dtp->dt_pdesc[epid];
260
261 return (0);
262}
263
264void
265dt_epid_destroy(dtrace_hdl_t *dtp)
266{
267 size_t i;
268
269 assert((dtp->dt_pdesc != NULL && dtp->dt_edesc != NULL &&
270 dtp->dt_maxprobe > 0) || (dtp->dt_pdesc == NULL &&
271 dtp->dt_edesc == NULL && dtp->dt_maxprobe == 0));
272
273 if (dtp->dt_pdesc == NULL)
274 return;
275
276 for (i = 0; i < dtp->dt_maxprobe; i++) {
277 if (dtp->dt_edesc[i] == NULL) {
278 assert(dtp->dt_pdesc[i] == NULL);
279 continue;
280 }
281
282 assert(dtp->dt_pdesc[i] != NULL);
283 free(dtp->dt_edesc[i]);
284 free(dtp->dt_pdesc[i]);
285 }
286
287 free(dtp->dt_pdesc);
288 dtp->dt_pdesc = NULL;
289
290 free(dtp->dt_edesc);
291 dtp->dt_edesc = NULL;
292 dtp->dt_maxprobe = 0;
293}
294
295void *
296dt_format_lookup(dtrace_hdl_t *dtp, int format)
297{
298 if (format == 0 || format > dtp->dt_maxformat)
299 return (NULL);
300
301 if (dtp->dt_formats == NULL)
302 return (NULL);
303
304 return (dtp->dt_formats[format - 1]);
305}
306
307void
308dt_format_destroy(dtrace_hdl_t *dtp)
309{
310 int i;
311
312 for (i = 0; i < dtp->dt_maxformat; i++) {
313 if (dtp->dt_formats[i] != NULL)
314 dt_printf_destroy(dtp->dt_formats[i]);
315 }
316
317 free(dtp->dt_formats);
318 dtp->dt_formats = NULL;
319}
320
321static int
322dt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id)
323{
324 dtrace_id_t max;
325 dtrace_epid_t epid;
326 int rval;
327
328 while (id >= (max = dtp->dt_maxagg) || dtp->dt_aggdesc == NULL) {
329 dtrace_id_t new_max = max ? (max << 1) : 1;
330 size_t nsize = new_max * sizeof (void *);
331 dtrace_aggdesc_t **new_aggdesc;
332
333 if ((new_aggdesc = malloc(nsize)) == NULL)
334 return (dt_set_errno(dtp, EDT_NOMEM));
335
336 bzero(new_aggdesc, nsize);
337
338 if (dtp->dt_aggdesc != NULL) {
339 bcopy(dtp->dt_aggdesc, new_aggdesc,
340 max * sizeof (void *));
341 free(dtp->dt_aggdesc);
342 }
343
344 dtp->dt_aggdesc = new_aggdesc;
345 dtp->dt_maxagg = new_max;
346 }
347
348 if (dtp->dt_aggdesc[id] == NULL) {
349 dtrace_aggdesc_t *agg, *nagg;
350
351 if ((agg = malloc(sizeof (dtrace_aggdesc_t))) == NULL)
352 return (dt_set_errno(dtp, EDT_NOMEM));
353
354 bzero(agg, sizeof (dtrace_aggdesc_t));
355 agg->dtagd_id = id;
356 agg->dtagd_nrecs = 1;
357
358#if defined(sun)
359 if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg) == -1) {
360#else
361 if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg) == -1) {
362#endif
363 rval = dt_set_errno(dtp, errno);
364 free(agg);
365 return (rval);
366 }
367
368 if (DTRACE_SIZEOF_AGGDESC(agg) != sizeof (*agg)) {
369 /*
370 * There must be more than one action. Allocate the
371 * appropriate amount of space and try again.
372 */
373 if ((nagg = malloc(DTRACE_SIZEOF_AGGDESC(agg))) != NULL)
374 bcopy(agg, nagg, sizeof (*agg));
375
376 free(agg);
377
378 if ((agg = nagg) == NULL)
379 return (dt_set_errno(dtp, EDT_NOMEM));
380
381#if defined(sun)
382 rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg);
383#else
384 rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg);
385#endif
386
387 if (rval == -1) {
388 rval = dt_set_errno(dtp, errno);
389 free(agg);
390 return (rval);
391 }
392 }
393
394 /*
395 * If we have a uarg, it's a pointer to the compiler-generated
396 * statement; we'll use this value to get the name and
397 * compiler-generated variable ID for the aggregation. If
398 * we're grabbing an anonymous enabling, this pointer value
399 * is obviously meaningless -- and in this case, we can't
400 * provide the compiler-generated aggregation information.
401 */
402 if (dtp->dt_options[DTRACEOPT_GRABANON] == DTRACEOPT_UNSET &&
403 agg->dtagd_rec[0].dtrd_uarg != 0) {
404 dtrace_stmtdesc_t *sdp;
405 dt_ident_t *aid;
406
407 sdp = (dtrace_stmtdesc_t *)(uintptr_t)
408 agg->dtagd_rec[0].dtrd_uarg;
409 aid = sdp->dtsd_aggdata;
410 agg->dtagd_name = aid->di_name;
411 agg->dtagd_varid = aid->di_id;
412 } else {
413 agg->dtagd_varid = DTRACE_AGGVARIDNONE;
414 }
415
416 if ((epid = agg->dtagd_epid) >= dtp->dt_maxprobe ||
417 dtp->dt_pdesc[epid] == NULL) {
418 if ((rval = dt_epid_add(dtp, epid)) != 0) {
419 free(agg);
420 return (rval);
421 }
422 }
423
424 dtp->dt_aggdesc[id] = agg;
425 }
426
427 return (0);
428}
429
430int
431dt_aggid_lookup(dtrace_hdl_t *dtp, dtrace_aggid_t aggid,
432 dtrace_aggdesc_t **adp)
433{
434 int rval;
435
436 if (aggid >= dtp->dt_maxagg || dtp->dt_aggdesc[aggid] == NULL) {
437 if ((rval = dt_aggid_add(dtp, aggid)) != 0)
438 return (rval);
439 }
440
441 assert(aggid < dtp->dt_maxagg);
442 assert(dtp->dt_aggdesc[aggid] != NULL);
443 *adp = dtp->dt_aggdesc[aggid];
444
445 return (0);
446}
447
448void
449dt_aggid_destroy(dtrace_hdl_t *dtp)
450{
451 size_t i;
452
453 assert((dtp->dt_aggdesc != NULL && dtp->dt_maxagg != 0) ||
454 (dtp->dt_aggdesc == NULL && dtp->dt_maxagg == 0));
455
456 if (dtp->dt_aggdesc == NULL)
457 return;
458
459 for (i = 0; i < dtp->dt_maxagg; i++) {
460 if (dtp->dt_aggdesc[i] != NULL)
461 free(dtp->dt_aggdesc[i]);
462 }
463
464 free(dtp->dt_aggdesc);
465 dtp->dt_aggdesc = NULL;
466 dtp->dt_maxagg = 0;
467}
468
469const char *
470dt_strdata_lookup(dtrace_hdl_t *dtp, int idx)
471{
472 if (idx == 0 || idx > dtp->dt_maxstrdata)
473 return (NULL);
474
475 if (dtp->dt_strdata == NULL)
476 return (NULL);
477
478 return (dtp->dt_strdata[idx - 1]);
479}
480
481void
482dt_strdata_destroy(dtrace_hdl_t *dtp)
483{
484 int i;
485
486 for (i = 0; i < dtp->dt_maxstrdata; i++) {
487 free(dtp->dt_strdata[i]);
488 }
489
490 free(dtp->dt_strdata);
491 dtp->dt_strdata = NULL;
492}
69 }
70
71 while (rec->dtrd_format > (maxformat = *max)) {
72 int new_max = maxformat ? (maxformat << 1) : 1;
73 size_t nsize = new_max * sizeof (void *);
74 size_t osize = maxformat * sizeof (void *);
75 void **new_data = dt_zalloc(dtp, nsize);
76
77 if (new_data == NULL) {
78 dt_free(dtp, fmt.dtfd_string);
79 return (dt_set_errno(dtp, EDT_NOMEM));
80 }
81
82 bcopy(*data, new_data, osize);
83 free(*data);
84
85 *data = new_data;
86 *max = new_max;
87 }
88
89 switch (rec->dtrd_action) {
90 case DTRACEACT_DIFEXPR:
91 result = fmt.dtfd_string;
92 break;
93 case DTRACEACT_PRINTA:
94 result = dtrace_printa_create(dtp, fmt.dtfd_string);
95 dt_free(dtp, fmt.dtfd_string);
96 break;
97 default:
98 result = dtrace_printf_create(dtp, fmt.dtfd_string);
99 dt_free(dtp, fmt.dtfd_string);
100 break;
101 }
102
103 if (result == NULL)
104 return (-1);
105
106 (*data)[rec->dtrd_format - 1] = result;
107
108 return (0);
109}
110
111static int
112dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
113{
114 dtrace_id_t max;
115 int rval, i;
116 dtrace_eprobedesc_t *enabled, *nenabled;
117 dtrace_probedesc_t *probe;
118
119 while (id >= (max = dtp->dt_maxprobe) || dtp->dt_pdesc == NULL) {
120 dtrace_id_t new_max = max ? (max << 1) : 1;
121 size_t nsize = new_max * sizeof (void *);
122 dtrace_probedesc_t **new_pdesc;
123 dtrace_eprobedesc_t **new_edesc;
124
125 if ((new_pdesc = malloc(nsize)) == NULL ||
126 (new_edesc = malloc(nsize)) == NULL) {
127 free(new_pdesc);
128 return (dt_set_errno(dtp, EDT_NOMEM));
129 }
130
131 bzero(new_pdesc, nsize);
132 bzero(new_edesc, nsize);
133
134 if (dtp->dt_pdesc != NULL) {
135 size_t osize = max * sizeof (void *);
136
137 bcopy(dtp->dt_pdesc, new_pdesc, osize);
138 free(dtp->dt_pdesc);
139
140 bcopy(dtp->dt_edesc, new_edesc, osize);
141 free(dtp->dt_edesc);
142 }
143
144 dtp->dt_pdesc = new_pdesc;
145 dtp->dt_edesc = new_edesc;
146 dtp->dt_maxprobe = new_max;
147 }
148
149 if (dtp->dt_pdesc[id] != NULL)
150 return (0);
151
152 if ((enabled = malloc(sizeof (dtrace_eprobedesc_t))) == NULL)
153 return (dt_set_errno(dtp, EDT_NOMEM));
154
155 bzero(enabled, sizeof (dtrace_eprobedesc_t));
156 enabled->dtepd_epid = id;
157 enabled->dtepd_nrecs = 1;
158
159#if defined(sun)
160 if (dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled) == -1) {
161#else
162 if (dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled) == -1) {
163#endif
164 rval = dt_set_errno(dtp, errno);
165 free(enabled);
166 return (rval);
167 }
168
169 if (DTRACE_SIZEOF_EPROBEDESC(enabled) != sizeof (*enabled)) {
170 /*
171 * There must be more than one action. Allocate the
172 * appropriate amount of space and try again.
173 */
174 if ((nenabled =
175 malloc(DTRACE_SIZEOF_EPROBEDESC(enabled))) != NULL)
176 bcopy(enabled, nenabled, sizeof (*enabled));
177
178 free(enabled);
179
180 if ((enabled = nenabled) == NULL)
181 return (dt_set_errno(dtp, EDT_NOMEM));
182
183#if defined(sun)
184 rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled);
185#else
186 rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled);
187#endif
188
189 if (rval == -1) {
190 rval = dt_set_errno(dtp, errno);
191 free(enabled);
192 return (rval);
193 }
194 }
195
196 if ((probe = malloc(sizeof (dtrace_probedesc_t))) == NULL) {
197 free(enabled);
198 return (dt_set_errno(dtp, EDT_NOMEM));
199 }
200
201 probe->dtpd_id = enabled->dtepd_probeid;
202
203 if (dt_ioctl(dtp, DTRACEIOC_PROBES, probe) == -1) {
204 rval = dt_set_errno(dtp, errno);
205 goto err;
206 }
207
208 for (i = 0; i < enabled->dtepd_nrecs; i++) {
209 dtrace_recdesc_t *rec = &enabled->dtepd_rec[i];
210
211 if (DTRACEACT_ISPRINTFLIKE(rec->dtrd_action)) {
212 if (dt_strdata_add(dtp, rec, &dtp->dt_formats,
213 &dtp->dt_maxformat) != 0) {
214 rval = -1;
215 goto err;
216 }
217 } else if (rec->dtrd_action == DTRACEACT_DIFEXPR) {
218 if (dt_strdata_add(dtp, rec,
219 (void ***)&dtp->dt_strdata,
220 &dtp->dt_maxstrdata) != 0) {
221 rval = -1;
222 goto err;
223 }
224 }
225
226 }
227
228 dtp->dt_pdesc[id] = probe;
229 dtp->dt_edesc[id] = enabled;
230
231 return (0);
232
233err:
234 /*
235 * If we failed, free our allocated probes. Note that if we failed
236 * while allocating formats, we aren't going to free formats that
237 * we have already allocated. This is okay; these formats are
238 * hanging off of dt_formats and will therefore not be leaked.
239 */
240 free(enabled);
241 free(probe);
242 return (rval);
243}
244
245int
246dt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid,
247 dtrace_eprobedesc_t **epdp, dtrace_probedesc_t **pdp)
248{
249 int rval;
250
251 if (epid >= dtp->dt_maxprobe || dtp->dt_pdesc[epid] == NULL) {
252 if ((rval = dt_epid_add(dtp, epid)) != 0)
253 return (rval);
254 }
255
256 assert(epid < dtp->dt_maxprobe);
257 assert(dtp->dt_edesc[epid] != NULL);
258 assert(dtp->dt_pdesc[epid] != NULL);
259 *epdp = dtp->dt_edesc[epid];
260 *pdp = dtp->dt_pdesc[epid];
261
262 return (0);
263}
264
265void
266dt_epid_destroy(dtrace_hdl_t *dtp)
267{
268 size_t i;
269
270 assert((dtp->dt_pdesc != NULL && dtp->dt_edesc != NULL &&
271 dtp->dt_maxprobe > 0) || (dtp->dt_pdesc == NULL &&
272 dtp->dt_edesc == NULL && dtp->dt_maxprobe == 0));
273
274 if (dtp->dt_pdesc == NULL)
275 return;
276
277 for (i = 0; i < dtp->dt_maxprobe; i++) {
278 if (dtp->dt_edesc[i] == NULL) {
279 assert(dtp->dt_pdesc[i] == NULL);
280 continue;
281 }
282
283 assert(dtp->dt_pdesc[i] != NULL);
284 free(dtp->dt_edesc[i]);
285 free(dtp->dt_pdesc[i]);
286 }
287
288 free(dtp->dt_pdesc);
289 dtp->dt_pdesc = NULL;
290
291 free(dtp->dt_edesc);
292 dtp->dt_edesc = NULL;
293 dtp->dt_maxprobe = 0;
294}
295
296void *
297dt_format_lookup(dtrace_hdl_t *dtp, int format)
298{
299 if (format == 0 || format > dtp->dt_maxformat)
300 return (NULL);
301
302 if (dtp->dt_formats == NULL)
303 return (NULL);
304
305 return (dtp->dt_formats[format - 1]);
306}
307
308void
309dt_format_destroy(dtrace_hdl_t *dtp)
310{
311 int i;
312
313 for (i = 0; i < dtp->dt_maxformat; i++) {
314 if (dtp->dt_formats[i] != NULL)
315 dt_printf_destroy(dtp->dt_formats[i]);
316 }
317
318 free(dtp->dt_formats);
319 dtp->dt_formats = NULL;
320}
321
322static int
323dt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id)
324{
325 dtrace_id_t max;
326 dtrace_epid_t epid;
327 int rval;
328
329 while (id >= (max = dtp->dt_maxagg) || dtp->dt_aggdesc == NULL) {
330 dtrace_id_t new_max = max ? (max << 1) : 1;
331 size_t nsize = new_max * sizeof (void *);
332 dtrace_aggdesc_t **new_aggdesc;
333
334 if ((new_aggdesc = malloc(nsize)) == NULL)
335 return (dt_set_errno(dtp, EDT_NOMEM));
336
337 bzero(new_aggdesc, nsize);
338
339 if (dtp->dt_aggdesc != NULL) {
340 bcopy(dtp->dt_aggdesc, new_aggdesc,
341 max * sizeof (void *));
342 free(dtp->dt_aggdesc);
343 }
344
345 dtp->dt_aggdesc = new_aggdesc;
346 dtp->dt_maxagg = new_max;
347 }
348
349 if (dtp->dt_aggdesc[id] == NULL) {
350 dtrace_aggdesc_t *agg, *nagg;
351
352 if ((agg = malloc(sizeof (dtrace_aggdesc_t))) == NULL)
353 return (dt_set_errno(dtp, EDT_NOMEM));
354
355 bzero(agg, sizeof (dtrace_aggdesc_t));
356 agg->dtagd_id = id;
357 agg->dtagd_nrecs = 1;
358
359#if defined(sun)
360 if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg) == -1) {
361#else
362 if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg) == -1) {
363#endif
364 rval = dt_set_errno(dtp, errno);
365 free(agg);
366 return (rval);
367 }
368
369 if (DTRACE_SIZEOF_AGGDESC(agg) != sizeof (*agg)) {
370 /*
371 * There must be more than one action. Allocate the
372 * appropriate amount of space and try again.
373 */
374 if ((nagg = malloc(DTRACE_SIZEOF_AGGDESC(agg))) != NULL)
375 bcopy(agg, nagg, sizeof (*agg));
376
377 free(agg);
378
379 if ((agg = nagg) == NULL)
380 return (dt_set_errno(dtp, EDT_NOMEM));
381
382#if defined(sun)
383 rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg);
384#else
385 rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg);
386#endif
387
388 if (rval == -1) {
389 rval = dt_set_errno(dtp, errno);
390 free(agg);
391 return (rval);
392 }
393 }
394
395 /*
396 * If we have a uarg, it's a pointer to the compiler-generated
397 * statement; we'll use this value to get the name and
398 * compiler-generated variable ID for the aggregation. If
399 * we're grabbing an anonymous enabling, this pointer value
400 * is obviously meaningless -- and in this case, we can't
401 * provide the compiler-generated aggregation information.
402 */
403 if (dtp->dt_options[DTRACEOPT_GRABANON] == DTRACEOPT_UNSET &&
404 agg->dtagd_rec[0].dtrd_uarg != 0) {
405 dtrace_stmtdesc_t *sdp;
406 dt_ident_t *aid;
407
408 sdp = (dtrace_stmtdesc_t *)(uintptr_t)
409 agg->dtagd_rec[0].dtrd_uarg;
410 aid = sdp->dtsd_aggdata;
411 agg->dtagd_name = aid->di_name;
412 agg->dtagd_varid = aid->di_id;
413 } else {
414 agg->dtagd_varid = DTRACE_AGGVARIDNONE;
415 }
416
417 if ((epid = agg->dtagd_epid) >= dtp->dt_maxprobe ||
418 dtp->dt_pdesc[epid] == NULL) {
419 if ((rval = dt_epid_add(dtp, epid)) != 0) {
420 free(agg);
421 return (rval);
422 }
423 }
424
425 dtp->dt_aggdesc[id] = agg;
426 }
427
428 return (0);
429}
430
431int
432dt_aggid_lookup(dtrace_hdl_t *dtp, dtrace_aggid_t aggid,
433 dtrace_aggdesc_t **adp)
434{
435 int rval;
436
437 if (aggid >= dtp->dt_maxagg || dtp->dt_aggdesc[aggid] == NULL) {
438 if ((rval = dt_aggid_add(dtp, aggid)) != 0)
439 return (rval);
440 }
441
442 assert(aggid < dtp->dt_maxagg);
443 assert(dtp->dt_aggdesc[aggid] != NULL);
444 *adp = dtp->dt_aggdesc[aggid];
445
446 return (0);
447}
448
449void
450dt_aggid_destroy(dtrace_hdl_t *dtp)
451{
452 size_t i;
453
454 assert((dtp->dt_aggdesc != NULL && dtp->dt_maxagg != 0) ||
455 (dtp->dt_aggdesc == NULL && dtp->dt_maxagg == 0));
456
457 if (dtp->dt_aggdesc == NULL)
458 return;
459
460 for (i = 0; i < dtp->dt_maxagg; i++) {
461 if (dtp->dt_aggdesc[i] != NULL)
462 free(dtp->dt_aggdesc[i]);
463 }
464
465 free(dtp->dt_aggdesc);
466 dtp->dt_aggdesc = NULL;
467 dtp->dt_maxagg = 0;
468}
469
470const char *
471dt_strdata_lookup(dtrace_hdl_t *dtp, int idx)
472{
473 if (idx == 0 || idx > dtp->dt_maxstrdata)
474 return (NULL);
475
476 if (dtp->dt_strdata == NULL)
477 return (NULL);
478
479 return (dtp->dt_strdata[idx - 1]);
480}
481
482void
483dt_strdata_destroy(dtrace_hdl_t *dtp)
484{
485 int i;
486
487 for (i = 0; i < dtp->dt_maxstrdata; i++) {
488 free(dtp->dt_strdata[i]);
489 }
490
491 free(dtp->dt_strdata);
492 dtp->dt_strdata = NULL;
493}