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_consume.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 2009 Sun Microsystems, Inc. All rights reserved.
23
* Use is subject to license terms.
24
*/
25
26
/*
27
* Copyright (c) 2023, Domagoj Stolfa. All rights reserved.
28
* Copyright (c) 2017, Joyent, Inc. All rights reserved.
29
* Copyright (c) 2012 by Delphix. All rights reserved.
30
*/
31
32
#include <stdlib.h>
33
#include <strings.h>
34
#include <errno.h>
35
#include <unistd.h>
36
#include <limits.h>
37
#include <assert.h>
38
#include <ctype.h>
39
#ifdef illumos
40
#include <alloca.h>
41
#endif
42
#include <dt_impl.h>
43
#include <dt_pq.h>
44
#include <dt_oformat.h>
45
#ifndef illumos
46
#include <libproc_compat.h>
47
#endif
48
49
#define DT_MASK_LO 0x00000000FFFFFFFFULL
50
51
#define dt_format_sym(dtp, addr) dt_print_sym((dtp), NULL, NULL, addr)
52
53
typedef struct dt_prepare_args {
54
int first_bin;
55
int last_bin;
56
union {
57
struct lquantize_args {
58
#define lquantize_step u.lquantize.step
59
#define lquantize_levels u.lquantize.levels
60
#define lquantize_base u.lquantize.base
61
int base;
62
uint16_t step;
63
uint16_t levels;
64
} lquantize;
65
struct llquantize_args {
66
#define llquantize_next u.llquantize.next
67
#define llquantize_step u.llquantize.step
68
#define llquantize_value u.llquantize.value
69
#define llquantize_levels u.llquantize.levels
70
#define llquantize_order u.llquantize.order
71
#define llquantize_factor u.llquantize.factor
72
#define llquantize_low u.llquantize.low
73
#define llquantize_high u.llquantize.high
74
#define llquantize_nsteps u.llquantize.nsteps
75
int64_t next;
76
int64_t step;
77
int64_t value;
78
int levels;
79
int order;
80
uint16_t factor;
81
uint16_t low;
82
uint16_t high;
83
uint16_t nsteps;
84
} llquantize;
85
} u;
86
} dt_prepare_args_t;
87
88
/*
89
* We declare this here because (1) we need it and (2) we want to avoid a
90
* dependency on libm in libdtrace.
91
*/
92
static long double
93
dt_fabsl(long double x)
94
{
95
if (x < 0)
96
return (-x);
97
98
return (x);
99
}
100
101
static int
102
dt_ndigits(long long val)
103
{
104
int rval = 1;
105
long long cmp = 10;
106
107
if (val < 0) {
108
val = val == INT64_MIN ? INT64_MAX : -val;
109
rval++;
110
}
111
112
while (val > cmp && cmp > 0) {
113
rval++;
114
cmp *= 10;
115
}
116
117
return (rval < 4 ? 4 : rval);
118
}
119
120
/*
121
* 128-bit arithmetic functions needed to support the stddev() aggregating
122
* action.
123
*/
124
static int
125
dt_gt_128(uint64_t *a, uint64_t *b)
126
{
127
return (a[1] > b[1] || (a[1] == b[1] && a[0] > b[0]));
128
}
129
130
static int
131
dt_ge_128(uint64_t *a, uint64_t *b)
132
{
133
return (a[1] > b[1] || (a[1] == b[1] && a[0] >= b[0]));
134
}
135
136
static int
137
dt_le_128(uint64_t *a, uint64_t *b)
138
{
139
return (a[1] < b[1] || (a[1] == b[1] && a[0] <= b[0]));
140
}
141
142
/*
143
* Shift the 128-bit value in a by b. If b is positive, shift left.
144
* If b is negative, shift right.
145
*/
146
static void
147
dt_shift_128(uint64_t *a, int b)
148
{
149
uint64_t mask;
150
151
if (b == 0)
152
return;
153
154
if (b < 0) {
155
b = -b;
156
if (b >= 64) {
157
a[0] = a[1] >> (b - 64);
158
a[1] = 0;
159
} else {
160
a[0] >>= b;
161
mask = 1LL << (64 - b);
162
mask -= 1;
163
a[0] |= ((a[1] & mask) << (64 - b));
164
a[1] >>= b;
165
}
166
} else {
167
if (b >= 64) {
168
a[1] = a[0] << (b - 64);
169
a[0] = 0;
170
} else {
171
a[1] <<= b;
172
mask = a[0] >> (64 - b);
173
a[1] |= mask;
174
a[0] <<= b;
175
}
176
}
177
}
178
179
static int
180
dt_nbits_128(uint64_t *a)
181
{
182
int nbits = 0;
183
uint64_t tmp[2];
184
uint64_t zero[2] = { 0, 0 };
185
186
tmp[0] = a[0];
187
tmp[1] = a[1];
188
189
dt_shift_128(tmp, -1);
190
while (dt_gt_128(tmp, zero)) {
191
dt_shift_128(tmp, -1);
192
nbits++;
193
}
194
195
return (nbits);
196
}
197
198
static void
199
dt_subtract_128(uint64_t *minuend, uint64_t *subtrahend, uint64_t *difference)
200
{
201
uint64_t result[2];
202
203
result[0] = minuend[0] - subtrahend[0];
204
result[1] = minuend[1] - subtrahend[1] -
205
(minuend[0] < subtrahend[0] ? 1 : 0);
206
207
difference[0] = result[0];
208
difference[1] = result[1];
209
}
210
211
static void
212
dt_add_128(uint64_t *addend1, uint64_t *addend2, uint64_t *sum)
213
{
214
uint64_t result[2];
215
216
result[0] = addend1[0] + addend2[0];
217
result[1] = addend1[1] + addend2[1] +
218
(result[0] < addend1[0] || result[0] < addend2[0] ? 1 : 0);
219
220
sum[0] = result[0];
221
sum[1] = result[1];
222
}
223
224
/*
225
* The basic idea is to break the 2 64-bit values into 4 32-bit values,
226
* use native multiplication on those, and then re-combine into the
227
* resulting 128-bit value.
228
*
229
* (hi1 << 32 + lo1) * (hi2 << 32 + lo2) =
230
* hi1 * hi2 << 64 +
231
* hi1 * lo2 << 32 +
232
* hi2 * lo1 << 32 +
233
* lo1 * lo2
234
*/
235
static void
236
dt_multiply_128(uint64_t factor1, uint64_t factor2, uint64_t *product)
237
{
238
uint64_t hi1, hi2, lo1, lo2;
239
uint64_t tmp[2];
240
241
hi1 = factor1 >> 32;
242
hi2 = factor2 >> 32;
243
244
lo1 = factor1 & DT_MASK_LO;
245
lo2 = factor2 & DT_MASK_LO;
246
247
product[0] = lo1 * lo2;
248
product[1] = hi1 * hi2;
249
250
tmp[0] = hi1 * lo2;
251
tmp[1] = 0;
252
dt_shift_128(tmp, 32);
253
dt_add_128(product, tmp, product);
254
255
tmp[0] = hi2 * lo1;
256
tmp[1] = 0;
257
dt_shift_128(tmp, 32);
258
dt_add_128(product, tmp, product);
259
}
260
261
/*
262
* This is long-hand division.
263
*
264
* We initialize subtrahend by shifting divisor left as far as possible. We
265
* loop, comparing subtrahend to dividend: if subtrahend is smaller, we
266
* subtract and set the appropriate bit in the result. We then shift
267
* subtrahend right by one bit for the next comparison.
268
*/
269
static void
270
dt_divide_128(uint64_t *dividend, uint64_t divisor, uint64_t *quotient)
271
{
272
uint64_t result[2] = { 0, 0 };
273
uint64_t remainder[2];
274
uint64_t subtrahend[2];
275
uint64_t divisor_128[2];
276
uint64_t mask[2] = { 1, 0 };
277
int log = 0;
278
279
assert(divisor != 0);
280
281
divisor_128[0] = divisor;
282
divisor_128[1] = 0;
283
284
remainder[0] = dividend[0];
285
remainder[1] = dividend[1];
286
287
subtrahend[0] = divisor;
288
subtrahend[1] = 0;
289
290
while (divisor > 0) {
291
log++;
292
divisor >>= 1;
293
}
294
295
dt_shift_128(subtrahend, 128 - log);
296
dt_shift_128(mask, 128 - log);
297
298
while (dt_ge_128(remainder, divisor_128)) {
299
if (dt_ge_128(remainder, subtrahend)) {
300
dt_subtract_128(remainder, subtrahend, remainder);
301
result[0] |= mask[0];
302
result[1] |= mask[1];
303
}
304
305
dt_shift_128(subtrahend, -1);
306
dt_shift_128(mask, -1);
307
}
308
309
quotient[0] = result[0];
310
quotient[1] = result[1];
311
}
312
313
/*
314
* This is the long-hand method of calculating a square root.
315
* The algorithm is as follows:
316
*
317
* 1. Group the digits by 2 from the right.
318
* 2. Over the leftmost group, find the largest single-digit number
319
* whose square is less than that group.
320
* 3. Subtract the result of the previous step (2 or 4, depending) and
321
* bring down the next two-digit group.
322
* 4. For the result R we have so far, find the largest single-digit number
323
* x such that 2 * R * 10 * x + x^2 is less than the result from step 3.
324
* (Note that this is doubling R and performing a decimal left-shift by 1
325
* and searching for the appropriate decimal to fill the one's place.)
326
* The value x is the next digit in the square root.
327
* Repeat steps 3 and 4 until the desired precision is reached. (We're
328
* dealing with integers, so the above is sufficient.)
329
*
330
* In decimal, the square root of 582,734 would be calculated as so:
331
*
332
* __7__6__3
333
* | 58 27 34
334
* -49 (7^2 == 49 => 7 is the first digit in the square root)
335
* --
336
* 9 27 (Subtract and bring down the next group.)
337
* 146 8 76 (2 * 7 * 10 * 6 + 6^2 == 876 => 6 is the next digit in
338
* ----- the square root)
339
* 51 34 (Subtract and bring down the next group.)
340
* 1523 45 69 (2 * 76 * 10 * 3 + 3^2 == 4569 => 3 is the next digit in
341
* ----- the square root)
342
* 5 65 (remainder)
343
*
344
* The above algorithm applies similarly in binary, but note that the
345
* only possible non-zero value for x in step 4 is 1, so step 4 becomes a
346
* simple decision: is 2 * R * 2 * 1 + 1^2 (aka R << 2 + 1) less than the
347
* preceding difference?
348
*
349
* In binary, the square root of 11011011 would be calculated as so:
350
*
351
* __1__1__1__0
352
* | 11 01 10 11
353
* 01 (0 << 2 + 1 == 1 < 11 => this bit is 1)
354
* --
355
* 10 01 10 11
356
* 101 1 01 (1 << 2 + 1 == 101 < 1001 => next bit is 1)
357
* -----
358
* 1 00 10 11
359
* 1101 11 01 (11 << 2 + 1 == 1101 < 10010 => next bit is 1)
360
* -------
361
* 1 01 11
362
* 11101 1 11 01 (111 << 2 + 1 == 11101 > 10111 => last bit is 0)
363
*
364
*/
365
static uint64_t
366
dt_sqrt_128(uint64_t *square)
367
{
368
uint64_t result[2] = { 0, 0 };
369
uint64_t diff[2] = { 0, 0 };
370
uint64_t one[2] = { 1, 0 };
371
uint64_t next_pair[2];
372
uint64_t next_try[2];
373
uint64_t bit_pairs, pair_shift;
374
int i;
375
376
bit_pairs = dt_nbits_128(square) / 2;
377
pair_shift = bit_pairs * 2;
378
379
for (i = 0; i <= bit_pairs; i++) {
380
/*
381
* Bring down the next pair of bits.
382
*/
383
next_pair[0] = square[0];
384
next_pair[1] = square[1];
385
dt_shift_128(next_pair, -pair_shift);
386
next_pair[0] &= 0x3;
387
next_pair[1] = 0;
388
389
dt_shift_128(diff, 2);
390
dt_add_128(diff, next_pair, diff);
391
392
/*
393
* next_try = R << 2 + 1
394
*/
395
next_try[0] = result[0];
396
next_try[1] = result[1];
397
dt_shift_128(next_try, 2);
398
dt_add_128(next_try, one, next_try);
399
400
if (dt_le_128(next_try, diff)) {
401
dt_subtract_128(diff, next_try, diff);
402
dt_shift_128(result, 1);
403
dt_add_128(result, one, result);
404
} else {
405
dt_shift_128(result, 1);
406
}
407
408
pair_shift -= 2;
409
}
410
411
assert(result[1] == 0);
412
413
return (result[0]);
414
}
415
416
uint64_t
417
dt_stddev(uint64_t *data, uint64_t normal)
418
{
419
uint64_t avg_of_squares[2];
420
uint64_t square_of_avg[2];
421
int64_t norm_avg;
422
uint64_t diff[2];
423
424
if (data[0] == 0)
425
return (0);
426
427
/*
428
* The standard approximation for standard deviation is
429
* sqrt(average(x**2) - average(x)**2), i.e. the square root
430
* of the average of the squares minus the square of the average.
431
* When normalizing, we should divide the sum of x**2 by normal**2.
432
*/
433
dt_divide_128(data + 2, normal, avg_of_squares);
434
dt_divide_128(avg_of_squares, normal, avg_of_squares);
435
dt_divide_128(avg_of_squares, data[0], avg_of_squares);
436
437
norm_avg = (int64_t)data[1] / (int64_t)normal / (int64_t)data[0];
438
439
if (norm_avg < 0)
440
norm_avg = -norm_avg;
441
442
dt_multiply_128((uint64_t)norm_avg, (uint64_t)norm_avg, square_of_avg);
443
444
dt_subtract_128(avg_of_squares, square_of_avg, diff);
445
446
return (dt_sqrt_128(diff));
447
}
448
449
static int
450
dt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last,
451
dtrace_bufdesc_t *buf, size_t offs)
452
{
453
dtrace_probedesc_t *pd = data->dtpda_pdesc, *npd;
454
dtrace_eprobedesc_t *epd = data->dtpda_edesc, *nepd;
455
char *p = pd->dtpd_provider, *n = pd->dtpd_name, *sub;
456
dtrace_flowkind_t flow = DTRACEFLOW_NONE;
457
const char *str = NULL;
458
static const char *e_str[2] = { " -> ", " => " };
459
static const char *r_str[2] = { " <- ", " <= " };
460
static const char *ent = "entry", *ret = "return";
461
static int entlen = 0, retlen = 0;
462
dtrace_epid_t next, id = epd->dtepd_epid;
463
int rval;
464
465
if (entlen == 0) {
466
assert(retlen == 0);
467
entlen = strlen(ent);
468
retlen = strlen(ret);
469
}
470
471
/*
472
* If the name of the probe is "entry" or ends with "-entry", we
473
* treat it as an entry; if it is "return" or ends with "-return",
474
* we treat it as a return. (This allows application-provided probes
475
* like "method-entry" or "function-entry" to participate in flow
476
* indentation -- without accidentally misinterpreting popular probe
477
* names like "carpentry", "gentry" or "Coventry".)
478
*/
479
if ((sub = strstr(n, ent)) != NULL && sub[entlen] == '\0' &&
480
(sub == n || sub[-1] == '-')) {
481
flow = DTRACEFLOW_ENTRY;
482
str = e_str[strcmp(p, "syscall") == 0];
483
} else if ((sub = strstr(n, ret)) != NULL && sub[retlen] == '\0' &&
484
(sub == n || sub[-1] == '-')) {
485
flow = DTRACEFLOW_RETURN;
486
str = r_str[strcmp(p, "syscall") == 0];
487
}
488
489
/*
490
* If we're going to indent this, we need to check the ID of our last
491
* call. If we're looking at the same probe ID but a different EPID,
492
* we _don't_ want to indent. (Yes, there are some minor holes in
493
* this scheme -- it's a heuristic.)
494
*/
495
if (flow == DTRACEFLOW_ENTRY) {
496
if ((last != DTRACE_EPIDNONE && id != last &&
497
pd->dtpd_id == dtp->dt_pdesc[last]->dtpd_id))
498
flow = DTRACEFLOW_NONE;
499
}
500
501
/*
502
* If we're going to unindent this, it's more difficult to see if
503
* we don't actually want to unindent it -- we need to look at the
504
* _next_ EPID.
505
*/
506
if (flow == DTRACEFLOW_RETURN) {
507
offs += epd->dtepd_size;
508
509
do {
510
if (offs >= buf->dtbd_size)
511
goto out;
512
513
next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);
514
515
if (next == DTRACE_EPIDNONE)
516
offs += sizeof (id);
517
} while (next == DTRACE_EPIDNONE);
518
519
if ((rval = dt_epid_lookup(dtp, next, &nepd, &npd)) != 0)
520
return (rval);
521
522
if (next != id && npd->dtpd_id == pd->dtpd_id)
523
flow = DTRACEFLOW_NONE;
524
}
525
526
out:
527
if (flow == DTRACEFLOW_ENTRY || flow == DTRACEFLOW_RETURN) {
528
data->dtpda_prefix = str;
529
} else {
530
data->dtpda_prefix = "| ";
531
}
532
533
if (flow == DTRACEFLOW_RETURN && data->dtpda_indent > 0)
534
data->dtpda_indent -= 2;
535
536
data->dtpda_flow = flow;
537
538
return (0);
539
}
540
541
static int
542
dt_nullprobe()
543
{
544
return (DTRACE_CONSUME_THIS);
545
}
546
547
static int
548
dt_nullrec()
549
{
550
return (DTRACE_CONSUME_NEXT);
551
}
552
553
static void
554
dt_quantize_total(dtrace_hdl_t *dtp, int64_t datum, long double *total)
555
{
556
long double val = dt_fabsl((long double)datum);
557
558
if (dtp->dt_options[DTRACEOPT_AGGZOOM] == DTRACEOPT_UNSET) {
559
*total += val;
560
return;
561
}
562
563
/*
564
* If we're zooming in on an aggregation, we want the height of the
565
* highest value to be approximately 95% of total bar height -- so we
566
* adjust up by the reciprocal of DTRACE_AGGZOOM_MAX when comparing to
567
* our highest value.
568
*/
569
val *= 1 / DTRACE_AGGZOOM_MAX;
570
571
if (*total < val)
572
*total = val;
573
}
574
575
static int
576
dt_print_quanthdr(dtrace_hdl_t *dtp, FILE *fp, int width)
577
{
578
return (dt_printf(dtp, fp, "\n%*s %41s %-9s\n",
579
width ? width : 16, width ? "key" : "value",
580
"------------- Distribution -------------", "count"));
581
}
582
583
static int
584
dt_print_quanthdr_packed(dtrace_hdl_t *dtp, FILE *fp, int width,
585
const dtrace_aggdata_t *aggdata, dtrace_actkind_t action)
586
{
587
int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin;
588
int minwidth, maxwidth, i;
589
590
assert(action == DTRACEAGG_QUANTIZE || action == DTRACEAGG_LQUANTIZE);
591
592
if (action == DTRACEAGG_QUANTIZE) {
593
if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
594
min--;
595
596
if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
597
max++;
598
599
minwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(min));
600
maxwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(max));
601
} else {
602
maxwidth = 8;
603
minwidth = maxwidth - 1;
604
max++;
605
}
606
607
if (dt_printf(dtp, fp, "\n%*s %*s .",
608
width, width > 0 ? "key" : "", minwidth, "min") < 0)
609
return (-1);
610
611
for (i = min; i <= max; i++) {
612
if (dt_printf(dtp, fp, "-") < 0)
613
return (-1);
614
}
615
616
return (dt_printf(dtp, fp, ". %*s | count\n", -maxwidth, "max"));
617
}
618
619
/*
620
* We use a subset of the Unicode Block Elements (U+2588 through U+258F,
621
* inclusive) to represent aggregations via UTF-8 -- which are expressed via
622
* 3-byte UTF-8 sequences.
623
*/
624
#define DTRACE_AGGUTF8_FULL 0x2588
625
#define DTRACE_AGGUTF8_BASE 0x258f
626
#define DTRACE_AGGUTF8_LEVELS 8
627
628
#define DTRACE_AGGUTF8_BYTE0(val) (0xe0 | ((val) >> 12))
629
#define DTRACE_AGGUTF8_BYTE1(val) (0x80 | (((val) >> 6) & 0x3f))
630
#define DTRACE_AGGUTF8_BYTE2(val) (0x80 | ((val) & 0x3f))
631
632
static int
633
dt_print_quantline_utf8(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
634
uint64_t normal, long double total)
635
{
636
uint_t len = 40, i, whole, partial;
637
long double f = (dt_fabsl((long double)val) * len) / total;
638
const char *spaces = " ";
639
640
whole = (uint_t)f;
641
partial = (uint_t)((f - (long double)(uint_t)f) *
642
(long double)DTRACE_AGGUTF8_LEVELS);
643
644
if (dt_printf(dtp, fp, "|") < 0)
645
return (-1);
646
647
for (i = 0; i < whole; i++) {
648
if (dt_printf(dtp, fp, "%c%c%c",
649
DTRACE_AGGUTF8_BYTE0(DTRACE_AGGUTF8_FULL),
650
DTRACE_AGGUTF8_BYTE1(DTRACE_AGGUTF8_FULL),
651
DTRACE_AGGUTF8_BYTE2(DTRACE_AGGUTF8_FULL)) < 0)
652
return (-1);
653
}
654
655
if (partial != 0) {
656
partial = DTRACE_AGGUTF8_BASE - (partial - 1);
657
658
if (dt_printf(dtp, fp, "%c%c%c",
659
DTRACE_AGGUTF8_BYTE0(partial),
660
DTRACE_AGGUTF8_BYTE1(partial),
661
DTRACE_AGGUTF8_BYTE2(partial)) < 0)
662
return (-1);
663
664
i++;
665
}
666
667
return (dt_printf(dtp, fp, "%s %-9lld\n", spaces + i,
668
(long long)val / normal));
669
}
670
671
static int
672
dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
673
uint64_t normal, long double total, char positives, char negatives)
674
{
675
long double f;
676
uint_t depth, len = 40;
677
678
const char *ats = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
679
const char *spaces = " ";
680
681
assert(strlen(ats) == len && strlen(spaces) == len);
682
assert(!(total == 0 && (positives || negatives)));
683
assert(!(val < 0 && !negatives));
684
assert(!(val > 0 && !positives));
685
assert(!(val != 0 && total == 0));
686
687
if (!negatives) {
688
if (positives) {
689
if (dtp->dt_encoding == DT_ENCODING_UTF8) {
690
return (dt_print_quantline_utf8(dtp, fp, val,
691
normal, total));
692
}
693
694
f = (dt_fabsl((long double)val) * len) / total;
695
depth = (uint_t)(f + 0.5);
696
} else {
697
depth = 0;
698
}
699
700
return (dt_printf(dtp, fp, "|%s%s %-9lld\n", ats + len - depth,
701
spaces + depth, (long long)val / normal));
702
}
703
704
if (!positives) {
705
f = (dt_fabsl((long double)val) * len) / total;
706
depth = (uint_t)(f + 0.5);
707
708
return (dt_printf(dtp, fp, "%s%s| %-9lld\n", spaces + depth,
709
ats + len - depth, (long long)val / normal));
710
}
711
712
/*
713
* If we're here, we have both positive and negative bucket values.
714
* To express this graphically, we're going to generate both positive
715
* and negative bars separated by a centerline. These bars are half
716
* the size of normal quantize()/lquantize() bars, so we divide the
717
* length in half before calculating the bar length.
718
*/
719
len /= 2;
720
ats = &ats[len];
721
spaces = &spaces[len];
722
723
f = (dt_fabsl((long double)val) * len) / total;
724
depth = (uint_t)(f + 0.5);
725
726
if (val <= 0) {
727
return (dt_printf(dtp, fp, "%s%s|%*s %-9lld\n", spaces + depth,
728
ats + len - depth, len, "", (long long)val / normal));
729
} else {
730
return (dt_printf(dtp, fp, "%20s|%s%s %-9lld\n", "",
731
ats + len - depth, spaces + depth,
732
(long long)val / normal));
733
}
734
}
735
736
/*
737
* As with UTF-8 printing of aggregations, we use a subset of the Unicode
738
* Block Elements (U+2581 through U+2588, inclusive) to represent our packed
739
* aggregation.
740
*/
741
#define DTRACE_AGGPACK_BASE 0x2581
742
#define DTRACE_AGGPACK_LEVELS 8
743
744
static int
745
dt_print_packed(dtrace_hdl_t *dtp, FILE *fp,
746
long double datum, long double total)
747
{
748
static boolean_t utf8_checked = B_FALSE;
749
static boolean_t utf8;
750
char *ascii = "__xxxxXX";
751
char *neg = "vvvvVV";
752
unsigned int len;
753
long double val;
754
755
if (!utf8_checked) {
756
char *term;
757
758
/*
759
* We want to determine if we can reasonably emit UTF-8 for our
760
* packed aggregation. To do this, we will check for terminals
761
* that are known to be primitive to emit UTF-8 on these.
762
*/
763
utf8_checked = B_TRUE;
764
765
if (dtp->dt_encoding == DT_ENCODING_ASCII) {
766
utf8 = B_FALSE;
767
} else if (dtp->dt_encoding == DT_ENCODING_UTF8) {
768
utf8 = B_TRUE;
769
} else if ((term = getenv("TERM")) != NULL &&
770
(strcmp(term, "sun") == 0 ||
771
strcmp(term, "sun-color") == 0 ||
772
strcmp(term, "dumb") == 0)) {
773
utf8 = B_FALSE;
774
} else {
775
utf8 = B_TRUE;
776
}
777
}
778
779
if (datum == 0)
780
return (dt_printf(dtp, fp, " "));
781
782
if (datum < 0) {
783
len = strlen(neg);
784
val = dt_fabsl(datum * (len - 1)) / total;
785
return (dt_printf(dtp, fp, "%c", neg[(uint_t)(val + 0.5)]));
786
}
787
788
if (utf8) {
789
int block = DTRACE_AGGPACK_BASE + (unsigned int)(((datum *
790
(DTRACE_AGGPACK_LEVELS - 1)) / total) + 0.5);
791
792
return (dt_printf(dtp, fp, "%c%c%c",
793
DTRACE_AGGUTF8_BYTE0(block),
794
DTRACE_AGGUTF8_BYTE1(block),
795
DTRACE_AGGUTF8_BYTE2(block)));
796
}
797
798
len = strlen(ascii);
799
val = (datum * (len - 1)) / total;
800
return (dt_printf(dtp, fp, "%c", ascii[(uint_t)(val + 0.5)]));
801
}
802
803
static const int64_t *
804
dt_format_quantize_prepare(dtrace_hdl_t *dtp, const void *addr, size_t size,
805
dt_prepare_args_t *args)
806
{
807
const int64_t *data = addr;
808
int first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1;
809
810
if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t)) {
811
(void) dt_set_errno(dtp, EDT_DMISMATCH);
812
return (NULL);
813
}
814
815
while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0)
816
first_bin++;
817
818
if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
819
/*
820
* There isn't any data. This is possible if the aggregation
821
* has been clear()'d or if negative increment values have been
822
* used. Regardless, we'll print the buckets around 0.
823
*/
824
first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
825
last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
826
} else {
827
if (first_bin > 0)
828
first_bin--;
829
830
while (last_bin > 0 && data[last_bin] == 0)
831
last_bin--;
832
833
if (last_bin < DTRACE_QUANTIZE_NBUCKETS - 1)
834
last_bin++;
835
}
836
837
args->first_bin = first_bin;
838
args->last_bin = last_bin;
839
return (data);
840
}
841
842
int
843
dt_format_quantize(dtrace_hdl_t *dtp, const void *addr, size_t size,
844
uint64_t normal)
845
{
846
const int64_t *data;
847
dt_prepare_args_t args = { 0 };
848
int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1;
849
850
data = dt_format_quantize_prepare(dtp, addr, size, &args);
851
/* dt_errno is set for us */
852
if (data == NULL)
853
return (-1);
854
855
first_bin = args.first_bin;
856
last_bin = args.last_bin;
857
858
xo_open_list("buckets");
859
for (i = first_bin; i <= last_bin; i++) {
860
long long value = (long long)DTRACE_QUANTIZE_BUCKETVAL(i);
861
xo_open_instance("buckets");
862
xo_emit("{:value/%lld} {:count/%lld}", value,
863
(long long)data[i] / normal);
864
xo_close_instance("buckets");
865
}
866
xo_close_list("buckets");
867
868
return (0);
869
}
870
871
int
872
dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
873
size_t size, uint64_t normal)
874
{
875
const int64_t *data;
876
dt_prepare_args_t args = { 0 };
877
int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1;
878
long double total = 0;
879
char positives = 0, negatives = 0;
880
881
data = dt_format_quantize_prepare(dtp, addr, size, &args);
882
/* dt_errno is set for us */
883
if (data == NULL)
884
return (-1);
885
886
first_bin = args.first_bin;
887
last_bin = args.last_bin;
888
889
for (i = first_bin; i <= last_bin; i++) {
890
positives |= (data[i] > 0);
891
negatives |= (data[i] < 0);
892
dt_quantize_total(dtp, data[i], &total);
893
}
894
895
if (dt_print_quanthdr(dtp, fp, 0) < 0)
896
return (-1);
897
898
for (i = first_bin; i <= last_bin; i++) {
899
if (dt_printf(dtp, fp, "%16lld ",
900
(long long)DTRACE_QUANTIZE_BUCKETVAL(i)) < 0)
901
return (-1);
902
903
if (dt_print_quantline(dtp, fp, data[i], normal, total,
904
positives, negatives) < 0)
905
return (-1);
906
}
907
908
return (0);
909
}
910
911
int
912
dt_print_quantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
913
size_t size, const dtrace_aggdata_t *aggdata)
914
{
915
const int64_t *data = addr;
916
long double total = 0, count = 0;
917
int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin, i;
918
int64_t minval, maxval;
919
920
if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
921
return (dt_set_errno(dtp, EDT_DMISMATCH));
922
923
if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
924
min--;
925
926
if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
927
max++;
928
929
minval = DTRACE_QUANTIZE_BUCKETVAL(min);
930
maxval = DTRACE_QUANTIZE_BUCKETVAL(max);
931
932
if (dt_printf(dtp, fp, " %*lld :", dt_ndigits(minval),
933
(long long)minval) < 0)
934
return (-1);
935
936
for (i = min; i <= max; i++) {
937
dt_quantize_total(dtp, data[i], &total);
938
count += data[i];
939
}
940
941
for (i = min; i <= max; i++) {
942
if (dt_print_packed(dtp, fp, data[i], total) < 0)
943
return (-1);
944
}
945
946
if (dt_printf(dtp, fp, ": %*lld | %lld\n",
947
-dt_ndigits(maxval), (long long)maxval, (long long)count) < 0)
948
return (-1);
949
950
return (0);
951
}
952
953
static const int64_t *
954
dt_format_lquantize_prepare(dtrace_hdl_t *dtp, const void *addr, size_t size,
955
dt_prepare_args_t *args)
956
{
957
const int64_t *data = addr;
958
int first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1, base;
959
uint64_t arg;
960
uint16_t step, levels;
961
962
if (size < sizeof (uint64_t)) {
963
(void) dt_set_errno(dtp, EDT_DMISMATCH);
964
return (NULL);
965
}
966
967
arg = *data++;
968
size -= sizeof (uint64_t);
969
970
base = DTRACE_LQUANTIZE_BASE(arg);
971
step = DTRACE_LQUANTIZE_STEP(arg);
972
levels = DTRACE_LQUANTIZE_LEVELS(arg);
973
974
first_bin = 0;
975
last_bin = levels + 1;
976
977
if (size != sizeof (uint64_t) * (levels + 2)) {
978
(void) dt_set_errno(dtp, EDT_DMISMATCH);
979
return (NULL);
980
}
981
982
while (first_bin <= levels + 1 && data[first_bin] == 0)
983
first_bin++;
984
985
if (first_bin > levels + 1) {
986
first_bin = 0;
987
last_bin = 2;
988
} else {
989
if (first_bin > 0)
990
first_bin--;
991
992
while (last_bin > 0 && data[last_bin] == 0)
993
last_bin--;
994
995
if (last_bin < levels + 1)
996
last_bin++;
997
}
998
999
args->first_bin = first_bin;
1000
args->last_bin = last_bin;
1001
args->lquantize_base = base;
1002
args->lquantize_step = step;
1003
args->lquantize_levels = levels;
1004
return (data);
1005
}
1006
1007
int
1008
dt_format_lquantize(dtrace_hdl_t *dtp, const void *addr, size_t size,
1009
uint64_t normal)
1010
{
1011
const int64_t *data;
1012
dt_prepare_args_t args = { 0 };
1013
int i, first_bin, last_bin, base;
1014
uint16_t step, levels;
1015
1016
data = dt_format_lquantize_prepare(dtp, addr, size, &args);
1017
/* dt_errno is set for us */
1018
if (data == NULL)
1019
return (-1);
1020
1021
first_bin = args.first_bin;
1022
last_bin = args.last_bin;
1023
step = args.lquantize_step;
1024
levels = args.lquantize_levels;
1025
base = args.lquantize_base;
1026
1027
xo_open_list("buckets");
1028
for (i = first_bin; i <= last_bin; i++) {
1029
char c[32];
1030
int err;
1031
1032
xo_open_instance("buckets");
1033
if (i == 0) {
1034
xo_emit("{:value/%d} {:operator/%s}", base, "<");
1035
} else if (i == levels + 1) {
1036
xo_emit("{:value/%d} {:operator/%s}",
1037
base + (levels * step), ">=");
1038
} else {
1039
xo_emit("{:value/%d}", base + (i - 1) * step);
1040
}
1041
1042
xo_emit("{:count/%lld}", (long long)data[i] / normal);
1043
xo_close_instance("buckets");
1044
}
1045
xo_close_list("buckets");
1046
1047
return (0);
1048
}
1049
1050
int
1051
dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
1052
size_t size, uint64_t normal)
1053
{
1054
const int64_t *data;
1055
dt_prepare_args_t args = { 0 };
1056
int i, first_bin, last_bin, base;
1057
uint64_t arg;
1058
long double total = 0;
1059
uint16_t step, levels;
1060
char positives = 0, negatives = 0;
1061
1062
data = dt_format_lquantize_prepare(dtp, addr, size, &args);
1063
/* dt_errno is set for us */
1064
if (data == NULL)
1065
return (-1);
1066
1067
first_bin = args.first_bin;
1068
last_bin = args.last_bin;
1069
step = args.lquantize_step;
1070
levels = args.lquantize_levels;
1071
base = args.lquantize_base;
1072
1073
for (i = first_bin; i <= last_bin; i++) {
1074
positives |= (data[i] > 0);
1075
negatives |= (data[i] < 0);
1076
dt_quantize_total(dtp, data[i], &total);
1077
}
1078
1079
if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
1080
"------------- Distribution -------------", "count") < 0)
1081
return (-1);
1082
1083
for (i = first_bin; i <= last_bin; i++) {
1084
char c[32];
1085
int err;
1086
1087
if (i == 0) {
1088
(void) snprintf(c, sizeof (c), "< %d", base);
1089
err = dt_printf(dtp, fp, "%16s ", c);
1090
} else if (i == levels + 1) {
1091
(void) snprintf(c, sizeof (c), ">= %d",
1092
base + (levels * step));
1093
err = dt_printf(dtp, fp, "%16s ", c);
1094
} else {
1095
err = dt_printf(dtp, fp, "%16d ",
1096
base + (i - 1) * step);
1097
}
1098
1099
if (err < 0 || dt_print_quantline(dtp, fp, data[i], normal,
1100
total, positives, negatives) < 0)
1101
return (-1);
1102
}
1103
1104
return (0);
1105
}
1106
1107
/*ARGSUSED*/
1108
int
1109
dt_print_lquantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
1110
size_t size, const dtrace_aggdata_t *aggdata)
1111
{
1112
const int64_t *data = addr;
1113
long double total = 0, count = 0;
1114
int min, max, base, err;
1115
uint64_t arg;
1116
uint16_t step, levels;
1117
char c[32];
1118
unsigned int i;
1119
1120
if (size < sizeof (uint64_t))
1121
return (dt_set_errno(dtp, EDT_DMISMATCH));
1122
1123
arg = *data++;
1124
size -= sizeof (uint64_t);
1125
1126
base = DTRACE_LQUANTIZE_BASE(arg);
1127
step = DTRACE_LQUANTIZE_STEP(arg);
1128
levels = DTRACE_LQUANTIZE_LEVELS(arg);
1129
1130
if (size != sizeof (uint64_t) * (levels + 2))
1131
return (dt_set_errno(dtp, EDT_DMISMATCH));
1132
1133
min = 0;
1134
max = levels + 1;
1135
1136
if (min == 0) {
1137
(void) snprintf(c, sizeof (c), "< %d", base);
1138
err = dt_printf(dtp, fp, "%8s :", c);
1139
} else {
1140
err = dt_printf(dtp, fp, "%8d :", base + (min - 1) * step);
1141
}
1142
1143
if (err < 0)
1144
return (-1);
1145
1146
for (i = min; i <= max; i++) {
1147
dt_quantize_total(dtp, data[i], &total);
1148
count += data[i];
1149
}
1150
1151
for (i = min; i <= max; i++) {
1152
if (dt_print_packed(dtp, fp, data[i], total) < 0)
1153
return (-1);
1154
}
1155
1156
(void) snprintf(c, sizeof (c), ">= %d", base + (levels * step));
1157
return (dt_printf(dtp, fp, ": %-8s | %lld\n", c, (long long)count));
1158
}
1159
1160
static const int64_t *
1161
dt_format_llquantize_prepare(dtrace_hdl_t *dtp, const void *addr, size_t size,
1162
dt_prepare_args_t *args)
1163
{
1164
int i, first_bin, last_bin, bin = 1, order, levels;
1165
uint16_t factor, low, high, nsteps;
1166
const int64_t *data = addr;
1167
int64_t value = 1, next, step;
1168
uint64_t arg;
1169
1170
if (size < sizeof(uint64_t)) {
1171
(void) dt_set_errno(dtp, EDT_DMISMATCH);
1172
return (NULL);
1173
}
1174
1175
arg = *data++;
1176
size -= sizeof (uint64_t);
1177
1178
factor = DTRACE_LLQUANTIZE_FACTOR(arg);
1179
low = DTRACE_LLQUANTIZE_LOW(arg);
1180
high = DTRACE_LLQUANTIZE_HIGH(arg);
1181
nsteps = DTRACE_LLQUANTIZE_NSTEP(arg);
1182
1183
/*
1184
* We don't expect to be handed invalid llquantize() parameters here,
1185
* but sanity check them (to a degree) nonetheless.
1186
*/
1187
if (size > INT32_MAX || factor < 2 || low >= high ||
1188
nsteps == 0 || factor > nsteps) {
1189
(void) dt_set_errno(dtp, EDT_DMISMATCH);
1190
return (NULL);
1191
}
1192
1193
levels = (int)size / sizeof (uint64_t);
1194
1195
first_bin = 0;
1196
last_bin = levels - 1;
1197
1198
while (first_bin < levels && data[first_bin] == 0)
1199
first_bin++;
1200
1201
if (first_bin == levels) {
1202
first_bin = 0;
1203
last_bin = 1;
1204
} else {
1205
if (first_bin > 0)
1206
first_bin--;
1207
1208
while (last_bin > 0 && data[last_bin] == 0)
1209
last_bin--;
1210
1211
if (last_bin < levels - 1)
1212
last_bin++;
1213
}
1214
1215
for (order = 0; order < low; order++)
1216
value *= factor;
1217
1218
next = value * factor;
1219
step = next > nsteps ? next / nsteps : 1;
1220
1221
args->first_bin = first_bin;
1222
args->last_bin = last_bin;
1223
args->llquantize_factor = factor;
1224
args->llquantize_low = low;
1225
args->llquantize_high = high;
1226
args->llquantize_nsteps = nsteps;
1227
args->llquantize_levels = levels;
1228
args->llquantize_order = order;
1229
args->llquantize_next = next;
1230
args->llquantize_step = step;
1231
args->llquantize_value = value;
1232
1233
return (data);
1234
}
1235
1236
int
1237
dt_format_llquantize(dtrace_hdl_t *dtp, const void *addr, size_t size,
1238
uint64_t normal)
1239
{
1240
int first_bin, last_bin, bin = 1, order, levels;
1241
uint16_t factor, low, high, nsteps;
1242
const int64_t *data;
1243
dt_prepare_args_t args = { 0 };
1244
int64_t value = 1, next, step;
1245
uint64_t arg;
1246
char c[32];
1247
1248
data = dt_format_llquantize_prepare(dtp, addr, size, &args);
1249
/* dt_errno is set for us */
1250
if (data == NULL)
1251
return (-1);
1252
1253
first_bin = args.first_bin;
1254
last_bin = args.last_bin;
1255
factor = args.llquantize_factor;
1256
low = args.llquantize_low;
1257
high = args.llquantize_high;
1258
nsteps = args.llquantize_nsteps;
1259
levels = args.llquantize_levels;
1260
order = args.llquantize_order;
1261
next = args.llquantize_next;
1262
step = args.llquantize_step;
1263
value = args.llquantize_value;
1264
1265
xo_open_list("buckets");
1266
if (first_bin == 0) {
1267
/*
1268
* We have to represent < value somehow in JSON, so we bundle an
1269
* optional "operator" in llquantize buckets.
1270
*/
1271
xo_open_instance("buckets");
1272
xo_emit("{:value/%lld} {:count/%lld} {:operator/%s}",
1273
(long long)value, (long long)data[0] / normal, "<");
1274
xo_close_instance("buckets");
1275
}
1276
1277
while (order <= high) {
1278
if (bin >= first_bin && bin <= last_bin) {
1279
xo_open_instance("buckets");
1280
xo_emit("{:value/%lld} {:count/%lld}", (long long)value,
1281
(long long)data[bin] / normal);
1282
xo_close_instance("buckets");
1283
}
1284
1285
assert(value < next);
1286
bin++;
1287
1288
if ((value += step) != next)
1289
continue;
1290
1291
next = value * factor;
1292
step = next > nsteps ? next / nsteps : 1;
1293
order++;
1294
}
1295
1296
if (last_bin < bin) {
1297
xo_close_list("buckets");
1298
return (0);
1299
}
1300
1301
assert(last_bin == bin);
1302
xo_open_instance("buckets");
1303
xo_emit("{:value/%lld} {:count/%lld} {:operator/%s}", (long long)value,
1304
(long long)data[bin] / normal, ">=");
1305
xo_close_instance("buckets");
1306
1307
xo_close_list("buckets");
1308
return (0);
1309
}
1310
1311
int
1312
dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
1313
size_t size, uint64_t normal)
1314
{
1315
int i, first_bin, last_bin, bin = 1, order, levels;
1316
uint16_t factor, low, high, nsteps;
1317
const int64_t *data;
1318
dt_prepare_args_t args = { 0 };
1319
int64_t value = 1, next, step;
1320
char positives = 0, negatives = 0;
1321
long double total = 0;
1322
uint64_t arg;
1323
char c[32];
1324
1325
data = dt_format_llquantize_prepare(dtp, addr, size, &args);
1326
/* dt_errno is set for us */
1327
if (data == NULL)
1328
return (-1);
1329
1330
first_bin = args.first_bin;
1331
last_bin = args.last_bin;
1332
factor = args.llquantize_factor;
1333
low = args.llquantize_low;
1334
high = args.llquantize_high;
1335
nsteps = args.llquantize_nsteps;
1336
levels = args.llquantize_levels;
1337
order = args.llquantize_order;
1338
next = args.llquantize_next;
1339
step = args.llquantize_step;
1340
value = args.llquantize_value;
1341
1342
for (i = first_bin; i <= last_bin; i++) {
1343
positives |= (data[i] > 0);
1344
negatives |= (data[i] < 0);
1345
dt_quantize_total(dtp, data[i], &total);
1346
}
1347
1348
if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
1349
"------------- Distribution -------------", "count") < 0)
1350
return (-1);
1351
1352
if (first_bin == 0) {
1353
(void) snprintf(c, sizeof (c), "< %lld", (long long)value);
1354
1355
if (dt_printf(dtp, fp, "%16s ", c) < 0)
1356
return (-1);
1357
1358
if (dt_print_quantline(dtp, fp, data[0], normal,
1359
total, positives, negatives) < 0)
1360
return (-1);
1361
}
1362
1363
while (order <= high) {
1364
if (bin >= first_bin && bin <= last_bin) {
1365
if (dt_printf(dtp, fp, "%16lld ", (long long)value) < 0)
1366
return (-1);
1367
1368
if (dt_print_quantline(dtp, fp, data[bin],
1369
normal, total, positives, negatives) < 0)
1370
return (-1);
1371
}
1372
1373
assert(value < next);
1374
bin++;
1375
1376
if ((value += step) != next)
1377
continue;
1378
1379
next = value * factor;
1380
step = next > nsteps ? next / nsteps : 1;
1381
order++;
1382
}
1383
1384
if (last_bin < bin)
1385
return (0);
1386
1387
assert(last_bin == bin);
1388
(void) snprintf(c, sizeof (c), ">= %lld", (long long)value);
1389
1390
if (dt_printf(dtp, fp, "%16s ", c) < 0)
1391
return (-1);
1392
1393
return (dt_print_quantline(dtp, fp, data[bin], normal,
1394
total, positives, negatives));
1395
}
1396
1397
static int
1398
dt_format_average(dtrace_hdl_t *dtp, caddr_t addr, size_t size, uint64_t normal)
1399
{
1400
int64_t *data = (int64_t *)addr;
1401
1402
xo_emit("{:average/%lld}",
1403
data[0] ? (long long)(data[1] / (int64_t)normal / data[0]) : 0);
1404
return (0);
1405
}
1406
1407
/*ARGSUSED*/
1408
static int
1409
dt_print_average(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
1410
size_t size, uint64_t normal)
1411
{
1412
/* LINTED - alignment */
1413
int64_t *data = (int64_t *)addr;
1414
1415
return (dt_printf(dtp, fp, " %16lld", data[0] ?
1416
(long long)(data[1] / (int64_t)normal / data[0]) : 0));
1417
}
1418
1419
static int
1420
dt_format_stddev(dtrace_hdl_t *dtp, caddr_t addr, size_t size, uint64_t normal)
1421
{
1422
uint64_t *data = (uint64_t *)addr;
1423
1424
xo_emit("{:stddev/%llu}",
1425
data[0] ? (unsigned long long)dt_stddev(data, normal) : 0);
1426
return (0);
1427
}
1428
1429
/*ARGSUSED*/
1430
static int
1431
dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
1432
size_t size, uint64_t normal)
1433
{
1434
/* LINTED - alignment */
1435
uint64_t *data = (uint64_t *)addr;
1436
1437
return (dt_printf(dtp, fp, " %16llu", data[0] ?
1438
(unsigned long long) dt_stddev(data, normal) : 0));
1439
}
1440
1441
/*ARGSUSED*/
1442
static int
1443
dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
1444
size_t nbytes, int width, int quiet, int forceraw)
1445
{
1446
/*
1447
* If the byte stream is a series of printable characters, followed by
1448
* a terminating byte, we print it out as a string. Otherwise, we
1449
* assume that it's something else and just print the bytes.
1450
*/
1451
int i, j, margin = 5;
1452
char *c = (char *)addr;
1453
1454
if (nbytes == 0)
1455
return (0);
1456
1457
if (forceraw)
1458
goto raw;
1459
1460
if (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET)
1461
goto raw;
1462
1463
for (i = 0; i < nbytes; i++) {
1464
/*
1465
* We define a "printable character" to be one for which
1466
* isprint(3C) returns non-zero, isspace(3C) returns non-zero,
1467
* or a character which is either backspace or the bell.
1468
* Backspace and the bell are regrettably special because
1469
* they fail the first two tests -- and yet they are entirely
1470
* printable. These are the only two control characters that
1471
* have meaning for the terminal and for which isprint(3C) and
1472
* isspace(3C) return 0.
1473
*/
1474
if (isprint(c[i]) || isspace(c[i]) ||
1475
c[i] == '\b' || c[i] == '\a')
1476
continue;
1477
1478
if (c[i] == '\0' && i > 0) {
1479
/*
1480
* This looks like it might be a string. Before we
1481
* assume that it is indeed a string, check the
1482
* remainder of the byte range; if it contains
1483
* additional non-nul characters, we'll assume that
1484
* it's a binary stream that just happens to look like
1485
* a string, and we'll print out the individual bytes.
1486
*/
1487
for (j = i + 1; j < nbytes; j++) {
1488
if (c[j] != '\0')
1489
break;
1490
}
1491
1492
if (j != nbytes)
1493
break;
1494
1495
if (quiet) {
1496
return (dt_printf(dtp, fp, "%s", c));
1497
} else {
1498
return (dt_printf(dtp, fp, " %s%*s",
1499
width < 0 ? " " : "", width, c));
1500
}
1501
}
1502
1503
break;
1504
}
1505
1506
if (i == nbytes) {
1507
/*
1508
* The byte range is all printable characters, but there is
1509
* no trailing nul byte. We'll assume that it's a string and
1510
* print it as such.
1511
*/
1512
char *s = alloca(nbytes + 1);
1513
bcopy(c, s, nbytes);
1514
s[nbytes] = '\0';
1515
return (dt_printf(dtp, fp, " %-*s", width, s));
1516
}
1517
1518
raw:
1519
if (dt_printf(dtp, fp, "\n%*s ", margin, "") < 0)
1520
return (-1);
1521
1522
for (i = 0; i < 16; i++)
1523
if (dt_printf(dtp, fp, " %c", "0123456789abcdef"[i]) < 0)
1524
return (-1);
1525
1526
if (dt_printf(dtp, fp, " 0123456789abcdef\n") < 0)
1527
return (-1);
1528
1529
1530
for (i = 0; i < nbytes; i += 16) {
1531
if (dt_printf(dtp, fp, "%*s%5x:", margin, "", i) < 0)
1532
return (-1);
1533
1534
for (j = i; j < i + 16 && j < nbytes; j++) {
1535
if (dt_printf(dtp, fp, " %02x", (uchar_t)c[j]) < 0)
1536
return (-1);
1537
}
1538
1539
while (j++ % 16) {
1540
if (dt_printf(dtp, fp, " ") < 0)
1541
return (-1);
1542
}
1543
1544
if (dt_printf(dtp, fp, " ") < 0)
1545
return (-1);
1546
1547
for (j = i; j < i + 16 && j < nbytes; j++) {
1548
if (dt_printf(dtp, fp, "%c",
1549
c[j] < ' ' || c[j] > '~' ? '.' : c[j]) < 0)
1550
return (-1);
1551
}
1552
1553
if (dt_printf(dtp, fp, "\n") < 0)
1554
return (-1);
1555
}
1556
1557
return (0);
1558
}
1559
1560
int
1561
dt_format_stack(dtrace_hdl_t *dtp, caddr_t addr, int depth, int size)
1562
{
1563
dtrace_syminfo_t dts;
1564
GElf_Sym sym;
1565
int i;
1566
uint64_t pc;
1567
1568
xo_open_list("stack-frames");
1569
for (i = 0; i < depth; i++) {
1570
switch (size) {
1571
case sizeof (uint32_t):
1572
pc = *((uint32_t *)addr);
1573
break;
1574
1575
case sizeof (uint64_t):
1576
pc = *((uint64_t *)addr);
1577
break;
1578
1579
default:
1580
return (dt_set_errno(dtp, EDT_BADSTACKPC));
1581
}
1582
1583
if (pc == 0)
1584
break;
1585
1586
addr += size;
1587
1588
xo_open_instance("stack-frames");
1589
if (dtrace_lookup_by_addr(dtp, pc, &sym, &dts) == 0) {
1590
if (pc > sym.st_value) {
1591
xo_emit("{:symbol/%s`%s+0x%llx} {:module/%s} "
1592
"{:name/%s} {:offset/0x%llx}",
1593
dts.dts_object, dts.dts_name,
1594
(u_longlong_t)(pc - sym.st_value),
1595
dts.dts_object, dts.dts_name,
1596
(u_longlong_t)(pc - sym.st_value));
1597
} else {
1598
xo_emit("{:symbol/%s`%s} {:module/%s} "
1599
"{:name/%s}",
1600
dts.dts_object, dts.dts_name,
1601
dts.dts_object, dts.dts_name);
1602
}
1603
} else {
1604
/*
1605
* We'll repeat the lookup, but this time we'll specify
1606
* a NULL GElf_Sym -- indicating that we're only
1607
* interested in the containing module.
1608
*/
1609
if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) {
1610
xo_emit("{:symbol/%s`0x%llx} {:module/%s} "
1611
"{:offset/0x%llx}",
1612
dts.dts_object, (u_longlong_t)pc,
1613
dts.dts_object, (u_longlong_t)pc);
1614
} else {
1615
xo_emit("{:symbol/0x%llx} {:offset/0x%llx}",
1616
(u_longlong_t)pc, (u_longlong_t)pc);
1617
}
1618
}
1619
xo_close_instance("stack-frames");
1620
}
1621
xo_close_list("stack-frames");
1622
1623
return (0);
1624
}
1625
1626
int
1627
dt_format_ustack(dtrace_hdl_t *dtp, caddr_t addr, uint64_t arg)
1628
{
1629
uint64_t *pc = (uint64_t *)addr;
1630
uint32_t depth = DTRACE_USTACK_NFRAMES(arg);
1631
uint32_t strsize = DTRACE_USTACK_STRSIZE(arg);
1632
const char *strbase = addr + (depth + 1) * sizeof (uint64_t);
1633
const char *str = strsize ? strbase : NULL;
1634
int err = 0;
1635
1636
char name[PATH_MAX], objname[PATH_MAX], c[PATH_MAX * 2];
1637
struct ps_prochandle *P;
1638
GElf_Sym sym;
1639
int i, indent;
1640
pid_t pid;
1641
1642
if (depth == 0)
1643
return (0);
1644
1645
pid = (pid_t)*pc++;
1646
1647
/*
1648
* Ultimately, we need to add an entry point in the library vector for
1649
* determining <symbol, offset> from <pid, address>. For now, if
1650
* this is a vector open, we just print the raw address or string.
1651
*/
1652
if (dtp->dt_vector == NULL)
1653
P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0);
1654
else
1655
P = NULL;
1656
1657
if (P != NULL)
1658
dt_proc_lock(dtp, P); /* lock handle while we perform lookups */
1659
1660
xo_open_list("ustack-frames");
1661
for (i = 0; i < depth && pc[i] != 0; i++) {
1662
const prmap_t *map;
1663
1664
xo_open_instance("ustack-frames");
1665
if (P != NULL && Plookup_by_addr(P, pc[i],
1666
name, sizeof (name), &sym) == 0) {
1667
(void) Pobjname(P, pc[i], objname, sizeof (objname));
1668
1669
if (pc[i] > sym.st_value) {
1670
xo_emit("{:symbol/%s`%s+0x%llx} {:module/%s} "
1671
"{:name/%s} {:offset/0x%llx}",
1672
dt_basename(objname), name,
1673
(u_longlong_t)(pc[i] - sym.st_value),
1674
dt_basename(objname), name,
1675
(u_longlong_t)(pc[i] - sym.st_value));
1676
} else {
1677
xo_emit("{:symbol/%s`%s} {:module/%s} "
1678
"{:name/%s}",
1679
dt_basename(objname), name,
1680
dt_basename(objname), name);
1681
}
1682
} else if (str != NULL && str[0] != '\0' && str[0] != '@' &&
1683
(P != NULL && ((map = Paddr_to_map(P, pc[i])) == NULL ||
1684
(map->pr_mflags & MA_WRITE)))) {
1685
/*
1686
* If the current string pointer in the string table
1687
* does not point to an empty string _and_ the program
1688
* counter falls in a writable region, we'll use the
1689
* string from the string table instead of the raw
1690
* address. This last condition is necessary because
1691
* some (broken) ustack helpers will return a string
1692
* even for a program counter that they can't
1693
* identify. If we have a string for a program
1694
* counter that falls in a segment that isn't
1695
* writable, we assume that we have fallen into this
1696
* case and we refuse to use the string.
1697
*/
1698
xo_emit("{:symbol/%s}", str);
1699
} else {
1700
if (P != NULL && Pobjname(P, pc[i], objname,
1701
sizeof (objname)) != 0) {
1702
xo_emit("{:symbol/%s`0x%llx} {:module/%s} "
1703
"{:offset/0x%llx}",
1704
dt_basename(objname), (u_longlong_t)pc[i],
1705
dt_basename(objname), (u_longlong_t)pc[i]);
1706
} else {
1707
xo_emit("{:symbol/0x%llx} {:offset/0x%llx}",
1708
(u_longlong_t)pc[i], (u_longlong_t)pc[i]);
1709
}
1710
}
1711
1712
if (str != NULL && str[0] == '@') {
1713
/*
1714
* If the first character of the string is an "at" sign,
1715
* then the string is inferred to be an annotation --
1716
* and it is printed out beneath the frame and offset
1717
* with brackets.
1718
*/
1719
xo_emit("{:annotation/%s}", &str[1]);
1720
}
1721
1722
if (str != NULL) {
1723
str += strlen(str) + 1;
1724
if (str - strbase >= strsize)
1725
str = NULL;
1726
}
1727
xo_close_instance("ustack-frames");
1728
}
1729
xo_close_list("ustack-frames");
1730
1731
if (P != NULL) {
1732
dt_proc_unlock(dtp, P);
1733
dt_proc_release(dtp, P);
1734
}
1735
1736
return (err);
1737
}
1738
1739
int
1740
dt_print_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
1741
caddr_t addr, int depth, int size)
1742
{
1743
dtrace_syminfo_t dts;
1744
GElf_Sym sym;
1745
int i, indent;
1746
char c[PATH_MAX * 2];
1747
uint64_t pc;
1748
1749
if (dt_printf(dtp, fp, "\n") < 0)
1750
return (-1);
1751
1752
if (format == NULL)
1753
format = "%s";
1754
1755
if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET)
1756
indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT];
1757
else
1758
indent = _dtrace_stkindent;
1759
1760
for (i = 0; i < depth; i++) {
1761
switch (size) {
1762
case sizeof (uint32_t):
1763
/* LINTED - alignment */
1764
pc = *((uint32_t *)addr);
1765
break;
1766
1767
case sizeof (uint64_t):
1768
/* LINTED - alignment */
1769
pc = *((uint64_t *)addr);
1770
break;
1771
1772
default:
1773
return (dt_set_errno(dtp, EDT_BADSTACKPC));
1774
}
1775
1776
if (pc == 0)
1777
break;
1778
1779
addr += size;
1780
1781
if (dt_printf(dtp, fp, "%*s", indent, "") < 0)
1782
return (-1);
1783
1784
if (dtrace_lookup_by_addr(dtp, pc, &sym, &dts) == 0) {
1785
if (pc > sym.st_value) {
1786
(void) snprintf(c, sizeof (c), "%s`%s+0x%llx",
1787
dts.dts_object, dts.dts_name,
1788
(u_longlong_t)(pc - sym.st_value));
1789
} else {
1790
(void) snprintf(c, sizeof (c), "%s`%s",
1791
dts.dts_object, dts.dts_name);
1792
}
1793
} else {
1794
/*
1795
* We'll repeat the lookup, but this time we'll specify
1796
* a NULL GElf_Sym -- indicating that we're only
1797
* interested in the containing module.
1798
*/
1799
if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) {
1800
(void) snprintf(c, sizeof (c), "%s`0x%llx",
1801
dts.dts_object, (u_longlong_t)pc);
1802
} else {
1803
(void) snprintf(c, sizeof (c), "0x%llx",
1804
(u_longlong_t)pc);
1805
}
1806
}
1807
1808
if (dt_printf(dtp, fp, format, c) < 0)
1809
return (-1);
1810
1811
if (dt_printf(dtp, fp, "\n") < 0)
1812
return (-1);
1813
}
1814
1815
return (0);
1816
}
1817
1818
int
1819
dt_print_ustack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
1820
caddr_t addr, uint64_t arg)
1821
{
1822
/* LINTED - alignment */
1823
uint64_t *pc = (uint64_t *)addr;
1824
uint32_t depth = DTRACE_USTACK_NFRAMES(arg);
1825
uint32_t strsize = DTRACE_USTACK_STRSIZE(arg);
1826
const char *strbase = addr + (depth + 1) * sizeof (uint64_t);
1827
const char *str = strsize ? strbase : NULL;
1828
int err = 0;
1829
1830
char name[PATH_MAX], objname[PATH_MAX], c[PATH_MAX * 2];
1831
struct ps_prochandle *P;
1832
GElf_Sym sym;
1833
int i, indent;
1834
pid_t pid;
1835
1836
if (depth == 0)
1837
return (0);
1838
1839
pid = (pid_t)*pc++;
1840
1841
if (dt_printf(dtp, fp, "\n") < 0)
1842
return (-1);
1843
1844
if (format == NULL)
1845
format = "%s";
1846
1847
if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET)
1848
indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT];
1849
else
1850
indent = _dtrace_stkindent;
1851
1852
/*
1853
* Ultimately, we need to add an entry point in the library vector for
1854
* determining <symbol, offset> from <pid, address>. For now, if
1855
* this is a vector open, we just print the raw address or string.
1856
*/
1857
if (dtp->dt_vector == NULL)
1858
P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0);
1859
else
1860
P = NULL;
1861
1862
if (P != NULL)
1863
dt_proc_lock(dtp, P); /* lock handle while we perform lookups */
1864
1865
for (i = 0; i < depth && pc[i] != 0; i++) {
1866
const prmap_t *map;
1867
1868
if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0)
1869
break;
1870
1871
if (P != NULL && Plookup_by_addr(P, pc[i],
1872
name, sizeof (name), &sym) == 0) {
1873
(void) Pobjname(P, pc[i], objname, sizeof (objname));
1874
1875
if (pc[i] > sym.st_value) {
1876
(void) snprintf(c, sizeof (c),
1877
"%s`%s+0x%llx", dt_basename(objname), name,
1878
(u_longlong_t)(pc[i] - sym.st_value));
1879
} else {
1880
(void) snprintf(c, sizeof (c),
1881
"%s`%s", dt_basename(objname), name);
1882
}
1883
} else if (str != NULL && str[0] != '\0' && str[0] != '@' &&
1884
(P != NULL && ((map = Paddr_to_map(P, pc[i])) == NULL ||
1885
(map->pr_mflags & MA_WRITE)))) {
1886
/*
1887
* If the current string pointer in the string table
1888
* does not point to an empty string _and_ the program
1889
* counter falls in a writable region, we'll use the
1890
* string from the string table instead of the raw
1891
* address. This last condition is necessary because
1892
* some (broken) ustack helpers will return a string
1893
* even for a program counter that they can't
1894
* identify. If we have a string for a program
1895
* counter that falls in a segment that isn't
1896
* writable, we assume that we have fallen into this
1897
* case and we refuse to use the string.
1898
*/
1899
(void) snprintf(c, sizeof (c), "%s", str);
1900
} else {
1901
if (P != NULL && Pobjname(P, pc[i], objname,
1902
sizeof (objname)) != 0) {
1903
(void) snprintf(c, sizeof (c), "%s`0x%llx",
1904
dt_basename(objname), (u_longlong_t)pc[i]);
1905
} else {
1906
(void) snprintf(c, sizeof (c), "0x%llx",
1907
(u_longlong_t)pc[i]);
1908
}
1909
}
1910
1911
if ((err = dt_printf(dtp, fp, format, c)) < 0)
1912
break;
1913
1914
if ((err = dt_printf(dtp, fp, "\n")) < 0)
1915
break;
1916
1917
if (str != NULL && str[0] == '@') {
1918
/*
1919
* If the first character of the string is an "at" sign,
1920
* then the string is inferred to be an annotation --
1921
* and it is printed out beneath the frame and offset
1922
* with brackets.
1923
*/
1924
if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0)
1925
break;
1926
1927
(void) snprintf(c, sizeof (c), " [ %s ]", &str[1]);
1928
1929
if ((err = dt_printf(dtp, fp, format, c)) < 0)
1930
break;
1931
1932
if ((err = dt_printf(dtp, fp, "\n")) < 0)
1933
break;
1934
}
1935
1936
if (str != NULL) {
1937
str += strlen(str) + 1;
1938
if (str - strbase >= strsize)
1939
str = NULL;
1940
}
1941
}
1942
1943
if (P != NULL) {
1944
dt_proc_unlock(dtp, P);
1945
dt_proc_release(dtp, P);
1946
}
1947
1948
return (err);
1949
}
1950
1951
static int
1952
dt_format_usym(dtrace_hdl_t *dtp, caddr_t addr, dtrace_actkind_t act)
1953
{
1954
uint64_t pid = ((uint64_t *)addr)[0];
1955
uint64_t pc = ((uint64_t *)addr)[1];
1956
char *s;
1957
int n, len = 256;
1958
1959
if (act == DTRACEACT_USYM && dtp->dt_vector == NULL) {
1960
struct ps_prochandle *P;
1961
1962
if ((P = dt_proc_grab(dtp, pid,
1963
PGRAB_RDONLY | PGRAB_FORCE, 0)) != NULL) {
1964
GElf_Sym sym;
1965
1966
dt_proc_lock(dtp, P);
1967
1968
if (Plookup_by_addr(P, pc, NULL, 0, &sym) == 0)
1969
pc = sym.st_value;
1970
1971
dt_proc_unlock(dtp, P);
1972
dt_proc_release(dtp, P);
1973
}
1974
}
1975
1976
do {
1977
n = len;
1978
s = alloca(n);
1979
} while ((len = dtrace_uaddr2str(dtp, pid, pc, s, n)) > n);
1980
1981
xo_emit("{:usym/%s}", s);
1982
return (0);
1983
}
1984
1985
1986
static int
1987
dt_print_usym(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, dtrace_actkind_t act)
1988
{
1989
/* LINTED - alignment */
1990
uint64_t pid = ((uint64_t *)addr)[0];
1991
/* LINTED - alignment */
1992
uint64_t pc = ((uint64_t *)addr)[1];
1993
const char *format = " %-50s";
1994
char *s;
1995
int n, len = 256;
1996
1997
if (act == DTRACEACT_USYM && dtp->dt_vector == NULL) {
1998
struct ps_prochandle *P;
1999
2000
if ((P = dt_proc_grab(dtp, pid,
2001
PGRAB_RDONLY | PGRAB_FORCE, 0)) != NULL) {
2002
GElf_Sym sym;
2003
2004
dt_proc_lock(dtp, P);
2005
2006
if (Plookup_by_addr(P, pc, NULL, 0, &sym) == 0)
2007
pc = sym.st_value;
2008
2009
dt_proc_unlock(dtp, P);
2010
dt_proc_release(dtp, P);
2011
}
2012
}
2013
2014
do {
2015
n = len;
2016
s = alloca(n);
2017
} while ((len = dtrace_uaddr2str(dtp, pid, pc, s, n)) > n);
2018
2019
return (dt_printf(dtp, fp, format, s));
2020
}
2021
2022
int
2023
dt_format_umod(dtrace_hdl_t *dtp, caddr_t addr)
2024
{
2025
uint64_t pid = ((uint64_t *)addr)[0];
2026
uint64_t pc = ((uint64_t *)addr)[1];
2027
int err = 0;
2028
2029
char objname[PATH_MAX];
2030
struct ps_prochandle *P;
2031
2032
/*
2033
* See the comment in dt_print_ustack() for the rationale for
2034
* printing raw addresses in the vectored case.
2035
*/
2036
if (dtp->dt_vector == NULL)
2037
P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0);
2038
else
2039
P = NULL;
2040
2041
if (P != NULL)
2042
dt_proc_lock(dtp, P); /* lock handle while we perform lookups */
2043
2044
if (P != NULL && Pobjname(P, pc, objname, sizeof (objname)) != 0) {
2045
xo_emit("{:umod/%s}", dt_basename(objname));
2046
} else {
2047
xo_emit("{:umod/0x%llx}", (u_longlong_t)pc);
2048
}
2049
2050
if (P != NULL) {
2051
dt_proc_unlock(dtp, P);
2052
dt_proc_release(dtp, P);
2053
}
2054
2055
return (0);
2056
}
2057
2058
int
2059
dt_print_umod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr)
2060
{
2061
/* LINTED - alignment */
2062
uint64_t pid = ((uint64_t *)addr)[0];
2063
/* LINTED - alignment */
2064
uint64_t pc = ((uint64_t *)addr)[1];
2065
int err = 0;
2066
2067
char objname[PATH_MAX], c[PATH_MAX * 2];
2068
struct ps_prochandle *P;
2069
2070
if (format == NULL)
2071
format = " %-50s";
2072
2073
/*
2074
* See the comment in dt_print_ustack() for the rationale for
2075
* printing raw addresses in the vectored case.
2076
*/
2077
if (dtp->dt_vector == NULL)
2078
P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0);
2079
else
2080
P = NULL;
2081
2082
if (P != NULL)
2083
dt_proc_lock(dtp, P); /* lock handle while we perform lookups */
2084
2085
if (P != NULL && Pobjname(P, pc, objname, sizeof (objname)) != 0) {
2086
(void) snprintf(c, sizeof (c), "%s", dt_basename(objname));
2087
} else {
2088
(void) snprintf(c, sizeof (c), "0x%llx", (u_longlong_t)pc);
2089
}
2090
2091
err = dt_printf(dtp, fp, format, c);
2092
2093
if (P != NULL) {
2094
dt_proc_unlock(dtp, P);
2095
dt_proc_release(dtp, P);
2096
}
2097
2098
return (err);
2099
}
2100
2101
static int
2102
dt_print_sym(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr)
2103
{
2104
/* LINTED - alignment */
2105
uint64_t pc = *((uint64_t *)addr);
2106
dtrace_syminfo_t dts;
2107
GElf_Sym sym;
2108
char c[PATH_MAX * 2];
2109
2110
if (format == NULL)
2111
format = " %-50s";
2112
2113
if (dtrace_lookup_by_addr(dtp, pc, &sym, &dts) == 0) {
2114
if (dtp->dt_oformat)
2115
xo_emit("{:sym/%s`%s} {:object/%s} {:name/%s}",
2116
dts.dts_object, dts.dts_name, dts.dts_object,
2117
dts.dts_name);
2118
else
2119
(void) snprintf(c, sizeof (c), "%s`%s",
2120
dts.dts_object, dts.dts_name);
2121
} else {
2122
/*
2123
* We'll repeat the lookup, but this time we'll specify a
2124
* NULL GElf_Sym -- indicating that we're only interested in
2125
* the containing module.
2126
*/
2127
if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) {
2128
if (dtp->dt_oformat)
2129
xo_emit("{:sym/%s`0x%llx} {:object/%s} "
2130
"{:offset/0x%llx}",
2131
dts.dts_object, (u_longlong_t)pc,
2132
dts.dts_object, (u_longlong_t)pc);
2133
else
2134
(void) snprintf(c, sizeof (c), "%s`0x%llx",
2135
dts.dts_object, (u_longlong_t)pc);
2136
} else {
2137
if (dtp->dt_oformat)
2138
xo_emit("{:sym/0x%llx} {:offset/0x%llx}",
2139
(u_longlong_t)pc, (u_longlong_t)pc);
2140
else
2141
(void) snprintf(c, sizeof (c), "0x%llx",
2142
(u_longlong_t)pc);
2143
}
2144
}
2145
2146
if (dtp->dt_oformat != 0 && dt_printf(dtp, fp, format, c) < 0)
2147
return (-1);
2148
2149
return (0);
2150
}
2151
2152
int
2153
dt_format_mod(dtrace_hdl_t *dtp, caddr_t addr)
2154
{
2155
/* LINTED - alignment */
2156
uint64_t pc = *((uint64_t *)addr);
2157
dtrace_syminfo_t dts;
2158
2159
if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) {
2160
xo_emit("{:mod/%s}", dts.dts_object);
2161
} else {
2162
xo_emit("{:mod/0x%llx}", (u_longlong_t)pc);
2163
}
2164
2165
return (0);
2166
}
2167
2168
int
2169
dt_print_mod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr)
2170
{
2171
/* LINTED - alignment */
2172
uint64_t pc = *((uint64_t *)addr);
2173
dtrace_syminfo_t dts;
2174
char c[PATH_MAX * 2];
2175
2176
if (format == NULL)
2177
format = " %-50s";
2178
2179
if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) {
2180
(void) snprintf(c, sizeof (c), "%s", dts.dts_object);
2181
} else {
2182
(void) snprintf(c, sizeof (c), "0x%llx", (u_longlong_t)pc);
2183
}
2184
2185
if (dt_printf(dtp, fp, format, c) < 0)
2186
return (-1);
2187
2188
return (0);
2189
}
2190
2191
static char *
2192
dt_format_bytes_get(dtrace_hdl_t *dtp, caddr_t addr, size_t nbytes)
2193
{
2194
char *s = dt_alloc(dtp, nbytes * 2 + 2 + 1); /* 2 bytes per byte + 0x + '\0' */
2195
char t[6];
2196
char *c = (char *)addr;
2197
size_t i, j;
2198
2199
if (s == NULL)
2200
return (NULL);
2201
2202
/*
2203
* XXX: Some duplication with dt_print_bytes().
2204
*/
2205
for (i = 0; i < nbytes; i++) {
2206
if (isprint(c[i]) || isspace(c[i]) || c[i] == '\b' || c[i] == '\a')
2207
continue;
2208
2209
if (c[i] == '\0' && i > 0) {
2210
for (j = i + 1; j < nbytes; j++) {
2211
if (c[j] != '\0')
2212
break;
2213
}
2214
2215
if (j != nbytes)
2216
break;
2217
2218
memcpy(s, c, nbytes);
2219
return (s);
2220
}
2221
2222
break;
2223
}
2224
2225
if (i == nbytes) {
2226
memcpy(s, c, nbytes);
2227
s[nbytes] = '\0';
2228
return (s);
2229
}
2230
2231
s[0] = '0';
2232
s[1] = 'x';
2233
for (i = 0; i < nbytes; i++) {
2234
snprintf(t, sizeof(t), "%02x", (uchar_t)c[i]);
2235
memcpy(s + (i * 2) + 2, t, 2);
2236
}
2237
2238
s[nbytes * 2 + 2] = 0;
2239
return (s);
2240
}
2241
2242
static int
2243
dt_format_memory(dtrace_hdl_t *dtp, caddr_t addr)
2244
{
2245
size_t nbytes = *((size_t *) addr);
2246
char *s;
2247
2248
s = dt_format_bytes_get(dtp, addr + sizeof(size_t), nbytes);
2249
if (s == NULL)
2250
return (-1);
2251
2252
xo_emit("{:printm/%s}", s);
2253
dt_free(dtp, s);
2254
2255
return (0);
2256
}
2257
2258
static int
2259
dt_print_memory(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr)
2260
{
2261
int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET);
2262
size_t nbytes = *((size_t *) addr);
2263
2264
return (dt_print_bytes(dtp, fp, addr + sizeof(size_t),
2265
nbytes, 50, quiet, 1));
2266
}
2267
2268
typedef struct dt_normal {
2269
dtrace_aggvarid_t dtnd_id;
2270
uint64_t dtnd_normal;
2271
} dt_normal_t;
2272
2273
static int
2274
dt_normalize_agg(const dtrace_aggdata_t *aggdata, void *arg)
2275
{
2276
dt_normal_t *normal = arg;
2277
dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2278
dtrace_aggvarid_t id = normal->dtnd_id;
2279
2280
if (agg->dtagd_nrecs == 0)
2281
return (DTRACE_AGGWALK_NEXT);
2282
2283
if (agg->dtagd_varid != id)
2284
return (DTRACE_AGGWALK_NEXT);
2285
2286
((dtrace_aggdata_t *)aggdata)->dtada_normal = normal->dtnd_normal;
2287
return (DTRACE_AGGWALK_NORMALIZE);
2288
}
2289
2290
static int
2291
dt_normalize(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec)
2292
{
2293
dt_normal_t normal;
2294
caddr_t addr;
2295
2296
/*
2297
* We (should) have two records: the aggregation ID followed by the
2298
* normalization value.
2299
*/
2300
addr = base + rec->dtrd_offset;
2301
2302
if (rec->dtrd_size != sizeof (dtrace_aggvarid_t))
2303
return (dt_set_errno(dtp, EDT_BADNORMAL));
2304
2305
/* LINTED - alignment */
2306
normal.dtnd_id = *((dtrace_aggvarid_t *)addr);
2307
rec++;
2308
2309
if (rec->dtrd_action != DTRACEACT_LIBACT)
2310
return (dt_set_errno(dtp, EDT_BADNORMAL));
2311
2312
if (rec->dtrd_arg != DT_ACT_NORMALIZE)
2313
return (dt_set_errno(dtp, EDT_BADNORMAL));
2314
2315
addr = base + rec->dtrd_offset;
2316
2317
switch (rec->dtrd_size) {
2318
case sizeof (uint64_t):
2319
/* LINTED - alignment */
2320
normal.dtnd_normal = *((uint64_t *)addr);
2321
break;
2322
case sizeof (uint32_t):
2323
/* LINTED - alignment */
2324
normal.dtnd_normal = *((uint32_t *)addr);
2325
break;
2326
case sizeof (uint16_t):
2327
/* LINTED - alignment */
2328
normal.dtnd_normal = *((uint16_t *)addr);
2329
break;
2330
case sizeof (uint8_t):
2331
normal.dtnd_normal = *((uint8_t *)addr);
2332
break;
2333
default:
2334
return (dt_set_errno(dtp, EDT_BADNORMAL));
2335
}
2336
2337
(void) dtrace_aggregate_walk(dtp, dt_normalize_agg, &normal);
2338
2339
return (0);
2340
}
2341
2342
static int
2343
dt_denormalize_agg(const dtrace_aggdata_t *aggdata, void *arg)
2344
{
2345
dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2346
dtrace_aggvarid_t id = *((dtrace_aggvarid_t *)arg);
2347
2348
if (agg->dtagd_nrecs == 0)
2349
return (DTRACE_AGGWALK_NEXT);
2350
2351
if (agg->dtagd_varid != id)
2352
return (DTRACE_AGGWALK_NEXT);
2353
2354
return (DTRACE_AGGWALK_DENORMALIZE);
2355
}
2356
2357
static int
2358
dt_clear_agg(const dtrace_aggdata_t *aggdata, void *arg)
2359
{
2360
dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2361
dtrace_aggvarid_t id = *((dtrace_aggvarid_t *)arg);
2362
2363
if (agg->dtagd_nrecs == 0)
2364
return (DTRACE_AGGWALK_NEXT);
2365
2366
if (agg->dtagd_varid != id)
2367
return (DTRACE_AGGWALK_NEXT);
2368
2369
return (DTRACE_AGGWALK_CLEAR);
2370
}
2371
2372
typedef struct dt_trunc {
2373
dtrace_aggvarid_t dttd_id;
2374
uint64_t dttd_remaining;
2375
} dt_trunc_t;
2376
2377
static int
2378
dt_trunc_agg(const dtrace_aggdata_t *aggdata, void *arg)
2379
{
2380
dt_trunc_t *trunc = arg;
2381
dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2382
dtrace_aggvarid_t id = trunc->dttd_id;
2383
2384
if (agg->dtagd_nrecs == 0)
2385
return (DTRACE_AGGWALK_NEXT);
2386
2387
if (agg->dtagd_varid != id)
2388
return (DTRACE_AGGWALK_NEXT);
2389
2390
if (trunc->dttd_remaining == 0)
2391
return (DTRACE_AGGWALK_REMOVE);
2392
2393
trunc->dttd_remaining--;
2394
return (DTRACE_AGGWALK_NEXT);
2395
}
2396
2397
static int
2398
dt_trunc(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec)
2399
{
2400
dt_trunc_t trunc;
2401
caddr_t addr;
2402
int64_t remaining;
2403
int (*func)(dtrace_hdl_t *, dtrace_aggregate_f *, void *);
2404
2405
/*
2406
* We (should) have two records: the aggregation ID followed by the
2407
* number of aggregation entries after which the aggregation is to be
2408
* truncated.
2409
*/
2410
addr = base + rec->dtrd_offset;
2411
2412
if (rec->dtrd_size != sizeof (dtrace_aggvarid_t))
2413
return (dt_set_errno(dtp, EDT_BADTRUNC));
2414
2415
/* LINTED - alignment */
2416
trunc.dttd_id = *((dtrace_aggvarid_t *)addr);
2417
rec++;
2418
2419
if (rec->dtrd_action != DTRACEACT_LIBACT)
2420
return (dt_set_errno(dtp, EDT_BADTRUNC));
2421
2422
if (rec->dtrd_arg != DT_ACT_TRUNC)
2423
return (dt_set_errno(dtp, EDT_BADTRUNC));
2424
2425
addr = base + rec->dtrd_offset;
2426
2427
switch (rec->dtrd_size) {
2428
case sizeof (uint64_t):
2429
/* LINTED - alignment */
2430
remaining = *((int64_t *)addr);
2431
break;
2432
case sizeof (uint32_t):
2433
/* LINTED - alignment */
2434
remaining = *((int32_t *)addr);
2435
break;
2436
case sizeof (uint16_t):
2437
/* LINTED - alignment */
2438
remaining = *((int16_t *)addr);
2439
break;
2440
case sizeof (uint8_t):
2441
remaining = *((int8_t *)addr);
2442
break;
2443
default:
2444
return (dt_set_errno(dtp, EDT_BADNORMAL));
2445
}
2446
2447
if (remaining < 0) {
2448
func = dtrace_aggregate_walk_valsorted;
2449
remaining = -remaining;
2450
} else {
2451
func = dtrace_aggregate_walk_valrevsorted;
2452
}
2453
2454
assert(remaining >= 0);
2455
trunc.dttd_remaining = remaining;
2456
2457
(void) func(dtp, dt_trunc_agg, &trunc);
2458
2459
return (0);
2460
}
2461
2462
static int
2463
dt_format_datum(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, caddr_t addr,
2464
size_t size, const dtrace_aggdata_t *aggdata, uint64_t normal,
2465
dt_print_aggdata_t *pd)
2466
{
2467
dtrace_actkind_t act = rec->dtrd_action;
2468
boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack;
2469
dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2470
char fmt[512];
2471
char *s;
2472
2473
if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid)
2474
pd->dtpa_agghisthdr = agg->dtagd_varid;
2475
2476
switch (act) {
2477
case DTRACEACT_STACK:
2478
return (dt_format_stack(dtp, addr, rec->dtrd_arg,
2479
rec->dtrd_size / rec->dtrd_arg));
2480
2481
case DTRACEACT_USTACK:
2482
case DTRACEACT_JSTACK:
2483
return (dt_format_ustack(dtp, addr, rec->dtrd_arg));
2484
2485
case DTRACEACT_USYM:
2486
case DTRACEACT_UADDR:
2487
return (dt_format_usym(dtp, addr, act));
2488
2489
case DTRACEACT_UMOD:
2490
return (dt_format_umod(dtp, addr));
2491
2492
case DTRACEACT_SYM:
2493
return (dt_format_sym(dtp, addr));
2494
case DTRACEACT_MOD:
2495
return (dt_format_mod(dtp, addr));
2496
2497
case DTRACEAGG_QUANTIZE:
2498
return (dt_format_quantize(dtp, addr, size, normal));
2499
2500
case DTRACEAGG_LQUANTIZE:
2501
return (dt_format_lquantize(dtp, addr, size, normal));
2502
2503
case DTRACEAGG_LLQUANTIZE:
2504
return (dt_format_llquantize(dtp, addr, size, normal));
2505
2506
case DTRACEAGG_AVG:
2507
return (dt_format_average(dtp, addr, size, normal));
2508
2509
case DTRACEAGG_STDDEV:
2510
return (dt_format_stddev(dtp, addr, size, normal));
2511
2512
default:
2513
break;
2514
}
2515
2516
switch (size) {
2517
case sizeof (uint64_t):
2518
snprintf(fmt, sizeof(fmt), "{:%s/%%lld}", pd->dtpa_keyname);
2519
xo_emit(fmt, (long long)*((uint64_t *)addr) / normal);
2520
break;
2521
case sizeof (uint32_t):
2522
snprintf(fmt, sizeof(fmt), "{:%s/%%d}", pd->dtpa_keyname);
2523
xo_emit(fmt, *((uint32_t *)addr) / (uint32_t)normal);
2524
break;
2525
case sizeof (uint16_t):
2526
snprintf(fmt, sizeof(fmt), "{:%s/%%d}", pd->dtpa_keyname);
2527
xo_emit(fmt, *((uint16_t *)addr) / (uint32_t)normal);
2528
break;
2529
case sizeof (uint8_t):
2530
snprintf(fmt, sizeof(fmt), "{:%s/%%d}", pd->dtpa_keyname);
2531
xo_emit(fmt, *((uint8_t *)addr) / (uint32_t)normal);
2532
break;
2533
default:
2534
s = dt_format_bytes_get(dtp, addr, size);
2535
if (s == NULL)
2536
return (-1);
2537
2538
xo_emit("{:value/%s}", s);
2539
dt_free(dtp, s);
2540
break;
2541
}
2542
2543
return (0);
2544
}
2545
2546
static int
2547
dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
2548
caddr_t addr, size_t size, const dtrace_aggdata_t *aggdata,
2549
uint64_t normal, dt_print_aggdata_t *pd)
2550
{
2551
int err, width;
2552
dtrace_actkind_t act = rec->dtrd_action;
2553
boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack;
2554
dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2555
2556
static struct {
2557
size_t size;
2558
int width;
2559
int packedwidth;
2560
} *fmt, fmttab[] = {
2561
{ sizeof (uint8_t), 3, 3 },
2562
{ sizeof (uint16_t), 5, 5 },
2563
{ sizeof (uint32_t), 8, 8 },
2564
{ sizeof (uint64_t), 16, 16 },
2565
{ 0, -50, 16 }
2566
};
2567
2568
if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid) {
2569
dtrace_recdesc_t *r;
2570
2571
width = 0;
2572
2573
/*
2574
* To print our quantization header for either an agghist or
2575
* aggpack aggregation, we need to iterate through all of our
2576
* of our records to determine their width.
2577
*/
2578
for (r = rec; !DTRACEACT_ISAGG(r->dtrd_action); r++) {
2579
for (fmt = fmttab; fmt->size &&
2580
fmt->size != r->dtrd_size; fmt++)
2581
continue;
2582
2583
width += fmt->packedwidth + 1;
2584
}
2585
2586
if (pd->dtpa_agghist) {
2587
if (dt_print_quanthdr(dtp, fp, width) < 0)
2588
return (-1);
2589
} else {
2590
if (dt_print_quanthdr_packed(dtp, fp,
2591
width, aggdata, r->dtrd_action) < 0)
2592
return (-1);
2593
}
2594
2595
pd->dtpa_agghisthdr = agg->dtagd_varid;
2596
}
2597
2598
if (pd->dtpa_agghist && DTRACEACT_ISAGG(act)) {
2599
char positives = aggdata->dtada_flags & DTRACE_A_HASPOSITIVES;
2600
char negatives = aggdata->dtada_flags & DTRACE_A_HASNEGATIVES;
2601
int64_t val;
2602
2603
assert(act == DTRACEAGG_SUM || act == DTRACEAGG_COUNT);
2604
val = (long long)*((uint64_t *)addr);
2605
2606
if (dt_printf(dtp, fp, " ") < 0)
2607
return (-1);
2608
2609
return (dt_print_quantline(dtp, fp, val, normal,
2610
aggdata->dtada_total, positives, negatives));
2611
}
2612
2613
if (pd->dtpa_aggpack && DTRACEACT_ISAGG(act)) {
2614
switch (act) {
2615
case DTRACEAGG_QUANTIZE:
2616
return (dt_print_quantize_packed(dtp,
2617
fp, addr, size, aggdata));
2618
case DTRACEAGG_LQUANTIZE:
2619
return (dt_print_lquantize_packed(dtp,
2620
fp, addr, size, aggdata));
2621
default:
2622
break;
2623
}
2624
}
2625
2626
switch (act) {
2627
case DTRACEACT_STACK:
2628
return (dt_print_stack(dtp, fp, NULL, addr,
2629
rec->dtrd_arg, rec->dtrd_size / rec->dtrd_arg));
2630
2631
case DTRACEACT_USTACK:
2632
case DTRACEACT_JSTACK:
2633
return (dt_print_ustack(dtp, fp, NULL, addr, rec->dtrd_arg));
2634
2635
case DTRACEACT_USYM:
2636
case DTRACEACT_UADDR:
2637
return (dt_print_usym(dtp, fp, addr, act));
2638
2639
case DTRACEACT_UMOD:
2640
return (dt_print_umod(dtp, fp, NULL, addr));
2641
2642
case DTRACEACT_SYM:
2643
return (dt_print_sym(dtp, fp, NULL, addr));
2644
2645
case DTRACEACT_MOD:
2646
return (dt_print_mod(dtp, fp, NULL, addr));
2647
2648
case DTRACEAGG_QUANTIZE:
2649
return (dt_print_quantize(dtp, fp, addr, size, normal));
2650
2651
case DTRACEAGG_LQUANTIZE:
2652
return (dt_print_lquantize(dtp, fp, addr, size, normal));
2653
2654
case DTRACEAGG_LLQUANTIZE:
2655
return (dt_print_llquantize(dtp, fp, addr, size, normal));
2656
2657
case DTRACEAGG_AVG:
2658
return (dt_print_average(dtp, fp, addr, size, normal));
2659
2660
case DTRACEAGG_STDDEV:
2661
return (dt_print_stddev(dtp, fp, addr, size, normal));
2662
2663
default:
2664
break;
2665
}
2666
2667
for (fmt = fmttab; fmt->size && fmt->size != size; fmt++)
2668
continue;
2669
2670
width = packed ? fmt->packedwidth : fmt->width;
2671
2672
switch (size) {
2673
case sizeof (uint64_t):
2674
err = dt_printf(dtp, fp, " %*lld", width,
2675
/* LINTED - alignment */
2676
(long long)*((uint64_t *)addr) / normal);
2677
break;
2678
case sizeof (uint32_t):
2679
/* LINTED - alignment */
2680
err = dt_printf(dtp, fp, " %*d", width, *((uint32_t *)addr) /
2681
(uint32_t)normal);
2682
break;
2683
case sizeof (uint16_t):
2684
/* LINTED - alignment */
2685
err = dt_printf(dtp, fp, " %*d", width, *((uint16_t *)addr) /
2686
(uint32_t)normal);
2687
break;
2688
case sizeof (uint8_t):
2689
err = dt_printf(dtp, fp, " %*d", width, *((uint8_t *)addr) /
2690
(uint32_t)normal);
2691
break;
2692
default:
2693
err = dt_print_bytes(dtp, fp, addr, size, width, 0, 0);
2694
break;
2695
}
2696
2697
return (err);
2698
}
2699
2700
int
2701
dt_format_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
2702
{
2703
int i, aggact = 0;
2704
dt_print_aggdata_t *pd = arg;
2705
const dtrace_aggdata_t *aggdata = aggsdata[0];
2706
dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2707
dtrace_hdl_t *dtp = pd->dtpa_dtp;
2708
dtrace_recdesc_t *rec;
2709
dtrace_actkind_t act;
2710
caddr_t addr;
2711
size_t size;
2712
2713
if (pd->dtpa_aggname == NULL)
2714
pd->dtpa_aggname = agg->dtagd_name;
2715
2716
xo_open_instance("aggregation-data");
2717
strcpy(pd->dtpa_keyname, "value");
2718
xo_open_list("keys");
2719
2720
/*
2721
* Iterate over each record description in the key, printing the traced
2722
* data, skipping the first datum (the tuple member created by the
2723
* compiler).
2724
*/
2725
for (i = 1; i < agg->dtagd_nrecs; i++) {
2726
rec = &agg->dtagd_rec[i];
2727
act = rec->dtrd_action;
2728
addr = aggdata->dtada_data + rec->dtrd_offset;
2729
size = rec->dtrd_size;
2730
2731
if (DTRACEACT_ISAGG(act)) {
2732
aggact = i;
2733
break;
2734
}
2735
2736
xo_open_instance("keys");
2737
if (dt_format_datum(dtp, rec, addr,
2738
size, aggdata, 1, pd) < 0) {
2739
xo_close_instance("keys");
2740
xo_close_instance("aggregation-data");
2741
return (-1);
2742
}
2743
xo_close_instance("keys");
2744
2745
if (dt_buffered_flush(dtp, NULL, rec, aggdata,
2746
DTRACE_BUFDATA_AGGKEY) < 0) {
2747
xo_close_instance("aggregation-data");
2748
return (-1);
2749
}
2750
}
2751
xo_close_list("keys");
2752
2753
assert(aggact != 0);
2754
2755
for (i = (naggvars == 1 ? 0 : 1); i < naggvars; i++) {
2756
uint64_t normal;
2757
2758
aggdata = aggsdata[i];
2759
agg = aggdata->dtada_desc;
2760
rec = &agg->dtagd_rec[aggact];
2761
act = rec->dtrd_action;
2762
addr = aggdata->dtada_data + rec->dtrd_offset;
2763
size = rec->dtrd_size;
2764
2765
assert(DTRACEACT_ISAGG(act));
2766
2767
switch (act) {
2768
case DTRACEAGG_MIN:
2769
strcpy(pd->dtpa_keyname, "min");
2770
break;
2771
case DTRACEAGG_MAX:
2772
strcpy(pd->dtpa_keyname, "max");
2773
break;
2774
case DTRACEAGG_COUNT:
2775
strcpy(pd->dtpa_keyname, "count");
2776
break;
2777
case DTRACEAGG_SUM:
2778
strcpy(pd->dtpa_keyname, "sum");
2779
break;
2780
default:
2781
strcpy(pd->dtpa_keyname, "UNKNOWN");
2782
break;
2783
}
2784
2785
normal = aggdata->dtada_normal;
2786
2787
if (dt_format_datum(dtp, rec, addr, size,
2788
aggdata, normal, pd) < 0) {
2789
xo_close_instance("aggregation-data");
2790
return (-1);
2791
}
2792
2793
if (dt_buffered_flush(dtp, NULL, rec, aggdata,
2794
DTRACE_BUFDATA_AGGVAL) < 0) {
2795
xo_close_instance("aggregation-data");
2796
return (-1);
2797
}
2798
2799
if (!pd->dtpa_allunprint)
2800
agg->dtagd_flags |= DTRACE_AGD_PRINTED;
2801
}
2802
2803
if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
2804
DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0) {
2805
xo_close_instance("aggregation-data");
2806
return (-1);
2807
}
2808
2809
xo_close_instance("aggregation-data");
2810
return (0);
2811
}
2812
2813
int
2814
dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
2815
{
2816
int i, aggact = 0;
2817
dt_print_aggdata_t *pd = arg;
2818
const dtrace_aggdata_t *aggdata = aggsdata[0];
2819
dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2820
FILE *fp = pd->dtpa_fp;
2821
dtrace_hdl_t *dtp = pd->dtpa_dtp;
2822
dtrace_recdesc_t *rec;
2823
dtrace_actkind_t act;
2824
caddr_t addr;
2825
size_t size;
2826
2827
pd->dtpa_agghist = (aggdata->dtada_flags & DTRACE_A_TOTAL);
2828
pd->dtpa_aggpack = (aggdata->dtada_flags & DTRACE_A_MINMAXBIN);
2829
2830
/*
2831
* Iterate over each record description in the key, printing the traced
2832
* data, skipping the first datum (the tuple member created by the
2833
* compiler).
2834
*/
2835
for (i = 1; i < agg->dtagd_nrecs; i++) {
2836
rec = &agg->dtagd_rec[i];
2837
act = rec->dtrd_action;
2838
addr = aggdata->dtada_data + rec->dtrd_offset;
2839
size = rec->dtrd_size;
2840
2841
if (DTRACEACT_ISAGG(act)) {
2842
aggact = i;
2843
break;
2844
}
2845
2846
if (dt_print_datum(dtp, fp, rec, addr,
2847
size, aggdata, 1, pd) < 0)
2848
return (-1);
2849
2850
if (dt_buffered_flush(dtp, NULL, rec, aggdata,
2851
DTRACE_BUFDATA_AGGKEY) < 0)
2852
return (-1);
2853
}
2854
2855
assert(aggact != 0);
2856
2857
for (i = (naggvars == 1 ? 0 : 1); i < naggvars; i++) {
2858
uint64_t normal;
2859
2860
aggdata = aggsdata[i];
2861
agg = aggdata->dtada_desc;
2862
rec = &agg->dtagd_rec[aggact];
2863
act = rec->dtrd_action;
2864
addr = aggdata->dtada_data + rec->dtrd_offset;
2865
size = rec->dtrd_size;
2866
2867
assert(DTRACEACT_ISAGG(act));
2868
normal = aggdata->dtada_normal;
2869
2870
if (dt_print_datum(dtp, fp, rec, addr,
2871
size, aggdata, normal, pd) < 0)
2872
return (-1);
2873
2874
if (dt_buffered_flush(dtp, NULL, rec, aggdata,
2875
DTRACE_BUFDATA_AGGVAL) < 0)
2876
return (-1);
2877
2878
if (!pd->dtpa_allunprint)
2879
agg->dtagd_flags |= DTRACE_AGD_PRINTED;
2880
}
2881
2882
if (!pd->dtpa_agghist && !pd->dtpa_aggpack) {
2883
if (dt_printf(dtp, fp, "\n") < 0)
2884
return (-1);
2885
}
2886
2887
if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
2888
DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
2889
return (-1);
2890
2891
return (0);
2892
}
2893
2894
int
2895
dt_format_agg(const dtrace_aggdata_t *aggdata, void *arg)
2896
{
2897
dt_print_aggdata_t *pd = arg;
2898
dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2899
dtrace_aggvarid_t aggvarid = pd->dtpa_id;
2900
2901
if (pd->dtpa_allunprint) {
2902
if (agg->dtagd_flags & DTRACE_AGD_PRINTED)
2903
return (0);
2904
} else {
2905
/*
2906
* If we're not printing all unprinted aggregations, then the
2907
* aggregation variable ID denotes a specific aggregation
2908
* variable that we should print -- skip any other aggregations
2909
* that we encounter.
2910
*/
2911
if (agg->dtagd_nrecs == 0)
2912
return (0);
2913
2914
if (aggvarid != agg->dtagd_varid)
2915
return (0);
2916
}
2917
2918
return (dt_format_aggs(&aggdata, 1, arg));
2919
}
2920
2921
int
2922
dt_print_agg(const dtrace_aggdata_t *aggdata, void *arg)
2923
{
2924
dt_print_aggdata_t *pd = arg;
2925
dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2926
dtrace_aggvarid_t aggvarid = pd->dtpa_id;
2927
2928
if (pd->dtpa_allunprint) {
2929
if (agg->dtagd_flags & DTRACE_AGD_PRINTED)
2930
return (0);
2931
} else {
2932
/*
2933
* If we're not printing all unprinted aggregations, then the
2934
* aggregation variable ID denotes a specific aggregation
2935
* variable that we should print -- skip any other aggregations
2936
* that we encounter.
2937
*/
2938
if (agg->dtagd_nrecs == 0)
2939
return (0);
2940
2941
if (aggvarid != agg->dtagd_varid)
2942
return (0);
2943
}
2944
2945
return (dt_print_aggs(&aggdata, 1, arg));
2946
}
2947
2948
int
2949
dt_setopt(dtrace_hdl_t *dtp, const dtrace_probedata_t *data,
2950
const char *option, const char *value)
2951
{
2952
int len, rval;
2953
char *msg;
2954
const char *errstr;
2955
dtrace_setoptdata_t optdata;
2956
2957
bzero(&optdata, sizeof (optdata));
2958
(void) dtrace_getopt(dtp, option, &optdata.dtsda_oldval);
2959
2960
if (dtrace_setopt(dtp, option, value) == 0) {
2961
(void) dtrace_getopt(dtp, option, &optdata.dtsda_newval);
2962
optdata.dtsda_probe = data;
2963
optdata.dtsda_option = option;
2964
optdata.dtsda_handle = dtp;
2965
2966
if ((rval = dt_handle_setopt(dtp, &optdata)) != 0)
2967
return (rval);
2968
2969
return (0);
2970
}
2971
2972
errstr = dtrace_errmsg(dtp, dtrace_errno(dtp));
2973
len = strlen(option) + strlen(value) + strlen(errstr) + 80;
2974
msg = alloca(len);
2975
2976
(void) snprintf(msg, len, "couldn't set option \"%s\" to \"%s\": %s\n",
2977
option, value, errstr);
2978
2979
if ((rval = dt_handle_liberr(dtp, data, msg)) == 0)
2980
return (0);
2981
2982
return (rval);
2983
}
2984
2985
/*
2986
* Helper functions to help maintain style(9) in dt_consume_cpu().
2987
*/
2988
static int
2989
dt_oformat_agg_sorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func,
2990
dt_print_aggdata_t *pd)
2991
{
2992
int r;
2993
2994
r = dtrace_aggregate_walk_sorted(dtp, dt_format_agg, pd);
2995
if (r < 0) {
2996
xo_close_list("aggregation-data");
2997
xo_emit("{:aggregation-name/%s}", pd->dtpa_aggname);
2998
xo_close_instance("output");
2999
}
3000
3001
return (r);
3002
}
3003
3004
static void
3005
dt_oformat_agg_name(dt_print_aggdata_t *pd)
3006
{
3007
3008
xo_close_list("aggregation-data");
3009
xo_emit("{:aggregation-name/%s}", pd->dtpa_aggname);
3010
}
3011
3012
static int
3013
dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
3014
dtrace_bufdesc_t *buf, boolean_t just_one,
3015
dtrace_consume_probe_f *efunc, dtrace_consume_rec_f *rfunc, void *arg)
3016
{
3017
dtrace_epid_t id;
3018
size_t offs;
3019
int flow = (dtp->dt_options[DTRACEOPT_FLOWINDENT] != DTRACEOPT_UNSET);
3020
int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET);
3021
int rval, i, n;
3022
uint64_t tracememsize = 0;
3023
dtrace_probedata_t data;
3024
uint64_t drops;
3025
size_t skip_format;
3026
3027
bzero(&data, sizeof (data));
3028
data.dtpda_handle = dtp;
3029
data.dtpda_cpu = cpu;
3030
data.dtpda_flow = dtp->dt_flow;
3031
data.dtpda_indent = dtp->dt_indent;
3032
data.dtpda_prefix = dtp->dt_prefix;
3033
3034
for (offs = buf->dtbd_oldest; offs < buf->dtbd_size; ) {
3035
dtrace_eprobedesc_t *epd;
3036
3037
/*
3038
* We're guaranteed to have an ID.
3039
*/
3040
id = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);
3041
3042
if (id == DTRACE_EPIDNONE) {
3043
/*
3044
* This is filler to assure proper alignment of the
3045
* next record; we simply ignore it.
3046
*/
3047
offs += sizeof (id);
3048
continue;
3049
}
3050
3051
if ((rval = dt_epid_lookup(dtp, id, &data.dtpda_edesc,
3052
&data.dtpda_pdesc)) != 0)
3053
return (rval);
3054
3055
epd = data.dtpda_edesc;
3056
data.dtpda_data = buf->dtbd_data + offs;
3057
data.dtpda_timestamp = DTRACE_RECORD_LOAD_TIMESTAMP(
3058
(struct dtrace_rechdr *)data.dtpda_data);
3059
3060
if (data.dtpda_edesc->dtepd_uarg != DT_ECB_DEFAULT) {
3061
rval = dt_handle(dtp, &data);
3062
3063
if (rval == DTRACE_CONSUME_NEXT)
3064
goto nextepid;
3065
3066
if (rval == DTRACE_CONSUME_ERROR)
3067
return (-1);
3068
}
3069
3070
if (flow)
3071
(void) dt_flowindent(dtp, &data, dtp->dt_last_epid,
3072
buf, offs);
3073
3074
if (dtp->dt_oformat)
3075
xo_open_instance("probes");
3076
rval = (*efunc)(&data, arg);
3077
3078
if (flow) {
3079
if (data.dtpda_flow == DTRACEFLOW_ENTRY)
3080
data.dtpda_indent += 2;
3081
}
3082
3083
if (rval == DTRACE_CONSUME_NEXT)
3084
goto nextepid;
3085
3086
if (rval == DTRACE_CONSUME_ABORT)
3087
return (dt_set_errno(dtp, EDT_DIRABORT));
3088
3089
if (rval != DTRACE_CONSUME_THIS)
3090
return (dt_set_errno(dtp, EDT_BADRVAL));
3091
3092
skip_format = 0;
3093
if (dtp->dt_oformat)
3094
xo_open_list("output");
3095
for (i = 0; i < epd->dtepd_nrecs; i++) {
3096
caddr_t addr;
3097
dtrace_recdesc_t *rec = &epd->dtepd_rec[i];
3098
dtrace_actkind_t act = rec->dtrd_action;
3099
3100
if (skip_format > 0)
3101
skip_format--;
3102
3103
data.dtpda_data = buf->dtbd_data + offs +
3104
rec->dtrd_offset;
3105
addr = data.dtpda_data;
3106
3107
if (act == DTRACEACT_LIBACT) {
3108
uint64_t arg = rec->dtrd_arg;
3109
dtrace_aggvarid_t id;
3110
3111
switch (arg) {
3112
case DT_ACT_CLEAR:
3113
/* LINTED - alignment */
3114
id = *((dtrace_aggvarid_t *)addr);
3115
(void) dtrace_aggregate_walk(dtp,
3116
dt_clear_agg, &id);
3117
continue;
3118
3119
case DT_ACT_DENORMALIZE:
3120
/* LINTED - alignment */
3121
id = *((dtrace_aggvarid_t *)addr);
3122
(void) dtrace_aggregate_walk(dtp,
3123
dt_denormalize_agg, &id);
3124
continue;
3125
3126
case DT_ACT_FTRUNCATE:
3127
if (fp == NULL)
3128
continue;
3129
3130
(void) fflush(fp);
3131
(void) ftruncate(fileno(fp), 0);
3132
(void) fseeko(fp, 0, SEEK_SET);
3133
continue;
3134
3135
case DT_ACT_NORMALIZE:
3136
if (i == epd->dtepd_nrecs - 1)
3137
return (dt_set_errno(dtp,
3138
EDT_BADNORMAL));
3139
3140
if (dt_normalize(dtp,
3141
buf->dtbd_data + offs, rec) != 0)
3142
return (-1);
3143
3144
i++;
3145
continue;
3146
3147
case DT_ACT_SETOPT: {
3148
uint64_t *opts = dtp->dt_options;
3149
dtrace_recdesc_t *valrec;
3150
uint32_t valsize;
3151
caddr_t val;
3152
int rv;
3153
3154
if (i == epd->dtepd_nrecs - 1) {
3155
return (dt_set_errno(dtp,
3156
EDT_BADSETOPT));
3157
}
3158
3159
valrec = &epd->dtepd_rec[++i];
3160
valsize = valrec->dtrd_size;
3161
3162
if (valrec->dtrd_action != act ||
3163
valrec->dtrd_arg != arg) {
3164
return (dt_set_errno(dtp,
3165
EDT_BADSETOPT));
3166
}
3167
3168
if (valsize > sizeof (uint64_t)) {
3169
val = buf->dtbd_data + offs +
3170
valrec->dtrd_offset;
3171
} else {
3172
val = "1";
3173
}
3174
3175
rv = dt_setopt(dtp, &data, addr, val);
3176
3177
if (rv != 0)
3178
return (-1);
3179
3180
flow = (opts[DTRACEOPT_FLOWINDENT] !=
3181
DTRACEOPT_UNSET);
3182
quiet = (opts[DTRACEOPT_QUIET] !=
3183
DTRACEOPT_UNSET);
3184
3185
continue;
3186
}
3187
3188
case DT_ACT_TRUNC:
3189
if (i == epd->dtepd_nrecs - 1)
3190
return (dt_set_errno(dtp,
3191
EDT_BADTRUNC));
3192
3193
if (dt_trunc(dtp,
3194
buf->dtbd_data + offs, rec) != 0)
3195
return (-1);
3196
3197
i++;
3198
continue;
3199
3200
default:
3201
continue;
3202
}
3203
}
3204
3205
if (act == DTRACEACT_TRACEMEM_DYNSIZE &&
3206
rec->dtrd_size == sizeof (uint64_t)) {
3207
/* LINTED - alignment */
3208
tracememsize = *((unsigned long long *)addr);
3209
continue;
3210
}
3211
3212
rval = (*rfunc)(&data, rec, arg);
3213
3214
if (rval == DTRACE_CONSUME_NEXT)
3215
continue;
3216
3217
if (rval == DTRACE_CONSUME_ABORT)
3218
return (dt_set_errno(dtp, EDT_DIRABORT));
3219
3220
if (rval != DTRACE_CONSUME_THIS)
3221
return (dt_set_errno(dtp, EDT_BADRVAL));
3222
3223
if (dtp->dt_oformat && rec->dtrd_size > 0)
3224
xo_open_instance("output");
3225
if (act == DTRACEACT_STACK) {
3226
int depth = rec->dtrd_arg;
3227
3228
if (dtp->dt_oformat) {
3229
if (dt_format_stack(dtp, addr, depth,
3230
rec->dtrd_size / depth) < 0) {
3231
xo_close_instance("output");
3232
return (-1);
3233
}
3234
} else {
3235
if (dt_print_stack(dtp,
3236
fp, NULL, addr, depth,
3237
rec->dtrd_size / depth) < 0)
3238
return (-1);
3239
}
3240
goto nextrec;
3241
}
3242
3243
if (act == DTRACEACT_USTACK ||
3244
act == DTRACEACT_JSTACK) {
3245
if (dtp->dt_oformat) {
3246
if (dt_format_ustack(dtp, addr,
3247
rec->dtrd_arg) < 0) {
3248
xo_close_instance("output");
3249
return (-1);
3250
}
3251
} else {
3252
if (dt_print_ustack(dtp, fp, NULL,
3253
addr, rec->dtrd_arg) < 0)
3254
return (-1);
3255
}
3256
goto nextrec;
3257
}
3258
3259
if (act == DTRACEACT_SYM) {
3260
if (dtp->dt_oformat) {
3261
if (dt_format_sym(dtp, addr) < 0) {
3262
xo_close_instance("output");
3263
return (-1);
3264
}
3265
} else {
3266
if (dt_print_sym(dtp, fp, NULL, addr) < 0)
3267
return (-1);
3268
}
3269
goto nextrec;
3270
}
3271
3272
if (act == DTRACEACT_MOD) {
3273
if (dtp->dt_oformat) {
3274
if (dt_format_mod(dtp, addr) < 0) {
3275
xo_close_instance("output");
3276
return (-1);
3277
}
3278
} else {
3279
if (dt_print_mod(dtp, fp, NULL, addr) < 0)
3280
return (-1);
3281
}
3282
goto nextrec;
3283
}
3284
3285
if (act == DTRACEACT_USYM || act == DTRACEACT_UADDR) {
3286
if (dtp->dt_oformat) {
3287
if (dt_format_usym(dtp, addr, act) < 0) {
3288
xo_close_instance("output");
3289
return (-1);
3290
}
3291
} else {
3292
if (dt_print_usym(dtp, fp, addr, act) < 0)
3293
return (-1);
3294
}
3295
goto nextrec;
3296
}
3297
3298
if (act == DTRACEACT_UMOD) {
3299
if (dtp->dt_oformat) {
3300
if (dt_format_umod(dtp, addr) < 0) {
3301
xo_close_instance("output");
3302
return (-1);
3303
}
3304
} else {
3305
if (dt_print_umod(dtp, fp, NULL, addr) < 0)
3306
return (-1);
3307
}
3308
goto nextrec;
3309
}
3310
3311
if (act == DTRACEACT_PRINTM) {
3312
if (dtp->dt_oformat) {
3313
if (dt_format_memory(dtp, addr) < 0) {
3314
xo_close_instance("output");
3315
return (-1);
3316
}
3317
} else {
3318
if (dt_print_memory(dtp, fp, addr) < 0)
3319
return (-1);
3320
}
3321
goto nextrec;
3322
}
3323
3324
if (dtp->dt_oformat == DTRACE_OFORMAT_TEXT &&
3325
DTRACEACT_ISPRINTFLIKE(act)) {
3326
void *fmtdata;
3327
int (*func)(dtrace_hdl_t *, FILE *, void *,
3328
const dtrace_probedata_t *,
3329
const dtrace_recdesc_t *, uint_t,
3330
const void *buf, size_t);
3331
3332
if ((fmtdata = dt_format_lookup(dtp,
3333
rec->dtrd_format)) == NULL)
3334
goto nofmt;
3335
3336
switch (act) {
3337
case DTRACEACT_PRINTF:
3338
func = dtrace_fprintf;
3339
break;
3340
case DTRACEACT_PRINTA:
3341
func = dtrace_fprinta;
3342
break;
3343
case DTRACEACT_SYSTEM:
3344
func = dtrace_system;
3345
break;
3346
case DTRACEACT_FREOPEN:
3347
func = dtrace_freopen;
3348
break;
3349
}
3350
3351
n = (*func)(dtp, fp, fmtdata, &data,
3352
rec, epd->dtepd_nrecs - i,
3353
(uchar_t *)buf->dtbd_data + offs,
3354
buf->dtbd_size - offs);
3355
3356
if (n < 0)
3357
return (-1); /* errno is set for us */
3358
3359
if (n > 0)
3360
i += n - 1;
3361
goto nextrec;
3362
}
3363
3364
/*
3365
* We don't care about a formatted printa, system or
3366
* freopen for oformat.
3367
*/
3368
if (dtp->dt_oformat && act == DTRACEACT_PRINTF &&
3369
skip_format == 0) {
3370
void *fmtdata;
3371
if ((fmtdata = dt_format_lookup(dtp,
3372
rec->dtrd_format)) == NULL)
3373
goto nofmt;
3374
3375
n = dtrace_sprintf(dtp, fp, fmtdata, rec,
3376
epd->dtepd_nrecs - i,
3377
(uchar_t *)buf->dtbd_data + offs,
3378
buf->dtbd_size - offs);
3379
3380
if (n < 0) {
3381
xo_close_instance("output");
3382
return (-1); /* errno is set for us */
3383
}
3384
3385
xo_emit("{:message/%s}", dtp->dt_sprintf_buf);
3386
skip_format += n;
3387
3388
/*
3389
* We want the "message" object to be its own
3390
* thing, but we still want to process the
3391
* current DIFEXPR in case there is a value
3392
* attached to it. If there is, we need to
3393
* re-open a new output instance, as otherwise
3394
* the message ends up bundled with the first
3395
* value.
3396
*
3397
* XXX: There is an edge case where a
3398
* printf("hello"); will produce a DIFO that
3399
* returns 0 attached to it and we have no good
3400
* way to determine if this 0 value is because
3401
* there's no real data attached to the printf
3402
* as an argument, or it's because the argument
3403
* actually returns 0.
3404
*/
3405
if (skip_format == 0)
3406
goto nextrec;
3407
3408
xo_close_instance("output");
3409
xo_open_instance("output");
3410
}
3411
3412
/*
3413
* If this is a DIF expression, and the record has a
3414
* format set, this indicates we have a CTF type name
3415
* associated with the data and we should try to print
3416
* it out by type.
3417
*/
3418
if (act == DTRACEACT_DIFEXPR) {
3419
const char *strdata = dt_strdata_lookup(dtp,
3420
rec->dtrd_format);
3421
if (strdata != NULL) {
3422
if (dtp->dt_oformat)
3423
n = dtrace_format_print(dtp, fp,
3424
strdata, addr,
3425
rec->dtrd_size);
3426
else
3427
n = dtrace_print(dtp, fp,
3428
strdata, addr,
3429
rec->dtrd_size);
3430
3431
/*
3432
* dtrace_print() will return -1 on
3433
* error, or return the number of bytes
3434
* consumed. It will return 0 if the
3435
* type couldn't be determined, and we
3436
* should fall through to the normal
3437
* trace method.
3438
*/
3439
if (n < 0) {
3440
if (dtp->dt_oformat)
3441
xo_close_instance(
3442
"output");
3443
return (-1);
3444
}
3445
3446
if (n > 0)
3447
goto nextrec;
3448
}
3449
}
3450
3451
nofmt:
3452
if (act == DTRACEACT_PRINTA) {
3453
dt_print_aggdata_t pd;
3454
dtrace_aggvarid_t *aggvars;
3455
int j, naggvars = 0;
3456
size_t size = ((epd->dtepd_nrecs - i) *
3457
sizeof (dtrace_aggvarid_t));
3458
3459
if ((aggvars = dt_alloc(dtp, size)) == NULL) {
3460
if (dtp->dt_oformat)
3461
xo_close_instance("output");
3462
return (-1);
3463
}
3464
3465
/*
3466
* This might be a printa() with multiple
3467
* aggregation variables. We need to scan
3468
* forward through the records until we find
3469
* a record from a different statement.
3470
*/
3471
for (j = i; j < epd->dtepd_nrecs; j++) {
3472
dtrace_recdesc_t *nrec;
3473
caddr_t naddr;
3474
3475
nrec = &epd->dtepd_rec[j];
3476
3477
if (nrec->dtrd_uarg != rec->dtrd_uarg)
3478
break;
3479
3480
if (nrec->dtrd_action != act) {
3481
if (dtp->dt_oformat)
3482
xo_close_instance(
3483
"output");
3484
return (dt_set_errno(dtp,
3485
EDT_BADAGG));
3486
}
3487
3488
naddr = buf->dtbd_data + offs +
3489
nrec->dtrd_offset;
3490
3491
aggvars[naggvars++] =
3492
/* LINTED - alignment */
3493
*((dtrace_aggvarid_t *)naddr);
3494
}
3495
3496
i = j - 1;
3497
bzero(&pd, sizeof (pd));
3498
pd.dtpa_dtp = dtp;
3499
pd.dtpa_fp = fp;
3500
3501
assert(naggvars >= 1);
3502
3503
if (dtp->dt_oformat)
3504
xo_open_list("aggregation-data");
3505
if (naggvars == 1) {
3506
pd.dtpa_id = aggvars[0];
3507
dt_free(dtp, aggvars);
3508
3509
if (dtp->dt_oformat) {
3510
n = dt_oformat_agg_sorted(dtp,
3511
dt_format_agg, &pd);
3512
if (n < 0)
3513
return (-1);
3514
} else {
3515
if (dt_printf(dtp, fp, "\n") < 0 ||
3516
dtrace_aggregate_walk_sorted(dtp,
3517
dt_print_agg, &pd) < 0)
3518
return (-1);
3519
}
3520
3521
if (dtp->dt_oformat)
3522
dt_oformat_agg_name(&pd);
3523
goto nextrec;
3524
}
3525
3526
if (dtp->dt_oformat) {
3527
if (dtrace_aggregate_walk_joined(dtp,
3528
aggvars, naggvars,
3529
dt_format_aggs, &pd) < 0) {
3530
dt_oformat_agg_name(&pd);
3531
xo_close_instance("output");
3532
dt_free(dtp, aggvars);
3533
return (-1);
3534
}
3535
} else {
3536
if (dt_printf(dtp, fp, "\n") < 0 ||
3537
dtrace_aggregate_walk_joined(dtp,
3538
aggvars, naggvars,
3539
dt_print_aggs, &pd) < 0) {
3540
dt_free(dtp, aggvars);
3541
return (-1);
3542
}
3543
}
3544
3545
if (dtp->dt_oformat)
3546
dt_oformat_agg_name(&pd);
3547
dt_free(dtp, aggvars);
3548
goto nextrec;
3549
}
3550
3551
if (act == DTRACEACT_TRACEMEM) {
3552
if (tracememsize == 0 ||
3553
tracememsize > rec->dtrd_size) {
3554
tracememsize = rec->dtrd_size;
3555
}
3556
3557
if (dtp->dt_oformat) {
3558
char *s;
3559
3560
s = dt_format_bytes_get(dtp, addr,
3561
tracememsize);
3562
n = xo_emit("{:tracemem/%s}", s);
3563
dt_free(dtp, s);
3564
} else {
3565
n = dt_print_bytes(dtp, fp, addr,
3566
tracememsize, -33, quiet, 1);
3567
}
3568
3569
tracememsize = 0;
3570
3571
if (n < 0)
3572
return (-1);
3573
3574
goto nextrec;
3575
}
3576
3577
switch (rec->dtrd_size) {
3578
case sizeof (uint64_t):
3579
if (dtp->dt_oformat) {
3580
xo_emit("{:value/%lld}",
3581
*((unsigned long long *)addr));
3582
n = 0;
3583
} else
3584
n = dt_printf(dtp, fp,
3585
quiet ? "%lld" : " %16lld",
3586
/* LINTED - alignment */
3587
*((unsigned long long *)addr));
3588
break;
3589
case sizeof (uint32_t):
3590
if (dtp->dt_oformat) {
3591
xo_emit("{:value/%d}",
3592
*((uint32_t *)addr));
3593
n = 0;
3594
} else
3595
n = dt_printf(dtp, fp,
3596
quiet ? "%d" : " %8d",
3597
/* LINTED - alignment */
3598
*((uint32_t *)addr));
3599
break;
3600
case sizeof (uint16_t):
3601
if (dtp->dt_oformat) {
3602
xo_emit("{:value/%d}",
3603
*((uint16_t *)addr));
3604
n = 0;
3605
} else
3606
n = dt_printf(dtp, fp,
3607
quiet ? "%d" : " %5d",
3608
/* LINTED - alignment */
3609
*((uint16_t *)addr));
3610
break;
3611
case sizeof (uint8_t):
3612
if (dtp->dt_oformat) {
3613
xo_emit("{:value/%d}",
3614
*((uint8_t *)addr));
3615
n = 0;
3616
} else
3617
n = dt_printf(dtp, fp,
3618
quiet ? "%d" : " %3d",
3619
*((uint8_t *)addr));
3620
break;
3621
default:
3622
if (dtp->dt_oformat && rec->dtrd_size > 0) {
3623
char *s;
3624
3625
s = dt_format_bytes_get(dtp, addr,
3626
rec->dtrd_size);
3627
xo_emit("{:value/%s}", s);
3628
dt_free(dtp, s);
3629
n = 0;
3630
} else {
3631
n = dt_print_bytes(dtp, fp, addr,
3632
rec->dtrd_size, -33, quiet, 0);
3633
}
3634
break;
3635
}
3636
3637
if (dtp->dt_oformat && rec->dtrd_size > 0)
3638
xo_close_instance("output");
3639
3640
if (n < 0)
3641
return (-1); /* errno is set for us */
3642
3643
nextrec:
3644
if (dt_buffered_flush(dtp, &data, rec, NULL, 0) < 0)
3645
return (-1); /* errno is set for us */
3646
}
3647
3648
/*
3649
* Call the record callback with a NULL record to indicate
3650
* that we're done processing this EPID.
3651
*/
3652
rval = (*rfunc)(&data, NULL, arg);
3653
nextepid:
3654
offs += epd->dtepd_size;
3655
dtp->dt_last_epid = id;
3656
3657
if (dtp->dt_oformat) {
3658
xo_close_list("output");
3659
xo_close_instance("probes");
3660
xo_flush();
3661
}
3662
if (just_one) {
3663
buf->dtbd_oldest = offs;
3664
break;
3665
}
3666
}
3667
3668
dtp->dt_flow = data.dtpda_flow;
3669
dtp->dt_indent = data.dtpda_indent;
3670
dtp->dt_prefix = data.dtpda_prefix;
3671
3672
if ((drops = buf->dtbd_drops) == 0)
3673
return (0);
3674
3675
/*
3676
* Explicitly zero the drops to prevent us from processing them again.
3677
*/
3678
buf->dtbd_drops = 0;
3679
3680
if (dtp->dt_oformat) {
3681
xo_open_instance("probes");
3682
dt_oformat_drop(dtp, cpu);
3683
}
3684
rval = dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops);
3685
if (dtp->dt_oformat)
3686
xo_close_instance("probes");
3687
3688
return (rval);
3689
}
3690
3691
/*
3692
* Reduce memory usage by shrinking the buffer if it's no more than half full.
3693
* Note, we need to preserve the alignment of the data at dtbd_oldest, which is
3694
* only 4-byte aligned.
3695
*/
3696
static void
3697
dt_realloc_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf, int cursize)
3698
{
3699
uint64_t used = buf->dtbd_size - buf->dtbd_oldest;
3700
if (used < cursize / 2) {
3701
int misalign = buf->dtbd_oldest & (sizeof (uint64_t) - 1);
3702
char *newdata = dt_alloc(dtp, used + misalign);
3703
if (newdata == NULL)
3704
return;
3705
bzero(newdata, misalign);
3706
bcopy(buf->dtbd_data + buf->dtbd_oldest,
3707
newdata + misalign, used);
3708
dt_free(dtp, buf->dtbd_data);
3709
buf->dtbd_oldest = misalign;
3710
buf->dtbd_size = used + misalign;
3711
buf->dtbd_data = newdata;
3712
}
3713
}
3714
3715
/*
3716
* If the ring buffer has wrapped, the data is not in order. Rearrange it
3717
* so that it is. Note, we need to preserve the alignment of the data at
3718
* dtbd_oldest, which is only 4-byte aligned.
3719
*/
3720
static int
3721
dt_unring_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
3722
{
3723
int misalign;
3724
char *newdata, *ndp;
3725
3726
if (buf->dtbd_oldest == 0)
3727
return (0);
3728
3729
misalign = buf->dtbd_oldest & (sizeof (uint64_t) - 1);
3730
newdata = ndp = dt_alloc(dtp, buf->dtbd_size + misalign);
3731
3732
if (newdata == NULL)
3733
return (-1);
3734
3735
assert(0 == (buf->dtbd_size & (sizeof (uint64_t) - 1)));
3736
3737
bzero(ndp, misalign);
3738
ndp += misalign;
3739
3740
bcopy(buf->dtbd_data + buf->dtbd_oldest, ndp,
3741
buf->dtbd_size - buf->dtbd_oldest);
3742
ndp += buf->dtbd_size - buf->dtbd_oldest;
3743
3744
bcopy(buf->dtbd_data, ndp, buf->dtbd_oldest);
3745
3746
dt_free(dtp, buf->dtbd_data);
3747
buf->dtbd_oldest = misalign;
3748
buf->dtbd_data = newdata;
3749
buf->dtbd_size += misalign;
3750
3751
return (0);
3752
}
3753
3754
static void
3755
dt_put_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
3756
{
3757
dt_free(dtp, buf->dtbd_data);
3758
dt_free(dtp, buf);
3759
}
3760
3761
/*
3762
* Returns 0 on success, in which case *cbp will be filled in if we retrieved
3763
* data, or NULL if there is no data for this CPU.
3764
* Returns -1 on failure and sets dt_errno.
3765
*/
3766
static int
3767
dt_get_buf(dtrace_hdl_t *dtp, int cpu, dtrace_bufdesc_t **bufp)
3768
{
3769
dtrace_optval_t size;
3770
dtrace_bufdesc_t *buf = dt_zalloc(dtp, sizeof (*buf));
3771
int error, rval;
3772
3773
if (buf == NULL)
3774
return (-1);
3775
3776
(void) dtrace_getopt(dtp, "bufsize", &size);
3777
buf->dtbd_data = dt_alloc(dtp, size);
3778
if (buf->dtbd_data == NULL) {
3779
dt_free(dtp, buf);
3780
return (-1);
3781
}
3782
buf->dtbd_size = size;
3783
buf->dtbd_cpu = cpu;
3784
3785
#ifdef illumos
3786
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
3787
#else
3788
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
3789
#endif
3790
/*
3791
* If we failed with ENOENT, it may be because the
3792
* CPU was unconfigured -- this is okay. Any other
3793
* error, however, is unexpected.
3794
*/
3795
if (errno == ENOENT) {
3796
*bufp = NULL;
3797
rval = 0;
3798
} else
3799
rval = dt_set_errno(dtp, errno);
3800
3801
dt_put_buf(dtp, buf);
3802
return (rval);
3803
}
3804
3805
error = dt_unring_buf(dtp, buf);
3806
if (error != 0) {
3807
dt_put_buf(dtp, buf);
3808
return (error);
3809
}
3810
dt_realloc_buf(dtp, buf, size);
3811
3812
*bufp = buf;
3813
return (0);
3814
}
3815
3816
typedef struct dt_begin {
3817
dtrace_consume_probe_f *dtbgn_probefunc;
3818
dtrace_consume_rec_f *dtbgn_recfunc;
3819
void *dtbgn_arg;
3820
dtrace_handle_err_f *dtbgn_errhdlr;
3821
void *dtbgn_errarg;
3822
int dtbgn_beginonly;
3823
} dt_begin_t;
3824
3825
static int
3826
dt_consume_begin_probe(const dtrace_probedata_t *data, void *arg)
3827
{
3828
dt_begin_t *begin = arg;
3829
dtrace_probedesc_t *pd = data->dtpda_pdesc;
3830
3831
int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0);
3832
int r2 = (strcmp(pd->dtpd_name, "BEGIN") == 0);
3833
3834
if (begin->dtbgn_beginonly) {
3835
if (!(r1 && r2))
3836
return (DTRACE_CONSUME_NEXT);
3837
} else {
3838
if (r1 && r2)
3839
return (DTRACE_CONSUME_NEXT);
3840
}
3841
3842
/*
3843
* We have a record that we're interested in. Now call the underlying
3844
* probe function...
3845
*/
3846
return (begin->dtbgn_probefunc(data, begin->dtbgn_arg));
3847
}
3848
3849
static int
3850
dt_consume_begin_record(const dtrace_probedata_t *data,
3851
const dtrace_recdesc_t *rec, void *arg)
3852
{
3853
dt_begin_t *begin = arg;
3854
3855
return (begin->dtbgn_recfunc(data, rec, begin->dtbgn_arg));
3856
}
3857
3858
static int
3859
dt_consume_begin_error(const dtrace_errdata_t *data, void *arg)
3860
{
3861
dt_begin_t *begin = (dt_begin_t *)arg;
3862
dtrace_probedesc_t *pd = data->dteda_pdesc;
3863
3864
int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0);
3865
int r2 = (strcmp(pd->dtpd_name, "BEGIN") == 0);
3866
3867
if (begin->dtbgn_beginonly) {
3868
if (!(r1 && r2))
3869
return (DTRACE_HANDLE_OK);
3870
} else {
3871
if (r1 && r2)
3872
return (DTRACE_HANDLE_OK);
3873
}
3874
3875
return (begin->dtbgn_errhdlr(data, begin->dtbgn_errarg));
3876
}
3877
3878
static int
3879
dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
3880
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
3881
{
3882
/*
3883
* There's this idea that the BEGIN probe should be processed before
3884
* everything else, and that the END probe should be processed after
3885
* anything else. In the common case, this is pretty easy to deal
3886
* with. However, a situation may arise where the BEGIN enabling and
3887
* END enabling are on the same CPU, and some enabling in the middle
3888
* occurred on a different CPU. To deal with this (blech!) we need to
3889
* consume the BEGIN buffer up until the end of the BEGIN probe, and
3890
* then set it aside. We will then process every other CPU, and then
3891
* we'll return to the BEGIN CPU and process the rest of the data
3892
* (which will inevitably include the END probe, if any). Making this
3893
* even more complicated (!) is the library's ERROR enabling. Because
3894
* this enabling is processed before we even get into the consume call
3895
* back, any ERROR firing would result in the library's ERROR enabling
3896
* being processed twice -- once in our first pass (for BEGIN probes),
3897
* and again in our second pass (for everything but BEGIN probes). To
3898
* deal with this, we interpose on the ERROR handler to assure that we
3899
* only process ERROR enablings induced by BEGIN enablings in the
3900
* first pass, and that we only process ERROR enablings _not_ induced
3901
* by BEGIN enablings in the second pass.
3902
*/
3903
3904
dt_begin_t begin;
3905
processorid_t cpu = dtp->dt_beganon;
3906
int rval, i;
3907
static int max_ncpus;
3908
dtrace_bufdesc_t *buf;
3909
3910
dtp->dt_beganon = -1;
3911
3912
if (dt_get_buf(dtp, cpu, &buf) != 0)
3913
return (-1);
3914
if (buf == NULL)
3915
return (0);
3916
3917
if (!dtp->dt_stopped || buf->dtbd_cpu != dtp->dt_endedon) {
3918
/*
3919
* This is the simple case. We're either not stopped, or if
3920
* we are, we actually processed any END probes on another
3921
* CPU. We can simply consume this buffer and return.
3922
*/
3923
rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
3924
pf, rf, arg);
3925
dt_put_buf(dtp, buf);
3926
return (rval);
3927
}
3928
3929
begin.dtbgn_probefunc = pf;
3930
begin.dtbgn_recfunc = rf;
3931
begin.dtbgn_arg = arg;
3932
begin.dtbgn_beginonly = 1;
3933
3934
/*
3935
* We need to interpose on the ERROR handler to be sure that we
3936
* only process ERRORs induced by BEGIN.
3937
*/
3938
begin.dtbgn_errhdlr = dtp->dt_errhdlr;
3939
begin.dtbgn_errarg = dtp->dt_errarg;
3940
dtp->dt_errhdlr = dt_consume_begin_error;
3941
dtp->dt_errarg = &begin;
3942
3943
rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
3944
dt_consume_begin_probe, dt_consume_begin_record, &begin);
3945
3946
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
3947
dtp->dt_errarg = begin.dtbgn_errarg;
3948
3949
if (rval != 0) {
3950
dt_put_buf(dtp, buf);
3951
return (rval);
3952
}
3953
3954
if (max_ncpus == 0 && (max_ncpus = dt_cpu_maxid(dtp) + 1) <= 0)
3955
return (-1);
3956
3957
for (i = 0; i < max_ncpus; i++) {
3958
dtrace_bufdesc_t *nbuf;
3959
if (i == cpu)
3960
continue;
3961
3962
if (dt_get_buf(dtp, i, &nbuf) != 0) {
3963
dt_put_buf(dtp, buf);
3964
return (-1);
3965
}
3966
if (nbuf == NULL)
3967
continue;
3968
3969
rval = dt_consume_cpu(dtp, fp, i, nbuf, B_FALSE,
3970
pf, rf, arg);
3971
dt_put_buf(dtp, nbuf);
3972
if (rval != 0) {
3973
dt_put_buf(dtp, buf);
3974
return (rval);
3975
}
3976
}
3977
3978
/*
3979
* Okay -- we're done with the other buffers. Now we want to
3980
* reconsume the first buffer -- but this time we're looking for
3981
* everything _but_ BEGIN. And of course, in order to only consume
3982
* those ERRORs _not_ associated with BEGIN, we need to reinstall our
3983
* ERROR interposition function...
3984
*/
3985
begin.dtbgn_beginonly = 0;
3986
3987
assert(begin.dtbgn_errhdlr == dtp->dt_errhdlr);
3988
assert(begin.dtbgn_errarg == dtp->dt_errarg);
3989
dtp->dt_errhdlr = dt_consume_begin_error;
3990
dtp->dt_errarg = &begin;
3991
3992
rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
3993
dt_consume_begin_probe, dt_consume_begin_record, &begin);
3994
3995
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
3996
dtp->dt_errarg = begin.dtbgn_errarg;
3997
3998
return (rval);
3999
}
4000
4001
/* ARGSUSED */
4002
static uint64_t
4003
dt_buf_oldest(void *elem, void *arg)
4004
{
4005
dtrace_bufdesc_t *buf = elem;
4006
size_t offs = buf->dtbd_oldest;
4007
4008
while (offs < buf->dtbd_size) {
4009
dtrace_rechdr_t *dtrh =
4010
/* LINTED - alignment */
4011
(dtrace_rechdr_t *)(buf->dtbd_data + offs);
4012
if (dtrh->dtrh_epid == DTRACE_EPIDNONE) {
4013
offs += sizeof (dtrace_epid_t);
4014
} else {
4015
return (DTRACE_RECORD_LOAD_TIMESTAMP(dtrh));
4016
}
4017
}
4018
4019
/* There are no records left; use the time the buffer was retrieved. */
4020
return (buf->dtbd_timestamp);
4021
}
4022
4023
int
4024
dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
4025
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
4026
{
4027
dtrace_optval_t size;
4028
static int max_ncpus;
4029
int i, rval;
4030
dtrace_optval_t interval = dtp->dt_options[DTRACEOPT_SWITCHRATE];
4031
hrtime_t now = gethrtime();
4032
4033
if (dtp->dt_lastswitch != 0) {
4034
if (now - dtp->dt_lastswitch < interval)
4035
return (0);
4036
4037
dtp->dt_lastswitch += interval;
4038
} else {
4039
dtp->dt_lastswitch = now;
4040
}
4041
4042
if (!dtp->dt_active)
4043
return (dt_set_errno(dtp, EINVAL));
4044
4045
if (max_ncpus == 0 && (max_ncpus = dt_cpu_maxid(dtp) + 1) <= 0)
4046
return (-1);
4047
4048
if (pf == NULL)
4049
pf = (dtrace_consume_probe_f *)dt_nullprobe;
4050
4051
if (rf == NULL)
4052
rf = (dtrace_consume_rec_f *)dt_nullrec;
4053
4054
if (dtp->dt_options[DTRACEOPT_TEMPORAL] == DTRACEOPT_UNSET) {
4055
/*
4056
* The output will not be in the order it was traced. Rather,
4057
* we will consume all of the data from each CPU's buffer in
4058
* turn. We apply special handling for the records from BEGIN
4059
* and END probes so that they are consumed first and last,
4060
* respectively.
4061
*
4062
* If we have just begun, we want to first process the CPU that
4063
* executed the BEGIN probe (if any).
4064
*/
4065
if (dtp->dt_active && dtp->dt_beganon != -1 &&
4066
(rval = dt_consume_begin(dtp, fp, pf, rf, arg)) != 0)
4067
return (rval);
4068
4069
for (i = 0; i < max_ncpus; i++) {
4070
dtrace_bufdesc_t *buf;
4071
4072
/*
4073
* If we have stopped, we want to process the CPU on
4074
* which the END probe was processed only _after_ we
4075
* have processed everything else.
4076
*/
4077
if (dtp->dt_stopped && (i == dtp->dt_endedon))
4078
continue;
4079
4080
if (dt_get_buf(dtp, i, &buf) != 0)
4081
return (-1);
4082
if (buf == NULL)
4083
continue;
4084
4085
dtp->dt_flow = 0;
4086
dtp->dt_indent = 0;
4087
dtp->dt_prefix = NULL;
4088
rval = dt_consume_cpu(dtp, fp, i,
4089
buf, B_FALSE, pf, rf, arg);
4090
dt_put_buf(dtp, buf);
4091
if (rval != 0)
4092
return (rval);
4093
}
4094
if (dtp->dt_stopped) {
4095
dtrace_bufdesc_t *buf;
4096
4097
if (dt_get_buf(dtp, dtp->dt_endedon, &buf) != 0)
4098
return (-1);
4099
if (buf == NULL)
4100
return (0);
4101
4102
rval = dt_consume_cpu(dtp, fp, dtp->dt_endedon,
4103
buf, B_FALSE, pf, rf, arg);
4104
dt_put_buf(dtp, buf);
4105
return (rval);
4106
}
4107
} else {
4108
/*
4109
* The output will be in the order it was traced (or for
4110
* speculations, when it was committed). We retrieve a buffer
4111
* from each CPU and put it into a priority queue, which sorts
4112
* based on the first entry in the buffer. This is sufficient
4113
* because entries within a buffer are already sorted.
4114
*
4115
* We then consume records one at a time, always consuming the
4116
* oldest record, as determined by the priority queue. When
4117
* we reach the end of the time covered by these buffers,
4118
* we need to stop and retrieve more records on the next pass.
4119
* The kernel tells us the time covered by each buffer, in
4120
* dtbd_timestamp. The first buffer's timestamp tells us the
4121
* time covered by all buffers, as subsequently retrieved
4122
* buffers will cover to a more recent time.
4123
*/
4124
4125
uint64_t *drops = alloca(max_ncpus * sizeof (uint64_t));
4126
uint64_t first_timestamp = 0;
4127
uint_t cookie = 0;
4128
dtrace_bufdesc_t *buf;
4129
4130
bzero(drops, max_ncpus * sizeof (uint64_t));
4131
4132
if (dtp->dt_bufq == NULL) {
4133
dtp->dt_bufq = dt_pq_init(dtp, max_ncpus * 2,
4134
dt_buf_oldest, NULL);
4135
if (dtp->dt_bufq == NULL) /* ENOMEM */
4136
return (-1);
4137
}
4138
4139
/* Retrieve data from each CPU. */
4140
(void) dtrace_getopt(dtp, "bufsize", &size);
4141
for (i = 0; i < max_ncpus; i++) {
4142
dtrace_bufdesc_t *buf;
4143
4144
if (dt_get_buf(dtp, i, &buf) != 0)
4145
return (-1);
4146
if (buf != NULL) {
4147
if (first_timestamp == 0)
4148
first_timestamp = buf->dtbd_timestamp;
4149
assert(buf->dtbd_timestamp >= first_timestamp);
4150
4151
dt_pq_insert(dtp->dt_bufq, buf);
4152
drops[i] = buf->dtbd_drops;
4153
buf->dtbd_drops = 0;
4154
}
4155
}
4156
4157
/* Consume records. */
4158
for (;;) {
4159
dtrace_bufdesc_t *buf = dt_pq_pop(dtp->dt_bufq);
4160
uint64_t timestamp;
4161
4162
if (buf == NULL)
4163
break;
4164
4165
timestamp = dt_buf_oldest(buf, dtp);
4166
if (timestamp == buf->dtbd_timestamp) {
4167
/*
4168
* We've reached the end of the time covered
4169
* by this buffer. If this is the oldest
4170
* buffer, we must do another pass
4171
* to retrieve more data.
4172
*/
4173
dt_put_buf(dtp, buf);
4174
if (timestamp == first_timestamp &&
4175
!dtp->dt_stopped)
4176
break;
4177
continue;
4178
}
4179
assert(timestamp >= dtp->dt_last_timestamp);
4180
dtp->dt_last_timestamp = timestamp;
4181
4182
if ((rval = dt_consume_cpu(dtp, fp,
4183
buf->dtbd_cpu, buf, B_TRUE, pf, rf, arg)) != 0)
4184
return (rval);
4185
dt_pq_insert(dtp->dt_bufq, buf);
4186
}
4187
4188
/* Consume drops. */
4189
for (i = 0; i < max_ncpus; i++) {
4190
if (drops[i] != 0) {
4191
int error;
4192
4193
if (dtp->dt_oformat) {
4194
xo_open_instance("probes");
4195
dt_oformat_drop(dtp, i);
4196
}
4197
error = dt_handle_cpudrop(dtp, i,
4198
DTRACEDROP_PRINCIPAL, drops[i]);
4199
if (dtp->dt_oformat)
4200
xo_close_instance("probes");
4201
if (error != 0)
4202
return (error);
4203
}
4204
}
4205
4206
/*
4207
* Reduce memory usage by re-allocating smaller buffers
4208
* for the "remnants".
4209
*/
4210
while (buf = dt_pq_walk(dtp->dt_bufq, &cookie))
4211
dt_realloc_buf(dtp, buf, buf->dtbd_size);
4212
}
4213
4214
return (0);
4215
}
4216
4217
void
4218
dtrace_oformat_probe(dtrace_hdl_t *dtp __unused, const dtrace_probedata_t *data,
4219
processorid_t cpu, dtrace_probedesc_t *pd)
4220
{
4221
4222
xo_emit("{:timestamp/%llu} {:cpu/%d} {:id/%d} {:provider/%s} "
4223
"{:module/%s} {:function/%s} {:name/%s}",
4224
(unsigned long long)data->dtpda_timestamp, cpu, pd->dtpd_id,
4225
pd->dtpd_provider, pd->dtpd_mod, pd->dtpd_func, pd->dtpd_name);
4226
}
4227
4228
void
4229
dt_oformat_drop(dtrace_hdl_t *dtp, processorid_t cpu)
4230
{
4231
xo_emit("{:cpu/%d} {:id/%d} {:provider/%s} "
4232
"{:module/%s} {:function/%s} {:name/%s}",
4233
cpu, -1, "dtrace", "INTERNAL", "INTERNAL", "DROP");
4234
}
4235
4236