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/*
23 * Portions copyright (c) 2013, Joyent, Inc. All rights reserved.
24 */
25
26/*
27 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
28 * Use is subject to license terms.
29 */
30
31#pragma ident	"@(#)dt_consume.c	1.23	08/01/29 SMI"
32
33#include <stdlib.h>
34#include <strings.h>
35#include <errno.h>
36#include <unistd.h>
37#include <limits.h>
38#include <assert.h>
39#include <ctype.h>
40#include <alloca.h>
41#include <dt_impl.h>
42
43#define	DT_MASK_LO 0x00000000FFFFFFFFULL
44
45int dtrace_aggregate_hash(dtrace_hdl_t *dtp, dtrace_bufdesc_t **agg_bufs);
46
47/*
48 * We declare this here because (1) we need it and (2) we want to avoid a
49 * dependency on libm in libdtrace.
50 */
51static long double
52dt_fabsl(long double x)
53{
54	if (x < 0)
55		return (-x);
56
57	return (x);
58}
59
60static int
61dt_ndigits(long long val)
62{
63	int rval = 1;
64	long long cmp = 10;
65
66	if (val < 0) {
67		val = val == INT64_MIN ? INT64_MAX : -val;
68		rval++;
69	}
70
71	while (val > cmp && cmp > 0) {
72		rval++;
73		cmp *= 10;
74	}
75
76	return (rval < 4 ? 4 : rval);
77}
78
79
80/*
81 * 128-bit arithmetic functions needed to support the stddev() aggregating
82 * action.
83 */
84static int
85dt_gt_128(uint64_t *a, uint64_t *b)
86{
87	return (a[1] > b[1] || (a[1] == b[1] && a[0] > b[0]));
88}
89
90static int
91dt_ge_128(uint64_t *a, uint64_t *b)
92{
93	return (a[1] > b[1] || (a[1] == b[1] && a[0] >= b[0]));
94}
95
96static int
97dt_le_128(uint64_t *a, uint64_t *b)
98{
99	return (a[1] < b[1] || (a[1] == b[1] && a[0] <= b[0]));
100}
101
102/*
103 * Shift the 128-bit value in a by b. If b is positive, shift left.
104 * If b is negative, shift right.
105 */
106static void
107dt_shift_128(uint64_t *a, int b)
108{
109	uint64_t mask;
110
111	if (b == 0)
112		return;
113
114	if (b < 0) {
115		b = -b;
116		if (b >= 64) {
117			a[0] = a[1] >> (b - 64);
118			a[1] = 0;
119		} else {
120			a[0] >>= b;
121			mask = 1LL << (64 - b);
122			mask -= 1;
123			a[0] |= ((a[1] & mask) << (64 - b));
124			a[1] >>= b;
125		}
126	} else {
127		if (b >= 64) {
128			a[1] = a[0] << (b - 64);
129			a[0] = 0;
130		} else {
131			a[1] <<= b;
132			mask = a[0] >> (64 - b);
133			a[1] |= mask;
134			a[0] <<= b;
135		}
136	}
137}
138
139static int
140dt_nbits_128(uint64_t *a)
141{
142	int nbits = 0;
143	uint64_t tmp[2];
144	uint64_t zero[2] = { 0, 0 };
145
146	tmp[0] = a[0];
147	tmp[1] = a[1];
148
149	dt_shift_128(tmp, -1);
150	while (dt_gt_128(tmp, zero)) {
151		dt_shift_128(tmp, -1);
152		nbits++;
153	}
154
155	return (nbits);
156}
157
158static void
159dt_subtract_128(uint64_t *minuend, uint64_t *subtrahend, uint64_t *difference)
160{
161	uint64_t result[2];
162
163	result[0] = minuend[0] - subtrahend[0];
164	result[1] = minuend[1] - subtrahend[1] -
165	    (minuend[0] < subtrahend[0] ? 1 : 0);
166
167	difference[0] = result[0];
168	difference[1] = result[1];
169}
170
171static void
172dt_add_128(uint64_t *addend1, uint64_t *addend2, uint64_t *sum)
173{
174	uint64_t result[2];
175
176	result[0] = addend1[0] + addend2[0];
177	result[1] = addend1[1] + addend2[1] +
178	    (result[0] < addend1[0] || result[0] < addend2[0] ? 1 : 0);
179
180	sum[0] = result[0];
181	sum[1] = result[1];
182}
183
184/*
185 * The basic idea is to break the 2 64-bit values into 4 32-bit values,
186 * use native multiplication on those, and then re-combine into the
187 * resulting 128-bit value.
188 *
189 * (hi1 << 32 + lo1) * (hi2 << 32 + lo2) =
190 *     hi1 * hi2 << 64 +
191 *     hi1 * lo2 << 32 +
192 *     hi2 * lo1 << 32 +
193 *     lo1 * lo2
194 */
195static void
196dt_multiply_128(uint64_t factor1, uint64_t factor2, uint64_t *product)
197{
198	uint64_t hi1, hi2, lo1, lo2;
199	uint64_t tmp[2];
200
201	hi1 = factor1 >> 32;
202	hi2 = factor2 >> 32;
203
204	lo1 = factor1 & DT_MASK_LO;
205	lo2 = factor2 & DT_MASK_LO;
206
207	product[0] = lo1 * lo2;
208	product[1] = hi1 * hi2;
209
210	tmp[0] = hi1 * lo2;
211	tmp[1] = 0;
212	dt_shift_128(tmp, 32);
213	dt_add_128(product, tmp, product);
214
215	tmp[0] = hi2 * lo1;
216	tmp[1] = 0;
217	dt_shift_128(tmp, 32);
218	dt_add_128(product, tmp, product);
219}
220
221/*
222 * This is long-hand division.
223 *
224 * We initialize subtrahend by shifting divisor left as far as possible. We
225 * loop, comparing subtrahend to dividend:  if subtrahend is smaller, we
226 * subtract and set the appropriate bit in the result.  We then shift
227 * subtrahend right by one bit for the next comparison.
228 */
229static void
230dt_divide_128(uint64_t *dividend, uint64_t divisor, uint64_t *quotient)
231{
232	uint64_t result[2] = { 0, 0 };
233	uint64_t remainder[2];
234	uint64_t subtrahend[2];
235	uint64_t divisor_128[2];
236	uint64_t mask[2] = { 1, 0 };
237	int log = 0;
238
239	assert(divisor != 0);
240
241	divisor_128[0] = divisor;
242	divisor_128[1] = 0;
243
244	remainder[0] = dividend[0];
245	remainder[1] = dividend[1];
246
247	subtrahend[0] = divisor;
248	subtrahend[1] = 0;
249
250	while (divisor > 0) {
251		log++;
252		divisor >>= 1;
253	}
254
255	dt_shift_128(subtrahend, 128 - log);
256	dt_shift_128(mask, 128 - log);
257
258	while (dt_ge_128(remainder, divisor_128)) {
259		if (dt_ge_128(remainder, subtrahend)) {
260			dt_subtract_128(remainder, subtrahend, remainder);
261			result[0] |= mask[0];
262			result[1] |= mask[1];
263		}
264
265		dt_shift_128(subtrahend, -1);
266		dt_shift_128(mask, -1);
267	}
268
269	quotient[0] = result[0];
270	quotient[1] = result[1];
271}
272
273/*
274 * This is the long-hand method of calculating a square root.
275 * The algorithm is as follows:
276 *
277 * 1. Group the digits by 2 from the right.
278 * 2. Over the leftmost group, find the largest single-digit number
279 *    whose square is less than that group.
280 * 3. Subtract the result of the previous step (2 or 4, depending) and
281 *    bring down the next two-digit group.
282 * 4. For the result R we have so far, find the largest single-digit number
283 *    x such that 2 * R * 10 * x + x^2 is less than the result from step 3.
284 *    (Note that this is doubling R and performing a decimal left-shift by 1
285 *    and searching for the appropriate decimal to fill the one's place.)
286 *    The value x is the next digit in the square root.
287 * Repeat steps 3 and 4 until the desired precision is reached.  (We're
288 * dealing with integers, so the above is sufficient.)
289 *
290 * In decimal, the square root of 582,734 would be calculated as so:
291 *
292 *     __7__6__3
293 *    | 58 27 34
294 *     -49       (7^2 == 49 => 7 is the first digit in the square root)
295 *      --
296 *       9 27    (Subtract and bring down the next group.)
297 * 146   8 76    (2 * 7 * 10 * 6 + 6^2 == 876 => 6 is the next digit in
298 *      -----     the square root)
299 *         51 34 (Subtract and bring down the next group.)
300 * 1523    45 69 (2 * 76 * 10 * 3 + 3^2 == 4569 => 3 is the next digit in
301 *         -----  the square root)
302 *          5 65 (remainder)
303 *
304 * The above algorithm applies similarly in binary, but note that the
305 * only possible non-zero value for x in step 4 is 1, so step 4 becomes a
306 * simple decision: is 2 * R * 2 * 1 + 1^2 (aka R << 2 + 1) less than the
307 * preceding difference?
308 *
309 * In binary, the square root of 11011011 would be calculated as so:
310 *
311 *     __1__1__1__0
312 *    | 11 01 10 11
313 *      01          (0 << 2 + 1 == 1 < 11 => this bit is 1)
314 *      --
315 *      10 01 10 11
316 * 101   1 01       (1 << 2 + 1 == 101 < 1001 => next bit is 1)
317 *      -----
318 *       1 00 10 11
319 * 1101    11 01    (11 << 2 + 1 == 1101 < 10010 => next bit is 1)
320 *       -------
321 *          1 01 11
322 * 11101    1 11 01 (111 << 2 + 1 == 11101 > 10111 => last bit is 0)
323 *
324 */
325static uint64_t
326dt_sqrt_128(uint64_t *square)
327{
328	uint64_t result[2] = { 0, 0 };
329	uint64_t diff[2] = { 0, 0 };
330	uint64_t one[2] = { 1, 0 };
331	uint64_t next_pair[2];
332	uint64_t next_try[2];
333	uint64_t bit_pairs, pair_shift;
334	int i;
335
336	bit_pairs = dt_nbits_128(square) / 2;
337	pair_shift = bit_pairs * 2;
338
339	for (i = 0; i <= bit_pairs; i++) {
340		/*
341		 * Bring down the next pair of bits.
342		 */
343		next_pair[0] = square[0];
344		next_pair[1] = square[1];
345		dt_shift_128(next_pair, -pair_shift);
346		next_pair[0] &= 0x3;
347		next_pair[1] = 0;
348
349		dt_shift_128(diff, 2);
350		dt_add_128(diff, next_pair, diff);
351
352		/*
353		 * next_try = R << 2 + 1
354		 */
355		next_try[0] = result[0];
356		next_try[1] = result[1];
357		dt_shift_128(next_try, 2);
358		dt_add_128(next_try, one, next_try);
359
360		if (dt_le_128(next_try, diff)) {
361			dt_subtract_128(diff, next_try, diff);
362			dt_shift_128(result, 1);
363			dt_add_128(result, one, result);
364		} else {
365			dt_shift_128(result, 1);
366		}
367
368		pair_shift -= 2;
369	}
370
371	assert(result[1] == 0);
372
373	return (result[0]);
374}
375
376uint64_t
377dt_stddev(uint64_t *data, uint64_t normal)
378{
379	uint64_t avg_of_squares[2];
380	uint64_t square_of_avg[2];
381	int64_t norm_avg;
382	uint64_t diff[2];
383
384	/*
385	 * The standard approximation for standard deviation is
386	 * sqrt(average(x**2) - average(x)**2), i.e. the square root
387	 * of the average of the squares minus the square of the average.
388	 */
389	dt_divide_128(data + 2, normal, avg_of_squares);
390	dt_divide_128(avg_of_squares, data[0], avg_of_squares);
391
392	norm_avg = (int64_t)data[1] / (int64_t)normal / (int64_t)data[0];
393
394	if (norm_avg < 0)
395		norm_avg = -norm_avg;
396
397	dt_multiply_128((uint64_t)norm_avg, (uint64_t)norm_avg, square_of_avg);
398
399	dt_subtract_128(avg_of_squares, square_of_avg, diff);
400
401	return (dt_sqrt_128(diff));
402}
403
404static int
405dt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last,
406    dtrace_bufdesc_t *buf, size_t offs)
407{
408	dtrace_probedesc_t *pd = data->dtpda_pdesc, *npd;
409	dtrace_eprobedesc_t *epd = data->dtpda_edesc, *nepd;
410	char *p = pd->dtpd_provider, *n = pd->dtpd_name, *sub;
411	dtrace_flowkind_t flow = DTRACEFLOW_NONE;
412	const char *str = NULL;
413	static const char *e_str[2] = { " -> ", " => " };
414	static const char *r_str[2] = { " <- ", " <= " };
415	static const char *ent = "entry", *ret = "return";
416	static int entlen = 0, retlen = 0;
417	dtrace_epid_t next, id = epd->dtepd_epid;
418	int rval;
419
420	if (entlen == 0) {
421		assert(retlen == 0);
422		entlen = strlen(ent);
423		retlen = strlen(ret);
424	}
425
426	/*
427	 * If the name of the probe is "entry" or ends with "-entry", we
428	 * treat it as an entry; if it is "return" or ends with "-return",
429	 * we treat it as a return.  (This allows application-provided probes
430	 * like "method-entry" or "function-entry" to participate in flow
431	 * indentation -- without accidentally misinterpreting popular probe
432	 * names like "carpentry", "gentry" or "Coventry".)
433	 */
434	if ((sub = strstr(n, ent)) != NULL && sub[entlen] == '\0' &&
435	    (sub == n || sub[-1] == '-')) {
436		flow = DTRACEFLOW_ENTRY;
437		str = e_str[strcmp(p, "syscall") == 0];
438	} else if ((sub = strstr(n, ret)) != NULL && sub[retlen] == '\0' &&
439	    (sub == n || sub[-1] == '-')) {
440		flow = DTRACEFLOW_RETURN;
441		str = r_str[strcmp(p, "syscall") == 0];
442	}
443
444	/*
445	 * If we're going to indent this, we need to check the ID of our last
446	 * call.  If we're looking at the same probe ID but a different EPID,
447	 * we _don't_ want to indent.  (Yes, there are some minor holes in
448	 * this scheme -- it's a heuristic.)
449	 */
450	if (flow == DTRACEFLOW_ENTRY) {
451		if ((last != DTRACE_EPIDNONE && id != last &&
452		    pd->dtpd_id == dtp->dt_pdesc[last]->dtpd_id))
453			flow = DTRACEFLOW_NONE;
454	}
455
456	/*
457	 * If we're going to unindent this, it's more difficult to see if
458	 * we don't actually want to unindent it -- we need to look at the
459	 * _next_ EPID.
460	 */
461	if (flow == DTRACEFLOW_RETURN) {
462		offs += epd->dtepd_size;
463
464		do {
465			if (offs >= buf->dtbd_size) {
466				/*
467				 * We're at the end -- maybe.  If the oldest
468				 * record is non-zero, we need to wrap.
469				 */
470				if (buf->dtbd_oldest != 0) {
471					offs = 0;
472				} else {
473					goto out;
474				}
475			}
476
477			next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);
478
479			if (next == DTRACE_EPIDNONE)
480				offs += sizeof (id);
481		} while (next == DTRACE_EPIDNONE);
482
483		if ((rval = dt_epid_lookup(dtp, next, &nepd, &npd)) != 0)
484			return (rval);
485
486		if (next != id && npd->dtpd_id == pd->dtpd_id)
487			flow = DTRACEFLOW_NONE;
488	}
489
490out:
491	if (flow == DTRACEFLOW_ENTRY || flow == DTRACEFLOW_RETURN) {
492		data->dtpda_prefix = str;
493	} else {
494		data->dtpda_prefix = "| ";
495	}
496
497	if (flow == DTRACEFLOW_RETURN && data->dtpda_indent > 0)
498		data->dtpda_indent -= 2;
499
500	data->dtpda_flow = flow;
501
502	return (0);
503}
504
505static int
506dt_nullprobe()
507{
508	return (DTRACE_CONSUME_THIS);
509}
510
511static int
512dt_nullrec()
513{
514	return (DTRACE_CONSUME_NEXT);
515}
516
517static void
518dt_quantize_total(dtrace_hdl_t *dtp, int64_t datum, long double *total)
519{
520	long double val = dt_fabsl((long double)datum);
521
522	if (dtp->dt_options[DTRACEOPT_AGGZOOM] == DTRACEOPT_UNSET) {
523		*total += val;
524		return;
525	}
526
527	/*
528	 * If we're zooming in on an aggregation, we want the height of the
529	 * highest value to be approximately 95% of total bar height -- so we
530	 * adjust up by the reciprocal of DTRACE_AGGZOOM_MAX when comparing to
531	 * our highest value.
532	 */
533	val *= 1 / DTRACE_AGGZOOM_MAX;
534
535	if (*total < val)
536		*total = val;
537}
538
539
540static int
541dt_print_quanthdr(dtrace_hdl_t *dtp, FILE *fp, int width)
542{
543	return (dt_printf(dtp, fp, "\n%*s %41s %-9s\n",
544	                  width ? width : 16, width ? "key" : "value",
545	                  "------------- Distribution -------------", "count"));
546}
547
548static int
549dt_print_quanthdr_packed(dtrace_hdl_t *dtp, FILE *fp, int width,
550    const dtrace_aggdata_t *aggdata, dtrace_actkind_t action)
551{
552	int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin;
553	int minwidth, maxwidth, i;
554
555	assert(action == DTRACEAGG_QUANTIZE || action == DTRACEAGG_LQUANTIZE);
556
557	if (action == DTRACEAGG_QUANTIZE) {
558		if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
559			min--;
560
561		if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
562			max++;
563
564		minwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(min));
565		maxwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(max));
566	} else {
567		maxwidth = 8;
568		minwidth = maxwidth - 1;
569		max++;
570	}
571
572	if (dt_printf(dtp, fp, "\n%*s %*s .",
573	              width, width > 0 ? "key" : "", minwidth, "min") < 0)
574		return (-1);
575
576	for (i = min; i <= max; i++) {
577		if (dt_printf(dtp, fp, "-") < 0)
578			return (-1);
579	}
580
581	return (dt_printf(dtp, fp, ". %*s | count\n", -maxwidth, "max"));
582}
583
584/*
585 * We use a subset of the Unicode Block Elements (U+2588 through U+258F,
586 * inclusive) to represent aggregations via UTF-8 -- which are expressed via
587 * 3-byte UTF-8 sequences.
588 */
589#define  DTRACE_AGGUTF8_FULL  0x2588
590#define  DTRACE_AGGUTF8_BASE  0x258f
591#define  DTRACE_AGGUTF8_LEVELS  8
592
593#define  DTRACE_AGGUTF8_BYTE0(val)  (0xe0 | ((val) >> 12))
594#define  DTRACE_AGGUTF8_BYTE1(val)  (0x80 | (((val) >> 6) & 0x3f))
595#define  DTRACE_AGGUTF8_BYTE2(val)  (0x80 | ((val) & 0x3f))
596
597static int
598dt_print_quantline_utf8(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
599    uint64_t normal, long double total)
600{
601	uint_t len = 40, i, whole, partial;
602	long double f = (dt_fabsl((long double)val) * len) / total;
603	const char *spaces = "                                        ";
604
605	whole = (uint_t)f;
606	partial = (uint_t)((f - (long double)(uint_t)f) *
607			(long double)DTRACE_AGGUTF8_LEVELS);
608
609	if (dt_printf(dtp, fp, "|") < 0)
610		return (-1);
611
612	for (i = 0; i < whole; i++) {
613		if (dt_printf(dtp, fp, "%c%c%c",
614		              DTRACE_AGGUTF8_BYTE0(DTRACE_AGGUTF8_FULL),
615		              DTRACE_AGGUTF8_BYTE1(DTRACE_AGGUTF8_FULL),
616		              DTRACE_AGGUTF8_BYTE2(DTRACE_AGGUTF8_FULL)) < 0)
617			return (-1);
618	}
619
620	if (partial != 0) {
621		partial = DTRACE_AGGUTF8_BASE - (partial - 1);
622
623		if (dt_printf(dtp, fp, "%c%c%c",
624		              DTRACE_AGGUTF8_BYTE0(partial),
625		              DTRACE_AGGUTF8_BYTE1(partial),
626		              DTRACE_AGGUTF8_BYTE2(partial)) < 0)
627			return (-1);
628
629		i++;
630	}
631
632	return (dt_printf(dtp, fp, "%s %-9lld\n", spaces + i,
633	                  (long long)val / normal));
634}
635
636int
637dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
638    uint64_t normal, long double total, char positives, char negatives)
639{
640	long double f;
641	uint_t depth, len = 40;
642
643	const char *ats = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
644	const char *spaces = "                                        ";
645
646	assert(strlen(ats) == len && strlen(spaces) == len);
647	assert(!(total == 0 && (positives || negatives)));
648	assert(!(val < 0 && !negatives));
649	assert(!(val > 0 && !positives));
650	assert(!(val != 0 && total == 0));
651
652	if (!negatives) {
653		if (positives) {
654			if (dtp->dt_encoding == DT_ENCODING_UTF8) {
655				return (dt_print_quantline_utf8(dtp, fp, val,
656				                                normal, total));
657			}
658
659			f = (dt_fabsl((long double)val) * len) / total;
660			depth = (uint_t)(f + 0.5);
661		} else {
662			depth = 0;
663		}
664
665		return (dt_printf(dtp, fp, "|%s%s %-9lld\n", ats + len - depth,
666		    spaces + depth, (long long)val / normal));
667	}
668
669	if (!positives) {
670		f = (dt_fabsl((long double)val) * len) / total;
671		depth = (uint_t)(f + 0.5);
672
673		return (dt_printf(dtp, fp, "%s%s| %-9lld\n", spaces + depth,
674		    ats + len - depth, (long long)val / normal));
675	}
676
677	/*
678	 * If we're here, we have both positive and negative bucket values.
679	 * To express this graphically, we're going to generate both positive
680	 * and negative bars separated by a centerline.  These bars are half
681	 * the size of normal quantize()/lquantize() bars, so we divide the
682	 * length in half before calculating the bar length.
683	 */
684	len /= 2;
685	ats = &ats[len];
686	spaces = &spaces[len];
687
688	f = (dt_fabsl((long double)val) * len) / total;
689	depth = (uint_t)(f + 0.5);
690
691	if (val <= 0) {
692		return (dt_printf(dtp, fp, "%s%s|%*s %-9lld\n", spaces + depth,
693		    ats + len - depth, len, "", (long long)val / normal));
694	} else {
695		return (dt_printf(dtp, fp, "%20s|%s%s %-9lld\n", "",
696		    ats + len - depth, spaces + depth,
697		    (long long)val / normal));
698	}
699}
700
701
702/*
703 * As with UTF-8 printing of aggregations, we use a subset of the Unicode
704 * Block Elements (U+2581 through U+2588, inclusive) to represent our packed
705 * aggregation.
706 */
707#define	DTRACE_AGGPACK_BASE	0x2581
708#define	DTRACE_AGGPACK_LEVELS	8
709
710static int
711dt_print_packed(dtrace_hdl_t *dtp, FILE *fp,
712    long double datum, long double total)
713{
714	static boolean_t utf8_checked = 0;
715	static boolean_t utf8;
716	char *ascii = "__xxxxXX";
717	char *neg = "vvvvVV";
718	unsigned int len;
719	long double val;
720
721	while (!utf8_checked) {
722		char *term;
723
724		/*
725		 * We want to determine if we can reasonably emit UTF-8 for our
726		 * packed aggregation.  To do this, we will check for terminals
727		 * that are known to be primitive to emit UTF-8 on these.
728		 */
729		utf8_checked = B_TRUE;
730
731		if (dtp->dt_encoding == DT_ENCODING_ASCII)
732			break;
733
734		if (dtp->dt_encoding == DT_ENCODING_UTF8) {
735			utf8 = B_TRUE;
736			break;
737		}
738
739		if ((term = getenv("TERM")) != NULL &&
740		    (strcmp(term, "sun") == 0 ||
741		    strcmp(term, "sun-color") == 0) ||
742		    strcmp(term, "dumb") == 0) {
743			break;
744		}
745
746		utf8 = B_TRUE;
747	}
748
749	if (datum == 0)
750		return (dt_printf(dtp, fp, " "));
751
752	if (datum < 0) {
753		len = strlen(neg);
754		val = dt_fabsl(datum * (len - 1)) / total;
755		return (dt_printf(dtp, fp, "%c", neg[(uint_t)(val + 0.5)]));
756	}
757
758	if (utf8) {
759		int block = DTRACE_AGGPACK_BASE + (unsigned int)(((datum *
760		            (DTRACE_AGGPACK_LEVELS - 1)) / total) + 0.5);
761
762		return (dt_printf(dtp, fp, "%c%c%c",
763		                  DTRACE_AGGUTF8_BYTE0(block),
764		                  DTRACE_AGGUTF8_BYTE1(block),
765		                  DTRACE_AGGUTF8_BYTE2(block)));
766	}
767
768	len = strlen(ascii);
769	val = (datum * (len - 1)) / total;
770	return (dt_printf(dtp, fp, "%c", ascii[(uint_t)(val + 0.5)]));
771}
772
773int
774dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
775    size_t size, uint64_t normal)
776{
777	const int64_t *data = addr;
778	int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1;
779	long double total = 0;
780	char positives = 0, negatives = 0;
781
782	if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
783		return (dt_set_errno(dtp, EDT_DMISMATCH));
784
785	while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0)
786		first_bin++;
787
788	if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
789		/*
790		 * There isn't any data.  This is possible if the aggregation
791		 * has been clear()'d or if negative increment values have been
792		 * used.  Regardless, we'll print the buckets around 0.
793		 */
794		first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
795		last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
796	} else {
797		if (first_bin > 0)
798			first_bin--;
799
800		while (last_bin > 0 && data[last_bin] == 0)
801			last_bin--;
802
803		if (last_bin < DTRACE_QUANTIZE_NBUCKETS - 1)
804			last_bin++;
805	}
806
807	for (i = first_bin; i <= last_bin; i++) {
808		positives |= (data[i] > 0);
809		negatives |= (data[i] < 0);
810		dt_quantize_total(dtp, data[i], &total);
811	}
812
813	if (dt_print_quanthdr(dtp, fp, 0) < 0)
814		return (-1);
815
816	for (i = first_bin; i <= last_bin; i++) {
817		if (dt_printf(dtp, fp, "%16lld ",
818		    (long long)DTRACE_QUANTIZE_BUCKETVAL(i)) < 0)
819			return (-1);
820
821		if (dt_print_quantline(dtp, fp, data[i], normal, total,
822		    positives, negatives) < 0)
823			return (-1);
824	}
825
826	return (0);
827}
828
829int
830dt_print_quantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
831    size_t size, const dtrace_aggdata_t *aggdata)
832{
833	const int64_t *data = addr;
834	long double total = 0, count = 0;
835	int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin, i;
836	int64_t minval, maxval;
837
838	if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
839		return (dt_set_errno(dtp, EDT_DMISMATCH));
840
841	if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
842		min--;
843
844	if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
845		max++;
846
847	minval = DTRACE_QUANTIZE_BUCKETVAL(min);
848	maxval = DTRACE_QUANTIZE_BUCKETVAL(max);
849
850	if (dt_printf(dtp, fp, " %*lld :", dt_ndigits(minval),
851	             (long long)minval) < 0)
852		return (-1);
853
854	for (i = min; i <= max; i++) {
855		dt_quantize_total(dtp, data[i], &total);
856		count += data[i];
857	}
858
859	for (i = min; i <= max; i++) {
860		if (dt_print_packed(dtp, fp, data[i], total) < 0)
861			return (-1);
862	}
863
864	if (dt_printf(dtp, fp, ": %*lld | %lld\n",
865	              -dt_ndigits(maxval), (long long)maxval,
866	              (long long)count) < 0)
867	{
868		return (-1);
869	}
870
871	return (0);
872}
873
874int
875dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
876    size_t size, uint64_t normal)
877{
878	const int64_t *data = addr;
879	int i, first_bin, last_bin, base;
880	uint64_t arg;
881	long double total = 0;
882	uint16_t step, levels;
883	char positives = 0, negatives = 0;
884
885	if (size < sizeof (uint64_t))
886		return (dt_set_errno(dtp, EDT_DMISMATCH));
887
888	arg = *data++;
889	size -= sizeof (uint64_t);
890
891	base = DTRACE_LQUANTIZE_BASE(arg);
892	step = DTRACE_LQUANTIZE_STEP(arg);
893	levels = DTRACE_LQUANTIZE_LEVELS(arg);
894
895	first_bin = 0;
896	last_bin = levels + 1;
897
898	if (size != sizeof (uint64_t) * (levels + 2))
899		return (dt_set_errno(dtp, EDT_DMISMATCH));
900
901	while (first_bin <= levels + 1 && data[first_bin] == 0)
902		first_bin++;
903
904	if (first_bin > levels + 1) {
905		first_bin = 0;
906		last_bin = 2;
907	} else {
908		if (first_bin > 0)
909			first_bin--;
910
911		while (last_bin > 0 && data[last_bin] == 0)
912			last_bin--;
913
914		if (last_bin < levels + 1)
915			last_bin++;
916	}
917
918	for (i = first_bin; i <= last_bin; i++) {
919		positives |= (data[i] > 0);
920		negatives |= (data[i] < 0);
921		dt_quantize_total(dtp, data[i], &total);
922	}
923
924	if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
925	    "------------- Distribution -------------", "count") < 0)
926		return (-1);
927
928	for (i = first_bin; i <= last_bin; i++) {
929		char c[32];
930		int err;
931
932		if (i == 0) {
933			(void) snprintf(c, sizeof (c), "< %d", base);
934			err = dt_printf(dtp, fp, "%16s ", c);
935		} else if (i == levels + 1) {
936			(void) snprintf(c, sizeof (c), ">= %d",
937			    base + (levels * step));
938			err = dt_printf(dtp, fp, "%16s ", c);
939		} else {
940			err = dt_printf(dtp, fp, "%16d ",
941			    base + (i - 1) * step);
942		}
943
944		if (err < 0 || dt_print_quantline(dtp, fp, data[i], normal,
945		    total, positives, negatives) < 0)
946			return (-1);
947	}
948
949	return (0);
950}
951
952/*ARGSUSED*/
953int
954dt_print_lquantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
955    size_t size, const dtrace_aggdata_t *aggdata)
956{
957	const int64_t *data = addr;
958	long double total = 0, count = 0;
959	int min, max, base, err;
960	uint64_t arg;
961	uint16_t step, levels;
962	char c[32];
963	unsigned int i;
964
965	if (size < sizeof (uint64_t))
966		return (dt_set_errno(dtp, EDT_DMISMATCH));
967
968	arg = *data++;
969	size -= sizeof (uint64_t);
970
971	base = DTRACE_LQUANTIZE_BASE(arg);
972	step = DTRACE_LQUANTIZE_STEP(arg);
973	levels = DTRACE_LQUANTIZE_LEVELS(arg);
974
975	if (size != sizeof (uint64_t) * (levels + 2))
976		return (dt_set_errno(dtp, EDT_DMISMATCH));
977
978	min = 0;
979	max = levels + 1;
980
981	if (min == 0) {
982		(void) snprintf(c, sizeof (c), "< %d", base);
983		err = dt_printf(dtp, fp, "%8s :", c);
984	} else {
985		err = dt_printf(dtp, fp, "%8d :", base + (min - 1) * step);
986	}
987
988	if (err < 0)
989		return (-1);
990
991	for (i = min; i <= max; i++) {
992		dt_quantize_total(dtp, data[i], &total);
993		count += data[i];
994	}
995
996	for (i = min; i <= max; i++) {
997		if (dt_print_packed(dtp, fp, data[i], total) < 0)
998			return (-1);
999	}
1000
1001	(void) snprintf(c, sizeof (c), ">= %d", base + (levels * step));
1002	return (dt_printf(dtp, fp, ": %-8s | %lld\n", c, (long long)count));
1003}
1004
1005int
1006dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
1007                    size_t size, uint64_t normal)
1008{
1009	int i, first_bin, last_bin, bin = 1, order, levels;
1010	uint16_t factor, low, high, nsteps;
1011	const int64_t *data = addr;
1012	int64_t value = 1, next, step;
1013	char positives = 0, negatives = 0;
1014	long double total = 0;
1015	uint64_t arg;
1016	char c[32];
1017
1018	if (size < sizeof (uint64_t))
1019		return (dt_set_errno(dtp, EDT_DMISMATCH));
1020
1021	arg = *data++;
1022	size -= sizeof (uint64_t);
1023
1024	factor = DTRACE_LLQUANTIZE_FACTOR(arg);
1025	low = DTRACE_LLQUANTIZE_LOW(arg);
1026	high = DTRACE_LLQUANTIZE_HIGH(arg);
1027	nsteps = DTRACE_LLQUANTIZE_NSTEP(arg);
1028
1029	/*
1030	 * We don't expect to be handed invalid llquantize() parameters here,
1031	 * but sanity check them (to a degree) nonetheless.
1032	 */
1033	if (size > INT32_MAX || factor < 2 || low >= high ||
1034			nsteps == 0 || factor > nsteps)
1035		return (dt_set_errno(dtp, EDT_DMISMATCH));
1036
1037	levels = (int)size / sizeof (uint64_t);
1038
1039	first_bin = 0;
1040	last_bin = levels - 1;
1041
1042	while (first_bin < levels && data[first_bin] == 0)
1043		first_bin++;
1044
1045	if (first_bin == levels) {
1046		first_bin = 0;
1047		last_bin = 1;
1048	} else {
1049		if (first_bin > 0)
1050			first_bin--;
1051
1052		while (last_bin > 0 && data[last_bin] == 0)
1053			last_bin--;
1054
1055		if (last_bin < levels - 1)
1056			last_bin++;
1057	}
1058
1059	for (i = first_bin; i <= last_bin; i++) {
1060		positives |= (data[i] > 0);
1061		negatives |= (data[i] < 0);
1062		dt_quantize_total(dtp, data[i], &total);
1063	}
1064
1065	if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
1066				"------------- Distribution -------------", "count") < 0)
1067		return (-1);
1068
1069	for (order = 0; order < low; order++)
1070		value *= factor;
1071
1072	next = value * factor;
1073	step = next > nsteps ? next / nsteps : 1;
1074
1075	if (first_bin == 0) {
1076		(void) snprintf(c, sizeof (c), "< %lld", value);
1077
1078		if (dt_printf(dtp, fp, "%16s ", c) < 0)
1079			return (-1);
1080
1081		if (dt_print_quantline(dtp, fp, data[0], normal,
1082					total, positives, negatives) < 0)
1083			return (-1);
1084	}
1085
1086	while (order <= high) {
1087		if (bin >= first_bin && bin <= last_bin) {
1088			if (dt_printf(dtp, fp, "%16lld ", (long long)value) < 0)
1089				return (-1);
1090
1091			if (dt_print_quantline(dtp, fp, data[bin],
1092						normal, total, positives, negatives) < 0)
1093				return (-1);
1094		}
1095
1096		assert(value < next);
1097		bin++;
1098
1099		if ((value += step) != next)
1100			continue;
1101
1102		next = value * factor;
1103		step = next > nsteps ? next / nsteps : 1;
1104		order++;
1105	}
1106
1107	if (last_bin < bin)
1108		return (0);
1109
1110	assert(last_bin == bin);
1111	(void) snprintf(c, sizeof (c), ">= %lld", value);
1112
1113	if (dt_printf(dtp, fp, "%16s ", c) < 0)
1114		return (-1);
1115
1116	return (dt_print_quantline(dtp, fp, data[bin], normal,
1117				total, positives, negatives));
1118}
1119
1120/*ARGSUSED*/
1121static int
1122dt_print_average(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
1123    size_t size, uint64_t normal)
1124{
1125	/* LINTED - alignment */
1126	int64_t *data = (int64_t *)addr;
1127
1128	return (dt_printf(dtp, fp, " %16lld", data[0] ?
1129	    (long long)(data[1] / (int64_t)normal / data[0]) : 0));
1130}
1131
1132/*ARGSUSED*/
1133static int
1134dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
1135    size_t size, uint64_t normal)
1136{
1137	/* LINTED - alignment */
1138	uint64_t *data = (uint64_t *)addr;
1139
1140	return (dt_printf(dtp, fp, " %16llu", data[0] ?
1141	    (unsigned long long) dt_stddev(data, normal) : 0));
1142}
1143
1144/*ARGSUSED*/
1145static int
1146dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
1147    size_t nbytes, int width, int quiet, int forceraw)
1148{
1149	/*
1150	 * If the byte stream is a series of printable characters, followed by
1151	 * a terminating byte, we print it out as a string.  Otherwise, we
1152	 * assume that it's something else and just print the bytes.
1153	 */
1154	int i, j, margin = 5;
1155	char *c = (char *)addr;
1156
1157	if (nbytes == 0)
1158		return (0);
1159
1160	if (forceraw || (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET))
1161		goto raw;
1162
1163	for (i = 0; i < nbytes; i++) {
1164		/*
1165		 * We define a "printable character" to be one for which
1166		 * isprint(3C) returns non-zero, isspace(3C) returns non-zero,
1167		 * or a character which is either backspace or the bell.
1168		 * Backspace and the bell are regrettably special because
1169		 * they fail the first two tests -- and yet they are entirely
1170		 * printable.  These are the only two control characters that
1171		 * have meaning for the terminal and for which isprint(3C) and
1172		 * isspace(3C) return 0.
1173		 */
1174		if (isprint(c[i]) || isspace(c[i]) ||
1175		    c[i] == '\b' || c[i] == '\a')
1176			continue;
1177
1178		if (c[i] == '\0' && i > 0) {
1179			/*
1180			 * This looks like it might be a string.  Before we
1181			 * assume that it is indeed a string, check the
1182			 * remainder of the byte range; if it contains
1183			 * additional non-nul characters, we'll assume that
1184			 * it's a binary stream that just happens to look like
1185			 * a string, and we'll print out the individual bytes.
1186			 */
1187			for (j = i + 1; j < nbytes; j++) {
1188				if (c[j] != '\0')
1189					break;
1190			}
1191
1192			if (j != nbytes)
1193				break;
1194
1195			if (quiet) {
1196				return (dt_printf(dtp, fp, "%s", c));
1197			} else {
1198				return (dt_printf(dtp, fp, " %s%*s",
1199				                  width < 0 ? " " : "", width, c));
1200			}
1201		}
1202
1203		break;
1204	}
1205
1206	if (i == nbytes) {
1207		/*
1208		 * The byte range is all printable characters, but there is
1209		 * no trailing nul byte.  We'll assume that it's a string and
1210		 * print it as such.
1211		 */
1212		char *s = alloca(nbytes + 1);
1213		bcopy(c, s, nbytes);
1214		s[nbytes] = '\0';
1215		return (dt_printf(dtp, fp, "  %-*s", width, s));
1216	}
1217
1218raw:
1219	if (dt_printf(dtp, fp, "\n%*s      ", margin, "") < 0)
1220		return (-1);
1221
1222	for (i = 0; i < 16; i++)
1223		if (dt_printf(dtp, fp, "  %c", "0123456789abcdef"[i]) < 0)
1224			return (-1);
1225
1226	if (dt_printf(dtp, fp, "  0123456789abcdef\n") < 0)
1227		return (-1);
1228
1229
1230	for (i = 0; i < nbytes; i += 16) {
1231		if (dt_printf(dtp, fp, "%*s%5x:", margin, "", i) < 0)
1232			return (-1);
1233
1234		for (j = i; j < i + 16 && j < nbytes; j++) {
1235			if (dt_printf(dtp, fp, " %02x", (uchar_t)c[j]) < 0)
1236				return (-1);
1237		}
1238
1239		while (j++ % 16) {
1240			if (dt_printf(dtp, fp, "   ") < 0)
1241				return (-1);
1242		}
1243
1244		if (dt_printf(dtp, fp, "  ") < 0)
1245			return (-1);
1246
1247		for (j = i; j < i + 16 && j < nbytes; j++) {
1248			if (dt_printf(dtp, fp, "%c",
1249			    c[j] < ' ' || c[j] > '~' ? '.' : c[j]) < 0)
1250				return (-1);
1251		}
1252
1253		if (dt_printf(dtp, fp, "\n") < 0)
1254			return (-1);
1255	}
1256
1257	return (0);
1258}
1259
1260int
1261dt_print_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
1262    caddr_t addr, int depth, int size)
1263{
1264        dtrace_syminfo_t dts;
1265        GElf_Sym sym;
1266        char aux_symbol_name[32];
1267        int i, indent;
1268        char c[PATH_MAX * 2];
1269        uint64_t pc;
1270
1271	if (dt_printf(dtp, fp, "\n") < 0)
1272		return (-1);
1273
1274	if (format == NULL)
1275		format = "%s";
1276
1277	if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET)
1278		indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT];
1279	else
1280		indent = _dtrace_stkindent;
1281
1282	for (i = 0; i < depth; i++) {
1283		switch (size) {
1284		case sizeof (uint32_t):
1285			/* LINTED - alignment */
1286			pc = *((uint32_t *)addr);
1287			break;
1288
1289		case sizeof (uint64_t):
1290			/* LINTED - alignment */
1291			pc = *((uint64_t *)addr);
1292			break;
1293
1294		default:
1295			return (dt_set_errno(dtp, EDT_BADSTACKPC));
1296		}
1297
1298		if (pc == NULL)
1299			break;
1300
1301		addr += size;
1302
1303		if (dt_printf(dtp, fp, "%*s", indent, "") < 0)
1304			return (-1);
1305
1306		if ((dtp->dt_options[DTRACEOPT_STACKSYMBOLS] != DTRACEOPT_UNSET) && dtrace_lookup_by_addr(dtp, pc, aux_symbol_name, sizeof(aux_symbol_name), &sym, &dts) == 0)
1307		{
1308			if (pc > sym.st_value) {
1309				(void) snprintf(c, sizeof (c), "%s`%s+0x%llx",
1310				    dts.dts_object, dts.dts_name,
1311				    pc - sym.st_value);
1312			} else {
1313				(void) snprintf(c, sizeof (c), "%s`%s",
1314				    dts.dts_object, dts.dts_name);
1315			}
1316		} else {
1317			/*
1318			 * We'll repeat the lookup, but this time we'll specify
1319			 * a NULL GElf_Sym -- indicating that we're only
1320			 * interested in the containing module.
1321			 */
1322			if ((dtp->dt_options[DTRACEOPT_STACKSYMBOLS] != DTRACEOPT_UNSET) && dtrace_lookup_by_addr(dtp, pc, NULL, 0, NULL, &dts) == 0)
1323			{
1324				(void) snprintf(c, sizeof (c), "%s`0x%llx",
1325				    dts.dts_object, pc);
1326			} else {
1327				(void) snprintf(c, sizeof (c), "0x%llx", pc);
1328			}
1329		}
1330
1331		if (dt_printf(dtp, fp, format, c) < 0)
1332			return (-1);
1333
1334		if (dt_printf(dtp, fp, "\n") < 0)
1335			return (-1);
1336	}
1337
1338	return (0);
1339}
1340
1341int
1342dt_print_ustack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
1343    caddr_t addr, uint64_t arg)
1344{
1345	/* LINTED - alignment */
1346	uint64_t *pc = (uint64_t *)addr;
1347	uint32_t depth = DTRACE_USTACK_NFRAMES(arg);
1348	uint32_t strsize = DTRACE_USTACK_STRSIZE(arg);
1349	const char *strbase = addr + (depth + 1) * sizeof (uint64_t);
1350	const char *str = strsize ? strbase : NULL;
1351	int err = 0;
1352
1353	char name[PATH_MAX], objname[PATH_MAX], c[PATH_MAX * 2];
1354	struct ps_prochandle *P;
1355	GElf_Sym sym;
1356	int i, indent;
1357	pid_t pid;
1358
1359	if (depth == 0)
1360		return (0);
1361
1362	pid = (pid_t)*pc++;
1363
1364	if (dt_printf(dtp, fp, "\n") < 0)
1365		return (-1);
1366
1367	if (format == NULL)
1368		format = "%s";
1369
1370	if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET)
1371		indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT];
1372	else
1373		indent = _dtrace_stkindent;
1374
1375	/*
1376	 * Ultimately, we need to add an entry point in the library vector for
1377	 * determining <symbol, offset> from <pid, address>.  For now, if
1378	 * this is a vector open, we just print the raw address or string.
1379	 */
1380	if ((dtp->dt_options[DTRACEOPT_STACKSYMBOLS] != DTRACEOPT_UNSET) && dtp->dt_vector == NULL)
1381		P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0);
1382	else
1383		P = NULL;
1384
1385	if (P != NULL)
1386		dt_proc_lock(dtp, P); /* lock handle while we perform lookups */
1387
1388	for (i = 0; i < depth && pc[i] != NULL; i++) {
1389		prmap_t thread_local_map;
1390		const prmap_t *map;
1391
1392		if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0)
1393			break;
1394
1395		if (P != NULL && Plookup_by_addr(P, pc[i],
1396		    name, sizeof (name), &sym) == 0) {
1397			(void) Pobjname(P, pc[i], objname, sizeof (objname));
1398
1399			if (pc[i] > sym.st_value) {
1400				(void) snprintf(c, sizeof (c),
1401				    "%s`%s+0x%llx", dt_basename(objname), name,
1402				    (u_longlong_t)(pc[i] - sym.st_value));
1403			} else {
1404				(void) snprintf(c, sizeof (c),
1405				    "%s`%s", dt_basename(objname), name);
1406			}
1407		} else if (str != NULL && str[0] != '\0' && str[0] != '@' &&
1408			   (P != NULL && ((map = Paddr_to_map(P, pc[i], &thread_local_map)) == NULL ||
1409					  (map->pr_mflags & MA_WRITE)))) {
1410			/*
1411			 * If the current string pointer in the string table
1412			 * does not point to an empty string _and_ the program
1413			 * counter falls in a writable region, we'll use the
1414			 * string from the string table instead of the raw
1415			 * address.  This last condition is necessary because
1416			 * some (broken) ustack helpers will return a string
1417			 * even for a program counter that they can't
1418			 * identify.  If we have a string for a program
1419			 * counter that falls in a segment that isn't
1420			 * writable, we assume that we have fallen into this
1421			 * case and we refuse to use the string.
1422			 */
1423			(void) snprintf(c, sizeof (c), "%s", str);
1424		} else {
1425			if (P != NULL && Pobjname(P, pc[i], objname,
1426			    sizeof (objname)) != NULL) {
1427				(void) snprintf(c, sizeof (c), "%s`0x%llx",
1428				    dt_basename(objname), (u_longlong_t)pc[i]);
1429			} else {
1430				(void) snprintf(c, sizeof (c), "0x%llx",
1431				    (u_longlong_t)pc[i]);
1432			}
1433		}
1434
1435		if ((err = dt_printf(dtp, fp, format, c)) < 0)
1436			break;
1437
1438		if ((err = dt_printf(dtp, fp, "\n")) < 0)
1439			break;
1440
1441		if (str != NULL && str[0] == '@') {
1442			/*
1443			 * If the first character of the string is an "at" sign,
1444			 * then the string is inferred to be an annotation --
1445			 * and it is printed out beneath the frame and offset
1446			 * with brackets.
1447			 */
1448			if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0)
1449				break;
1450
1451			(void) snprintf(c, sizeof (c), "  [ %s ]", &str[1]);
1452
1453			if ((err = dt_printf(dtp, fp, format, c)) < 0)
1454				break;
1455
1456			if ((err = dt_printf(dtp, fp, "\n")) < 0)
1457				break;
1458		}
1459
1460		if (str != NULL) {
1461			str += strlen(str) + 1;
1462			if (str - strbase >= strsize)
1463				str = NULL;
1464		}
1465	}
1466
1467	if (P != NULL) {
1468		dt_proc_unlock(dtp, P);
1469		dt_proc_release(dtp, P);
1470	}
1471
1472	return (err);
1473}
1474
1475static int
1476dt_print_usym(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, dtrace_actkind_t act)
1477{
1478	/* LINTED - alignment */
1479	uint64_t pid = ((uint64_t *)addr)[0];
1480	/* LINTED - alignment */
1481	uint64_t pc = ((uint64_t *)addr)[1];
1482	const char *format = "  %-50s";
1483	char *s;
1484	int n, len = 256;
1485
1486	if (act == DTRACEACT_USYM && dtp->dt_vector == NULL) {
1487		struct ps_prochandle *P;
1488
1489		if ((P = dt_proc_grab(dtp, pid,
1490		    PGRAB_RDONLY | PGRAB_FORCE, 0)) != NULL) {
1491			GElf_Sym sym;
1492
1493			dt_proc_lock(dtp, P);
1494
1495			if (Plookup_by_addr(P, pc, NULL, 0, &sym) == 0)
1496				pc = sym.st_value;
1497
1498			dt_proc_unlock(dtp, P);
1499			dt_proc_release(dtp, P);
1500		}
1501	}
1502
1503	do {
1504		n = len;
1505		s = alloca(n);
1506	} while ((len = dtrace_uaddr2str(dtp, pid, pc, s, n)) > n);
1507
1508	return (dt_printf(dtp, fp, format, s));
1509}
1510
1511int
1512dt_print_umod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr)
1513{
1514	/* LINTED - alignment */
1515	uint64_t pid = ((uint64_t *)addr)[0];
1516	/* LINTED - alignment */
1517	uint64_t pc = ((uint64_t *)addr)[1];
1518	int err = 0;
1519
1520	char objname[PATH_MAX], c[PATH_MAX * 2];
1521	struct ps_prochandle *P;
1522
1523	if (format == NULL)
1524		format = "  %-50s";
1525
1526	/*
1527	 * See the comment in dt_print_ustack() for the rationale for
1528	 * printing raw addresses in the vectored case.
1529	 */
1530	if (dtp->dt_vector == NULL)
1531		P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0);
1532	else
1533		P = NULL;
1534
1535	if (P != NULL)
1536		dt_proc_lock(dtp, P); /* lock handle while we perform lookups */
1537
1538	if (P != NULL && Pobjname(P, pc, objname, sizeof (objname)) != NULL) {
1539		(void) snprintf(c, sizeof (c), "%s", dt_basename(objname));
1540	} else {
1541		(void) snprintf(c, sizeof (c), "0x%llx", (u_longlong_t)pc);
1542	}
1543
1544	err = dt_printf(dtp, fp, format, c);
1545
1546	if (P != NULL) {
1547		dt_proc_unlock(dtp, P);
1548		dt_proc_release(dtp, P);
1549	}
1550
1551	return (err);
1552}
1553
1554static int
1555dt_print_sym(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr)
1556{
1557	/* LINTED - alignment */
1558        uint64_t pc = *((uint64_t *)addr);
1559        dtrace_syminfo_t dts;
1560        GElf_Sym sym;
1561        char c[PATH_MAX * 2];
1562        char aux_symbol_name[32];
1563
1564	if (format == NULL)
1565		format = "  %-50s";
1566
1567	if (dtrace_lookup_by_addr(dtp, pc, aux_symbol_name, sizeof(aux_symbol_name), &sym, &dts) == 0) {
1568		(void) snprintf(c, sizeof (c), "%s`%s",
1569		    dts.dts_object, dts.dts_name);
1570	} else {
1571		/*
1572		 * We'll repeat the lookup, but this time we'll specify a
1573		 * NULL GElf_Sym -- indicating that we're only interested in
1574		 * the containing module.
1575		 */
1576		if (dtrace_lookup_by_addr(dtp, pc, NULL, 0, NULL, &dts) == 0) {
1577			(void) snprintf(c, sizeof (c), "%s`0x%llx",
1578			    dts.dts_object, (u_longlong_t)pc);
1579		} else {
1580			(void) snprintf(c, sizeof (c), "0x%llx",
1581			    (u_longlong_t)pc);
1582		}
1583	}
1584
1585	if (dt_printf(dtp, fp, format, c) < 0)
1586		return (-1);
1587
1588	return (0);
1589}
1590
1591int
1592dt_print_mod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr)
1593{
1594	/* LINTED - alignment */
1595	uint64_t pc = *((uint64_t *)addr);
1596	dtrace_syminfo_t dts;
1597	char c[PATH_MAX * 2];
1598        char aux_symbol_name[32];
1599
1600	if (format == NULL)
1601		format = "  %-50s";
1602
1603	if (dtrace_lookup_by_addr(dtp, pc, NULL, 0, NULL, &dts) == 0) {
1604		(void) snprintf(c, sizeof (c), "%s", dts.dts_object);
1605	} else {
1606		(void) snprintf(c, sizeof (c), "0x%llx", (u_longlong_t)pc);
1607	}
1608
1609	if (dt_printf(dtp, fp, format, c) < 0)
1610		return (-1);
1611
1612	return (0);
1613}
1614
1615typedef struct dt_normal {
1616	dtrace_aggvarid_t dtnd_id;
1617	uint64_t dtnd_normal;
1618} dt_normal_t;
1619
1620static int
1621dt_normalize_agg(const dtrace_aggdata_t *aggdata, void *arg)
1622{
1623	dt_normal_t *normal = arg;
1624	dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1625	dtrace_aggvarid_t id = normal->dtnd_id;
1626
1627	if (agg->dtagd_nrecs == 0)
1628		return (DTRACE_AGGWALK_NEXT);
1629
1630	if (agg->dtagd_varid != id)
1631		return (DTRACE_AGGWALK_NEXT);
1632
1633	((dtrace_aggdata_t *)aggdata)->dtada_normal = normal->dtnd_normal;
1634	return (DTRACE_AGGWALK_NORMALIZE);
1635}
1636
1637static int
1638dt_normalize(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec)
1639{
1640	dt_normal_t normal;
1641	caddr_t addr;
1642
1643	/*
1644	 * We (should) have two records:  the aggregation ID followed by the
1645	 * normalization value.
1646	 */
1647	addr = base + rec->dtrd_offset;
1648
1649	if (rec->dtrd_size != sizeof (dtrace_aggvarid_t))
1650		return (dt_set_errno(dtp, EDT_BADNORMAL));
1651
1652	/* LINTED - alignment */
1653	normal.dtnd_id = *((dtrace_aggvarid_t *)addr);
1654	rec++;
1655
1656	if (rec->dtrd_action != DTRACEACT_LIBACT)
1657		return (dt_set_errno(dtp, EDT_BADNORMAL));
1658
1659	if (rec->dtrd_arg != DT_ACT_NORMALIZE)
1660		return (dt_set_errno(dtp, EDT_BADNORMAL));
1661
1662	addr = base + rec->dtrd_offset;
1663
1664	switch (rec->dtrd_size) {
1665	case sizeof (uint64_t):
1666		/* LINTED - alignment */
1667		normal.dtnd_normal = *((uint64_t *)addr);
1668		break;
1669	case sizeof (uint32_t):
1670		/* LINTED - alignment */
1671		normal.dtnd_normal = *((uint32_t *)addr);
1672		break;
1673	case sizeof (uint16_t):
1674		/* LINTED - alignment */
1675		normal.dtnd_normal = *((uint16_t *)addr);
1676		break;
1677	case sizeof (uint8_t):
1678		normal.dtnd_normal = *((uint8_t *)addr);
1679		break;
1680	default:
1681		return (dt_set_errno(dtp, EDT_BADNORMAL));
1682	}
1683
1684	(void) dtrace_aggregate_walk(dtp, dt_normalize_agg, &normal);
1685
1686	return (0);
1687}
1688
1689static int
1690dt_denormalize_agg(const dtrace_aggdata_t *aggdata, void *arg)
1691{
1692	dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1693	dtrace_aggvarid_t id = *((dtrace_aggvarid_t *)arg);
1694
1695	if (agg->dtagd_nrecs == 0)
1696		return (DTRACE_AGGWALK_NEXT);
1697
1698	if (agg->dtagd_varid != id)
1699		return (DTRACE_AGGWALK_NEXT);
1700
1701	return (DTRACE_AGGWALK_DENORMALIZE);
1702}
1703
1704static int
1705dt_clear_agg(const dtrace_aggdata_t *aggdata, void *arg)
1706{
1707	dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1708	dtrace_aggvarid_t id = *((dtrace_aggvarid_t *)arg);
1709
1710	if (agg->dtagd_nrecs == 0)
1711		return (DTRACE_AGGWALK_NEXT);
1712
1713	if (agg->dtagd_varid != id)
1714		return (DTRACE_AGGWALK_NEXT);
1715
1716	return (DTRACE_AGGWALK_CLEAR);
1717}
1718
1719typedef struct dt_trunc {
1720	dtrace_aggvarid_t dttd_id;
1721	uint64_t dttd_remaining;
1722} dt_trunc_t;
1723
1724static int
1725dt_trunc_agg(const dtrace_aggdata_t *aggdata, void *arg)
1726{
1727	dt_trunc_t *trunc = arg;
1728	dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1729	dtrace_aggvarid_t id = trunc->dttd_id;
1730
1731	if (agg->dtagd_nrecs == 0)
1732		return (DTRACE_AGGWALK_NEXT);
1733
1734	if (agg->dtagd_varid != id)
1735		return (DTRACE_AGGWALK_NEXT);
1736
1737	if (trunc->dttd_remaining == 0)
1738		return (DTRACE_AGGWALK_REMOVE);
1739
1740	trunc->dttd_remaining--;
1741	return (DTRACE_AGGWALK_NEXT);
1742}
1743
1744static int
1745dt_trunc(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec)
1746{
1747	dt_trunc_t trunc;
1748	caddr_t addr;
1749	int64_t remaining;
1750	int (*func)(dtrace_hdl_t *, dtrace_aggregate_f *, void *);
1751
1752	/*
1753	 * We (should) have two records:  the aggregation ID followed by the
1754	 * number of aggregation entries after which the aggregation is to be
1755	 * truncated.
1756	 */
1757	addr = base + rec->dtrd_offset;
1758
1759	if (rec->dtrd_size != sizeof (dtrace_aggvarid_t))
1760		return (dt_set_errno(dtp, EDT_BADTRUNC));
1761
1762	/* LINTED - alignment */
1763	trunc.dttd_id = *((dtrace_aggvarid_t *)addr);
1764	rec++;
1765
1766	if (rec->dtrd_action != DTRACEACT_LIBACT)
1767		return (dt_set_errno(dtp, EDT_BADTRUNC));
1768
1769	if (rec->dtrd_arg != DT_ACT_TRUNC)
1770		return (dt_set_errno(dtp, EDT_BADTRUNC));
1771
1772	addr = base + rec->dtrd_offset;
1773
1774	switch (rec->dtrd_size) {
1775	case sizeof (uint64_t):
1776		/* LINTED - alignment */
1777		remaining = *((int64_t *)addr);
1778		break;
1779	case sizeof (uint32_t):
1780		/* LINTED - alignment */
1781		remaining = *((int32_t *)addr);
1782		break;
1783	case sizeof (uint16_t):
1784		/* LINTED - alignment */
1785		remaining = *((int16_t *)addr);
1786		break;
1787	case sizeof (uint8_t):
1788		remaining = *((int8_t *)addr);
1789		break;
1790	default:
1791		return (dt_set_errno(dtp, EDT_BADNORMAL));
1792	}
1793
1794	if (remaining < 0) {
1795		func = dtrace_aggregate_walk_valsorted;
1796		remaining = -remaining;
1797	} else {
1798		func = dtrace_aggregate_walk_valrevsorted;
1799	}
1800
1801	assert(remaining >= 0);
1802	trunc.dttd_remaining = remaining;
1803
1804	(void) func(dtp, dt_trunc_agg, &trunc);
1805
1806	return (0);
1807}
1808
1809static int
1810dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
1811	caddr_t addr, size_t size, const dtrace_aggdata_t *aggdata,
1812	uint64_t normal, dt_print_aggdata_t *pd)
1813{
1814	int err, width;
1815	dtrace_actkind_t act = rec->dtrd_action;
1816	boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack;
1817	dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1818
1819	static struct {
1820		size_t size;
1821		int width;
1822		int packedwidth;
1823	} *fmt, fmttab[] = {
1824		{ sizeof (uint8_t),  3,  3 },
1825		{ sizeof (uint16_t),  5,  5 },
1826		{ sizeof (uint32_t),  8,  8 },
1827		{ sizeof (uint64_t),  16,  16 },
1828		{ 0,      -50,  32 }
1829	};
1830
1831	if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid) {
1832		dtrace_recdesc_t *r;
1833
1834		width = 0;
1835
1836		/*
1837		 * To print our quantization header for either an agghist or
1838		 * aggpack aggregation, we need to iterate through all of our
1839		 * of our records to determine their width.
1840		 */
1841		for (r = rec; !DTRACEACT_ISAGG(r->dtrd_action); r++) {
1842			for (fmt = fmttab; fmt->size &&
1843			     fmt->size != r->dtrd_size; fmt++)
1844				continue;
1845
1846			width += fmt->packedwidth + 1;
1847		}
1848
1849		if (pd->dtpa_agghist) {
1850			if (dt_print_quanthdr(dtp, fp, width) < 0)
1851				return (-1);
1852		} else {
1853			if (dt_print_quanthdr_packed(dtp, fp, width, aggdata,
1854                                                     r->dtrd_action) < 0)
1855				return (-1);
1856		}
1857
1858		pd->dtpa_agghisthdr = agg->dtagd_varid;
1859	}
1860
1861	if (pd->dtpa_agghist && DTRACEACT_ISAGG(act)) {
1862		char positives = aggdata->dtada_flags & DTRACE_A_HASPOSITIVES;
1863		char negatives = aggdata->dtada_flags & DTRACE_A_HASNEGATIVES;
1864		int64_t val;
1865
1866		assert(act == DTRACEAGG_SUM || act == DTRACEAGG_COUNT);
1867		val = (long long)*((uint64_t *)addr);
1868
1869		if (dt_printf(dtp, fp, " ") < 0)
1870			return (-1);
1871
1872		return (dt_print_quantline(dtp, fp, val, normal, aggdata->dtada_total,
1873                                           positives, negatives));
1874	}
1875
1876	if (pd->dtpa_aggpack && DTRACEACT_ISAGG(act)) {
1877		switch (act) {
1878		case DTRACEAGG_QUANTIZE:
1879			return (dt_print_quantize_packed(dtp, fp, addr,
1880			                                 size, aggdata));
1881		case DTRACEAGG_LQUANTIZE:
1882			return (dt_print_lquantize_packed(dtp, fp, addr,
1883							  size, aggdata));
1884		default:
1885			break;
1886		}
1887	}
1888
1889
1890	switch (act) {
1891	case DTRACEACT_STACK:
1892		return (dt_print_stack(dtp, fp, NULL, addr,
1893		    rec->dtrd_arg, rec->dtrd_size / rec->dtrd_arg));
1894
1895	case DTRACEACT_USTACK:
1896	case DTRACEACT_JSTACK:
1897		return (dt_print_ustack(dtp, fp, NULL, addr, rec->dtrd_arg));
1898
1899	case DTRACEACT_USYM:
1900	case DTRACEACT_UADDR:
1901		return (dt_print_usym(dtp, fp, addr, act));
1902
1903	case DTRACEACT_UMOD:
1904		return (dt_print_umod(dtp, fp, NULL, addr));
1905
1906	case DTRACEACT_SYM:
1907		return (dt_print_sym(dtp, fp, NULL, addr));
1908
1909	case DTRACEACT_MOD:
1910		return (dt_print_mod(dtp, fp, NULL, addr));
1911
1912	case DTRACEAGG_QUANTIZE:
1913		return (dt_print_quantize(dtp, fp, addr, size, normal));
1914
1915	case DTRACEAGG_LQUANTIZE:
1916		return (dt_print_lquantize(dtp, fp, addr, size, normal));
1917
1918	case DTRACEAGG_LLQUANTIZE:
1919		return (dt_print_llquantize(dtp, fp, addr, size, normal));
1920
1921	case DTRACEAGG_AVG:
1922		return (dt_print_average(dtp, fp, addr, size, normal));
1923
1924	case DTRACEAGG_STDDEV:
1925		return (dt_print_stddev(dtp, fp, addr, size, normal));
1926
1927	default:
1928		break;
1929	}
1930
1931	for (fmt = fmttab; fmt->size && fmt->size != size; fmt++)
1932		continue;
1933
1934	width = packed ? fmt->packedwidth : fmt->width;
1935
1936	switch (size) {
1937	case sizeof (uint64_t):
1938		err = dt_printf(dtp, fp, " %*lld", width,
1939		    /* LINTED - alignment */
1940		    (long long)*((uint64_t *)addr) / normal);
1941		break;
1942	case sizeof (uint32_t):
1943		/* LINTED - alignment */
1944		 err = dt_printf(dtp, fp, " %*d", width, *((uint32_t *)addr) /
1945		    (uint32_t)normal);
1946		break;
1947	case sizeof (uint16_t):
1948		/* LINTED - alignment */
1949		err = dt_printf(dtp, fp, " %*d", width, *((uint16_t *)addr) /
1950		    (uint32_t)normal);
1951		break;
1952	case sizeof (uint8_t):
1953		err = dt_printf(dtp, fp, " %*d", width, *((uint8_t *)addr) /
1954		    (uint32_t)normal);
1955		break;
1956	default:
1957		err = dt_print_bytes(dtp, fp, addr, size, width, 0, 0);
1958		break;
1959	}
1960
1961	return (err);
1962}
1963
1964int
1965dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
1966{
1967	int i, aggact = 0;
1968	dt_print_aggdata_t *pd = arg;
1969	const dtrace_aggdata_t *aggdata = aggsdata[0];
1970	dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1971	FILE *fp = pd->dtpa_fp;
1972	dtrace_hdl_t *dtp = pd->dtpa_dtp;
1973	dtrace_recdesc_t *rec;
1974	dtrace_actkind_t act;
1975	caddr_t addr;
1976	size_t size;
1977
1978	pd->dtpa_agghist = (aggdata->dtada_flags & DTRACE_A_TOTAL);
1979	pd->dtpa_aggpack = (aggdata->dtada_flags & DTRACE_A_MINMAXBIN);
1980
1981	/*
1982	 * Iterate over each record description in the key, printing the traced
1983	 * data, skipping the first datum (the tuple member created by the
1984	 * compiler).
1985	 */
1986	for (i = 1; i < agg->dtagd_nrecs; i++) {
1987		rec = &agg->dtagd_rec[i];
1988		act = rec->dtrd_action;
1989		addr = aggdata->dtada_data + rec->dtrd_offset;
1990		size = rec->dtrd_size;
1991
1992		if (DTRACEACT_ISAGG(act)) {
1993			aggact = i;
1994			break;
1995		}
1996
1997		if (dt_print_datum(dtp, fp, rec, addr,
1998		                   size, aggdata, 1, pd) < 0)
1999			return (-1);
2000
2001		if (dt_buffered_flush(dtp, NULL, rec, aggdata,
2002		    DTRACE_BUFDATA_AGGKEY) < 0)
2003			return (-1);
2004	}
2005
2006	assert(aggact != 0);
2007
2008	for (i = (naggvars == 1 ? 0 : 1); i < naggvars; i++) {
2009		uint64_t normal;
2010
2011		aggdata = aggsdata[i];
2012		agg = aggdata->dtada_desc;
2013		rec = &agg->dtagd_rec[aggact];
2014		act = rec->dtrd_action;
2015		addr = aggdata->dtada_data + rec->dtrd_offset;
2016		size = rec->dtrd_size;
2017
2018		assert(DTRACEACT_ISAGG(act));
2019		normal = aggdata->dtada_normal;
2020
2021		if (dt_print_datum(dtp, fp, rec, addr,
2022		                   size, aggdata, normal, pd) < 0)
2023			return (-1);
2024
2025		if (dt_buffered_flush(dtp, NULL, rec, aggdata,
2026		    DTRACE_BUFDATA_AGGVAL) < 0)
2027			return (-1);
2028
2029		if (!pd->dtpa_allunprint)
2030			agg->dtagd_flags |= DTRACE_AGD_PRINTED;
2031	}
2032
2033	if (!pd->dtpa_agghist && !pd->dtpa_aggpack) {
2034		if (dt_printf(dtp, fp, "\n") < 0)
2035			return (-1);
2036	}
2037
2038	if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
2039	    DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
2040		return (-1);
2041
2042	return (0);
2043}
2044
2045int
2046dt_print_agg(const dtrace_aggdata_t *aggdata, void *arg)
2047{
2048	dt_print_aggdata_t *pd = arg;
2049	dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2050	dtrace_aggvarid_t aggvarid = pd->dtpa_id;
2051
2052	if (pd->dtpa_allunprint) {
2053		if (agg->dtagd_flags & DTRACE_AGD_PRINTED)
2054			return (0);
2055	} else {
2056		/*
2057		 * If we're not printing all unprinted aggregations, then the
2058		 * aggregation variable ID denotes a specific aggregation
2059		 * variable that we should print -- skip any other aggregations
2060		 * that we encounter.
2061		 */
2062		if (agg->dtagd_nrecs == 0)
2063			return (0);
2064
2065		if (aggvarid != agg->dtagd_varid)
2066			return (0);
2067	}
2068
2069	return (dt_print_aggs(&aggdata, 1, arg));
2070}
2071
2072int
2073dt_setopt(dtrace_hdl_t *dtp, const dtrace_probedata_t *data,
2074    const char *option, const char *value)
2075{
2076	int len, rval;
2077	char *msg;
2078	const char *errstr;
2079	dtrace_setoptdata_t optdata;
2080
2081	bzero(&optdata, sizeof (optdata));
2082	(void) dtrace_getopt(dtp, option, &optdata.dtsda_oldval);
2083
2084	if (dtrace_setopt(dtp, option, value) == 0) {
2085		(void) dtrace_getopt(dtp, option, &optdata.dtsda_newval);
2086		optdata.dtsda_probe = data;
2087		optdata.dtsda_option = option;
2088		optdata.dtsda_handle = dtp;
2089
2090		if ((rval = dt_handle_setopt(dtp, &optdata)) != 0)
2091			return (rval);
2092
2093		return (0);
2094	}
2095
2096	errstr = dtrace_errmsg(dtp, dtrace_errno(dtp));
2097	len = strlen(option) + strlen(value) + strlen(errstr) + 80;
2098	msg = alloca(len);
2099
2100	(void) snprintf(msg, len, "couldn't set option \"%s\" to \"%s\": %s\n",
2101	    option, value, errstr);
2102
2103	if ((rval = dt_handle_liberr(dtp, data, msg)) == 0)
2104		return (0);
2105
2106	return (rval);
2107}
2108
2109static int
2110dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf,
2111    dtrace_consume_probe_f *efunc, dtrace_consume_rec_f *rfunc, void *arg)
2112{
2113	dtrace_epid_t id;
2114	size_t offs, start = buf->dtbd_oldest, end = buf->dtbd_size;
2115	int flow = (dtp->dt_options[DTRACEOPT_FLOWINDENT] != DTRACEOPT_UNSET);
2116	int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET);
2117	int rval, i, n;
2118	dtrace_epid_t last = DTRACE_EPIDNONE;
2119	uint64_t tracememsize = 0;
2120	dtrace_probedata_t data;
2121	uint64_t drops;
2122	caddr_t addr;
2123
2124	bzero(&data, sizeof (data));
2125	data.dtpda_handle = dtp;
2126	data.dtpda_cpu = cpu;
2127
2128again:
2129	//XXX please don't nuke any of these dt_dprintf's... I need them to track the correctness
2130	//XXX of the function calls while I'm breaking the consume routines into collect/analyze
2131	//XXX modules that can be called separately -- epmiller 05/04/07
2132	//XXX I'll pull them out once everything is 100%, it's about 95% now
2133
2134	// EPM DEBUG PRINT
2135	// dt_dprintf("---0-------> dt_consume_cpu - %d start: %d end: %d\n",cpu, start, end);
2136	for (offs = start; offs < end; ) {
2137		dtrace_eprobedesc_t *epd;
2138
2139		/*
2140		 * We're guaranteed to have an ID.
2141		 */
2142		id = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);
2143		// EPM DEBUG PRINT
2144		// dt_dprintf("---1-------> dt_consume_cpu - %d ID: %d\n",cpu, id);
2145		if (id == DTRACE_EPIDNONE) {
2146			/*
2147			 * This is filler to assure proper alignment of the
2148			 * next record; we simply ignore it.
2149			 */
2150			offs += sizeof (id);
2151			continue;
2152		}
2153
2154		if ((rval = dt_epid_lookup(dtp, id, &data.dtpda_edesc,
2155		    &data.dtpda_pdesc)) != 0)
2156			return (rval);
2157		// EPM DEBUG PRINT
2158		// dt_dprintf("-----> dt_epid_lookup - %d ID: %d\n",cpu, id);
2159		epd = data.dtpda_edesc;
2160		data.dtpda_data = buf->dtbd_data + offs;
2161
2162		if (data.dtpda_edesc->dtepd_uarg != DT_ECB_DEFAULT) {
2163			rval = dt_handle(dtp, &data);
2164
2165			if (rval == DTRACE_CONSUME_NEXT)
2166				goto nextepid;
2167
2168			if (rval == DTRACE_CONSUME_ERROR)
2169				return (-1);
2170		}
2171
2172		if (flow)
2173			(void) dt_flowindent(dtp, &data, last, buf, offs);
2174
2175		rval = (*efunc)(&data, arg);
2176
2177		if (flow) {
2178			if (data.dtpda_flow == DTRACEFLOW_ENTRY)
2179				data.dtpda_indent += 2;
2180		}
2181
2182		if (rval == DTRACE_CONSUME_NEXT)
2183			goto nextepid;
2184
2185		if (rval == DTRACE_CONSUME_ABORT)
2186			return (dt_set_errno(dtp, EDT_DIRABORT));
2187
2188		if (rval != DTRACE_CONSUME_THIS)
2189			return (dt_set_errno(dtp, EDT_BADRVAL));
2190
2191		for (i = 0; i < epd->dtepd_nrecs; i++) {
2192			dtrace_recdesc_t *rec = &epd->dtepd_rec[i];
2193			dtrace_actkind_t act = rec->dtrd_action;
2194			// EPM DEBUG PRINT
2195			// dt_dprintf("----------> dt_consume_cpu - %d ACT: %d\n",cpu, act);
2196			data.dtpda_data = buf->dtbd_data + offs +
2197			    rec->dtrd_offset;
2198			addr = data.dtpda_data;
2199
2200			if (act == DTRACEACT_LIBACT) {
2201				uint64_t arg = rec->dtrd_arg;
2202				dtrace_aggvarid_t id;
2203
2204				switch (arg) {
2205				case DT_ACT_CLEAR:
2206					/* LINTED - alignment */
2207					id = *((dtrace_aggvarid_t *)addr);
2208					(void) dtrace_aggregate_walk(dtp,
2209					    dt_clear_agg, &id);
2210					continue;
2211
2212				case DT_ACT_DENORMALIZE:
2213					/* LINTED - alignment */
2214					id = *((dtrace_aggvarid_t *)addr);
2215					(void) dtrace_aggregate_walk(dtp,
2216					    dt_denormalize_agg, &id);
2217					continue;
2218
2219				case DT_ACT_FTRUNCATE:
2220					if (fp == NULL)
2221						continue;
2222
2223					(void) fflush(fp);
2224					(void) ftruncate(fileno(fp), 0);
2225					(void) fseeko(fp, 0, SEEK_SET);
2226					continue;
2227
2228				case DT_ACT_NORMALIZE:
2229					if (i == epd->dtepd_nrecs - 1)
2230						return (dt_set_errno(dtp,
2231						    EDT_BADNORMAL));
2232
2233					if (dt_normalize(dtp,
2234					    buf->dtbd_data + offs, rec) != 0)
2235						return (-1);
2236
2237					i++;
2238					continue;
2239
2240				case DT_ACT_SETOPT: {
2241					uint64_t *opts = dtp->dt_options;
2242					dtrace_recdesc_t *valrec;
2243					uint32_t valsize;
2244					caddr_t val;
2245					int rv;
2246
2247					if (i == epd->dtepd_nrecs - 1) {
2248						return (dt_set_errno(dtp,
2249						    EDT_BADSETOPT));
2250					}
2251
2252					valrec = &epd->dtepd_rec[++i];
2253					valsize = valrec->dtrd_size;
2254
2255					if (valrec->dtrd_action != act ||
2256					    valrec->dtrd_arg != arg) {
2257						return (dt_set_errno(dtp,
2258						    EDT_BADSETOPT));
2259					}
2260
2261					if (valsize > sizeof (uint64_t)) {
2262						val = buf->dtbd_data + offs +
2263						    valrec->dtrd_offset;
2264					} else {
2265						val = "1";
2266					}
2267
2268					rv = dt_setopt(dtp, &data, addr, val);
2269
2270					if (rv != 0)
2271						return (-1);
2272
2273					flow = (opts[DTRACEOPT_FLOWINDENT] !=
2274					    DTRACEOPT_UNSET);
2275					quiet = (opts[DTRACEOPT_QUIET] !=
2276					    DTRACEOPT_UNSET);
2277
2278					continue;
2279				}
2280
2281				case DT_ACT_TRUNC:
2282					if (i == epd->dtepd_nrecs - 1)
2283						return (dt_set_errno(dtp,
2284						    EDT_BADTRUNC));
2285
2286					if (dt_trunc(dtp,
2287					    buf->dtbd_data + offs, rec) != 0)
2288						return (-1);
2289
2290					i++;
2291					continue;
2292
2293				default:
2294					continue;
2295				}
2296			}
2297
2298			if (act == DTRACEACT_TRACEMEM_DYNSIZE &&
2299			    rec->dtrd_size == sizeof (uint64_t))
2300			{
2301				tracememsize = *((unsigned long long *)addr);
2302				continue;
2303			}
2304
2305			rval = (*rfunc)(&data, rec, arg);
2306
2307            if (act == DTRACEACT_APPLEBINARY) {
2308                /*
2309                 * Let's skip the records following a compound
2310                 * APPLEBINARY action and go to the next record
2311                 * since the default handling behavior is to
2312                 * do nothing.
2313                 */
2314                uint64_t arg = rec->dtrd_arg;
2315				uint16_t following_recs =
2316                (uint16_t)((arg >> 16)&0xFFFF);
2317
2318                i += following_recs;
2319                goto nextrec;
2320            }
2321			if (rval == DTRACE_CONSUME_NEXT)
2322				continue;
2323
2324			if (rval == DTRACE_CONSUME_ABORT)
2325				return (dt_set_errno(dtp, EDT_DIRABORT));
2326
2327			if (rval != DTRACE_CONSUME_THIS)
2328				return (dt_set_errno(dtp, EDT_BADRVAL));
2329
2330			if (act == DTRACEACT_STACK) {
2331				int depth = rec->dtrd_arg;
2332
2333				if (dt_print_stack(dtp, fp, NULL, addr, depth,
2334				    rec->dtrd_size / depth) < 0)
2335					return (-1);
2336				goto nextrec;
2337			}
2338
2339			if (act == DTRACEACT_USTACK ||
2340			    act == DTRACEACT_JSTACK) {
2341				if (dt_print_ustack(dtp, fp, NULL,
2342				    addr, rec->dtrd_arg) < 0)
2343					return (-1);
2344				goto nextrec;
2345			}
2346
2347			if (act == DTRACEACT_SYM) {
2348				if (dt_print_sym(dtp, fp, NULL, addr) < 0)
2349					return (-1);
2350				goto nextrec;
2351			}
2352
2353			if (act == DTRACEACT_MOD) {
2354				if (dt_print_mod(dtp, fp, NULL, addr) < 0)
2355					return (-1);
2356				goto nextrec;
2357			}
2358
2359			if (act == DTRACEACT_USYM || act == DTRACEACT_UADDR) {
2360				if (dt_print_usym(dtp, fp, addr, act) < 0)
2361					return (-1);
2362				goto nextrec;
2363			}
2364
2365			if (act == DTRACEACT_UMOD) {
2366				if (dt_print_umod(dtp, fp, NULL, addr) < 0)
2367					return (-1);
2368				goto nextrec;
2369			}
2370
2371			if (DTRACEACT_ISPRINTFLIKE(act)) {
2372				void *fmtdata;
2373				int (*func)(dtrace_hdl_t *, FILE *, void *,
2374				    const dtrace_probedata_t *,
2375				    const dtrace_recdesc_t *, uint_t,
2376				    const void *buf, size_t);
2377
2378				if ((fmtdata = dt_format_lookup(dtp,
2379				    rec->dtrd_format)) == NULL)
2380					goto nofmt;
2381
2382				switch (act) {
2383				case DTRACEACT_PRINTF:
2384					func = dtrace_fprintf;
2385					break;
2386				case DTRACEACT_PRINTA:
2387					func = dtrace_fprinta;
2388					break;
2389				case DTRACEACT_SYSTEM:
2390					func = dtrace_system;
2391					break;
2392				case DTRACEACT_FREOPEN:
2393					func = dtrace_freopen;
2394					break;
2395				}
2396
2397				n = (*func)(dtp, fp, fmtdata, &data,
2398				    rec, epd->dtepd_nrecs - i,
2399				    (uchar_t *)buf->dtbd_data + offs,
2400				    buf->dtbd_size - offs);
2401
2402				if (n < 0)
2403					return (-1); /* errno is set for us */
2404
2405				if (n > 0)
2406					i += n - 1;
2407				goto nextrec;
2408			}
2409
2410nofmt:
2411			if (act == DTRACEACT_PRINTA) {
2412				dt_print_aggdata_t pd;
2413				dtrace_aggvarid_t *aggvars;
2414				int j, naggvars = 0;
2415				size_t size = ((epd->dtepd_nrecs - i) *
2416				    sizeof (dtrace_aggvarid_t));
2417
2418				if ((aggvars = dt_alloc(dtp, size)) == NULL)
2419					return (-1);
2420
2421				/*
2422				 * This might be a printa() with multiple
2423				 * aggregation variables.  We need to scan
2424				 * forward through the records until we find
2425				 * a record from a different statement.
2426				 */
2427				for (j = i; j < epd->dtepd_nrecs; j++) {
2428					dtrace_recdesc_t *nrec;
2429					caddr_t naddr;
2430
2431					nrec = &epd->dtepd_rec[j];
2432
2433					if (nrec->dtrd_uarg != rec->dtrd_uarg)
2434						break;
2435
2436					if (nrec->dtrd_action != act) {
2437						return (dt_set_errno(dtp,
2438						    EDT_BADAGG));
2439					}
2440
2441					naddr = buf->dtbd_data + offs +
2442					    nrec->dtrd_offset;
2443
2444					aggvars[naggvars++] =
2445					    /* LINTED - alignment */
2446					    *((dtrace_aggvarid_t *)naddr);
2447				}
2448
2449				i = j - 1;
2450				bzero(&pd, sizeof (pd));
2451				pd.dtpa_dtp = dtp;
2452				pd.dtpa_fp = fp;
2453
2454				assert(naggvars >= 1);
2455
2456				if (naggvars == 1) {
2457					pd.dtpa_id = aggvars[0];
2458					dt_free(dtp, aggvars);
2459
2460					if (dt_printf(dtp, fp, "\n") < 0 ||
2461					    dtrace_aggregate_walk_sorted(dtp,
2462					    dt_print_agg, &pd) < 0)
2463						return (-1);
2464					goto nextrec;
2465				}
2466
2467				if (dt_printf(dtp, fp, "\n") < 0 ||
2468				    dtrace_aggregate_walk_joined(dtp, aggvars,
2469				    naggvars, dt_print_aggs, &pd) < 0) {
2470					dt_free(dtp, aggvars);
2471					return (-1);
2472				}
2473
2474				dt_free(dtp, aggvars);
2475				goto nextrec;
2476			}
2477
2478			if (act == DTRACEACT_TRACEMEM) {
2479				if (tracememsize == 0 ||
2480				    tracememsize > rec->dtrd_size) {
2481					tracememsize = rec->dtrd_size;
2482				}
2483
2484				n = dt_print_bytes(dtp, fp, addr,
2485				    tracememsize, -33, quiet, 1);
2486
2487				tracememsize = 0;
2488
2489				if (n < 0)
2490					return (-1);
2491
2492				goto nextrec;
2493			}
2494
2495			switch (rec->dtrd_size) {
2496			case sizeof (uint64_t):
2497				n = dt_printf(dtp, fp,
2498				    quiet ? "%lld" : " %16lld",
2499				    /* LINTED - alignment */
2500				    *((unsigned long long *)addr));
2501				break;
2502			case sizeof (uint32_t):
2503				n = dt_printf(dtp, fp, quiet ? "%d" : " %8d",
2504				    /* LINTED - alignment */
2505				    *((uint32_t *)addr));
2506				break;
2507			case sizeof (uint16_t):
2508				n = dt_printf(dtp, fp, quiet ? "%d" : " %5d",
2509				    /* LINTED - alignment */
2510				    *((uint16_t *)addr));
2511				break;
2512			case sizeof (uint8_t):
2513				n = dt_printf(dtp, fp, quiet ? "%d" : " %3d",
2514				    *((uint8_t *)addr));
2515				break;
2516			default:
2517				n = dt_print_bytes(dtp, fp, addr,
2518				    rec->dtrd_size, -33, quiet, 0);
2519				break;
2520			}
2521
2522			if (n < 0)
2523				return (-1); /* errno is set for us */
2524
2525nextrec:
2526			if (dt_buffered_flush(dtp, &data, rec, NULL, 0) < 0)
2527				return (-1); /* errno is set for us */
2528		}
2529
2530		/*
2531		 * Call the record callback with a NULL record to indicate
2532		 * that we're done processing this EPID.
2533		 */
2534		rval = (*rfunc)(&data, NULL, arg);
2535nextepid:
2536		offs += epd->dtepd_size;
2537		last = id;
2538		// EPM DEBUG PRINT
2539		// dt_dprintf("---E-------> dt_consume_cpu - %d ID: %d\n",cpu, id);
2540	}
2541
2542	if (buf->dtbd_oldest != 0 && start == buf->dtbd_oldest) {
2543		end = buf->dtbd_oldest;
2544		start = 0;
2545		// EPM DEBUG PRINT
2546		// dt_dprintf("---2-------> dt_consume_cpu - %d AGAIN!!\n");
2547		goto again;
2548	}
2549
2550	if ((drops = buf->dtbd_drops) == 0)
2551		return (0);
2552
2553	/*
2554	 * Explicitly zero the drops to prevent us from processing them again.
2555	 */
2556	buf->dtbd_drops = 0;
2557
2558	// EPM DEBUG PRINT
2559	// dt_dprintf("-XXXXX----> dt_consume_cpu - %d DROPS!!\n",cpu);
2560	return (dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops));
2561}
2562
2563typedef struct dt_begin {
2564	dtrace_consume_probe_f *dtbgn_probefunc;
2565	dtrace_consume_rec_f *dtbgn_recfunc;
2566	void *dtbgn_arg;
2567	dtrace_handle_err_f *dtbgn_errhdlr;
2568	void *dtbgn_errarg;
2569	int dtbgn_beginonly;
2570} dt_begin_t;
2571
2572static int
2573dt_consume_begin_probe(const dtrace_probedata_t *data, void *arg)
2574{
2575	dt_begin_t *begin = (dt_begin_t *)arg;
2576	dtrace_probedesc_t *pd = data->dtpda_pdesc;
2577
2578	int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0);
2579	int r2 = (strcmp(pd->dtpd_name, "BEGIN") == 0);
2580
2581	if (begin->dtbgn_beginonly) {
2582		if (!(r1 && r2))
2583			return (DTRACE_CONSUME_NEXT);
2584	} else {
2585		if (r1 && r2)
2586			return (DTRACE_CONSUME_NEXT);
2587	}
2588
2589	/*
2590	 * We have a record that we're interested in.  Now call the underlying
2591	 * probe function...
2592	 */
2593	return (begin->dtbgn_probefunc(data, begin->dtbgn_arg));
2594}
2595
2596static int
2597dt_consume_begin_record(const dtrace_probedata_t *data,
2598    const dtrace_recdesc_t *rec, void *arg)
2599{
2600	dt_begin_t *begin = (dt_begin_t *)arg;
2601
2602	return (begin->dtbgn_recfunc(data, rec, begin->dtbgn_arg));
2603}
2604
2605static int
2606dt_consume_begin_error(const dtrace_errdata_t *data, void *arg)
2607{
2608	dt_begin_t *begin = (dt_begin_t *)arg;
2609	dtrace_probedesc_t *pd = data->dteda_pdesc;
2610
2611	int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0);
2612	int r2 = (strcmp(pd->dtpd_name, "BEGIN") == 0);
2613
2614	if (begin->dtbgn_beginonly) {
2615		if (!(r1 && r2))
2616			return (DTRACE_HANDLE_OK);
2617	} else {
2618		if (r1 && r2)
2619			return (DTRACE_HANDLE_OK);
2620	}
2621
2622	return (begin->dtbgn_errhdlr(data, begin->dtbgn_errarg));
2623}
2624
2625static int
2626dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp, dtrace_bufdesc_t *buf,
2627    dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
2628{
2629	/*
2630	 * There's this idea that the BEGIN probe should be processed before
2631	 * everything else, and that the END probe should be processed after
2632	 * anything else.  In the common case, this is pretty easy to deal
2633	 * with.  However, a situation may arise where the BEGIN enabling and
2634	 * END enabling are on the same CPU, and some enabling in the middle
2635	 * occurred on a different CPU.  To deal with this (blech!) we need to
2636	 * consume the BEGIN buffer up until the end of the BEGIN probe, and
2637	 * then set it aside.  We will then process every other CPU, and then
2638	 * we'll return to the BEGIN CPU and process the rest of the data
2639	 * (which will inevitably include the END probe, if any).  Making this
2640	 * even more complicated (!) is the library's ERROR enabling.  Because
2641	 * this enabling is processed before we even get into the consume call
2642	 * back, any ERROR firing would result in the library's ERROR enabling
2643	 * being processed twice -- once in our first pass (for BEGIN probes),
2644	 * and again in our second pass (for everything but BEGIN probes).  To
2645	 * deal with this, we interpose on the ERROR handler to assure that we
2646	 * only process ERROR enablings induced by BEGIN enablings in the
2647	 * first pass, and that we only process ERROR enablings _not_ induced
2648	 * by BEGIN enablings in the second pass.
2649	 */
2650	dt_begin_t begin;
2651	processorid_t cpu = dtp->dt_beganon;
2652	dtrace_bufdesc_t nbuf;
2653	int rval, i;
2654	static int max_ncpus;
2655	dtrace_optval_t size;
2656
2657	dtp->dt_beganon = -1;
2658
2659	if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
2660		/*
2661		 * We really don't expect this to fail, but it is at least
2662		 * technically possible for this to fail with ENOENT.  In this
2663		 * case, we just drive on...
2664		 */
2665		if (errno == ENOENT)
2666			return (0);
2667		// EPM DEBUG PRINT
2668		// dt_dprintf("1) dt consume begin: buf snap failed... returning\n");
2669		return (dt_set_errno(dtp, errno));
2670	}
2671
2672	if (!dtp->dt_stopped || buf->dtbd_cpu != dtp->dt_endedon) {
2673		// EPM DEBUG PRINT
2674		// dt_dprintf("]]]] dt_consume_cpu on: %d, simple case\n",cpu);
2675		/*
2676		 * This is the simple case.  We're either not stopped, or if
2677		 * we are, we actually processed any END probes on another
2678		 * CPU.  We can simply consume this buffer and return.
2679		 */
2680		return (dt_consume_cpu(dtp, fp, cpu, buf, pf, rf, arg));
2681	}
2682
2683	begin.dtbgn_probefunc = pf;
2684	begin.dtbgn_recfunc = rf;
2685	begin.dtbgn_arg = arg;
2686	begin.dtbgn_beginonly = 1;
2687
2688	/*
2689	 * We need to interpose on the ERROR handler to be sure that we
2690	 * only process ERRORs induced by BEGIN.
2691	 */
2692	begin.dtbgn_errhdlr = dtp->dt_errhdlr;
2693	begin.dtbgn_errarg = dtp->dt_errarg;
2694	dtp->dt_errhdlr = dt_consume_begin_error;
2695	dtp->dt_errarg = &begin;
2696	// EPM DEBUG PRINT
2697	// dt_dprintf("]]]] dt_consume_cpu: (begin) : %d\n", cpu);
2698	rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
2699	    dt_consume_begin_record, &begin);
2700
2701	dtp->dt_errhdlr = begin.dtbgn_errhdlr;
2702	dtp->dt_errarg = begin.dtbgn_errarg;
2703
2704	if (rval != 0)
2705		return (rval);
2706
2707	/*
2708	 * Now allocate a new buffer.  We'll use this to deal with every other
2709	 * CPU.
2710	 */
2711	bzero(&nbuf, sizeof (dtrace_bufdesc_t));
2712	(void) dtrace_getopt(dtp, "bufsize", &size);
2713	if ((nbuf.dtbd_data = malloc(size)) == NULL)
2714		return (dt_set_errno(dtp, EDT_NOMEM));
2715
2716	if (max_ncpus == 0)
2717		max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1;
2718
2719	for (i = 0; i < max_ncpus; i++) {
2720		nbuf.dtbd_cpu = i;
2721
2722		if (i == cpu)
2723			continue;
2724
2725		if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &nbuf) == -1) {
2726			/*
2727			 * If we failed with ENOENT, it may be because the
2728			 * CPU was unconfigured -- this is okay.  Any other
2729			 * error, however, is unexpected.
2730			 */
2731			if (errno == ENOENT)
2732				continue;
2733			// EPM DEBUG PRINT
2734			// dt_dprintf("2) dt consume begin: buf snap failed... returning\n");
2735			free(nbuf.dtbd_data);
2736
2737			return (dt_set_errno(dtp, errno));
2738		}
2739
2740		// EPM DEBUG PRINT
2741		// dt_dprintf("]]]] dt_consume_cpu: (every other) : %d\n", i);
2742		if ((rval = dt_consume_cpu(dtp, fp,
2743		    i, &nbuf, pf, rf, arg)) != 0) {
2744			free(nbuf.dtbd_data);
2745			return (rval);
2746		}
2747	}
2748
2749	free(nbuf.dtbd_data);
2750
2751	/*
2752	 * Okay -- we're done with the other buffers.  Now we want to
2753	 * reconsume the first buffer -- but this time we're looking for
2754	 * everything _but_ BEGIN.  And of course, in order to only consume
2755	 * those ERRORs _not_ associated with BEGIN, we need to reinstall our
2756	 * ERROR interposition function...
2757	 */
2758	begin.dtbgn_beginonly = 0;
2759
2760	assert(begin.dtbgn_errhdlr == dtp->dt_errhdlr);
2761	assert(begin.dtbgn_errarg == dtp->dt_errarg);
2762	dtp->dt_errhdlr = dt_consume_begin_error;
2763	dtp->dt_errarg = &begin;
2764
2765	// EPM DEBUG PRINT
2766	// dt_dprintf("]]]] dt_consume_cpu: (reconsume first) : %d\n", cpu);
2767	rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
2768	    dt_consume_begin_record, &begin);
2769
2770	dtp->dt_errhdlr = begin.dtbgn_errhdlr;
2771	dtp->dt_errarg = begin.dtbgn_errarg;
2772
2773	return (rval);
2774}
2775
2776int
2777dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
2778    dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
2779{
2780	dtrace_bufdesc_t *buf = &dtp->dt_buf;
2781	dtrace_optval_t size;
2782	static int max_ncpus;
2783	int i, rval;
2784	dtrace_optval_t interval = dtp->dt_options[DTRACEOPT_SWITCHRATE];
2785	hrtime_t now = gethrtime();
2786
2787	if (dtp->dt_lastswitch != 0) {
2788		if (now - dtp->dt_lastswitch < interval) {
2789			// EPM DEBUG PRINT
2790			// dt_dprintf("rrrrr consume: It's not time to consume yet...%lld < %lld returning\n",now - dtp->dt_lastswitch,interval);
2791			return (0);
2792		}
2793		dtp->dt_lastswitch += interval;
2794	} else {
2795		dtp->dt_lastswitch = now;
2796	}
2797
2798	if (!dtp->dt_active) {
2799		// EPM DEBUG PRINT
2800		// dt_dprintf("act act act dtrace no longer active... returning\n");
2801		return (dt_set_errno(dtp, EINVAL));
2802	}
2803	if (max_ncpus == 0)
2804		max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1;
2805
2806	if (pf == NULL)
2807		pf = (dtrace_consume_probe_f *)dt_nullprobe;
2808
2809	if (rf == NULL)
2810		rf = (dtrace_consume_rec_f *)dt_nullrec;
2811
2812	if (buf->dtbd_data == NULL) {
2813		(void) dtrace_getopt(dtp, "bufsize", &size);
2814		if ((buf->dtbd_data = malloc(size)) == NULL)
2815			return (dt_set_errno(dtp, EDT_NOMEM));
2816
2817		buf->dtbd_size = size;
2818	}
2819	// EPM DEBUG PRINT
2820	// dt_dprintf("Time: CONSUME: timing...E %lld : I %lld\n",now - dtp->dt_lastswitch, interval);
2821	/*
2822	 * If we have just begun, we want to first process the CPU that
2823	 * executed the BEGIN probe (if any).
2824	 */
2825	if (dtp->dt_active && dtp->dt_beganon != -1) {
2826		buf->dtbd_cpu = dtp->dt_beganon;
2827		if ((rval = dt_consume_begin(dtp, fp, buf, pf, rf, arg)) != 0)
2828			return (rval);
2829	}
2830
2831	for (i = 0; i < max_ncpus; i++) {
2832		buf->dtbd_cpu = i;
2833
2834		/*
2835		 * If we have stopped, we want to process the CPU on which the
2836		 * END probe was processed only _after_ we have processed
2837		 * everything else.
2838		 */
2839		if (dtp->dt_stopped && (i == dtp->dt_endedon))
2840			continue;
2841
2842		if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
2843			/*
2844			 * If we failed with ENOENT, it may be because the
2845			 * CPU was unconfigured -- this is okay.  Any other
2846			 * error, however, is unexpected.
2847			 */
2848			if (errno == ENOENT)
2849				continue;
2850			// EPM DEBUG PRINT
2851			// dt_dprintf("1) consume: buf snap failed... returning\n");
2852			return (dt_set_errno(dtp, errno));
2853		}
2854
2855		// EPM DEBUG PRINT
2856		// dt_dprintf("]]]] calling dt_consume_cpu on %d, in everything else loop\n",i);
2857		if ((rval = dt_consume_cpu(dtp, fp, i, buf, pf, rf, arg)) != 0)
2858			return (rval);
2859	}
2860
2861	if (!dtp->dt_stopped)
2862		return (0);
2863
2864	buf->dtbd_cpu = dtp->dt_endedon;
2865
2866	if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
2867		/*
2868		 * This _really_ shouldn't fail, but it is strictly speaking
2869		 * possible for this to return ENOENT if the CPU that called
2870		 * the END enabling somehow managed to become unconfigured.
2871		 * It's unclear how the user can possibly expect anything
2872		 * rational to happen in this case -- the state has been thrown
2873		 * out along with the unconfigured CPU -- so we'll just drive
2874		 * on...
2875		 */
2876		if (errno == ENOENT)
2877			return (0);
2878		// EPM DEBUG PRINT
2879		// dt_dprintf("2) consume: buf snap failed... returning\n");
2880		return (dt_set_errno(dtp, errno));
2881	}
2882
2883	// EPM DEBUG PRINT
2884	// dt_dprintf("]]]] calling dt_consume_cpu on %d...ended-on\n",dtp->dt_endedon);
2885	return (dt_consume_cpu(dtp, fp, dtp->dt_endedon, buf, pf, rf, arg));
2886}
2887
2888