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.
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.
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]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Copyright (c) 2011 by Delphix. All rights reserved.
37 #include <dt_printf.h>
40 dt_strdata_add(dtrace_hdl_t
*dtp
, dtrace_recdesc_t
*rec
, void ***data
, int *max
)
46 if (rec
->dtrd_format
== 0)
49 if (rec
->dtrd_format
<= *max
&&
50 (*data
)[rec
->dtrd_format
- 1] != NULL
) {
54 bzero(&fmt
, sizeof (fmt
));
55 fmt
.dtfd_format
= rec
->dtrd_format
;
56 fmt
.dtfd_string
= NULL
;
59 if (dt_ioctl(dtp
, DTRACEIOC_FORMAT
, &fmt
) == -1)
60 return (dt_set_errno(dtp
, errno
));
62 if ((fmt
.dtfd_string
= dt_alloc(dtp
, fmt
.dtfd_length
)) == NULL
)
63 return (dt_set_errno(dtp
, EDT_NOMEM
));
65 if (dt_ioctl(dtp
, DTRACEIOC_FORMAT
, &fmt
) == -1) {
66 free(fmt
.dtfd_string
);
67 return (dt_set_errno(dtp
, errno
));
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
);
76 if (new_data
== NULL
) {
77 dt_free(dtp
, fmt
.dtfd_string
);
78 return (dt_set_errno(dtp
, EDT_NOMEM
));
81 bcopy(*data
, new_data
, osize
);
88 switch (rec
->dtrd_action
) {
89 case DTRACEACT_DIFEXPR
:
90 result
= fmt
.dtfd_string
;
92 case DTRACEACT_PRINTA
:
93 result
= dtrace_printa_create(dtp
, fmt
.dtfd_string
);
94 dt_free(dtp
, fmt
.dtfd_string
);
97 result
= dtrace_printf_create(dtp
, fmt
.dtfd_string
);
98 dt_free(dtp
, fmt
.dtfd_string
);
105 (*data
)[rec
->dtrd_format
- 1] = result
;
111 dt_epid_add(dtrace_hdl_t
*dtp
, dtrace_epid_t id
)
115 dtrace_eprobedesc_t
*enabled
, *nenabled
;
116 dtrace_probedesc_t
*probe
;
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
;
124 if ((new_pdesc
= malloc(nsize
)) == NULL
||
125 (new_edesc
= malloc(nsize
)) == NULL
) {
127 return (dt_set_errno(dtp
, EDT_NOMEM
));
130 bzero(new_pdesc
, nsize
);
131 bzero(new_edesc
, nsize
);
133 if (dtp
->dt_pdesc
!= NULL
) {
134 size_t osize
= max
* sizeof (void *);
136 bcopy(dtp
->dt_pdesc
, new_pdesc
, osize
);
139 bcopy(dtp
->dt_edesc
, new_edesc
, osize
);
143 dtp
->dt_pdesc
= new_pdesc
;
144 dtp
->dt_edesc
= new_edesc
;
145 dtp
->dt_maxprobe
= new_max
;
148 if (dtp
->dt_pdesc
[id
] != NULL
)
151 if ((enabled
= malloc(sizeof (dtrace_eprobedesc_t
))) == NULL
)
152 return (dt_set_errno(dtp
, EDT_NOMEM
));
154 bzero(enabled
, sizeof (dtrace_eprobedesc_t
));
155 enabled
->dtepd_epid
= id
;
156 enabled
->dtepd_nrecs
= 1;
158 if (dt_ioctl(dtp
, DTRACEIOC_EPROBE
, enabled
) == -1) {
159 rval
= dt_set_errno(dtp
, errno
);
164 if (DTRACE_SIZEOF_EPROBEDESC(enabled
) != sizeof (*enabled
)) {
166 * There must be more than one action. Allocate the
167 * appropriate amount of space and try again.
170 malloc(DTRACE_SIZEOF_EPROBEDESC(enabled
))) != NULL
)
171 bcopy(enabled
, nenabled
, sizeof (*enabled
));
175 if ((enabled
= nenabled
) == NULL
)
176 return (dt_set_errno(dtp
, EDT_NOMEM
));
178 rval
= dt_ioctl(dtp
, DTRACEIOC_EPROBE
, enabled
);
181 rval
= dt_set_errno(dtp
, errno
);
187 if ((probe
= malloc(sizeof (dtrace_probedesc_t
))) == NULL
) {
189 return (dt_set_errno(dtp
, EDT_NOMEM
));
192 probe
->dtpd_id
= enabled
->dtepd_probeid
;
194 if (dt_ioctl(dtp
, DTRACEIOC_PROBES
, probe
) == -1) {
195 rval
= dt_set_errno(dtp
, errno
);
199 for (i
= 0; i
< enabled
->dtepd_nrecs
; i
++) {
200 dtrace_recdesc_t
*rec
= &enabled
->dtepd_rec
[i
];
202 if (DTRACEACT_ISPRINTFLIKE(rec
->dtrd_action
)) {
203 if (dt_strdata_add(dtp
, rec
, &dtp
->dt_formats
,
204 &dtp
->dt_maxformat
) != 0) {
208 } else if (rec
->dtrd_action
== DTRACEACT_DIFEXPR
) {
209 if (dt_strdata_add(dtp
, rec
,
210 (void ***)&dtp
->dt_strdata
,
211 &dtp
->dt_maxstrdata
) != 0) {
219 dtp
->dt_pdesc
[id
] = probe
;
220 dtp
->dt_edesc
[id
] = enabled
;
226 * If we failed, free our allocated probes. Note that if we failed
227 * while allocating formats, we aren't going to free formats that
228 * we have already allocated. This is okay; these formats are
229 * hanging off of dt_formats and will therefore not be leaked.
237 dt_epid_lookup(dtrace_hdl_t
*dtp
, dtrace_epid_t epid
,
238 dtrace_eprobedesc_t
**epdp
, dtrace_probedesc_t
**pdp
)
242 if (epid
>= dtp
->dt_maxprobe
|| dtp
->dt_pdesc
[epid
] == NULL
) {
243 if ((rval
= dt_epid_add(dtp
, epid
)) != 0)
247 assert(epid
< dtp
->dt_maxprobe
);
248 assert(dtp
->dt_edesc
[epid
] != NULL
);
249 assert(dtp
->dt_pdesc
[epid
] != NULL
);
250 *epdp
= dtp
->dt_edesc
[epid
];
251 *pdp
= dtp
->dt_pdesc
[epid
];
257 dt_epid_destroy(dtrace_hdl_t
*dtp
)
261 assert((dtp
->dt_pdesc
!= NULL
&& dtp
->dt_edesc
!= NULL
&&
262 dtp
->dt_maxprobe
> 0) || (dtp
->dt_pdesc
== NULL
&&
263 dtp
->dt_edesc
== NULL
&& dtp
->dt_maxprobe
== 0));
265 if (dtp
->dt_pdesc
== NULL
)
268 for (i
= 0; i
< dtp
->dt_maxprobe
; i
++) {
269 if (dtp
->dt_edesc
[i
] == NULL
) {
270 assert(dtp
->dt_pdesc
[i
] == NULL
);
274 assert(dtp
->dt_pdesc
[i
] != NULL
);
275 free(dtp
->dt_edesc
[i
]);
276 free(dtp
->dt_pdesc
[i
]);
280 dtp
->dt_pdesc
= NULL
;
283 dtp
->dt_edesc
= NULL
;
284 dtp
->dt_maxprobe
= 0;
288 dt_format_lookup(dtrace_hdl_t
*dtp
, int format
)
290 if (format
== 0 || format
> dtp
->dt_maxformat
)
293 if (dtp
->dt_formats
== NULL
)
296 return (dtp
->dt_formats
[format
- 1]);
300 dt_format_destroy(dtrace_hdl_t
*dtp
)
304 for (i
= 0; i
< dtp
->dt_maxformat
; i
++) {
305 if (dtp
->dt_formats
[i
] != NULL
)
306 dt_printf_destroy(dtp
->dt_formats
[i
]);
309 free(dtp
->dt_formats
);
310 dtp
->dt_formats
= NULL
;
314 dt_aggid_add(dtrace_hdl_t
*dtp
, dtrace_aggid_t id
)
320 while (id
>= (max
= dtp
->dt_maxagg
) || dtp
->dt_aggdesc
== NULL
) {
321 dtrace_id_t new_max
= max
? (max
<< 1) : 1;
322 size_t nsize
= new_max
* sizeof (void *);
323 dtrace_aggdesc_t
**new_aggdesc
;
325 if ((new_aggdesc
= malloc(nsize
)) == NULL
)
326 return (dt_set_errno(dtp
, EDT_NOMEM
));
328 bzero(new_aggdesc
, nsize
);
330 if (dtp
->dt_aggdesc
!= NULL
) {
331 bcopy(dtp
->dt_aggdesc
, new_aggdesc
,
332 max
* sizeof (void *));
333 free(dtp
->dt_aggdesc
);
336 dtp
->dt_aggdesc
= new_aggdesc
;
337 dtp
->dt_maxagg
= new_max
;
340 if (dtp
->dt_aggdesc
[id
] == NULL
) {
341 dtrace_aggdesc_t
*agg
, *nagg
;
343 if ((agg
= malloc(sizeof (dtrace_aggdesc_t
))) == NULL
)
344 return (dt_set_errno(dtp
, EDT_NOMEM
));
346 bzero(agg
, sizeof (dtrace_aggdesc_t
));
348 agg
->dtagd_nrecs
= 1;
350 if (dt_ioctl(dtp
, DTRACEIOC_AGGDESC
, agg
) == -1) {
351 rval
= dt_set_errno(dtp
, errno
);
356 if (DTRACE_SIZEOF_AGGDESC(agg
) != sizeof (*agg
)) {
358 * There must be more than one action. Allocate the
359 * appropriate amount of space and try again.
361 if ((nagg
= malloc(DTRACE_SIZEOF_AGGDESC(agg
))) != NULL
)
362 bcopy(agg
, nagg
, sizeof (*agg
));
366 if ((agg
= nagg
) == NULL
)
367 return (dt_set_errno(dtp
, EDT_NOMEM
));
369 rval
= dt_ioctl(dtp
, DTRACEIOC_AGGDESC
, agg
);
372 rval
= dt_set_errno(dtp
, errno
);
379 * If we have a uarg, it's a pointer to the compiler-generated
380 * statement; we'll use this value to get the name and
381 * compiler-generated variable ID for the aggregation. If
382 * we're grabbing an anonymous enabling, this pointer value
383 * is obviously meaningless -- and in this case, we can't
384 * provide the compiler-generated aggregation information.
386 if (dtp
->dt_options
[DTRACEOPT_GRABANON
] == DTRACEOPT_UNSET
&&
387 agg
->dtagd_rec
[0].dtrd_uarg
!= NULL
) {
388 dtrace_stmtdesc_t
*sdp
;
391 sdp
= (dtrace_stmtdesc_t
*)(uintptr_t)
392 agg
->dtagd_rec
[0].dtrd_uarg
;
393 aid
= sdp
->dtsd_aggdata
;
394 agg
->dtagd_name
= aid
->di_name
;
395 agg
->dtagd_varid
= aid
->di_id
;
397 agg
->dtagd_varid
= DTRACE_AGGVARIDNONE
;
400 if ((epid
= agg
->dtagd_epid
) >= dtp
->dt_maxprobe
||
401 dtp
->dt_pdesc
[epid
] == NULL
) {
402 if ((rval
= dt_epid_add(dtp
, epid
)) != 0) {
408 dtp
->dt_aggdesc
[id
] = agg
;
415 dt_aggid_lookup(dtrace_hdl_t
*dtp
, dtrace_aggid_t aggid
,
416 dtrace_aggdesc_t
**adp
)
420 if (aggid
>= dtp
->dt_maxagg
|| dtp
->dt_aggdesc
[aggid
] == NULL
) {
421 if ((rval
= dt_aggid_add(dtp
, aggid
)) != 0)
425 assert(aggid
< dtp
->dt_maxagg
);
426 assert(dtp
->dt_aggdesc
[aggid
] != NULL
);
427 *adp
= dtp
->dt_aggdesc
[aggid
];
433 dt_aggid_destroy(dtrace_hdl_t
*dtp
)
437 assert((dtp
->dt_aggdesc
!= NULL
&& dtp
->dt_maxagg
!= 0) ||
438 (dtp
->dt_aggdesc
== NULL
&& dtp
->dt_maxagg
== 0));
440 if (dtp
->dt_aggdesc
== NULL
)
443 for (i
= 0; i
< dtp
->dt_maxagg
; i
++) {
444 if (dtp
->dt_aggdesc
[i
] != NULL
)
445 free(dtp
->dt_aggdesc
[i
]);
448 free(dtp
->dt_aggdesc
);
449 dtp
->dt_aggdesc
= NULL
;
454 dt_strdata_lookup(dtrace_hdl_t
*dtp
, int idx
)
456 if (idx
== 0 || idx
> dtp
->dt_maxstrdata
)
459 if (dtp
->dt_strdata
== NULL
)
462 return (dtp
->dt_strdata
[idx
- 1]);
466 dt_strdata_destroy(dtrace_hdl_t
*dtp
)
470 for (i
= 0; i
< dtp
->dt_maxstrdata
; i
++) {
471 free(dtp
->dt_strdata
[i
]);
474 free(dtp
->dt_strdata
);
475 dtp
->dt_strdata
= NULL
;