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