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