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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdlib.h> 30 #include <strings.h> 31 #include <errno.h> 32 #include <unistd.h> 33 #include <limits.h> 34 #include <assert.h> 35 #include <ctype.h> 36 #include <alloca.h> 37 #include <dt_impl.h> 38 39 /* 40 * We declare this here because (1) we need it and (2) we want to avoid a 41 * dependency on libm in libdtrace. 42 */ 43 static long double 44 dt_fabsl(long double x) 45 { 46 if (x < 0) 47 return (-x); 48 49 return (x); 50 } 51 52 static int 53 dt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last, 54 dtrace_bufdesc_t *buf, size_t offs) 55 { 56 dtrace_probedesc_t *pd = data->dtpda_pdesc, *npd; 57 dtrace_eprobedesc_t *epd = data->dtpda_edesc, *nepd; 58 char *p = pd->dtpd_provider, *n = pd->dtpd_name, *sub; 59 dtrace_flowkind_t flow = DTRACEFLOW_NONE; 60 const char *str = NULL; 61 static const char *e_str[2] = { " -> ", " => " }; 62 static const char *r_str[2] = { " <- ", " <= " }; 63 static const char *ent = "entry", *ret = "return"; 64 static int entlen = 0, retlen = 0; 65 dtrace_epid_t next, id = epd->dtepd_epid; 66 int rval; 67 68 if (entlen == 0) { 69 assert(retlen == 0); 70 entlen = strlen(ent); 71 retlen = strlen(ret); 72 } 73 74 /* 75 * If the name of the probe is "entry" or ends with "-entry", we 76 * treat it as an entry; if it is "return" or ends with "-return", 77 * we treat it as a return. (This allows application-provided probes 78 * like "method-entry" or "function-entry" to participate in flow 79 * indentation -- without accidentally misinterpreting popular probe 80 * names like "carpentry", "gentry" or "Coventry".) 81 */ 82 if ((sub = strstr(n, ent)) != NULL && sub[entlen] == '\0' && 83 (sub == n || sub[-1] == '-')) { 84 flow = DTRACEFLOW_ENTRY; 85 str = e_str[strcmp(p, "syscall") == 0]; 86 } else if ((sub = strstr(n, ret)) != NULL && sub[retlen] == '\0' && 87 (sub == n || sub[-1] == '-')) { 88 flow = DTRACEFLOW_RETURN; 89 str = r_str[strcmp(p, "syscall") == 0]; 90 } 91 92 /* 93 * If we're going to indent this, we need to check the ID of our last 94 * call. If we're looking at the same probe ID but a different EPID, 95 * we _don't_ want to indent. (Yes, there are some minor holes in 96 * this scheme -- it's a heuristic.) 97 */ 98 if (flow == DTRACEFLOW_ENTRY) { 99 if ((last != DTRACE_EPIDNONE && id != last && 100 pd->dtpd_id == dtp->dt_pdesc[last]->dtpd_id)) 101 flow = DTRACEFLOW_NONE; 102 } 103 104 /* 105 * If we're going to unindent this, it's more difficult to see if 106 * we don't actually want to unindent it -- we need to look at the 107 * _next_ EPID. 108 */ 109 if (flow == DTRACEFLOW_RETURN) { 110 offs += epd->dtepd_size; 111 112 do { 113 if (offs >= buf->dtbd_size) { 114 /* 115 * We're at the end -- maybe. If the oldest 116 * record is non-zero, we need to wrap. 117 */ 118 if (buf->dtbd_oldest != 0) { 119 offs = 0; 120 } else { 121 goto out; 122 } 123 } 124 125 next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs); 126 127 if (next == DTRACE_EPIDNONE) 128 offs += sizeof (id); 129 } while (next == DTRACE_EPIDNONE); 130 131 if ((rval = dt_epid_lookup(dtp, next, &nepd, &npd)) != 0) 132 return (rval); 133 134 if (next != id && npd->dtpd_id == pd->dtpd_id) 135 flow = DTRACEFLOW_NONE; 136 } 137 138 out: 139 if (flow == DTRACEFLOW_ENTRY || flow == DTRACEFLOW_RETURN) { 140 data->dtpda_prefix = str; 141 } else { 142 data->dtpda_prefix = "| "; 143 } 144 145 if (flow == DTRACEFLOW_RETURN && data->dtpda_indent > 0) 146 data->dtpda_indent -= 2; 147 148 data->dtpda_flow = flow; 149 150 return (0); 151 } 152 153 static int 154 dt_nullprobe() 155 { 156 return (DTRACE_CONSUME_THIS); 157 } 158 159 static int 160 dt_nullrec() 161 { 162 return (DTRACE_CONSUME_NEXT); 163 } 164 165 int 166 dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val, 167 uint64_t normal, long double total, char positives, char negatives) 168 { 169 long double f; 170 uint_t depth, len = 40; 171 172 const char *ats = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"; 173 const char *spaces = " "; 174 175 assert(strlen(ats) == len && strlen(spaces) == len); 176 assert(!(total == 0 && (positives || negatives))); 177 assert(!(val < 0 && !negatives)); 178 assert(!(val > 0 && !positives)); 179 assert(!(val != 0 && total == 0)); 180 181 if (!negatives) { 182 if (positives) { 183 f = (dt_fabsl((long double)val) * len) / total; 184 depth = (uint_t)(f + 0.5); 185 } else { 186 depth = 0; 187 } 188 189 return (dt_printf(dtp, fp, "|%s%s %-9lld\n", ats + len - depth, 190 spaces + depth, (long long)val / normal)); 191 } 192 193 if (!positives) { 194 f = (dt_fabsl((long double)val) * len) / total; 195 depth = (uint_t)(f + 0.5); 196 197 return (dt_printf(dtp, fp, "%s%s| %-9lld\n", spaces + depth, 198 ats + len - depth, (long long)val / normal)); 199 } 200 201 /* 202 * If we're here, we have both positive and negative bucket values. 203 * To express this graphically, we're going to generate both positive 204 * and negative bars separated by a centerline. These bars are half 205 * the size of normal quantize()/lquantize() bars, so we divide the 206 * length in half before calculating the bar length. 207 */ 208 len /= 2; 209 ats = &ats[len]; 210 spaces = &spaces[len]; 211 212 f = (dt_fabsl((long double)val) * len) / total; 213 depth = (uint_t)(f + 0.5); 214 215 if (val <= 0) { 216 return (dt_printf(dtp, fp, "%s%s|%*s %-9lld\n", spaces + depth, 217 ats + len - depth, len, "", (long long)val / normal)); 218 } else { 219 return (dt_printf(dtp, fp, "%20s|%s%s %-9lld\n", "", 220 ats + len - depth, spaces + depth, 221 (long long)val / normal)); 222 } 223 } 224 225 int 226 dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, 227 size_t size, uint64_t normal) 228 { 229 const int64_t *data = addr; 230 int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1; 231 long double total = 0; 232 char positives = 0, negatives = 0; 233 234 if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t)) 235 return (dt_set_errno(dtp, EDT_DMISMATCH)); 236 237 while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0) 238 first_bin++; 239 240 if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) { 241 /* 242 * There isn't any data. This is possible if (and only if) 243 * negative increment values have been used. In this case, 244 * we'll print the buckets around 0. 245 */ 246 first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1; 247 last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1; 248 } else { 249 if (first_bin > 0) 250 first_bin--; 251 252 while (last_bin > 0 && data[last_bin] == 0) 253 last_bin--; 254 255 if (last_bin < DTRACE_QUANTIZE_NBUCKETS - 1) 256 last_bin++; 257 } 258 259 for (i = first_bin; i <= last_bin; i++) { 260 positives |= (data[i] > 0); 261 negatives |= (data[i] < 0); 262 total += dt_fabsl((long double)data[i]); 263 } 264 265 if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value", 266 "------------- Distribution -------------", "count") < 0) 267 return (-1); 268 269 for (i = first_bin; i <= last_bin; i++) { 270 if (dt_printf(dtp, fp, "%16lld ", 271 (long long)DTRACE_QUANTIZE_BUCKETVAL(i)) < 0) 272 return (-1); 273 274 if (dt_print_quantline(dtp, fp, data[i], normal, total, 275 positives, negatives) < 0) 276 return (-1); 277 } 278 279 return (0); 280 } 281 282 int 283 dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, 284 size_t size, uint64_t normal) 285 { 286 const int64_t *data = addr; 287 int i, first_bin, last_bin, base; 288 uint64_t arg; 289 long double total = 0; 290 uint16_t step, levels; 291 char positives = 0, negatives = 0; 292 293 if (size < sizeof (uint64_t)) 294 return (dt_set_errno(dtp, EDT_DMISMATCH)); 295 296 arg = *data++; 297 size -= sizeof (uint64_t); 298 299 base = DTRACE_LQUANTIZE_BASE(arg); 300 step = DTRACE_LQUANTIZE_STEP(arg); 301 levels = DTRACE_LQUANTIZE_LEVELS(arg); 302 303 first_bin = 0; 304 last_bin = levels + 1; 305 306 if (size != sizeof (uint64_t) * (levels + 2)) 307 return (dt_set_errno(dtp, EDT_DMISMATCH)); 308 309 while (first_bin <= levels + 1 && data[first_bin] == 0) 310 first_bin++; 311 312 if (first_bin > levels + 1) { 313 first_bin = 0; 314 last_bin = 2; 315 } else { 316 if (first_bin > 0) 317 first_bin--; 318 319 while (last_bin > 0 && data[last_bin] == 0) 320 last_bin--; 321 322 if (last_bin < levels + 1) 323 last_bin++; 324 } 325 326 for (i = first_bin; i <= last_bin; i++) { 327 positives |= (data[i] > 0); 328 negatives |= (data[i] < 0); 329 total += dt_fabsl((long double)data[i]); 330 } 331 332 if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value", 333 "------------- Distribution -------------", "count") < 0) 334 return (-1); 335 336 for (i = first_bin; i <= last_bin; i++) { 337 char c[32]; 338 int err; 339 340 if (i == 0) { 341 (void) snprintf(c, sizeof (c), "< %d", 342 base / (uint32_t)normal); 343 err = dt_printf(dtp, fp, "%16s ", c); 344 } else if (i == levels + 1) { 345 (void) snprintf(c, sizeof (c), ">= %d", 346 base + (levels * step)); 347 err = dt_printf(dtp, fp, "%16s ", c); 348 } else { 349 err = dt_printf(dtp, fp, "%16d ", 350 base + (i - 1) * step); 351 } 352 353 if (err < 0 || dt_print_quantline(dtp, fp, data[i], normal, 354 total, positives, negatives) < 0) 355 return (-1); 356 } 357 358 return (0); 359 } 360 361 /*ARGSUSED*/ 362 static int 363 dt_print_average(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, 364 size_t size, uint64_t normal) 365 { 366 /* LINTED - alignment */ 367 uint64_t *data = (uint64_t *)addr; 368 369 return (dt_printf(dtp, fp, " %16lld", data[0] ? 370 (long long)(data[1] / normal / data[0]) : 0)); 371 } 372 373 /*ARGSUSED*/ 374 int 375 dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, 376 size_t nbytes, int width, int quiet) 377 { 378 /* 379 * If the byte stream is a series of printable characters, followed by 380 * a terminating byte, we print it out as a string. Otherwise, we 381 * assume that it's something else and just print the bytes. 382 */ 383 int i, j, margin = 5; 384 char *c = (char *)addr; 385 386 if (nbytes == 0) 387 return (0); 388 389 if (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET) 390 goto raw; 391 392 for (i = 0; i < nbytes; i++) { 393 /* 394 * We define a "printable character" to be one for which 395 * isprint(3C) returns non-zero, isspace(3C) returns non-zero, 396 * or a character which is either backspace or the bell. 397 * Backspace and the bell are regrettably special because 398 * they fail the first two tests -- and yet they are entirely 399 * printable. These are the only two control characters that 400 * have meaning for the terminal and for which isprint(3C) and 401 * isspace(3C) return 0. 402 */ 403 if (isprint(c[i]) || isspace(c[i]) || 404 c[i] == '\b' || c[i] == '\a') 405 continue; 406 407 if (c[i] == '\0' && i > 0) { 408 /* 409 * This looks like it might be a string. Before we 410 * assume that it is indeed a string, check the 411 * remainder of the byte range; if it contains 412 * additional non-nul characters, we'll assume that 413 * it's a binary stream that just happens to look like 414 * a string, and we'll print out the individual bytes. 415 */ 416 for (j = i + 1; j < nbytes; j++) { 417 if (c[j] != '\0') 418 break; 419 } 420 421 if (j != nbytes) 422 break; 423 424 if (quiet) 425 return (dt_printf(dtp, fp, "%s", c)); 426 else 427 return (dt_printf(dtp, fp, " %-*s", width, c)); 428 } 429 430 break; 431 } 432 433 if (i == nbytes) { 434 /* 435 * The byte range is all printable characters, but there is 436 * no trailing nul byte. We'll assume that it's a string and 437 * print it as such. 438 */ 439 char *s = alloca(nbytes + 1); 440 bcopy(c, s, nbytes); 441 s[nbytes] = '\0'; 442 return (dt_printf(dtp, fp, " %-*s", width, s)); 443 } 444 445 raw: 446 if (dt_printf(dtp, fp, "\n%*s ", margin, "") < 0) 447 return (-1); 448 449 for (i = 0; i < 16; i++) 450 if (dt_printf(dtp, fp, " %c", "0123456789abcdef"[i]) < 0) 451 return (-1); 452 453 if (dt_printf(dtp, fp, " 0123456789abcdef\n") < 0) 454 return (-1); 455 456 457 for (i = 0; i < nbytes; i += 16) { 458 if (dt_printf(dtp, fp, "%*s%5x:", margin, "", i) < 0) 459 return (-1); 460 461 for (j = i; j < i + 16 && j < nbytes; j++) { 462 if (dt_printf(dtp, fp, " %02x", (uchar_t)c[j]) < 0) 463 return (-1); 464 } 465 466 while (j++ % 16) { 467 if (dt_printf(dtp, fp, " ") < 0) 468 return (-1); 469 } 470 471 if (dt_printf(dtp, fp, " ") < 0) 472 return (-1); 473 474 for (j = i; j < i + 16 && j < nbytes; j++) { 475 if (dt_printf(dtp, fp, "%c", 476 c[j] < ' ' || c[j] > '~' ? '.' : c[j]) < 0) 477 return (-1); 478 } 479 480 if (dt_printf(dtp, fp, "\n") < 0) 481 return (-1); 482 } 483 484 return (0); 485 } 486 487 int 488 dt_print_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format, 489 caddr_t addr, int depth, int size) 490 { 491 dtrace_syminfo_t dts; 492 GElf_Sym sym; 493 int i, indent; 494 char c[PATH_MAX * 2]; 495 uint64_t pc; 496 497 if (dt_printf(dtp, fp, "\n") < 0) 498 return (-1); 499 500 if (format == NULL) 501 format = "%s"; 502 503 if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET) 504 indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT]; 505 else 506 indent = _dtrace_stkindent; 507 508 for (i = 0; i < depth; i++) { 509 switch (size) { 510 case sizeof (uint32_t): 511 /* LINTED - alignment */ 512 pc = *((uint32_t *)addr); 513 break; 514 515 case sizeof (uint64_t): 516 /* LINTED - alignment */ 517 pc = *((uint64_t *)addr); 518 break; 519 520 default: 521 return (dt_set_errno(dtp, EDT_BADSTACKPC)); 522 } 523 524 if (pc == NULL) 525 break; 526 527 addr += size; 528 529 if (dt_printf(dtp, fp, "%*s", indent, "") < 0) 530 return (-1); 531 532 if (dtrace_lookup_by_addr(dtp, pc, &sym, &dts) == 0) { 533 if (pc > sym.st_value) { 534 (void) snprintf(c, sizeof (c), "%s`%s+0x%llx", 535 dts.dts_object, dts.dts_name, 536 pc - sym.st_value); 537 } else { 538 (void) snprintf(c, sizeof (c), "%s`%s", 539 dts.dts_object, dts.dts_name); 540 } 541 } else { 542 /* 543 * We'll repeat the lookup, but this time we'll specify 544 * a NULL GElf_Sym -- indicating that we're only 545 * interested in the containing module. 546 */ 547 if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) { 548 (void) snprintf(c, sizeof (c), "%s`0x%llx", 549 dts.dts_object, pc); 550 } else { 551 (void) snprintf(c, sizeof (c), "0x%llx", pc); 552 } 553 } 554 555 if (dt_printf(dtp, fp, format, c) < 0) 556 return (-1); 557 558 if (dt_printf(dtp, fp, "\n") < 0) 559 return (-1); 560 } 561 562 return (0); 563 } 564 565 int 566 dt_print_ustack(dtrace_hdl_t *dtp, FILE *fp, const char *format, 567 caddr_t addr, uint64_t arg) 568 { 569 /* LINTED - alignment */ 570 uint64_t *pc = (uint64_t *)addr; 571 uint32_t depth = DTRACE_USTACK_NFRAMES(arg); 572 uint32_t strsize = DTRACE_USTACK_STRSIZE(arg); 573 const char *strbase = addr + (depth + 1) * sizeof (uint64_t); 574 const char *str = strsize ? strbase : NULL; 575 int err = 0; 576 577 char name[PATH_MAX], objname[PATH_MAX], c[PATH_MAX * 2]; 578 struct ps_prochandle *P; 579 GElf_Sym sym; 580 int i, indent; 581 pid_t pid; 582 583 if (depth == 0) 584 return (0); 585 586 pid = (pid_t)*pc++; 587 588 if (dt_printf(dtp, fp, "\n") < 0) 589 return (-1); 590 591 if (format == NULL) 592 format = "%s"; 593 594 if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET) 595 indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT]; 596 else 597 indent = _dtrace_stkindent; 598 599 /* 600 * Ultimately, we need to add an entry point in the library vector for 601 * determining <symbol, offset> from <pid, address>. For now, if 602 * this is a vector open, we just print the raw address or string. 603 */ 604 if (dtp->dt_vector == NULL) 605 P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0); 606 else 607 P = NULL; 608 609 if (P != NULL) 610 dt_proc_lock(dtp, P); /* lock handle while we perform lookups */ 611 612 for (i = 0; i < depth && pc[i] != NULL; i++) { 613 const prmap_t *map; 614 615 if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0) 616 break; 617 618 if (P != NULL && Plookup_by_addr(P, pc[i], 619 name, sizeof (name), &sym) == 0) { 620 (void) Pobjname(P, pc[i], objname, sizeof (objname)); 621 622 if (pc[i] > sym.st_value) { 623 (void) snprintf(c, sizeof (c), 624 "%s`%s+0x%llx", dt_basename(objname), name, 625 (u_longlong_t)(pc[i] - sym.st_value)); 626 } else { 627 (void) snprintf(c, sizeof (c), 628 "%s`%s", dt_basename(objname), name); 629 } 630 } else if (str != NULL && str[0] != '\0' && str[0] != '@' && 631 (P != NULL && ((map = Paddr_to_map(P, pc[i])) == NULL || 632 (map->pr_mflags & MA_WRITE)))) { 633 /* 634 * If the current string pointer in the string table 635 * does not point to an empty string _and_ the program 636 * counter falls in a writable region, we'll use the 637 * string from the string table instead of the raw 638 * address. This last condition is necessary because 639 * some (broken) ustack helpers will return a string 640 * even for a program counter that they can't 641 * identify. If we have a string for a program 642 * counter that falls in a segment that isn't 643 * writable, we assume that we have fallen into this 644 * case and we refuse to use the string. 645 */ 646 (void) snprintf(c, sizeof (c), "%s", str); 647 } else { 648 if (P != NULL && Pobjname(P, pc[i], objname, 649 sizeof (objname)) != NULL) { 650 (void) snprintf(c, sizeof (c), "%s`0x%llx", 651 dt_basename(objname), (u_longlong_t)pc[i]); 652 } else { 653 (void) snprintf(c, sizeof (c), "0x%llx", 654 (u_longlong_t)pc[i]); 655 } 656 } 657 658 if ((err = dt_printf(dtp, fp, format, c)) < 0) 659 break; 660 661 if ((err = dt_printf(dtp, fp, "\n")) < 0) 662 break; 663 664 if (str != NULL && str[0] == '@') { 665 /* 666 * If the first character of the string is an "at" sign, 667 * then the string is inferred to be an annotation -- 668 * and it is printed out beneath the frame and offset 669 * with brackets. 670 */ 671 if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0) 672 break; 673 674 (void) snprintf(c, sizeof (c), " [ %s ]", &str[1]); 675 676 if ((err = dt_printf(dtp, fp, format, c)) < 0) 677 break; 678 679 if ((err = dt_printf(dtp, fp, "\n")) < 0) 680 break; 681 } 682 683 if (str != NULL) { 684 str += strlen(str) + 1; 685 if (str - strbase >= strsize) 686 str = NULL; 687 } 688 } 689 690 if (P != NULL) { 691 dt_proc_unlock(dtp, P); 692 dt_proc_release(dtp, P); 693 } 694 695 return (err); 696 } 697 698 static int 699 dt_print_usym(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, dtrace_actkind_t act) 700 { 701 /* LINTED - alignment */ 702 uint64_t pid = ((uint64_t *)addr)[0]; 703 /* LINTED - alignment */ 704 uint64_t pc = ((uint64_t *)addr)[1]; 705 const char *format = " %-50s"; 706 char *s; 707 int n, len = 256; 708 709 if (act == DTRACEACT_USYM && dtp->dt_vector == NULL) { 710 struct ps_prochandle *P; 711 712 if ((P = dt_proc_grab(dtp, pid, 713 PGRAB_RDONLY | PGRAB_FORCE, 0)) != NULL) { 714 GElf_Sym sym; 715 716 dt_proc_lock(dtp, P); 717 718 if (Plookup_by_addr(P, pc, NULL, 0, &sym) == 0) 719 pc = sym.st_value; 720 721 dt_proc_unlock(dtp, P); 722 dt_proc_release(dtp, P); 723 } 724 } 725 726 do { 727 n = len; 728 s = alloca(n); 729 } while ((len = dtrace_uaddr2str(dtp, pid, pc, s, n)) >= n); 730 731 return (dt_printf(dtp, fp, format, s)); 732 } 733 734 int 735 dt_print_umod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) 736 { 737 /* LINTED - alignment */ 738 uint64_t pid = ((uint64_t *)addr)[0]; 739 /* LINTED - alignment */ 740 uint64_t pc = ((uint64_t *)addr)[1]; 741 int err = 0; 742 743 char objname[PATH_MAX], c[PATH_MAX * 2]; 744 struct ps_prochandle *P; 745 746 if (format == NULL) 747 format = " %-50s"; 748 749 /* 750 * See the comment in dt_print_ustack() for the rationale for 751 * printing raw addresses in the vectored case. 752 */ 753 if (dtp->dt_vector == NULL) 754 P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0); 755 else 756 P = NULL; 757 758 if (P != NULL) 759 dt_proc_lock(dtp, P); /* lock handle while we perform lookups */ 760 761 if (P != NULL && Pobjname(P, pc, objname, sizeof (objname)) != NULL) { 762 (void) snprintf(c, sizeof (c), "%s", dt_basename(objname)); 763 } else { 764 (void) snprintf(c, sizeof (c), "0x%llx", (u_longlong_t)pc); 765 } 766 767 err = dt_printf(dtp, fp, format, c); 768 769 if (P != NULL) { 770 dt_proc_unlock(dtp, P); 771 dt_proc_release(dtp, P); 772 } 773 774 return (err); 775 } 776 777 static int 778 dt_print_sym(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) 779 { 780 /* LINTED - alignment */ 781 uint64_t pc = *((uint64_t *)addr); 782 dtrace_syminfo_t dts; 783 GElf_Sym sym; 784 char c[PATH_MAX * 2]; 785 786 if (format == NULL) 787 format = " %-50s"; 788 789 if (dtrace_lookup_by_addr(dtp, pc, &sym, &dts) == 0) { 790 (void) snprintf(c, sizeof (c), "%s`%s", 791 dts.dts_object, dts.dts_name); 792 } else { 793 /* 794 * We'll repeat the lookup, but this time we'll specify a 795 * NULL GElf_Sym -- indicating that we're only interested in 796 * the containing module. 797 */ 798 if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) { 799 (void) snprintf(c, sizeof (c), "%s`0x%llx", 800 dts.dts_object, (u_longlong_t)pc); 801 } else { 802 (void) snprintf(c, sizeof (c), "0x%llx", 803 (u_longlong_t)pc); 804 } 805 } 806 807 if (dt_printf(dtp, fp, format, c) < 0) 808 return (-1); 809 810 return (0); 811 } 812 813 int 814 dt_print_mod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) 815 { 816 /* LINTED - alignment */ 817 uint64_t pc = *((uint64_t *)addr); 818 dtrace_syminfo_t dts; 819 char c[PATH_MAX * 2]; 820 821 if (format == NULL) 822 format = " %-50s"; 823 824 if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) { 825 (void) snprintf(c, sizeof (c), "%s", dts.dts_object); 826 } else { 827 (void) snprintf(c, sizeof (c), "0x%llx", (u_longlong_t)pc); 828 } 829 830 if (dt_printf(dtp, fp, format, c) < 0) 831 return (-1); 832 833 return (0); 834 } 835 836 typedef struct dt_normal { 837 dtrace_aggvarid_t dtnd_id; 838 uint64_t dtnd_normal; 839 } dt_normal_t; 840 841 static int 842 dt_normalize_agg(const dtrace_aggdata_t *aggdata, void *arg) 843 { 844 dt_normal_t *normal = arg; 845 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 846 dtrace_aggvarid_t id = normal->dtnd_id; 847 848 if (agg->dtagd_nrecs == 0) 849 return (DTRACE_AGGWALK_NEXT); 850 851 if (agg->dtagd_varid != id) 852 return (DTRACE_AGGWALK_NEXT); 853 854 ((dtrace_aggdata_t *)aggdata)->dtada_normal = normal->dtnd_normal; 855 return (DTRACE_AGGWALK_NORMALIZE); 856 } 857 858 static int 859 dt_normalize(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec) 860 { 861 dt_normal_t normal; 862 caddr_t addr; 863 864 /* 865 * We (should) have two records: the aggregation ID followed by the 866 * normalization value. 867 */ 868 addr = base + rec->dtrd_offset; 869 870 if (rec->dtrd_size != sizeof (dtrace_aggvarid_t)) 871 return (dt_set_errno(dtp, EDT_BADNORMAL)); 872 873 /* LINTED - alignment */ 874 normal.dtnd_id = *((dtrace_aggvarid_t *)addr); 875 rec++; 876 877 if (rec->dtrd_action != DTRACEACT_LIBACT) 878 return (dt_set_errno(dtp, EDT_BADNORMAL)); 879 880 if (rec->dtrd_arg != DT_ACT_NORMALIZE) 881 return (dt_set_errno(dtp, EDT_BADNORMAL)); 882 883 addr = base + rec->dtrd_offset; 884 885 switch (rec->dtrd_size) { 886 case sizeof (uint64_t): 887 /* LINTED - alignment */ 888 normal.dtnd_normal = *((uint64_t *)addr); 889 break; 890 case sizeof (uint32_t): 891 /* LINTED - alignment */ 892 normal.dtnd_normal = *((uint32_t *)addr); 893 break; 894 case sizeof (uint16_t): 895 /* LINTED - alignment */ 896 normal.dtnd_normal = *((uint16_t *)addr); 897 break; 898 case sizeof (uint8_t): 899 normal.dtnd_normal = *((uint8_t *)addr); 900 break; 901 default: 902 return (dt_set_errno(dtp, EDT_BADNORMAL)); 903 } 904 905 (void) dtrace_aggregate_walk(dtp, dt_normalize_agg, &normal); 906 907 return (0); 908 } 909 910 static int 911 dt_denormalize_agg(const dtrace_aggdata_t *aggdata, void *arg) 912 { 913 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 914 dtrace_aggvarid_t id = *((dtrace_aggvarid_t *)arg); 915 916 if (agg->dtagd_nrecs == 0) 917 return (DTRACE_AGGWALK_NEXT); 918 919 if (agg->dtagd_varid != id) 920 return (DTRACE_AGGWALK_NEXT); 921 922 return (DTRACE_AGGWALK_DENORMALIZE); 923 } 924 925 static int 926 dt_clear_agg(const dtrace_aggdata_t *aggdata, void *arg) 927 { 928 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 929 dtrace_aggvarid_t id = *((dtrace_aggvarid_t *)arg); 930 931 if (agg->dtagd_nrecs == 0) 932 return (DTRACE_AGGWALK_NEXT); 933 934 if (agg->dtagd_varid != id) 935 return (DTRACE_AGGWALK_NEXT); 936 937 return (DTRACE_AGGWALK_CLEAR); 938 } 939 940 typedef struct dt_trunc { 941 dtrace_aggvarid_t dttd_id; 942 uint64_t dttd_remaining; 943 } dt_trunc_t; 944 945 static int 946 dt_trunc_agg(const dtrace_aggdata_t *aggdata, void *arg) 947 { 948 dt_trunc_t *trunc = arg; 949 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 950 dtrace_aggvarid_t id = trunc->dttd_id; 951 952 if (agg->dtagd_nrecs == 0) 953 return (DTRACE_AGGWALK_NEXT); 954 955 if (agg->dtagd_varid != id) 956 return (DTRACE_AGGWALK_NEXT); 957 958 if (trunc->dttd_remaining == 0) 959 return (DTRACE_AGGWALK_REMOVE); 960 961 trunc->dttd_remaining--; 962 return (DTRACE_AGGWALK_NEXT); 963 } 964 965 static int 966 dt_trunc(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec) 967 { 968 dt_trunc_t trunc; 969 caddr_t addr; 970 int64_t remaining; 971 int (*func)(dtrace_hdl_t *, dtrace_aggregate_f *, void *); 972 973 /* 974 * We (should) have two records: the aggregation ID followed by the 975 * number of aggregation entries after which the aggregation is to be 976 * truncated. 977 */ 978 addr = base + rec->dtrd_offset; 979 980 if (rec->dtrd_size != sizeof (dtrace_aggvarid_t)) 981 return (dt_set_errno(dtp, EDT_BADTRUNC)); 982 983 /* LINTED - alignment */ 984 trunc.dttd_id = *((dtrace_aggvarid_t *)addr); 985 rec++; 986 987 if (rec->dtrd_action != DTRACEACT_LIBACT) 988 return (dt_set_errno(dtp, EDT_BADTRUNC)); 989 990 if (rec->dtrd_arg != DT_ACT_TRUNC) 991 return (dt_set_errno(dtp, EDT_BADTRUNC)); 992 993 addr = base + rec->dtrd_offset; 994 995 switch (rec->dtrd_size) { 996 case sizeof (uint64_t): 997 /* LINTED - alignment */ 998 remaining = *((int64_t *)addr); 999 break; 1000 case sizeof (uint32_t): 1001 /* LINTED - alignment */ 1002 remaining = *((int32_t *)addr); 1003 break; 1004 case sizeof (uint16_t): 1005 /* LINTED - alignment */ 1006 remaining = *((int16_t *)addr); 1007 break; 1008 case sizeof (uint8_t): 1009 remaining = *((int8_t *)addr); 1010 break; 1011 default: 1012 return (dt_set_errno(dtp, EDT_BADNORMAL)); 1013 } 1014 1015 if (remaining < 0) { 1016 func = dtrace_aggregate_walk_valsorted; 1017 remaining = -remaining; 1018 } else { 1019 func = dtrace_aggregate_walk_valrevsorted; 1020 } 1021 1022 assert(remaining >= 0); 1023 trunc.dttd_remaining = remaining; 1024 1025 (void) func(dtp, dt_trunc_agg, &trunc); 1026 1027 return (0); 1028 } 1029 1030 static int 1031 dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec, 1032 caddr_t addr, size_t size, uint64_t normal) 1033 { 1034 int err; 1035 dtrace_actkind_t act = rec->dtrd_action; 1036 1037 switch (act) { 1038 case DTRACEACT_STACK: 1039 return (dt_print_stack(dtp, fp, NULL, addr, 1040 rec->dtrd_arg, rec->dtrd_size / rec->dtrd_arg)); 1041 1042 case DTRACEACT_USTACK: 1043 case DTRACEACT_JSTACK: 1044 return (dt_print_ustack(dtp, fp, NULL, addr, rec->dtrd_arg)); 1045 1046 case DTRACEACT_USYM: 1047 case DTRACEACT_UADDR: 1048 return (dt_print_usym(dtp, fp, addr, act)); 1049 1050 case DTRACEACT_UMOD: 1051 return (dt_print_umod(dtp, fp, NULL, addr)); 1052 1053 case DTRACEACT_SYM: 1054 return (dt_print_sym(dtp, fp, NULL, addr)); 1055 1056 case DTRACEACT_MOD: 1057 return (dt_print_mod(dtp, fp, NULL, addr)); 1058 1059 case DTRACEAGG_QUANTIZE: 1060 return (dt_print_quantize(dtp, fp, addr, size, normal)); 1061 1062 case DTRACEAGG_LQUANTIZE: 1063 return (dt_print_lquantize(dtp, fp, addr, size, normal)); 1064 1065 case DTRACEAGG_AVG: 1066 return (dt_print_average(dtp, fp, addr, size, normal)); 1067 1068 default: 1069 break; 1070 } 1071 1072 switch (size) { 1073 case sizeof (uint64_t): 1074 err = dt_printf(dtp, fp, " %16lld", 1075 /* LINTED - alignment */ 1076 (long long)*((uint64_t *)addr) / normal); 1077 break; 1078 case sizeof (uint32_t): 1079 /* LINTED - alignment */ 1080 err = dt_printf(dtp, fp, " %8d", *((uint32_t *)addr) / 1081 (uint32_t)normal); 1082 break; 1083 case sizeof (uint16_t): 1084 /* LINTED - alignment */ 1085 err = dt_printf(dtp, fp, " %5d", *((uint16_t *)addr) / 1086 (uint32_t)normal); 1087 break; 1088 case sizeof (uint8_t): 1089 err = dt_printf(dtp, fp, " %3d", *((uint8_t *)addr) / 1090 (uint32_t)normal); 1091 break; 1092 default: 1093 err = dt_print_bytes(dtp, fp, addr, size, 50, 0); 1094 break; 1095 } 1096 1097 return (err); 1098 } 1099 1100 int 1101 dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg) 1102 { 1103 int i, aggact = 0; 1104 dt_print_aggdata_t *pd = arg; 1105 const dtrace_aggdata_t *aggdata = aggsdata[0]; 1106 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 1107 FILE *fp = pd->dtpa_fp; 1108 dtrace_hdl_t *dtp = pd->dtpa_dtp; 1109 dtrace_recdesc_t *rec; 1110 dtrace_actkind_t act; 1111 caddr_t addr; 1112 size_t size; 1113 1114 /* 1115 * Iterate over each record description in the key, printing the traced 1116 * data, skipping the first datum (the tuple member created by the 1117 * compiler). 1118 */ 1119 for (i = 1; i < agg->dtagd_nrecs; i++) { 1120 rec = &agg->dtagd_rec[i]; 1121 act = rec->dtrd_action; 1122 addr = aggdata->dtada_data + rec->dtrd_offset; 1123 size = rec->dtrd_size; 1124 1125 if (DTRACEACT_ISAGG(act)) { 1126 aggact = i; 1127 break; 1128 } 1129 1130 if (dt_print_datum(dtp, fp, rec, addr, size, 1) < 0) 1131 return (-1); 1132 1133 if (dt_buffered_flush(dtp, NULL, rec, aggdata, 1134 DTRACE_BUFDATA_AGGKEY) < 0) 1135 return (-1); 1136 } 1137 1138 assert(aggact != 0); 1139 1140 for (i = (naggvars == 1 ? 0 : 1); i < naggvars; i++) { 1141 uint64_t normal; 1142 1143 aggdata = aggsdata[i]; 1144 agg = aggdata->dtada_desc; 1145 rec = &agg->dtagd_rec[aggact]; 1146 act = rec->dtrd_action; 1147 addr = aggdata->dtada_data + rec->dtrd_offset; 1148 size = rec->dtrd_size; 1149 1150 assert(DTRACEACT_ISAGG(act)); 1151 normal = aggdata->dtada_normal; 1152 1153 if (dt_print_datum(dtp, fp, rec, addr, size, normal) < 0) 1154 return (-1); 1155 1156 if (dt_buffered_flush(dtp, NULL, rec, aggdata, 1157 DTRACE_BUFDATA_AGGVAL) < 0) 1158 return (-1); 1159 1160 if (!pd->dtpa_allunprint) 1161 agg->dtagd_flags |= DTRACE_AGD_PRINTED; 1162 } 1163 1164 if (dt_printf(dtp, fp, "\n") < 0) 1165 return (-1); 1166 1167 if (dt_buffered_flush(dtp, NULL, NULL, aggdata, 1168 DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0) 1169 return (-1); 1170 1171 return (0); 1172 } 1173 1174 int 1175 dt_print_agg(const dtrace_aggdata_t *aggdata, void *arg) 1176 { 1177 dt_print_aggdata_t *pd = arg; 1178 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 1179 dtrace_aggvarid_t aggvarid = pd->dtpa_id; 1180 1181 if (pd->dtpa_allunprint) { 1182 if (agg->dtagd_flags & DTRACE_AGD_PRINTED) 1183 return (0); 1184 } else { 1185 /* 1186 * If we're not printing all unprinted aggregations, then the 1187 * aggregation variable ID denotes a specific aggregation 1188 * variable that we should print -- skip any other aggregations 1189 * that we encounter. 1190 */ 1191 if (agg->dtagd_nrecs == 0) 1192 return (0); 1193 1194 if (aggvarid != agg->dtagd_varid) 1195 return (0); 1196 } 1197 1198 return (dt_print_aggs(&aggdata, 1, arg)); 1199 } 1200 1201 int 1202 dt_setopt(dtrace_hdl_t *dtp, const dtrace_probedata_t *data, 1203 const char *option, const char *value) 1204 { 1205 int len, rval; 1206 char *msg; 1207 const char *errstr; 1208 dtrace_setoptdata_t optdata; 1209 1210 bzero(&optdata, sizeof (optdata)); 1211 (void) dtrace_getopt(dtp, option, &optdata.dtsda_oldval); 1212 1213 if (dtrace_setopt(dtp, option, value) == 0) { 1214 (void) dtrace_getopt(dtp, option, &optdata.dtsda_newval); 1215 optdata.dtsda_probe = data; 1216 optdata.dtsda_option = option; 1217 optdata.dtsda_handle = dtp; 1218 1219 if ((rval = dt_handle_setopt(dtp, &optdata)) != 0) 1220 return (rval); 1221 1222 return (0); 1223 } 1224 1225 errstr = dtrace_errmsg(dtp, dtrace_errno(dtp)); 1226 len = strlen(option) + strlen(value) + strlen(errstr) + 80; 1227 msg = alloca(len); 1228 1229 (void) snprintf(msg, len, "couldn't set option \"%s\" to \"%s\": %s\n", 1230 option, value, errstr); 1231 1232 if ((rval = dt_handle_liberr(dtp, data, msg)) == 0) 1233 return (0); 1234 1235 return (rval); 1236 } 1237 1238 static int 1239 dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf, 1240 dtrace_consume_probe_f *efunc, dtrace_consume_rec_f *rfunc, void *arg) 1241 { 1242 dtrace_epid_t id; 1243 size_t offs, start = buf->dtbd_oldest, end = buf->dtbd_size; 1244 int flow = (dtp->dt_options[DTRACEOPT_FLOWINDENT] != DTRACEOPT_UNSET); 1245 int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET); 1246 int rval, i, n; 1247 dtrace_epid_t last = DTRACE_EPIDNONE; 1248 dtrace_probedata_t data; 1249 uint64_t drops; 1250 caddr_t addr; 1251 1252 bzero(&data, sizeof (data)); 1253 data.dtpda_handle = dtp; 1254 data.dtpda_cpu = cpu; 1255 1256 again: 1257 for (offs = start; offs < end; ) { 1258 dtrace_eprobedesc_t *epd; 1259 1260 /* 1261 * We're guaranteed to have an ID. 1262 */ 1263 id = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs); 1264 1265 if (id == DTRACE_EPIDNONE) { 1266 /* 1267 * This is filler to assure proper alignment of the 1268 * next record; we simply ignore it. 1269 */ 1270 offs += sizeof (id); 1271 continue; 1272 } 1273 1274 if ((rval = dt_epid_lookup(dtp, id, &data.dtpda_edesc, 1275 &data.dtpda_pdesc)) != 0) 1276 return (rval); 1277 1278 epd = data.dtpda_edesc; 1279 data.dtpda_data = buf->dtbd_data + offs; 1280 1281 if (data.dtpda_edesc->dtepd_uarg != DT_ECB_DEFAULT) { 1282 rval = dt_handle(dtp, &data); 1283 1284 if (rval == DTRACE_CONSUME_NEXT) 1285 goto nextepid; 1286 1287 if (rval == DTRACE_CONSUME_ERROR) 1288 return (-1); 1289 } 1290 1291 if (flow) 1292 (void) dt_flowindent(dtp, &data, last, buf, offs); 1293 1294 rval = (*efunc)(&data, arg); 1295 1296 if (flow) { 1297 if (data.dtpda_flow == DTRACEFLOW_ENTRY) 1298 data.dtpda_indent += 2; 1299 } 1300 1301 if (rval == DTRACE_CONSUME_NEXT) 1302 goto nextepid; 1303 1304 if (rval == DTRACE_CONSUME_ABORT) 1305 return (dt_set_errno(dtp, EDT_DIRABORT)); 1306 1307 if (rval != DTRACE_CONSUME_THIS) 1308 return (dt_set_errno(dtp, EDT_BADRVAL)); 1309 1310 for (i = 0; i < epd->dtepd_nrecs; i++) { 1311 dtrace_recdesc_t *rec = &epd->dtepd_rec[i]; 1312 dtrace_actkind_t act = rec->dtrd_action; 1313 1314 data.dtpda_data = buf->dtbd_data + offs + 1315 rec->dtrd_offset; 1316 addr = data.dtpda_data; 1317 1318 if (act == DTRACEACT_LIBACT) { 1319 uint64_t arg = rec->dtrd_arg; 1320 dtrace_aggvarid_t id; 1321 1322 switch (arg) { 1323 case DT_ACT_CLEAR: 1324 /* LINTED - alignment */ 1325 id = *((dtrace_aggvarid_t *)addr); 1326 (void) dtrace_aggregate_walk(dtp, 1327 dt_clear_agg, &id); 1328 continue; 1329 1330 case DT_ACT_DENORMALIZE: 1331 /* LINTED - alignment */ 1332 id = *((dtrace_aggvarid_t *)addr); 1333 (void) dtrace_aggregate_walk(dtp, 1334 dt_denormalize_agg, &id); 1335 continue; 1336 1337 case DT_ACT_FTRUNCATE: 1338 if (fp == NULL) 1339 continue; 1340 1341 (void) fflush(fp); 1342 (void) ftruncate(fileno(fp), 0); 1343 (void) fseeko(fp, 0, SEEK_SET); 1344 continue; 1345 1346 case DT_ACT_NORMALIZE: 1347 if (i == epd->dtepd_nrecs - 1) 1348 return (dt_set_errno(dtp, 1349 EDT_BADNORMAL)); 1350 1351 if (dt_normalize(dtp, 1352 buf->dtbd_data + offs, rec) != 0) 1353 return (-1); 1354 1355 i++; 1356 continue; 1357 1358 case DT_ACT_SETOPT: { 1359 uint64_t *opts = dtp->dt_options; 1360 dtrace_recdesc_t *valrec; 1361 uint32_t valsize; 1362 caddr_t val; 1363 int rv; 1364 1365 if (i == epd->dtepd_nrecs - 1) { 1366 return (dt_set_errno(dtp, 1367 EDT_BADSETOPT)); 1368 } 1369 1370 valrec = &epd->dtepd_rec[++i]; 1371 valsize = valrec->dtrd_size; 1372 1373 if (valrec->dtrd_action != act || 1374 valrec->dtrd_arg != arg) { 1375 return (dt_set_errno(dtp, 1376 EDT_BADSETOPT)); 1377 } 1378 1379 if (valsize > sizeof (uint64_t)) { 1380 val = buf->dtbd_data + offs + 1381 valrec->dtrd_offset; 1382 } else { 1383 val = "1"; 1384 } 1385 1386 rv = dt_setopt(dtp, &data, addr, val); 1387 1388 if (rv != 0) 1389 return (-1); 1390 1391 flow = (opts[DTRACEOPT_FLOWINDENT] != 1392 DTRACEOPT_UNSET); 1393 quiet = (opts[DTRACEOPT_QUIET] != 1394 DTRACEOPT_UNSET); 1395 1396 continue; 1397 } 1398 1399 case DT_ACT_TRUNC: 1400 if (i == epd->dtepd_nrecs - 1) 1401 return (dt_set_errno(dtp, 1402 EDT_BADTRUNC)); 1403 1404 if (dt_trunc(dtp, 1405 buf->dtbd_data + offs, rec) != 0) 1406 return (-1); 1407 1408 i++; 1409 continue; 1410 1411 default: 1412 continue; 1413 } 1414 } 1415 1416 rval = (*rfunc)(&data, rec, arg); 1417 1418 if (rval == DTRACE_CONSUME_NEXT) 1419 continue; 1420 1421 if (rval == DTRACE_CONSUME_ABORT) 1422 return (dt_set_errno(dtp, EDT_DIRABORT)); 1423 1424 if (rval != DTRACE_CONSUME_THIS) 1425 return (dt_set_errno(dtp, EDT_BADRVAL)); 1426 1427 if (act == DTRACEACT_STACK) { 1428 int depth = rec->dtrd_arg; 1429 1430 if (dt_print_stack(dtp, fp, NULL, addr, depth, 1431 rec->dtrd_size / depth) < 0) 1432 return (-1); 1433 goto nextrec; 1434 } 1435 1436 if (act == DTRACEACT_USTACK || 1437 act == DTRACEACT_JSTACK) { 1438 if (dt_print_ustack(dtp, fp, NULL, 1439 addr, rec->dtrd_arg) < 0) 1440 return (-1); 1441 goto nextrec; 1442 } 1443 1444 if (act == DTRACEACT_SYM) { 1445 if (dt_print_sym(dtp, fp, NULL, addr) < 0) 1446 return (-1); 1447 goto nextrec; 1448 } 1449 1450 if (act == DTRACEACT_MOD) { 1451 if (dt_print_mod(dtp, fp, NULL, addr) < 0) 1452 return (-1); 1453 goto nextrec; 1454 } 1455 1456 if (act == DTRACEACT_USYM || act == DTRACEACT_UADDR) { 1457 if (dt_print_usym(dtp, fp, addr, act) < 0) 1458 return (-1); 1459 goto nextrec; 1460 } 1461 1462 if (act == DTRACEACT_UMOD) { 1463 if (dt_print_umod(dtp, fp, NULL, addr) < 0) 1464 return (-1); 1465 goto nextrec; 1466 } 1467 1468 if (DTRACEACT_ISPRINTFLIKE(act)) { 1469 void *fmtdata; 1470 int (*func)(dtrace_hdl_t *, FILE *, void *, 1471 const dtrace_probedata_t *, 1472 const dtrace_recdesc_t *, uint_t, 1473 const void *buf, size_t); 1474 1475 if ((fmtdata = dt_format_lookup(dtp, 1476 rec->dtrd_format)) == NULL) 1477 goto nofmt; 1478 1479 switch (act) { 1480 case DTRACEACT_PRINTF: 1481 func = dtrace_fprintf; 1482 break; 1483 case DTRACEACT_PRINTA: 1484 func = dtrace_fprinta; 1485 break; 1486 case DTRACEACT_SYSTEM: 1487 func = dtrace_system; 1488 break; 1489 case DTRACEACT_FREOPEN: 1490 func = dtrace_freopen; 1491 break; 1492 } 1493 1494 n = (*func)(dtp, fp, fmtdata, &data, 1495 rec, epd->dtepd_nrecs - i, 1496 (uchar_t *)buf->dtbd_data + offs, 1497 buf->dtbd_size - offs); 1498 1499 if (n < 0) 1500 return (-1); /* errno is set for us */ 1501 1502 if (n > 0) 1503 i += n - 1; 1504 goto nextrec; 1505 } 1506 1507 nofmt: 1508 if (act == DTRACEACT_PRINTA) { 1509 dt_print_aggdata_t pd; 1510 dtrace_aggvarid_t *aggvars; 1511 int j, naggvars = 0; 1512 size_t size = ((epd->dtepd_nrecs - i) * 1513 sizeof (dtrace_aggvarid_t)); 1514 1515 if ((aggvars = dt_alloc(dtp, size)) == NULL) 1516 return (-1); 1517 1518 /* 1519 * This might be a printa() with multiple 1520 * aggregation variables. We need to scan 1521 * forward through the records until we find 1522 * a record from a different statement. 1523 */ 1524 for (j = i; j < epd->dtepd_nrecs; j++) { 1525 dtrace_recdesc_t *nrec; 1526 caddr_t naddr; 1527 1528 nrec = &epd->dtepd_rec[j]; 1529 1530 if (nrec->dtrd_uarg != rec->dtrd_uarg) 1531 break; 1532 1533 if (nrec->dtrd_action != act) { 1534 return (dt_set_errno(dtp, 1535 EDT_BADAGG)); 1536 } 1537 1538 naddr = buf->dtbd_data + offs + 1539 nrec->dtrd_offset; 1540 1541 aggvars[naggvars++] = 1542 /* LINTED - alignment */ 1543 *((dtrace_aggvarid_t *)naddr); 1544 } 1545 1546 i = j - 1; 1547 bzero(&pd, sizeof (pd)); 1548 pd.dtpa_dtp = dtp; 1549 pd.dtpa_fp = fp; 1550 1551 assert(naggvars >= 1); 1552 1553 if (naggvars == 1) { 1554 pd.dtpa_id = aggvars[0]; 1555 dt_free(dtp, aggvars); 1556 1557 if (dt_printf(dtp, fp, "\n") < 0 || 1558 dtrace_aggregate_walk_sorted(dtp, 1559 dt_print_agg, &pd) < 0) 1560 return (-1); 1561 goto nextrec; 1562 } 1563 1564 if (dt_printf(dtp, fp, "\n") < 0 || 1565 dtrace_aggregate_walk_joined(dtp, aggvars, 1566 naggvars, dt_print_aggs, &pd) < 0) { 1567 dt_free(dtp, aggvars); 1568 return (-1); 1569 } 1570 1571 dt_free(dtp, aggvars); 1572 goto nextrec; 1573 } 1574 1575 switch (rec->dtrd_size) { 1576 case sizeof (uint64_t): 1577 n = dt_printf(dtp, fp, 1578 quiet ? "%lld" : " %16lld", 1579 /* LINTED - alignment */ 1580 *((unsigned long long *)addr)); 1581 break; 1582 case sizeof (uint32_t): 1583 n = dt_printf(dtp, fp, quiet ? "%d" : " %8d", 1584 /* LINTED - alignment */ 1585 *((uint32_t *)addr)); 1586 break; 1587 case sizeof (uint16_t): 1588 n = dt_printf(dtp, fp, quiet ? "%d" : " %5d", 1589 /* LINTED - alignment */ 1590 *((uint16_t *)addr)); 1591 break; 1592 case sizeof (uint8_t): 1593 n = dt_printf(dtp, fp, quiet ? "%d" : " %3d", 1594 *((uint8_t *)addr)); 1595 break; 1596 default: 1597 n = dt_print_bytes(dtp, fp, addr, 1598 rec->dtrd_size, 33, quiet); 1599 break; 1600 } 1601 1602 if (n < 0) 1603 return (-1); /* errno is set for us */ 1604 1605 nextrec: 1606 if (dt_buffered_flush(dtp, &data, rec, NULL, 0) < 0) 1607 return (-1); /* errno is set for us */ 1608 } 1609 1610 /* 1611 * Call the record callback with a NULL record to indicate 1612 * that we're done processing this EPID. 1613 */ 1614 rval = (*rfunc)(&data, NULL, arg); 1615 nextepid: 1616 offs += epd->dtepd_size; 1617 last = id; 1618 } 1619 1620 if (buf->dtbd_oldest != 0 && start == buf->dtbd_oldest) { 1621 end = buf->dtbd_oldest; 1622 start = 0; 1623 goto again; 1624 } 1625 1626 if ((drops = buf->dtbd_drops) == 0) 1627 return (0); 1628 1629 /* 1630 * Explicitly zero the drops to prevent us from processing them again. 1631 */ 1632 buf->dtbd_drops = 0; 1633 1634 return (dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops)); 1635 } 1636 1637 typedef struct dt_begin { 1638 dtrace_consume_probe_f *dtbgn_probefunc; 1639 dtrace_consume_rec_f *dtbgn_recfunc; 1640 void *dtbgn_arg; 1641 dtrace_handle_err_f *dtbgn_errhdlr; 1642 void *dtbgn_errarg; 1643 int dtbgn_beginonly; 1644 } dt_begin_t; 1645 1646 static int 1647 dt_consume_begin_probe(const dtrace_probedata_t *data, void *arg) 1648 { 1649 dt_begin_t *begin = (dt_begin_t *)arg; 1650 dtrace_probedesc_t *pd = data->dtpda_pdesc; 1651 1652 int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0); 1653 int r2 = (strcmp(pd->dtpd_name, "BEGIN") == 0); 1654 1655 if (begin->dtbgn_beginonly) { 1656 if (!(r1 && r2)) 1657 return (DTRACE_CONSUME_NEXT); 1658 } else { 1659 if (r1 && r2) 1660 return (DTRACE_CONSUME_NEXT); 1661 } 1662 1663 /* 1664 * We have a record that we're interested in. Now call the underlying 1665 * probe function... 1666 */ 1667 return (begin->dtbgn_probefunc(data, begin->dtbgn_arg)); 1668 } 1669 1670 static int 1671 dt_consume_begin_record(const dtrace_probedata_t *data, 1672 const dtrace_recdesc_t *rec, void *arg) 1673 { 1674 dt_begin_t *begin = (dt_begin_t *)arg; 1675 1676 return (begin->dtbgn_recfunc(data, rec, begin->dtbgn_arg)); 1677 } 1678 1679 static int 1680 dt_consume_begin_error(const dtrace_errdata_t *data, void *arg) 1681 { 1682 dt_begin_t *begin = (dt_begin_t *)arg; 1683 dtrace_probedesc_t *pd = data->dteda_pdesc; 1684 1685 int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0); 1686 int r2 = (strcmp(pd->dtpd_name, "BEGIN") == 0); 1687 1688 if (begin->dtbgn_beginonly) { 1689 if (!(r1 && r2)) 1690 return (DTRACE_HANDLE_OK); 1691 } else { 1692 if (r1 && r2) 1693 return (DTRACE_HANDLE_OK); 1694 } 1695 1696 return (begin->dtbgn_errhdlr(data, begin->dtbgn_errarg)); 1697 } 1698 1699 static int 1700 dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp, dtrace_bufdesc_t *buf, 1701 dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg) 1702 { 1703 /* 1704 * There's this idea that the BEGIN probe should be processed before 1705 * everything else, and that the END probe should be processed after 1706 * anything else. In the common case, this is pretty easy to deal 1707 * with. However, a situation may arise where the BEGIN enabling and 1708 * END enabling are on the same CPU, and some enabling in the middle 1709 * occurred on a different CPU. To deal with this (blech!) we need to 1710 * consume the BEGIN buffer up until the end of the BEGIN probe, and 1711 * then set it aside. We will then process every other CPU, and then 1712 * we'll return to the BEGIN CPU and process the rest of the data 1713 * (which will inevitably include the END probe, if any). Making this 1714 * even more complicated (!) is the library's ERROR enabling. Because 1715 * this enabling is processed before we even get into the consume call 1716 * back, any ERROR firing would result in the library's ERROR enabling 1717 * being processed twice -- once in our first pass (for BEGIN probes), 1718 * and again in our second pass (for everything but BEGIN probes). To 1719 * deal with this, we interpose on the ERROR handler to assure that we 1720 * only process ERROR enablings induced by BEGIN enablings in the 1721 * first pass, and that we only process ERROR enablings _not_ induced 1722 * by BEGIN enablings in the second pass. 1723 */ 1724 dt_begin_t begin; 1725 processorid_t cpu = dtp->dt_beganon; 1726 dtrace_bufdesc_t nbuf; 1727 int rval, i; 1728 static int max_ncpus; 1729 dtrace_optval_t size; 1730 1731 dtp->dt_beganon = -1; 1732 1733 if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) { 1734 /* 1735 * We really don't expect this to fail, but it is at least 1736 * technically possible for this to fail with ENOENT. In this 1737 * case, we just drive on... 1738 */ 1739 if (errno == ENOENT) 1740 return (0); 1741 1742 return (dt_set_errno(dtp, errno)); 1743 } 1744 1745 if (!dtp->dt_stopped || buf->dtbd_cpu != dtp->dt_endedon) { 1746 /* 1747 * This is the simple case. We're either not stopped, or if 1748 * we are, we actually processed any END probes on another 1749 * CPU. We can simply consume this buffer and return. 1750 */ 1751 return (dt_consume_cpu(dtp, fp, cpu, buf, pf, rf, arg)); 1752 } 1753 1754 begin.dtbgn_probefunc = pf; 1755 begin.dtbgn_recfunc = rf; 1756 begin.dtbgn_arg = arg; 1757 begin.dtbgn_beginonly = 1; 1758 1759 /* 1760 * We need to interpose on the ERROR handler to be sure that we 1761 * only process ERRORs induced by BEGIN. 1762 */ 1763 begin.dtbgn_errhdlr = dtp->dt_errhdlr; 1764 begin.dtbgn_errarg = dtp->dt_errarg; 1765 dtp->dt_errhdlr = dt_consume_begin_error; 1766 dtp->dt_errarg = &begin; 1767 1768 rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe, 1769 dt_consume_begin_record, &begin); 1770 1771 dtp->dt_errhdlr = begin.dtbgn_errhdlr; 1772 dtp->dt_errarg = begin.dtbgn_errarg; 1773 1774 if (rval != 0) 1775 return (rval); 1776 1777 /* 1778 * Now allocate a new buffer. We'll use this to deal with every other 1779 * CPU. 1780 */ 1781 bzero(&nbuf, sizeof (dtrace_bufdesc_t)); 1782 (void) dtrace_getopt(dtp, "bufsize", &size); 1783 if ((nbuf.dtbd_data = malloc(size)) == NULL) 1784 return (dt_set_errno(dtp, EDT_NOMEM)); 1785 1786 if (max_ncpus == 0) 1787 max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1; 1788 1789 for (i = 0; i < max_ncpus; i++) { 1790 nbuf.dtbd_cpu = i; 1791 1792 if (i == cpu) 1793 continue; 1794 1795 if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &nbuf) == -1) { 1796 /* 1797 * If we failed with ENOENT, it may be because the 1798 * CPU was unconfigured -- this is okay. Any other 1799 * error, however, is unexpected. 1800 */ 1801 if (errno == ENOENT) 1802 continue; 1803 1804 free(nbuf.dtbd_data); 1805 1806 return (dt_set_errno(dtp, errno)); 1807 } 1808 1809 if ((rval = dt_consume_cpu(dtp, fp, 1810 i, &nbuf, pf, rf, arg)) != 0) { 1811 free(nbuf.dtbd_data); 1812 return (rval); 1813 } 1814 } 1815 1816 free(nbuf.dtbd_data); 1817 1818 /* 1819 * Okay -- we're done with the other buffers. Now we want to 1820 * reconsume the first buffer -- but this time we're looking for 1821 * everything _but_ BEGIN. And of course, in order to only consume 1822 * those ERRORs _not_ associated with BEGIN, we need to reinstall our 1823 * ERROR interposition function... 1824 */ 1825 begin.dtbgn_beginonly = 0; 1826 1827 assert(begin.dtbgn_errhdlr == dtp->dt_errhdlr); 1828 assert(begin.dtbgn_errarg == dtp->dt_errarg); 1829 dtp->dt_errhdlr = dt_consume_begin_error; 1830 dtp->dt_errarg = &begin; 1831 1832 rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe, 1833 dt_consume_begin_record, &begin); 1834 1835 dtp->dt_errhdlr = begin.dtbgn_errhdlr; 1836 dtp->dt_errarg = begin.dtbgn_errarg; 1837 1838 return (rval); 1839 } 1840 1841 int 1842 dtrace_consume(dtrace_hdl_t *dtp, FILE *fp, 1843 dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg) 1844 { 1845 dtrace_bufdesc_t *buf = &dtp->dt_buf; 1846 dtrace_optval_t size; 1847 static int max_ncpus; 1848 int i, rval; 1849 dtrace_optval_t interval = dtp->dt_options[DTRACEOPT_SWITCHRATE]; 1850 hrtime_t now = gethrtime(); 1851 1852 if (dtp->dt_lastswitch != 0) { 1853 if (now - dtp->dt_lastswitch < interval) 1854 return (0); 1855 1856 dtp->dt_lastswitch += interval; 1857 } else { 1858 dtp->dt_lastswitch = now; 1859 } 1860 1861 if (!dtp->dt_active) 1862 return (dt_set_errno(dtp, EINVAL)); 1863 1864 if (max_ncpus == 0) 1865 max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1; 1866 1867 if (pf == NULL) 1868 pf = (dtrace_consume_probe_f *)dt_nullprobe; 1869 1870 if (rf == NULL) 1871 rf = (dtrace_consume_rec_f *)dt_nullrec; 1872 1873 if (buf->dtbd_data == NULL) { 1874 (void) dtrace_getopt(dtp, "bufsize", &size); 1875 if ((buf->dtbd_data = malloc(size)) == NULL) 1876 return (dt_set_errno(dtp, EDT_NOMEM)); 1877 1878 buf->dtbd_size = size; 1879 } 1880 1881 /* 1882 * If we have just begun, we want to first process the CPU that 1883 * executed the BEGIN probe (if any). 1884 */ 1885 if (dtp->dt_active && dtp->dt_beganon != -1) { 1886 buf->dtbd_cpu = dtp->dt_beganon; 1887 if ((rval = dt_consume_begin(dtp, fp, buf, pf, rf, arg)) != 0) 1888 return (rval); 1889 } 1890 1891 for (i = 0; i < max_ncpus; i++) { 1892 buf->dtbd_cpu = i; 1893 1894 /* 1895 * If we have stopped, we want to process the CPU on which the 1896 * END probe was processed only _after_ we have processed 1897 * everything else. 1898 */ 1899 if (dtp->dt_stopped && (i == dtp->dt_endedon)) 1900 continue; 1901 1902 if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) { 1903 /* 1904 * If we failed with ENOENT, it may be because the 1905 * CPU was unconfigured -- this is okay. Any other 1906 * error, however, is unexpected. 1907 */ 1908 if (errno == ENOENT) 1909 continue; 1910 1911 return (dt_set_errno(dtp, errno)); 1912 } 1913 1914 if ((rval = dt_consume_cpu(dtp, fp, i, buf, pf, rf, arg)) != 0) 1915 return (rval); 1916 } 1917 1918 if (!dtp->dt_stopped) 1919 return (0); 1920 1921 buf->dtbd_cpu = dtp->dt_endedon; 1922 1923 if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) { 1924 /* 1925 * This _really_ shouldn't fail, but it is strictly speaking 1926 * possible for this to return ENOENT if the CPU that called 1927 * the END enabling somehow managed to become unconfigured. 1928 * It's unclear how the user can possibly expect anything 1929 * rational to happen in this case -- the state has been thrown 1930 * out along with the unconfigured CPU -- so we'll just drive 1931 * on... 1932 */ 1933 if (errno == ENOENT) 1934 return (0); 1935 1936 return (dt_set_errno(dtp, errno)); 1937 } 1938 1939 return (dt_consume_cpu(dtp, fp, dtp->dt_endedon, buf, pf, rf, arg)); 1940 } 1941