8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libdtrace / common / dt_map.c
blob8a3ce817e4d7a7929a60d4b5b456cb94cb060c0a
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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.
30 #include <stdlib.h>
31 #include <strings.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <assert.h>
36 #include <dt_impl.h>
37 #include <dt_printf.h>
39 static int
40 dt_strdata_add(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, void ***data, int *max)
42 int maxformat;
43 dtrace_fmtdesc_t fmt;
44 void *result;
46 if (rec->dtrd_format == 0)
47 return (0);
49 if (rec->dtrd_format <= *max &&
50 (*data)[rec->dtrd_format - 1] != NULL) {
51 return (0);
54 bzero(&fmt, sizeof (fmt));
55 fmt.dtfd_format = rec->dtrd_format;
56 fmt.dtfd_string = NULL;
57 fmt.dtfd_length = 0;
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);
82 free(*data);
84 *data = new_data;
85 *max = new_max;
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;
102 if (result == NULL)
103 return (-1);
105 (*data)[rec->dtrd_format - 1] = result;
107 return (0);
110 static int
111 dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
113 dtrace_id_t max;
114 int rval, i;
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) {
126 free(new_pdesc);
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);
137 free(dtp->dt_pdesc);
139 bcopy(dtp->dt_edesc, new_edesc, osize);
140 free(dtp->dt_edesc);
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)
149 return (0);
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);
160 free(enabled);
161 return (rval);
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.
169 if ((nenabled =
170 malloc(DTRACE_SIZEOF_EPROBEDESC(enabled))) != NULL)
171 bcopy(enabled, nenabled, sizeof (*enabled));
173 free(enabled);
175 if ((enabled = nenabled) == NULL)
176 return (dt_set_errno(dtp, EDT_NOMEM));
178 rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled);
180 if (rval == -1) {
181 rval = dt_set_errno(dtp, errno);
182 free(enabled);
183 return (rval);
187 if ((probe = malloc(sizeof (dtrace_probedesc_t))) == NULL) {
188 free(enabled);
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);
196 goto err;
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) {
205 rval = -1;
206 goto err;
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) {
212 rval = -1;
213 goto err;
219 dtp->dt_pdesc[id] = probe;
220 dtp->dt_edesc[id] = enabled;
222 return (0);
224 err:
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.
231 free(enabled);
232 free(probe);
233 return (rval);
237 dt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid,
238 dtrace_eprobedesc_t **epdp, dtrace_probedesc_t **pdp)
240 int rval;
242 if (epid >= dtp->dt_maxprobe || dtp->dt_pdesc[epid] == NULL) {
243 if ((rval = dt_epid_add(dtp, epid)) != 0)
244 return (rval);
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];
253 return (0);
256 void
257 dt_epid_destroy(dtrace_hdl_t *dtp)
259 size_t i;
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)
266 return;
268 for (i = 0; i < dtp->dt_maxprobe; i++) {
269 if (dtp->dt_edesc[i] == NULL) {
270 assert(dtp->dt_pdesc[i] == NULL);
271 continue;
274 assert(dtp->dt_pdesc[i] != NULL);
275 free(dtp->dt_edesc[i]);
276 free(dtp->dt_pdesc[i]);
279 free(dtp->dt_pdesc);
280 dtp->dt_pdesc = NULL;
282 free(dtp->dt_edesc);
283 dtp->dt_edesc = NULL;
284 dtp->dt_maxprobe = 0;
287 void *
288 dt_format_lookup(dtrace_hdl_t *dtp, int format)
290 if (format == 0 || format > dtp->dt_maxformat)
291 return (NULL);
293 if (dtp->dt_formats == NULL)
294 return (NULL);
296 return (dtp->dt_formats[format - 1]);
299 void
300 dt_format_destroy(dtrace_hdl_t *dtp)
302 int i;
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;
313 static int
314 dt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id)
316 dtrace_id_t max;
317 dtrace_epid_t epid;
318 int rval;
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));
347 agg->dtagd_id = id;
348 agg->dtagd_nrecs = 1;
350 if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg) == -1) {
351 rval = dt_set_errno(dtp, errno);
352 free(agg);
353 return (rval);
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));
364 free(agg);
366 if ((agg = nagg) == NULL)
367 return (dt_set_errno(dtp, EDT_NOMEM));
369 rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg);
371 if (rval == -1) {
372 rval = dt_set_errno(dtp, errno);
373 free(agg);
374 return (rval);
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;
389 dt_ident_t *aid;
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;
396 } else {
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) {
403 free(agg);
404 return (rval);
408 dtp->dt_aggdesc[id] = agg;
411 return (0);
415 dt_aggid_lookup(dtrace_hdl_t *dtp, dtrace_aggid_t aggid,
416 dtrace_aggdesc_t **adp)
418 int rval;
420 if (aggid >= dtp->dt_maxagg || dtp->dt_aggdesc[aggid] == NULL) {
421 if ((rval = dt_aggid_add(dtp, aggid)) != 0)
422 return (rval);
425 assert(aggid < dtp->dt_maxagg);
426 assert(dtp->dt_aggdesc[aggid] != NULL);
427 *adp = dtp->dt_aggdesc[aggid];
429 return (0);
432 void
433 dt_aggid_destroy(dtrace_hdl_t *dtp)
435 size_t i;
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)
441 return;
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;
450 dtp->dt_maxagg = 0;
453 const char *
454 dt_strdata_lookup(dtrace_hdl_t *dtp, int idx)
456 if (idx == 0 || idx > dtp->dt_maxstrdata)
457 return (NULL);
459 if (dtp->dt_strdata == NULL)
460 return (NULL);
462 return (dtp->dt_strdata[idx - 1]);
465 void
466 dt_strdata_destroy(dtrace_hdl_t *dtp)
468 int i;
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;