Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/cddl/contrib/opensolaris/lib/libdtrace/common/dt_map.c
39562 views
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
39
static int
40
dt_strdata_add(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, void ***data, int *max)
41
{
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) {
66
rval = dt_set_errno(dtp, errno);
67
free(fmt.dtfd_string);
68
return (rval);
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
111
static int
112
dt_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
#ifdef illumos
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
#ifdef illumos
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
233
err:
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
245
int
246
dt_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
265
void
266
dt_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
296
void *
297
dt_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
308
void
309
dt_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
322
static int
323
dt_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
#ifdef illumos
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
#ifdef illumos
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
431
int
432
dt_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
449
void
450
dt_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
470
const char *
471
dt_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
482
void
483
dt_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
}
494
495