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 38 #include <dt_impl.h> 39 40 static int 41 dt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last, 42 dtrace_bufdesc_t *buf, size_t offs) 43 { 44 dtrace_probedesc_t *pd = data->dtpda_pdesc, *npd; 45 dtrace_eprobedesc_t *epd = data->dtpda_edesc, *nepd; 46 char *p = pd->dtpd_provider, *n = pd->dtpd_name; 47 dtrace_flowkind_t flow = DTRACEFLOW_NONE; 48 const char *str = NULL; 49 static const char *e_str[2] = { " -> ", " => " }; 50 static const char *r_str[2] = { " <- ", " <= " }; 51 dtrace_epid_t next, id = epd->dtepd_epid; 52 int rval; 53 54 if (strcmp(n, "entry") == 0) { 55 flow = DTRACEFLOW_ENTRY; 56 str = e_str[strcmp(p, "syscall") == 0]; 57 } else if (strcmp(n, "return") == 0 || 58 strcmp(n, "exit") == 0) { 59 flow = DTRACEFLOW_RETURN; 60 str = r_str[strcmp(p, "syscall") == 0]; 61 } 62 63 /* 64 * If we're going to indent this, we need to check the ID of our last 65 * call. If we're looking at the same probe ID but a different EPID, 66 * we _don't_ want to indent. (Yes, there are some minor holes in 67 * this scheme -- it's a heuristic.) 68 */ 69 if (flow == DTRACEFLOW_ENTRY) { 70 if ((last != DTRACE_EPIDNONE && id != last && 71 pd->dtpd_id == dtp->dt_pdesc[last]->dtpd_id)) 72 flow = DTRACEFLOW_NONE; 73 } 74 75 /* 76 * If we're going to unindent this, it's more difficult to see if 77 * we don't actually want to unindent it -- we need to look at the 78 * _next_ EPID. 79 */ 80 if (flow == DTRACEFLOW_RETURN) { 81 offs += epd->dtepd_size; 82 83 do { 84 if (offs >= buf->dtbd_size) { 85 /* 86 * We're at the end -- maybe. If the oldest 87 * record is non-zero, we need to wrap. 88 */ 89 if (buf->dtbd_oldest != 0) { 90 offs = 0; 91 } else { 92 goto out; 93 } 94 } 95 96 next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs); 97 98 if (next == DTRACE_EPIDNONE) 99 offs += sizeof (id); 100 } while (next == DTRACE_EPIDNONE); 101 102 if ((rval = dt_epid_lookup(dtp, next, &nepd, &npd)) != 0) 103 return (rval); 104 105 if (next != id && npd->dtpd_id == pd->dtpd_id) 106 flow = DTRACEFLOW_NONE; 107 } 108 109 out: 110 if (flow == DTRACEFLOW_ENTRY || flow == DTRACEFLOW_RETURN) { 111 data->dtpda_prefix = str; 112 } else { 113 data->dtpda_prefix = "| "; 114 } 115 116 if (flow == DTRACEFLOW_RETURN && data->dtpda_indent > 0) 117 data->dtpda_indent -= 2; 118 119 data->dtpda_flow = flow; 120 121 return (0); 122 } 123 124 static int 125 dt_nullprobe() 126 { 127 return (DTRACE_CONSUME_THIS); 128 } 129 130 static int 131 dt_nullrec() 132 { 133 return (DTRACE_CONSUME_NEXT); 134 } 135 136 int 137 dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, 138 size_t size, uint64_t normal) 139 { 140 const uint64_t *data = addr; 141 int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1; 142 uint64_t total_bin_count = 0; 143 144 if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t)) 145 return (dt_set_errno(dtp, EDT_DMISMATCH)); 146 147 while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0) 148 first_bin++; 149 150 if (first_bin > 0) 151 first_bin--; 152 153 while (last_bin > 0 && data[last_bin] == 0) 154 last_bin--; 155 156 if (last_bin < DTRACE_QUANTIZE_NBUCKETS - 1) 157 last_bin++; 158 159 for (i = first_bin; i <= last_bin; i++) 160 total_bin_count += data[i]; 161 162 if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value", 163 "------------- Distribution -------------", "count") < 0) 164 return (-1); 165 166 for (i = first_bin; i <= last_bin; i++) { 167 float f = ((float)data[i] * 40.0) / (float)total_bin_count; 168 uint_t depth = (uint_t)(f + 0.5); 169 170 if (dt_printf(dtp, fp, "%16lld |%s%s %-9llu\n", 171 (long long)DTRACE_QUANTIZE_BUCKETVAL(i), 172 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" + 40 - depth, 173 " " + depth, 174 (u_longlong_t)data[i] / normal) < 0) 175 return (-1); 176 } 177 178 return (0); 179 } 180 181 int 182 dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, 183 size_t size, uint64_t normal) 184 { 185 const uint64_t *data = addr; 186 int i, first_bin, last_bin, base; 187 uint64_t arg, total_bin_count = 0; 188 uint16_t step, levels; 189 190 if (size < sizeof (uint64_t)) 191 return (dt_set_errno(dtp, EDT_DMISMATCH)); 192 193 arg = *data++; 194 size -= sizeof (uint64_t); 195 196 base = DTRACE_LQUANTIZE_BASE(arg); 197 step = DTRACE_LQUANTIZE_STEP(arg); 198 levels = DTRACE_LQUANTIZE_LEVELS(arg); 199 200 first_bin = 0; 201 last_bin = levels + 1; 202 203 if (size != sizeof (uint64_t) * (levels + 2)) 204 return (dt_set_errno(dtp, EDT_DMISMATCH)); 205 206 while (first_bin < levels + 1 && data[first_bin] == 0) 207 first_bin++; 208 209 if (first_bin > 0) 210 first_bin--; 211 212 while (last_bin > 0 && data[last_bin] == 0) 213 last_bin--; 214 215 if (last_bin < levels + 1) 216 last_bin++; 217 218 for (i = first_bin; i <= last_bin; i++) 219 total_bin_count += data[i]; 220 221 if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value", 222 "------------- Distribution -------------", "count") < 0) 223 return (-1); 224 225 for (i = first_bin; i <= last_bin; i++) { 226 float f = ((float)data[i] * 40.0) / (float)total_bin_count; 227 uint_t depth = (uint_t)(f + 0.5); 228 char c[32]; 229 int err; 230 231 if (i == 0) { 232 (void) snprintf(c, sizeof (c), "< %d", 233 base / (uint32_t)normal); 234 err = dt_printf(dtp, fp, "%16s ", c); 235 } else if (i == levels + 1) { 236 (void) snprintf(c, sizeof (c), ">= %d", 237 base + (levels * step)); 238 err = dt_printf(dtp, fp, "%16s ", c); 239 } else { 240 err = dt_printf(dtp, fp, "%16d ", 241 base + (i - 1) * step); 242 } 243 244 if (err < 0 || dt_printf(dtp, fp, "|%s%s %-9llu\n", 245 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" + 40 - depth, 246 " " + depth, 247 (u_longlong_t)data[i] / normal) < 0) 248 return (-1); 249 } 250 251 return (0); 252 } 253 254 /*ARGSUSED*/ 255 static int 256 dt_print_average(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, 257 size_t size, uint64_t normal) 258 { 259 /* LINTED - alignment */ 260 uint64_t *data = (uint64_t *)addr; 261 262 return (dt_printf(dtp, fp, " %16lld", data[0] ? 263 (long long)(data[1] / normal / data[0]) : 0)); 264 } 265 266 /*ARGSUSED*/ 267 int 268 dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, 269 size_t nbytes, int width, int quiet) 270 { 271 /* 272 * If the byte stream is a series of printable characters, followed by 273 * a terminating byte, we print it out as a string. Otherwise, we 274 * assume that it's something else and just print the bytes. 275 */ 276 int i, j, margin = 5; 277 char *c = (char *)addr; 278 279 if (nbytes == 0) 280 return (0); 281 282 if (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET) 283 goto raw; 284 285 for (i = 0; i < nbytes; i++) { 286 /* 287 * We define a "printable character" to be one for which 288 * isprint(3C) returns non-zero, isspace(3C) returns non-zero, 289 * or a character which is either backspace or the bell. 290 * Backspace and the bell are regrettably special because 291 * they fail the first two tests -- and yet they are entirely 292 * printable. These are the only two control characters that 293 * have meaning for the terminal and for which isprint(3C) and 294 * isspace(3C) return 0. 295 */ 296 if (isprint(c[i]) || isspace(c[i]) || 297 c[i] == '\b' || c[i] == '\a') 298 continue; 299 300 if (c[i] == '\0' && i > 0) { 301 /* 302 * This looks like it might be a string. Before we 303 * assume that it is indeed a string, check the 304 * remainder of the byte range; if it contains 305 * additional non-nul characters, we'll assume that 306 * it's a binary stream that just happens to look like 307 * a string, and we'll print out the individual bytes. 308 */ 309 for (j = i + 1; j < nbytes; j++) { 310 if (c[j] != '\0') 311 break; 312 } 313 314 if (j != nbytes) 315 break; 316 317 if (quiet) 318 return (dt_printf(dtp, fp, "%s", c)); 319 else 320 return (dt_printf(dtp, fp, " %-*s", width, c)); 321 } 322 323 break; 324 } 325 326 if (i == nbytes) { 327 /* 328 * The byte range is all printable characters, but there is 329 * no trailing nul byte. We'll assume that it's a string and 330 * print it as such. 331 */ 332 char *s = alloca(nbytes + 1); 333 bcopy(c, s, nbytes); 334 s[nbytes] = '\0'; 335 return (dt_printf(dtp, fp, " %-*s", width, s)); 336 } 337 338 raw: 339 if (dt_printf(dtp, fp, "\n%*s ", margin, "") < 0) 340 return (-1); 341 342 for (i = 0; i < 16; i++) 343 if (dt_printf(dtp, fp, " %c", "0123456789abcdef"[i]) < 0) 344 return (-1); 345 346 if (dt_printf(dtp, fp, " 0123456789abcdef\n") < 0) 347 return (-1); 348 349 350 for (i = 0; i < nbytes; i += 16) { 351 if (dt_printf(dtp, fp, "%*s%5x:", margin, "", i) < 0) 352 return (-1); 353 354 for (j = i; j < i + 16 && j < nbytes; j++) { 355 if (dt_printf(dtp, fp, " %02x", (uchar_t)c[j]) < 0) 356 return (-1); 357 } 358 359 while (j++ % 16) { 360 if (dt_printf(dtp, fp, " ") < 0) 361 return (-1); 362 } 363 364 if (dt_printf(dtp, fp, " ") < 0) 365 return (-1); 366 367 for (j = i; j < i + 16 && j < nbytes; j++) { 368 if (dt_printf(dtp, fp, "%c", 369 c[j] < ' ' || c[j] > '~' ? '.' : c[j]) < 0) 370 return (-1); 371 } 372 373 if (dt_printf(dtp, fp, "\n") < 0) 374 return (-1); 375 } 376 377 return (0); 378 } 379 380 int 381 dt_print_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format, 382 caddr_t addr, int depth) 383 { 384 pc_t *pc = (pc_t *)(uintptr_t)addr; 385 dtrace_syminfo_t dts; 386 GElf_Sym sym; 387 int i, indent; 388 char c[PATH_MAX * 2]; 389 390 if (dt_printf(dtp, fp, "\n") < 0) 391 return (-1); 392 393 if (format == NULL) 394 format = "%s"; 395 396 if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET) 397 indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT]; 398 else 399 indent = _dtrace_stkindent; 400 401 for (i = 0; i < depth && pc[i] != NULL; i++) { 402 if (dt_printf(dtp, fp, "%*s", indent, "") < 0) 403 return (-1); 404 405 if (dtrace_lookup_by_addr(dtp, pc[i], &sym, &dts) == 0) { 406 if (pc[i] > sym.st_value) { 407 (void) snprintf(c, sizeof (c), "%s`%s+0x%llx", 408 dts.dts_object, dts.dts_name, 409 (u_longlong_t)pc[i] - sym.st_value); 410 } else { 411 (void) snprintf(c, sizeof (c), "%s`%s", 412 dts.dts_object, dts.dts_name); 413 } 414 } else { 415 /* 416 * We'll repeat the lookup, but this time we'll specify 417 * a NULL GElf_Sym -- indicating that we're only 418 * interested in the containing module. 419 */ 420 if (dtrace_lookup_by_addr(dtp, pc[i], 421 NULL, &dts) == 0) { 422 (void) snprintf(c, sizeof (c), "%s`0x%llx", 423 dts.dts_object, (u_longlong_t)pc[i]); 424 } else { 425 (void) snprintf(c, sizeof (c), "0x%llx", 426 (u_longlong_t)pc[i]); 427 } 428 } 429 430 if (dt_printf(dtp, fp, format, c) < 0) 431 return (-1); 432 433 if (dt_printf(dtp, fp, "\n") < 0) 434 return (-1); 435 } 436 437 return (0); 438 } 439 440 int 441 dt_print_ustack(dtrace_hdl_t *dtp, FILE *fp, const char *format, 442 caddr_t addr, uint64_t arg) 443 { 444 uint64_t *pc = (uint64_t *)(uintptr_t)addr; 445 uint32_t depth = DTRACE_USTACK_NFRAMES(arg); 446 uint32_t strsize = DTRACE_USTACK_STRSIZE(arg); 447 const char *strbase = addr + (depth + 1) * sizeof (uint64_t); 448 const char *str = strsize ? strbase : NULL; 449 int err = 0; 450 451 char name[PATH_MAX], objname[PATH_MAX], c[PATH_MAX * 2]; 452 struct ps_prochandle *P; 453 GElf_Sym sym; 454 int i, indent; 455 pid_t pid; 456 457 if (depth == 0) 458 return (0); 459 460 pid = (pid_t)*pc++; 461 462 if (dt_printf(dtp, fp, "\n") < 0) 463 return (-1); 464 465 if (format == NULL) 466 format = "%s"; 467 468 if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET) 469 indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT]; 470 else 471 indent = _dtrace_stkindent; 472 473 /* 474 * Ultimately, we need to add an entry point in the library vector for 475 * determining <symbol, offset> from <pid, address>. For now, if 476 * this is a vector open, we just print the raw address or string. 477 */ 478 if (dtp->dt_vector == NULL) 479 P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0); 480 else 481 P = NULL; 482 483 if (P != NULL) 484 dt_proc_lock(dtp, P); /* lock handle while we perform lookups */ 485 486 for (i = 0; i < depth && pc[i] != NULL; i++) { 487 if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0) 488 break; 489 490 if (P != NULL && Plookup_by_addr(P, pc[i], 491 name, sizeof (name), &sym) == 0) { 492 (void) Pobjname(P, pc[i], objname, sizeof (objname)); 493 494 if (pc[i] > sym.st_value) { 495 (void) snprintf(c, sizeof (c), 496 "%s`%s+0x%llx", dt_basename(objname), name, 497 (u_longlong_t)(pc[i] - sym.st_value)); 498 } else { 499 (void) snprintf(c, sizeof (c), 500 "%s`%s", dt_basename(objname), name); 501 } 502 } else if (str != NULL && str[0] != '\0') { 503 (void) snprintf(c, sizeof (c), "%s", str); 504 } else { 505 if (P != NULL && Pobjname(P, pc[i], objname, 506 sizeof (objname)) != NULL) { 507 (void) snprintf(c, sizeof (c), "%s`0x%llx", 508 dt_basename(objname), (u_longlong_t)pc[i]); 509 } else { 510 (void) snprintf(c, sizeof (c), "0x%llx", 511 (u_longlong_t)pc[i]); 512 } 513 } 514 515 if ((err = dt_printf(dtp, fp, format, c)) < 0) 516 break; 517 518 if ((err = dt_printf(dtp, fp, "\n")) < 0) 519 break; 520 521 if (str != NULL) { 522 str += strlen(str) + 1; 523 if (str - strbase >= strsize) 524 str = NULL; 525 } 526 } 527 528 if (P != NULL) { 529 dt_proc_unlock(dtp, P); 530 dt_proc_release(dtp, P); 531 } 532 533 return (err); 534 } 535 536 typedef struct dt_normal { 537 dtrace_aggvarid_t dtnd_id; 538 uint64_t dtnd_normal; 539 } dt_normal_t; 540 541 static int 542 dt_normalize_agg(dtrace_aggdata_t *aggdata, void *arg) 543 { 544 dt_normal_t *normal = arg; 545 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 546 dtrace_aggvarid_t id = normal->dtnd_id; 547 uintptr_t data = (uintptr_t)aggdata->dtada_data; 548 549 if (agg->dtagd_nrecs == 0) 550 return (DTRACE_AGGWALK_NEXT); 551 552 if (id != *(dtrace_aggvarid_t *)(data + agg->dtagd_rec[0].dtrd_offset)) 553 return (DTRACE_AGGWALK_NEXT); 554 555 aggdata->dtada_normal = normal->dtnd_normal; 556 return (DTRACE_AGGWALK_NORMALIZE); 557 } 558 559 static int 560 dt_normalize(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec) 561 { 562 dt_normal_t normal; 563 caddr_t addr; 564 565 /* 566 * We (should) have two records: the aggregation ID followed by the 567 * normalization value. 568 */ 569 addr = base + rec->dtrd_offset; 570 571 if (rec->dtrd_size != sizeof (dtrace_aggvarid_t)) 572 return (dt_set_errno(dtp, EDT_BADNORMAL)); 573 574 /* LINTED - alignment */ 575 normal.dtnd_id = *((dtrace_aggvarid_t *)addr); 576 rec++; 577 578 if (rec->dtrd_action != DTRACEACT_LIBACT) 579 return (dt_set_errno(dtp, EDT_BADNORMAL)); 580 581 if (rec->dtrd_arg != DT_ACT_NORMALIZE) 582 return (dt_set_errno(dtp, EDT_BADNORMAL)); 583 584 addr = base + rec->dtrd_offset; 585 586 switch (rec->dtrd_size) { 587 case sizeof (uint64_t): 588 /* LINTED - alignment */ 589 normal.dtnd_normal = *((uint64_t *)addr); 590 break; 591 case sizeof (uint32_t): 592 /* LINTED - alignment */ 593 normal.dtnd_normal = *((uint32_t *)addr); 594 break; 595 case sizeof (uint16_t): 596 /* LINTED - alignment */ 597 normal.dtnd_normal = *((uint16_t *)addr); 598 break; 599 case sizeof (uint8_t): 600 normal.dtnd_normal = *((uint8_t *)addr); 601 break; 602 default: 603 return (dt_set_errno(dtp, EDT_BADNORMAL)); 604 } 605 606 (void) dtrace_aggregate_walk(dtp, dt_normalize_agg, &normal); 607 608 return (0); 609 } 610 611 static int 612 dt_denormalize_agg(dtrace_aggdata_t *aggdata, void *arg) 613 { 614 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 615 dtrace_aggvarid_t id = *((dtrace_aggvarid_t *)arg); 616 uintptr_t data = (uintptr_t)aggdata->dtada_data; 617 618 if (agg->dtagd_nrecs == 0) 619 return (DTRACE_AGGWALK_NEXT); 620 621 if (id != *(dtrace_aggvarid_t *)(data + agg->dtagd_rec[0].dtrd_offset)) 622 return (DTRACE_AGGWALK_NEXT); 623 624 return (DTRACE_AGGWALK_DENORMALIZE); 625 } 626 627 static int 628 dt_clear_agg(dtrace_aggdata_t *aggdata, void *arg) 629 { 630 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 631 dtrace_aggvarid_t id = *((dtrace_aggvarid_t *)arg); 632 uintptr_t data = (uintptr_t)aggdata->dtada_data; 633 634 if (agg->dtagd_nrecs == 0) 635 return (DTRACE_AGGWALK_NEXT); 636 637 if (id != *(dtrace_aggvarid_t *)(data + agg->dtagd_rec[0].dtrd_offset)) 638 return (DTRACE_AGGWALK_NEXT); 639 640 return (DTRACE_AGGWALK_CLEAR); 641 } 642 643 typedef struct dt_trunc { 644 dtrace_aggvarid_t dttd_id; 645 uint64_t dttd_remaining; 646 } dt_trunc_t; 647 648 static int 649 dt_trunc_agg(dtrace_aggdata_t *aggdata, void *arg) 650 { 651 dt_trunc_t *trunc = arg; 652 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 653 dtrace_aggvarid_t id = trunc->dttd_id; 654 uintptr_t data = (uintptr_t)aggdata->dtada_data; 655 656 if (agg->dtagd_nrecs == 0) 657 return (DTRACE_AGGWALK_NEXT); 658 659 if (id != *(dtrace_aggvarid_t *)(data + agg->dtagd_rec[0].dtrd_offset)) 660 return (DTRACE_AGGWALK_NEXT); 661 662 if (trunc->dttd_remaining == 0) 663 return (DTRACE_AGGWALK_REMOVE); 664 665 trunc->dttd_remaining--; 666 return (DTRACE_AGGWALK_NEXT); 667 } 668 669 static int 670 dt_trunc(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec) 671 { 672 dt_trunc_t trunc; 673 caddr_t addr; 674 int64_t remaining; 675 int (*func)(dtrace_hdl_t *, dtrace_aggregate_f *, void *); 676 677 /* 678 * We (should) have two records: the aggregation ID followed by the 679 * number of aggregation entries after which the aggregation is to be 680 * truncated. 681 */ 682 addr = base + rec->dtrd_offset; 683 684 if (rec->dtrd_size != sizeof (dtrace_aggvarid_t)) 685 return (dt_set_errno(dtp, EDT_BADTRUNC)); 686 687 /* LINTED - alignment */ 688 trunc.dttd_id = *((dtrace_aggvarid_t *)addr); 689 rec++; 690 691 if (rec->dtrd_action != DTRACEACT_LIBACT) 692 return (dt_set_errno(dtp, EDT_BADTRUNC)); 693 694 if (rec->dtrd_arg != DT_ACT_TRUNC) 695 return (dt_set_errno(dtp, EDT_BADTRUNC)); 696 697 addr = base + rec->dtrd_offset; 698 699 switch (rec->dtrd_size) { 700 case sizeof (uint64_t): 701 /* LINTED - alignment */ 702 remaining = *((int64_t *)addr); 703 break; 704 case sizeof (uint32_t): 705 /* LINTED - alignment */ 706 remaining = *((int32_t *)addr); 707 break; 708 case sizeof (uint16_t): 709 /* LINTED - alignment */ 710 remaining = *((int16_t *)addr); 711 break; 712 case sizeof (uint8_t): 713 remaining = *((int8_t *)addr); 714 break; 715 default: 716 return (dt_set_errno(dtp, EDT_BADNORMAL)); 717 } 718 719 if (remaining < 0) { 720 func = dtrace_aggregate_walk_valsorted; 721 remaining = -remaining; 722 } else { 723 func = dtrace_aggregate_walk_valrevsorted; 724 } 725 726 assert(remaining >= 0); 727 trunc.dttd_remaining = remaining; 728 729 (void) func(dtp, dt_trunc_agg, &trunc); 730 731 return (0); 732 } 733 734 int 735 dt_print_agg(dtrace_aggdata_t *aggdata, void *arg) 736 { 737 int i, err = 0; 738 dt_print_aggdata_t *pd = arg; 739 dtrace_aggdesc_t *agg = aggdata->dtada_desc; 740 FILE *fp = pd->dtpa_fp; 741 dtrace_hdl_t *dtp = pd->dtpa_dtp; 742 dtrace_aggvarid_t aggvarid = pd->dtpa_id; 743 uintptr_t data = (uintptr_t)aggdata->dtada_data; 744 745 if (pd->dtpa_allunprint) { 746 if (agg->dtagd_flags & DTRACE_AGD_PRINTED) 747 return (0); 748 } else { 749 /* 750 * If we're not printing all unprinted aggregations, then the 751 * aggregation variable ID denotes a specific aggregation 752 * variable that we should print -- skip any other aggregations 753 * that we encounter. 754 */ 755 if (agg->dtagd_nrecs == 0) 756 return (0); 757 758 if (aggvarid != *(dtrace_aggvarid_t *)(data + 759 agg->dtagd_rec[0].dtrd_offset)) 760 return (0); 761 } 762 763 /* 764 * Iterate over each record description, printing the traced data, 765 * skipping the first datum (the tuple member created by the compiler). 766 */ 767 for (i = 1; err >= 0 && i < agg->dtagd_nrecs; i++) { 768 dtrace_recdesc_t *rec = &agg->dtagd_rec[i]; 769 dtrace_actkind_t act = rec->dtrd_action; 770 caddr_t addr = aggdata->dtada_data + rec->dtrd_offset; 771 size_t size = rec->dtrd_size; 772 uint64_t normal; 773 774 normal = DTRACEACT_ISAGG(act) ? aggdata->dtada_normal : 1; 775 776 if (act == DTRACEACT_STACK) { 777 int depth = rec->dtrd_size / sizeof (pc_t); 778 err = dt_print_stack(dtp, fp, NULL, addr, depth); 779 goto nextrec; 780 } 781 782 if (act == DTRACEACT_USTACK || act == DTRACEACT_JSTACK) { 783 err = dt_print_ustack(dtp, fp, NULL, addr, 784 rec->dtrd_arg); 785 goto nextrec; 786 } 787 788 if (act == DTRACEAGG_QUANTIZE) { 789 err = dt_print_quantize(dtp, fp, addr, size, normal); 790 goto nextrec; 791 } 792 793 if (act == DTRACEAGG_LQUANTIZE) { 794 err = dt_print_lquantize(dtp, fp, addr, size, normal); 795 goto nextrec; 796 } 797 798 if (act == DTRACEAGG_AVG) { 799 err = dt_print_average(dtp, fp, addr, size, normal); 800 goto nextrec; 801 } 802 803 switch (size) { 804 case sizeof (uint64_t): 805 err = dt_printf(dtp, fp, " %16lld", 806 /* LINTED - alignment */ 807 (long long)*((uint64_t *)addr) / normal); 808 break; 809 case sizeof (uint32_t): 810 /* LINTED - alignment */ 811 err = dt_printf(dtp, fp, " %8d", *((uint32_t *)addr) / 812 (uint32_t)normal); 813 break; 814 case sizeof (uint16_t): 815 /* LINTED - alignment */ 816 err = dt_printf(dtp, fp, " %5d", *((uint16_t *)addr) / 817 (uint32_t)normal); 818 break; 819 case sizeof (uint8_t): 820 err = dt_printf(dtp, fp, " %3d", *((uint8_t *)addr) / 821 (uint32_t)normal); 822 break; 823 default: 824 err = dt_print_bytes(dtp, fp, addr, size, 50, 0); 825 break; 826 } 827 828 nextrec: 829 if (dt_buffered_flush(dtp, NULL, rec, aggdata) < 0) 830 return (-1); 831 } 832 833 if (err >= 0) 834 err = dt_printf(dtp, fp, "\n"); 835 836 if (dt_buffered_flush(dtp, NULL, NULL, aggdata) < 0) 837 return (-1); 838 839 if (!pd->dtpa_allunprint) 840 agg->dtagd_flags |= DTRACE_AGD_PRINTED; 841 842 return (err < 0 ? -1 : 0); 843 } 844 845 static int 846 dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf, 847 dtrace_consume_probe_f *efunc, dtrace_consume_rec_f *rfunc, void *arg) 848 { 849 dtrace_epid_t id; 850 size_t offs, start = buf->dtbd_oldest, end = buf->dtbd_size; 851 int flow = (dtp->dt_options[DTRACEOPT_FLOWINDENT] != DTRACEOPT_UNSET); 852 int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET); 853 int rval, i, n; 854 dtrace_epid_t last = DTRACE_EPIDNONE; 855 dtrace_probedata_t data; 856 uint64_t drops; 857 caddr_t addr; 858 859 bzero(&data, sizeof (data)); 860 data.dtpda_handle = dtp; 861 data.dtpda_cpu = cpu; 862 863 again: 864 for (offs = start; offs < end; ) { 865 dtrace_eprobedesc_t *epd; 866 867 /* 868 * We're guaranteed to have an ID. 869 */ 870 id = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs); 871 872 if (id == DTRACE_EPIDNONE) { 873 /* 874 * This is filler to assure proper alignment of the 875 * next record; we simply ignore it. 876 */ 877 offs += sizeof (id); 878 continue; 879 } 880 881 if ((rval = dt_epid_lookup(dtp, id, &data.dtpda_edesc, 882 &data.dtpda_pdesc)) != 0) 883 return (rval); 884 885 epd = data.dtpda_edesc; 886 data.dtpda_data = buf->dtbd_data + offs; 887 888 if (data.dtpda_edesc->dtepd_uarg != DT_ECB_DEFAULT) { 889 rval = dt_handle(dtp, &data); 890 891 if (rval == DTRACE_CONSUME_NEXT) 892 goto nextepid; 893 894 if (rval == DTRACE_CONSUME_ERROR) 895 return (-1); 896 } 897 898 if (flow) 899 (void) dt_flowindent(dtp, &data, last, buf, offs); 900 901 rval = (*efunc)(&data, arg); 902 903 if (flow) { 904 if (data.dtpda_flow == DTRACEFLOW_ENTRY) 905 data.dtpda_indent += 2; 906 } 907 908 if (rval == DTRACE_CONSUME_NEXT) 909 goto nextepid; 910 911 if (rval == DTRACE_CONSUME_ABORT) 912 return (dt_set_errno(dtp, EDT_DIRABORT)); 913 914 if (rval != DTRACE_CONSUME_THIS) 915 return (dt_set_errno(dtp, EDT_BADRVAL)); 916 917 for (i = 0; i < epd->dtepd_nrecs; i++) { 918 dtrace_recdesc_t *rec = &epd->dtepd_rec[i]; 919 dtrace_actkind_t act = rec->dtrd_action; 920 921 data.dtpda_data = buf->dtbd_data + offs + 922 rec->dtrd_offset; 923 addr = data.dtpda_data; 924 925 if (act == DTRACEACT_LIBACT) { 926 if (rec->dtrd_arg == DT_ACT_CLEAR) { 927 dtrace_aggvarid_t id; 928 929 /* LINTED - alignment */ 930 id = *((dtrace_aggvarid_t *)addr); 931 (void) dtrace_aggregate_walk(dtp, 932 dt_clear_agg, &id); 933 continue; 934 } 935 936 if (rec->dtrd_arg == DT_ACT_DENORMALIZE) { 937 dtrace_aggvarid_t id; 938 939 /* LINTED - alignment */ 940 id = *((dtrace_aggvarid_t *)addr); 941 (void) dtrace_aggregate_walk(dtp, 942 dt_denormalize_agg, &id); 943 continue; 944 } 945 946 if (rec->dtrd_arg == DT_ACT_NORMALIZE) { 947 if (i == epd->dtepd_nrecs - 1) 948 return (dt_set_errno(dtp, 949 EDT_BADNORMAL)); 950 951 if (dt_normalize(dtp, 952 buf->dtbd_data + offs, rec) != 0) 953 return (-1); 954 955 i++; 956 continue; 957 } 958 959 if (rec->dtrd_arg == DT_ACT_TRUNC) { 960 if (i == epd->dtepd_nrecs - 1) 961 return (dt_set_errno(dtp, 962 EDT_BADTRUNC)); 963 964 if (dt_trunc(dtp, 965 buf->dtbd_data + offs, rec) != 0) 966 return (-1); 967 968 i++; 969 continue; 970 } 971 972 if (rec->dtrd_arg == DT_ACT_FTRUNCATE) { 973 if (fp == NULL) 974 continue; 975 976 (void) fflush(fp); 977 (void) ftruncate(fileno(fp), 0); 978 (void) fseeko(fp, 0, SEEK_SET); 979 continue; 980 } 981 } 982 983 rval = (*rfunc)(&data, rec, arg); 984 985 if (rval == DTRACE_CONSUME_NEXT) 986 continue; 987 988 if (rval == DTRACE_CONSUME_ABORT) 989 return (dt_set_errno(dtp, EDT_DIRABORT)); 990 991 if (rval != DTRACE_CONSUME_THIS) 992 return (dt_set_errno(dtp, EDT_BADRVAL)); 993 994 if (act == DTRACEACT_STACK) { 995 int depth = rec->dtrd_size / sizeof (pc_t); 996 if (dt_print_stack(dtp, fp, NULL, 997 addr, depth) < 0) 998 return (-1); 999 goto nextrec; 1000 } 1001 1002 if (act == DTRACEACT_USTACK || 1003 act == DTRACEACT_JSTACK) { 1004 if (dt_print_ustack(dtp, fp, NULL, 1005 addr, rec->dtrd_arg) < 0) 1006 return (-1); 1007 goto nextrec; 1008 } 1009 1010 if (DTRACEACT_ISPRINTFLIKE(act)) { 1011 void *fmtdata; 1012 int (*func)(dtrace_hdl_t *, FILE *, void *, 1013 const dtrace_probedata_t *, 1014 const dtrace_recdesc_t *, uint_t, 1015 const void *buf, size_t); 1016 1017 if ((fmtdata = dt_format_lookup(dtp, 1018 rec->dtrd_format)) == NULL) 1019 goto nofmt; 1020 1021 switch (act) { 1022 case DTRACEACT_PRINTF: 1023 func = dtrace_fprintf; 1024 break; 1025 case DTRACEACT_PRINTA: 1026 func = dtrace_fprinta; 1027 break; 1028 case DTRACEACT_SYSTEM: 1029 func = dtrace_system; 1030 break; 1031 case DTRACEACT_FREOPEN: 1032 func = dtrace_freopen; 1033 break; 1034 } 1035 1036 n = (*func)(dtp, fp, fmtdata, &data, 1037 rec, epd->dtepd_nrecs - i, 1038 (uchar_t *)buf->dtbd_data + offs, 1039 buf->dtbd_size - offs); 1040 1041 if (n < 0) 1042 return (-1); /* errno is set for us */ 1043 1044 if (n > 0) 1045 i += n - 1; 1046 goto nextrec; 1047 } 1048 1049 nofmt: 1050 if (act == DTRACEACT_PRINTA) { 1051 dt_print_aggdata_t pd; 1052 1053 bzero(&pd, sizeof (pd)); 1054 pd.dtpa_dtp = dtp; 1055 pd.dtpa_fp = fp; 1056 /* LINTED - alignment */ 1057 pd.dtpa_id = *((dtrace_aggvarid_t *)addr); 1058 1059 if (dt_printf(dtp, fp, "\n") < 0 || 1060 dtrace_aggregate_walk_valsorted(dtp, 1061 dt_print_agg, &pd) < 0) 1062 return (-1); 1063 1064 goto nextrec; 1065 } 1066 1067 switch (rec->dtrd_size) { 1068 case sizeof (uint64_t): 1069 n = dt_printf(dtp, fp, 1070 quiet ? "%lld" : " %16lld", 1071 /* LINTED - alignment */ 1072 *((unsigned long long *)addr)); 1073 break; 1074 case sizeof (uint32_t): 1075 n = dt_printf(dtp, fp, quiet ? "%d" : " %8d", 1076 /* LINTED - alignment */ 1077 *((uint32_t *)addr)); 1078 break; 1079 case sizeof (uint16_t): 1080 n = dt_printf(dtp, fp, quiet ? "%d" : " %5d", 1081 /* LINTED - alignment */ 1082 *((uint16_t *)addr)); 1083 break; 1084 case sizeof (uint8_t): 1085 n = dt_printf(dtp, fp, quiet ? "%d" : " %3d", 1086 *((uint8_t *)addr)); 1087 break; 1088 default: 1089 n = dt_print_bytes(dtp, fp, addr, 1090 rec->dtrd_size, 33, quiet); 1091 break; 1092 } 1093 1094 if (n < 0) 1095 return (-1); /* errno is set for us */ 1096 1097 nextrec: 1098 if (dt_buffered_flush(dtp, &data, rec, NULL) < 0) 1099 return (-1); /* errno is set for us */ 1100 } 1101 1102 /* 1103 * Call the record callback with a NULL record to indicate 1104 * that we're done processing this EPID. 1105 */ 1106 rval = (*rfunc)(&data, NULL, arg); 1107 nextepid: 1108 offs += epd->dtepd_size; 1109 last = id; 1110 } 1111 1112 if (buf->dtbd_oldest != 0 && start == buf->dtbd_oldest) { 1113 end = buf->dtbd_oldest; 1114 start = 0; 1115 goto again; 1116 } 1117 1118 if ((drops = buf->dtbd_drops) == 0) 1119 return (0); 1120 1121 /* 1122 * Explicitly zero the drops to prevent us from processing them again. 1123 */ 1124 buf->dtbd_drops = 0; 1125 1126 return (dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops)); 1127 } 1128 1129 typedef struct dt_begin { 1130 dtrace_consume_probe_f *dtbgn_probefunc; 1131 dtrace_consume_rec_f *dtbgn_recfunc; 1132 void *dtbgn_arg; 1133 dtrace_handle_err_f *dtbgn_errhdlr; 1134 void *dtbgn_errarg; 1135 int dtbgn_beginonly; 1136 } dt_begin_t; 1137 1138 static int 1139 dt_consume_begin_probe(const dtrace_probedata_t *data, void *arg) 1140 { 1141 dt_begin_t *begin = (dt_begin_t *)arg; 1142 dtrace_probedesc_t *pd = data->dtpda_pdesc; 1143 1144 int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0); 1145 int r2 = (strcmp(pd->dtpd_name, "BEGIN") == 0); 1146 1147 if (begin->dtbgn_beginonly) { 1148 if (!(r1 && r2)) 1149 return (DTRACE_CONSUME_NEXT); 1150 } else { 1151 if (r1 && r2) 1152 return (DTRACE_CONSUME_NEXT); 1153 } 1154 1155 /* 1156 * We have a record that we're interested in. Now call the underlying 1157 * probe function... 1158 */ 1159 return (begin->dtbgn_probefunc(data, begin->dtbgn_arg)); 1160 } 1161 1162 static int 1163 dt_consume_begin_record(const dtrace_probedata_t *data, 1164 const dtrace_recdesc_t *rec, void *arg) 1165 { 1166 dt_begin_t *begin = (dt_begin_t *)arg; 1167 1168 return (begin->dtbgn_recfunc(data, rec, begin->dtbgn_arg)); 1169 } 1170 1171 static int 1172 dt_consume_begin_error(dtrace_errdata_t *data, void *arg) 1173 { 1174 dt_begin_t *begin = (dt_begin_t *)arg; 1175 dtrace_probedesc_t *pd = data->dteda_pdesc; 1176 1177 int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0); 1178 int r2 = (strcmp(pd->dtpd_name, "BEGIN") == 0); 1179 1180 if (begin->dtbgn_beginonly) { 1181 if (!(r1 && r2)) 1182 return (DTRACE_HANDLE_OK); 1183 } else { 1184 if (r1 && r2) 1185 return (DTRACE_HANDLE_OK); 1186 } 1187 1188 return (begin->dtbgn_errhdlr(data, begin->dtbgn_errarg)); 1189 } 1190 1191 static int 1192 dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp, dtrace_bufdesc_t *buf, 1193 dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg) 1194 { 1195 /* 1196 * There's this idea that the BEGIN probe should be processed before 1197 * everything else, and that the END probe should be processed after 1198 * anything else. In the common case, this is pretty easy to deal 1199 * with. However, a situation may arise where the BEGIN enabling and 1200 * END enabling are on the same CPU, and some enabling in the middle 1201 * occurred on a different CPU. To deal with this (blech!) we need to 1202 * consume the BEGIN buffer up until the end of the BEGIN probe, and 1203 * then set it aside. We will then process every other CPU, and then 1204 * we'll return to the BEGIN CPU and process the rest of the data 1205 * (which will inevitably include the END probe, if any). Making this 1206 * even more complicated (!) is the library's ERROR enabling. Because 1207 * this enabling is processed before we even get into the consume call 1208 * back, any ERROR firing would result in the library's ERROR enabling 1209 * being processed twice -- once in our first pass (for BEGIN probes), 1210 * and again in our second pass (for everything but BEGIN probes). To 1211 * deal with this, we interpose on the ERROR handler to assure that we 1212 * only process ERROR enablings induced by BEGIN enablings in the 1213 * first pass, and that we only process ERROR enablings _not_ induced 1214 * by BEGIN enablings in the second pass. 1215 */ 1216 dt_begin_t begin; 1217 processorid_t cpu = dtp->dt_beganon; 1218 dtrace_bufdesc_t nbuf; 1219 int rval, i; 1220 static int max_ncpus; 1221 dtrace_optval_t size; 1222 1223 dtp->dt_beganon = -1; 1224 1225 if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) { 1226 /* 1227 * We really don't expect this to fail, but it is at least 1228 * technically possible for this to fail with ENOENT. In this 1229 * case, we just drive on... 1230 */ 1231 if (errno == ENOENT) 1232 return (0); 1233 1234 return (dt_set_errno(dtp, errno)); 1235 } 1236 1237 if (!dtp->dt_stopped || buf->dtbd_cpu != dtp->dt_endedon) { 1238 /* 1239 * This is the simple case. We're either not stopped, or if 1240 * we are, we actually processed any END probes on another 1241 * CPU. We can simply consume this buffer and return. 1242 */ 1243 return (dt_consume_cpu(dtp, fp, cpu, buf, pf, rf, arg)); 1244 } 1245 1246 begin.dtbgn_probefunc = pf; 1247 begin.dtbgn_recfunc = rf; 1248 begin.dtbgn_arg = arg; 1249 begin.dtbgn_beginonly = 1; 1250 1251 /* 1252 * We need to interpose on the ERROR handler to be sure that we 1253 * only process ERRORs induced by BEGIN. 1254 */ 1255 begin.dtbgn_errhdlr = dtp->dt_errhdlr; 1256 begin.dtbgn_errarg = dtp->dt_errarg; 1257 dtp->dt_errhdlr = dt_consume_begin_error; 1258 dtp->dt_errarg = &begin; 1259 1260 rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe, 1261 dt_consume_begin_record, &begin); 1262 1263 dtp->dt_errhdlr = begin.dtbgn_errhdlr; 1264 dtp->dt_errarg = begin.dtbgn_errarg; 1265 1266 if (rval != 0) 1267 return (rval); 1268 1269 /* 1270 * Now allocate a new buffer. We'll use this to deal with every other 1271 * CPU. 1272 */ 1273 bzero(&nbuf, sizeof (dtrace_bufdesc_t)); 1274 (void) dtrace_getopt(dtp, "bufsize", &size); 1275 if ((nbuf.dtbd_data = malloc(size)) == NULL) 1276 return (dt_set_errno(dtp, EDT_NOMEM)); 1277 1278 if (max_ncpus == 0) 1279 max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1; 1280 1281 for (i = 0; i < max_ncpus; i++) { 1282 nbuf.dtbd_cpu = i; 1283 1284 if (i == cpu) 1285 continue; 1286 1287 if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &nbuf) == -1) { 1288 /* 1289 * If we failed with ENOENT, it may be because the 1290 * CPU was unconfigured -- this is okay. Any other 1291 * error, however, is unexpected. 1292 */ 1293 if (errno == ENOENT) 1294 continue; 1295 1296 free(nbuf.dtbd_data); 1297 1298 return (dt_set_errno(dtp, errno)); 1299 } 1300 1301 if ((rval = dt_consume_cpu(dtp, fp, 1302 i, &nbuf, pf, rf, arg)) != 0) { 1303 free(nbuf.dtbd_data); 1304 return (rval); 1305 } 1306 } 1307 1308 free(nbuf.dtbd_data); 1309 1310 /* 1311 * Okay -- we're done with the other buffers. Now we want to 1312 * reconsume the first buffer -- but this time we're looking for 1313 * everything _but_ BEGIN. And of course, in order to only consume 1314 * those ERRORs _not_ associated with BEGIN, we need to reinstall our 1315 * ERROR interposition function... 1316 */ 1317 begin.dtbgn_beginonly = 0; 1318 1319 assert(begin.dtbgn_errhdlr == dtp->dt_errhdlr); 1320 assert(begin.dtbgn_errarg == dtp->dt_errarg); 1321 dtp->dt_errhdlr = dt_consume_begin_error; 1322 dtp->dt_errarg = &begin; 1323 1324 rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe, 1325 dt_consume_begin_record, &begin); 1326 1327 dtp->dt_errhdlr = begin.dtbgn_errhdlr; 1328 dtp->dt_errarg = begin.dtbgn_errarg; 1329 1330 return (rval); 1331 } 1332 1333 int 1334 dtrace_consume(dtrace_hdl_t *dtp, FILE *fp, 1335 dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg) 1336 { 1337 dtrace_bufdesc_t *buf = &dtp->dt_buf; 1338 dtrace_optval_t size; 1339 static int max_ncpus; 1340 int i, rval; 1341 dtrace_optval_t interval = dtp->dt_options[DTRACEOPT_SWITCHRATE]; 1342 hrtime_t now = gethrtime(); 1343 1344 if (dtp->dt_lastswitch != 0) { 1345 if (now - dtp->dt_lastswitch < interval) 1346 return (0); 1347 1348 dtp->dt_lastswitch += interval; 1349 } else { 1350 dtp->dt_lastswitch = now; 1351 } 1352 1353 if (!dtp->dt_active) 1354 return (dt_set_errno(dtp, EINVAL)); 1355 1356 if (max_ncpus == 0) 1357 max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1; 1358 1359 if (pf == NULL) 1360 pf = (dtrace_consume_probe_f *)dt_nullprobe; 1361 1362 if (rf == NULL) 1363 rf = (dtrace_consume_rec_f *)dt_nullrec; 1364 1365 if (buf->dtbd_data == NULL) { 1366 (void) dtrace_getopt(dtp, "bufsize", &size); 1367 if ((buf->dtbd_data = malloc(size)) == NULL) 1368 return (dt_set_errno(dtp, EDT_NOMEM)); 1369 1370 buf->dtbd_size = size; 1371 } 1372 1373 /* 1374 * If we have just begun, we want to first process the CPU that 1375 * executed the BEGIN probe (if any). 1376 */ 1377 if (dtp->dt_active && dtp->dt_beganon != -1) { 1378 buf->dtbd_cpu = dtp->dt_beganon; 1379 if ((rval = dt_consume_begin(dtp, fp, buf, pf, rf, arg)) != 0) 1380 return (rval); 1381 } 1382 1383 for (i = 0; i < max_ncpus; i++) { 1384 buf->dtbd_cpu = i; 1385 1386 /* 1387 * If we have stopped, we want to process the CPU on which the 1388 * END probe was processed only _after_ we have processed 1389 * everything else. 1390 */ 1391 if (dtp->dt_stopped && (i == dtp->dt_endedon)) 1392 continue; 1393 1394 if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) { 1395 /* 1396 * If we failed with ENOENT, it may be because the 1397 * CPU was unconfigured -- this is okay. Any other 1398 * error, however, is unexpected. 1399 */ 1400 if (errno == ENOENT) 1401 continue; 1402 1403 return (dt_set_errno(dtp, errno)); 1404 } 1405 1406 if ((rval = dt_consume_cpu(dtp, fp, i, buf, pf, rf, arg)) != 0) 1407 return (rval); 1408 } 1409 1410 if (!dtp->dt_stopped) 1411 return (0); 1412 1413 buf->dtbd_cpu = dtp->dt_endedon; 1414 1415 if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) { 1416 /* 1417 * This _really_ shouldn't fail, but it is strictly speaking 1418 * possible for this to return ENOENT if the CPU that called 1419 * the END enabling somehow managed to become unconfigured. 1420 * It's unclear how the user can possibly expect anything 1421 * rational to happen in this case -- the state has been thrown 1422 * out along with the unconfigured CPU -- so we'll just drive 1423 * on... 1424 */ 1425 if (errno == ENOENT) 1426 return (0); 1427 1428 return (dt_set_errno(dtp, errno)); 1429 } 1430 1431 return (dt_consume_cpu(dtp, fp, dtp->dt_endedon, buf, pf, rf, arg)); 1432 } 1433