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 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2013, Josef 'Jeff' Sipek <jeffpc@josefsipek.net> 25 * Copyright 2018 Joyent, Inc. 26 */ 27 28 #include <mdb/mdb_modapi.h> 29 #include <mdb/mdb_ctf.h> 30 31 #include <sys/types.h> 32 #include <sys/regset.h> 33 #include <sys/stack.h> 34 #include <sys/thread.h> 35 #include <sys/modctl.h> 36 #include <assert.h> 37 38 #include "findstack.h" 39 #include "thread.h" 40 #include "sobj.h" 41 42 /* 43 * Parts of this file are shared between targets, but this section is only 44 * used for KVM and KMDB. 45 */ 46 #ifdef _KERNEL 47 48 int findstack_debug_on = 0; 49 50 /* 51 * "sp" is a kernel VA. 52 */ 53 static int 54 print_stack(uintptr_t sp, uintptr_t pc, uintptr_t addr, 55 int argc, const mdb_arg_t *argv, int free_state) 56 { 57 int showargs = 0, count, err; 58 char tdesc[128] = ""; 59 60 count = mdb_getopts(argc, argv, 61 'v', MDB_OPT_SETBITS, TRUE, &showargs, NULL); 62 argc -= count; 63 argv += count; 64 65 if (argc > 1 || (argc == 1 && argv->a_type != MDB_TYPE_STRING)) 66 return (DCMD_USAGE); 67 68 (void) thread_getdesc(addr, B_TRUE, tdesc, sizeof (tdesc)); 69 70 mdb_printf("stack pointer for thread %p%s (%s): %p\n", 71 addr, (free_state ? " (TS_FREE)" : ""), tdesc, sp); 72 if (pc != 0) 73 mdb_printf("[ %0?lr %a() ]\n", sp, pc); 74 75 mdb_inc_indent(2); 76 mdb_set_dot(sp); 77 78 if (argc == 1) 79 err = mdb_eval(argv->a_un.a_str); 80 else if (showargs) 81 err = mdb_eval("<.$C"); 82 else 83 err = mdb_eval("<.$C0"); 84 85 mdb_dec_indent(2); 86 87 return ((err == -1) ? DCMD_ABORT : DCMD_OK); 88 } 89 90 int 91 findstack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 92 { 93 findstack_info_t fsi; 94 int retval; 95 96 if (!(flags & DCMD_ADDRSPEC)) 97 return (DCMD_USAGE); 98 99 bzero(&fsi, sizeof (fsi)); 100 101 if ((retval = stacks_findstack(addr, &fsi, 1)) != DCMD_OK || 102 fsi.fsi_failed) 103 return (retval); 104 105 return (print_stack(fsi.fsi_sp, fsi.fsi_pc, addr, 106 argc, argv, fsi.fsi_tstate == TS_FREE)); 107 } 108 109 /*ARGSUSED*/ 110 int 111 findstack_debug(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *av) 112 { 113 findstack_debug_on ^= 1; 114 115 mdb_printf("findstack: debugging is now %s\n", 116 findstack_debug_on ? "on" : "off"); 117 118 return (DCMD_OK); 119 } 120 121 #endif /* _KERNEL */ 122 123 static void 124 uppercase(char *p) 125 { 126 for (; *p != '\0'; p++) { 127 if (*p >= 'a' && *p <= 'z') 128 *p += 'A' - 'a'; 129 } 130 } 131 132 static void 133 sobj_to_text(uintptr_t addr, char *out, size_t out_sz) 134 { 135 sobj_ops_to_text(addr, out, out_sz); 136 uppercase(out); 137 } 138 139 #define SOBJ_ALL 1 140 141 static int 142 text_to_sobj(const char *text, uintptr_t *out) 143 { 144 if (strcasecmp(text, "ALL") == 0) { 145 *out = SOBJ_ALL; 146 return (0); 147 } 148 149 return (sobj_text_to_ops(text, out)); 150 } 151 152 #define TSTATE_PANIC -2U 153 static int 154 text_to_tstate(const char *text, uint_t *out) 155 { 156 if (strcasecmp(text, "panic") == 0) 157 *out = TSTATE_PANIC; 158 else if (thread_text_to_state(text, out) != 0) { 159 mdb_warn("tstate \"%s\" not recognized\n", text); 160 return (-1); 161 } 162 return (0); 163 } 164 165 static void 166 tstate_to_text(uint_t tstate, uint_t paniced, char *out, size_t out_sz) 167 { 168 if (paniced) 169 mdb_snprintf(out, out_sz, "panic"); 170 else 171 thread_state_to_text(tstate, out, out_sz); 172 uppercase(out); 173 } 174 175 typedef struct stacks_entry { 176 struct stacks_entry *se_next; 177 struct stacks_entry *se_dup; /* dups of this stack */ 178 uintptr_t se_thread; 179 uintptr_t se_sp; 180 uintptr_t se_sobj_ops; 181 uint32_t se_tstate; 182 uint32_t se_count; /* # threads w/ this stack */ 183 uint8_t se_overflow; 184 uint8_t se_depth; 185 uint8_t se_failed; /* failure reason; FSI_FAIL_* */ 186 uint8_t se_panic; 187 uintptr_t se_stack[1]; 188 } stacks_entry_t; 189 #define STACKS_ENTRY_SIZE(x) OFFSETOF(stacks_entry_t, se_stack[(x)]) 190 191 #define STACKS_HSIZE 127 192 193 /* Maximum stack depth reported in stacks */ 194 #define STACKS_MAX_DEPTH 254 195 196 typedef struct stacks_info { 197 size_t si_count; /* total stacks_entry_ts (incl dups) */ 198 size_t si_entries; /* # entries in hash table */ 199 stacks_entry_t **si_hash; /* hash table */ 200 findstack_info_t si_fsi; /* transient callback state */ 201 } stacks_info_t; 202 203 /* global state cached between invocations */ 204 #define STACKS_STATE_CLEAN 0 205 #define STACKS_STATE_DIRTY 1 206 #define STACKS_STATE_DONE 2 207 static uint_t stacks_state = STACKS_STATE_CLEAN; 208 static stacks_entry_t **stacks_hash; 209 static stacks_entry_t **stacks_array; 210 static size_t stacks_array_size; 211 212 static size_t 213 stacks_hash_entry(stacks_entry_t *sep) 214 { 215 size_t depth = sep->se_depth; 216 uintptr_t *stack = sep->se_stack; 217 218 uint64_t total = depth; 219 220 while (depth > 0) { 221 total += *stack; 222 stack++; depth--; 223 } 224 225 return (total % STACKS_HSIZE); 226 } 227 228 /* 229 * This is used to both compare stacks for equality and to sort the final 230 * list of unique stacks. forsort specifies the latter behavior, which 231 * additionally: 232 * compares se_count, and 233 * sorts the stacks by text function name. 234 * 235 * The equality test is independent of se_count, and doesn't care about 236 * relative ordering, so we don't do the extra work of looking up symbols 237 * for the stack addresses. 238 */ 239 static int 240 stacks_entry_comp_impl(stacks_entry_t *l, stacks_entry_t *r, 241 uint_t forsort) 242 { 243 int idx; 244 245 int depth = MIN(l->se_depth, r->se_depth); 246 247 /* no matter what, panic stacks come last. */ 248 if (l->se_panic > r->se_panic) 249 return (1); 250 if (l->se_panic < r->se_panic) 251 return (-1); 252 253 if (forsort) { 254 /* put large counts earlier */ 255 if (l->se_count > r->se_count) 256 return (-1); 257 if (l->se_count < r->se_count) 258 return (1); 259 } 260 261 if (l->se_tstate > r->se_tstate) 262 return (1); 263 if (l->se_tstate < r->se_tstate) 264 return (-1); 265 266 if (l->se_failed > r->se_failed) 267 return (1); 268 if (l->se_failed < r->se_failed) 269 return (-1); 270 271 for (idx = 0; idx < depth; idx++) { 272 char lbuf[MDB_SYM_NAMLEN]; 273 char rbuf[MDB_SYM_NAMLEN]; 274 275 int rval; 276 uintptr_t laddr = l->se_stack[idx]; 277 uintptr_t raddr = r->se_stack[idx]; 278 279 if (laddr == raddr) 280 continue; 281 282 if (forsort && 283 mdb_lookup_by_addr(laddr, MDB_SYM_FUZZY, 284 lbuf, sizeof (lbuf), NULL) != -1 && 285 mdb_lookup_by_addr(raddr, MDB_SYM_FUZZY, 286 rbuf, sizeof (rbuf), NULL) != -1 && 287 (rval = strcmp(lbuf, rbuf)) != 0) 288 return (rval); 289 290 if (laddr > raddr) 291 return (1); 292 return (-1); 293 } 294 295 if (l->se_overflow > r->se_overflow) 296 return (-1); 297 if (l->se_overflow < r->se_overflow) 298 return (1); 299 300 if (l->se_depth > r->se_depth) 301 return (1); 302 if (l->se_depth < r->se_depth) 303 return (-1); 304 305 if (l->se_sobj_ops > r->se_sobj_ops) 306 return (1); 307 if (l->se_sobj_ops < r->se_sobj_ops) 308 return (-1); 309 310 return (0); 311 } 312 313 static int 314 stacks_entry_comp(const void *l_arg, const void *r_arg) 315 { 316 stacks_entry_t * const *lp = l_arg; 317 stacks_entry_t * const *rp = r_arg; 318 319 return (stacks_entry_comp_impl(*lp, *rp, 1)); 320 } 321 322 void 323 stacks_cleanup(int force) 324 { 325 int idx = 0; 326 stacks_entry_t *cur, *next; 327 328 if (stacks_state == STACKS_STATE_CLEAN) 329 return; 330 331 if (!force && stacks_state == STACKS_STATE_DONE) 332 return; 333 334 /* 335 * Until the array is sorted and stable, stacks_hash will be non-NULL. 336 * This way, we can get at all of the data, even if qsort() was 337 * interrupted while mucking with the array. 338 */ 339 if (stacks_hash != NULL) { 340 for (idx = 0; idx < STACKS_HSIZE; idx++) { 341 while ((cur = stacks_hash[idx]) != NULL) { 342 while ((next = cur->se_dup) != NULL) { 343 cur->se_dup = next->se_dup; 344 mdb_free(next, 345 STACKS_ENTRY_SIZE(next->se_depth)); 346 } 347 next = cur->se_next; 348 stacks_hash[idx] = next; 349 mdb_free(cur, STACKS_ENTRY_SIZE(cur->se_depth)); 350 } 351 } 352 if (stacks_array != NULL) 353 mdb_free(stacks_array, 354 stacks_array_size * sizeof (*stacks_array)); 355 356 mdb_free(stacks_hash, STACKS_HSIZE * sizeof (*stacks_hash)); 357 358 } else if (stacks_array != NULL) { 359 for (idx = 0; idx < stacks_array_size; idx++) { 360 if ((cur = stacks_array[idx]) != NULL) { 361 while ((next = cur->se_dup) != NULL) { 362 cur->se_dup = next->se_dup; 363 mdb_free(next, 364 STACKS_ENTRY_SIZE(next->se_depth)); 365 } 366 stacks_array[idx] = NULL; 367 mdb_free(cur, STACKS_ENTRY_SIZE(cur->se_depth)); 368 } 369 } 370 mdb_free(stacks_array, 371 stacks_array_size * sizeof (*stacks_array)); 372 } 373 374 stacks_findstack_cleanup(); 375 376 stacks_array_size = 0; 377 stacks_state = STACKS_STATE_CLEAN; 378 stacks_hash = NULL; 379 stacks_array = NULL; 380 } 381 382 /*ARGSUSED*/ 383 static int 384 stacks_thread_cb(uintptr_t addr, const void *ignored, void *cbarg) 385 { 386 stacks_info_t *sip = cbarg; 387 findstack_info_t *fsip = &sip->si_fsi; 388 389 stacks_entry_t **sepp, *nsep, *sep; 390 int idx; 391 size_t depth; 392 393 if (stacks_findstack(addr, fsip, 0) != DCMD_OK && 394 fsip->fsi_failed == FSI_FAIL_BADTHREAD) { 395 mdb_warn("couldn't read thread at %p\n", addr); 396 return (WALK_NEXT); 397 } 398 399 sip->si_count++; 400 401 depth = fsip->fsi_depth; 402 nsep = mdb_zalloc(STACKS_ENTRY_SIZE(depth), UM_SLEEP); 403 nsep->se_thread = addr; 404 nsep->se_sp = fsip->fsi_sp; 405 nsep->se_sobj_ops = fsip->fsi_sobj_ops; 406 nsep->se_tstate = fsip->fsi_tstate; 407 nsep->se_count = 1; 408 nsep->se_overflow = fsip->fsi_overflow; 409 nsep->se_depth = depth; 410 nsep->se_failed = fsip->fsi_failed; 411 nsep->se_panic = fsip->fsi_panic; 412 413 for (idx = 0; idx < depth; idx++) 414 nsep->se_stack[idx] = fsip->fsi_stack[idx]; 415 416 for (sepp = &sip->si_hash[stacks_hash_entry(nsep)]; 417 (sep = *sepp) != NULL; 418 sepp = &sep->se_next) { 419 420 if (stacks_entry_comp_impl(sep, nsep, 0) != 0) 421 continue; 422 423 nsep->se_dup = sep->se_dup; 424 sep->se_dup = nsep; 425 sep->se_count++; 426 return (WALK_NEXT); 427 } 428 429 nsep->se_next = NULL; 430 *sepp = nsep; 431 sip->si_entries++; 432 433 return (WALK_NEXT); 434 } 435 436 static int 437 stacks_run_tlist(mdb_pipe_t *tlist, stacks_info_t *si) 438 { 439 size_t idx; 440 size_t found = 0; 441 int ret; 442 443 for (idx = 0; idx < tlist->pipe_len; idx++) { 444 uintptr_t addr = tlist->pipe_data[idx]; 445 446 found++; 447 448 ret = stacks_thread_cb(addr, NULL, si); 449 if (ret == WALK_DONE) 450 break; 451 if (ret != WALK_NEXT) 452 return (-1); 453 } 454 455 if (found) 456 return (0); 457 return (-1); 458 } 459 460 static int 461 stacks_run(int verbose, mdb_pipe_t *tlist) 462 { 463 stacks_info_t si; 464 findstack_info_t *fsip = &si.si_fsi; 465 size_t idx; 466 stacks_entry_t **cur; 467 468 bzero(&si, sizeof (si)); 469 470 stacks_state = STACKS_STATE_DIRTY; 471 472 stacks_hash = si.si_hash = 473 mdb_zalloc(STACKS_HSIZE * sizeof (*si.si_hash), UM_SLEEP); 474 si.si_entries = 0; 475 si.si_count = 0; 476 477 fsip->fsi_max_depth = STACKS_MAX_DEPTH; 478 fsip->fsi_stack = 479 mdb_alloc(fsip->fsi_max_depth * sizeof (*fsip->fsi_stack), 480 UM_SLEEP | UM_GC); 481 482 if (verbose) 483 mdb_warn("stacks: processing kernel threads\n"); 484 485 if (tlist != NULL) { 486 if (stacks_run_tlist(tlist, &si)) 487 return (DCMD_ERR); 488 } else { 489 if (mdb_walk("thread", stacks_thread_cb, &si) != 0) { 490 mdb_warn("cannot walk \"thread\""); 491 return (DCMD_ERR); 492 } 493 } 494 495 if (verbose) 496 mdb_warn("stacks: %d unique stacks / %d threads\n", 497 si.si_entries, si.si_count); 498 499 stacks_array_size = si.si_entries; 500 stacks_array = 501 mdb_zalloc(si.si_entries * sizeof (*stacks_array), UM_SLEEP); 502 cur = stacks_array; 503 for (idx = 0; idx < STACKS_HSIZE; idx++) { 504 stacks_entry_t *sep; 505 for (sep = si.si_hash[idx]; sep != NULL; sep = sep->se_next) 506 *(cur++) = sep; 507 } 508 509 if (cur != stacks_array + si.si_entries) { 510 mdb_warn("stacks: miscounted array size (%d != size: %d)\n", 511 (cur - stacks_array), stacks_array_size); 512 return (DCMD_ERR); 513 } 514 qsort(stacks_array, si.si_entries, sizeof (*stacks_array), 515 stacks_entry_comp); 516 517 /* Now that we're done, free the hash table */ 518 stacks_hash = NULL; 519 mdb_free(si.si_hash, STACKS_HSIZE * sizeof (*si.si_hash)); 520 521 if (tlist == NULL) 522 stacks_state = STACKS_STATE_DONE; 523 524 if (verbose) 525 mdb_warn("stacks: done\n"); 526 527 return (DCMD_OK); 528 } 529 530 static int 531 stacks_has_caller(stacks_entry_t *sep, uintptr_t addr) 532 { 533 uintptr_t laddr = addr; 534 uintptr_t haddr = addr + 1; 535 int idx; 536 char c[MDB_SYM_NAMLEN]; 537 GElf_Sym sym; 538 539 if (mdb_lookup_by_addr(addr, MDB_SYM_FUZZY, 540 c, sizeof (c), &sym) != -1 && 541 addr == (uintptr_t)sym.st_value) { 542 laddr = (uintptr_t)sym.st_value; 543 haddr = (uintptr_t)sym.st_value + sym.st_size; 544 } 545 546 for (idx = 0; idx < sep->se_depth; idx++) 547 if (sep->se_stack[idx] >= laddr && sep->se_stack[idx] < haddr) 548 return (1); 549 550 return (0); 551 } 552 553 static int 554 stacks_has_module(stacks_entry_t *sep, stacks_module_t *mp) 555 { 556 int idx; 557 558 for (idx = 0; idx < sep->se_depth; idx++) { 559 if (sep->se_stack[idx] >= mp->sm_text && 560 sep->se_stack[idx] < mp->sm_text + mp->sm_size) 561 return (1); 562 } 563 564 return (0); 565 } 566 567 static int 568 stacks_module_find(const char *name, stacks_module_t *mp) 569 { 570 (void) strncpy(mp->sm_name, name, sizeof (mp->sm_name)); 571 572 if (stacks_module(mp) != 0) 573 return (-1); 574 575 if (mp->sm_size == 0) { 576 mdb_warn("stacks: module \"%s\" is unknown\n", name); 577 return (-1); 578 } 579 580 return (0); 581 } 582 583 static int 584 uintptrcomp(const void *lp, const void *rp) 585 { 586 uintptr_t lhs = *(const uintptr_t *)lp; 587 uintptr_t rhs = *(const uintptr_t *)rp; 588 if (lhs > rhs) 589 return (1); 590 if (lhs < rhs) 591 return (-1); 592 return (0); 593 } 594 595 /*ARGSUSED*/ 596 int 597 stacks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 598 { 599 size_t idx; 600 601 char *seen = NULL; 602 603 const char *caller_str = NULL; 604 const char *excl_caller_str = NULL; 605 uintptr_t caller = 0, excl_caller = 0; 606 const char *module_str = NULL; 607 const char *excl_module_str = NULL; 608 stacks_module_t module, excl_module; 609 const char *sobj = NULL; 610 const char *excl_sobj = NULL; 611 uintptr_t sobj_ops = 0, excl_sobj_ops = 0; 612 const char *tstate_str = NULL; 613 const char *excl_tstate_str = NULL; 614 uint_t tstate = -1U; 615 uint_t excl_tstate = -1U; 616 uint_t printed = 0; 617 618 uint_t all = 0; 619 uint_t force = 0; 620 uint_t interesting = 0; 621 uint_t verbose = 0; 622 623 /* 624 * We have a slight behavior difference between having piped 625 * input and 'addr::stacks'. Without a pipe, we assume the 626 * thread pointer given is a representative thread, and so 627 * we include all similar threads in the system in our output. 628 * 629 * With a pipe, we filter down to just the threads in our 630 * input. 631 */ 632 uint_t addrspec = (flags & DCMD_ADDRSPEC); 633 uint_t only_matching = addrspec && (flags & DCMD_PIPE); 634 635 mdb_pipe_t p; 636 637 bzero(&module, sizeof (module)); 638 bzero(&excl_module, sizeof (excl_module)); 639 640 if (mdb_getopts(argc, argv, 641 'a', MDB_OPT_SETBITS, TRUE, &all, 642 'f', MDB_OPT_SETBITS, TRUE, &force, 643 'i', MDB_OPT_SETBITS, TRUE, &interesting, 644 'v', MDB_OPT_SETBITS, TRUE, &verbose, 645 'c', MDB_OPT_STR, &caller_str, 646 'C', MDB_OPT_STR, &excl_caller_str, 647 'm', MDB_OPT_STR, &module_str, 648 'M', MDB_OPT_STR, &excl_module_str, 649 's', MDB_OPT_STR, &sobj, 650 'S', MDB_OPT_STR, &excl_sobj, 651 't', MDB_OPT_STR, &tstate_str, 652 'T', MDB_OPT_STR, &excl_tstate_str, 653 NULL) != argc) 654 return (DCMD_USAGE); 655 656 if (interesting) { 657 if (sobj != NULL || excl_sobj != NULL || 658 tstate_str != NULL || excl_tstate_str != NULL) { 659 mdb_warn( 660 "stacks: -i is incompatible with -[sStT]\n"); 661 return (DCMD_USAGE); 662 } 663 excl_sobj = "CV"; 664 excl_tstate_str = "FREE"; 665 } 666 667 if (caller_str != NULL) { 668 mdb_set_dot(0); 669 if (mdb_eval(caller_str) != 0) { 670 mdb_warn("stacks: evaluation of \"%s\" failed", 671 caller_str); 672 return (DCMD_ABORT); 673 } 674 caller = mdb_get_dot(); 675 } 676 677 if (excl_caller_str != NULL) { 678 mdb_set_dot(0); 679 if (mdb_eval(excl_caller_str) != 0) { 680 mdb_warn("stacks: evaluation of \"%s\" failed", 681 excl_caller_str); 682 return (DCMD_ABORT); 683 } 684 excl_caller = mdb_get_dot(); 685 } 686 mdb_set_dot(addr); 687 688 if (module_str != NULL && stacks_module_find(module_str, &module) != 0) 689 return (DCMD_ABORT); 690 691 if (excl_module_str != NULL && 692 stacks_module_find(excl_module_str, &excl_module) != 0) 693 return (DCMD_ABORT); 694 695 if (sobj != NULL && text_to_sobj(sobj, &sobj_ops) != 0) 696 return (DCMD_USAGE); 697 698 if (excl_sobj != NULL && text_to_sobj(excl_sobj, &excl_sobj_ops) != 0) 699 return (DCMD_USAGE); 700 701 if (sobj_ops != 0 && excl_sobj_ops != 0) { 702 mdb_warn("stacks: only one of -s and -S can be specified\n"); 703 return (DCMD_USAGE); 704 } 705 706 if (tstate_str != NULL && text_to_tstate(tstate_str, &tstate) != 0) 707 return (DCMD_USAGE); 708 709 if (excl_tstate_str != NULL && 710 text_to_tstate(excl_tstate_str, &excl_tstate) != 0) 711 return (DCMD_USAGE); 712 713 if (tstate != -1U && excl_tstate != -1U) { 714 mdb_warn("stacks: only one of -t and -T can be specified\n"); 715 return (DCMD_USAGE); 716 } 717 718 /* 719 * If there's an address specified, we're going to further filter 720 * to only entries which have an address in the input. To reduce 721 * overhead (and make the sorted output come out right), we 722 * use mdb_get_pipe() to grab the entire pipeline of input, then 723 * use qsort() and bsearch() to speed up the search. 724 */ 725 if (addrspec) { 726 mdb_get_pipe(&p); 727 if (p.pipe_data == NULL || p.pipe_len == 0) { 728 p.pipe_data = &addr; 729 p.pipe_len = 1; 730 } 731 qsort(p.pipe_data, p.pipe_len, sizeof (uintptr_t), 732 uintptrcomp); 733 734 /* remove any duplicates in the data */ 735 idx = 0; 736 while (idx < p.pipe_len - 1) { 737 uintptr_t *data = &p.pipe_data[idx]; 738 size_t len = p.pipe_len - idx; 739 740 if (data[0] == data[1]) { 741 memmove(data, data + 1, 742 (len - 1) * sizeof (*data)); 743 p.pipe_len--; 744 continue; /* repeat without incrementing idx */ 745 } 746 idx++; 747 } 748 749 seen = mdb_zalloc(p.pipe_len, UM_SLEEP | UM_GC); 750 } 751 752 /* 753 * Force a cleanup if we're connected to a live system. Never 754 * do a cleanup after the first invocation around the loop. 755 */ 756 force |= (mdb_get_state() == MDB_STATE_RUNNING); 757 if (force && (flags & (DCMD_LOOPFIRST|DCMD_LOOP)) == DCMD_LOOP) 758 force = 0; 759 760 stacks_cleanup(force); 761 762 if (stacks_state == STACKS_STATE_CLEAN) { 763 int res = stacks_run(verbose, addrspec ? &p : NULL); 764 if (res != DCMD_OK) 765 return (res); 766 } 767 768 for (idx = 0; idx < stacks_array_size; idx++) { 769 stacks_entry_t *sep = stacks_array[idx]; 770 stacks_entry_t *cur = sep; 771 int frame; 772 size_t count = sep->se_count; 773 774 if (addrspec) { 775 stacks_entry_t *head = NULL, *tail = NULL, *sp; 776 size_t foundcount = 0; 777 /* 778 * We use the now-unused hash chain field se_next to 779 * link together the dups which match our list. 780 */ 781 for (sp = sep; sp != NULL; sp = sp->se_dup) { 782 uintptr_t *entry = bsearch(&sp->se_thread, 783 p.pipe_data, p.pipe_len, sizeof (uintptr_t), 784 uintptrcomp); 785 if (entry != NULL) { 786 foundcount++; 787 seen[entry - p.pipe_data]++; 788 if (head == NULL) 789 head = sp; 790 else 791 tail->se_next = sp; 792 tail = sp; 793 sp->se_next = NULL; 794 } 795 } 796 if (head == NULL) 797 continue; /* no match, skip entry */ 798 799 if (only_matching) { 800 cur = sep = head; 801 count = foundcount; 802 } 803 } 804 805 if (caller != 0 && !stacks_has_caller(sep, caller)) 806 continue; 807 808 if (excl_caller != 0 && stacks_has_caller(sep, excl_caller)) 809 continue; 810 811 if (module.sm_size != 0 && !stacks_has_module(sep, &module)) 812 continue; 813 814 if (excl_module.sm_size != 0 && 815 stacks_has_module(sep, &excl_module)) 816 continue; 817 818 if (tstate != -1U) { 819 if (tstate == TSTATE_PANIC) { 820 if (!sep->se_panic) 821 continue; 822 } else if (sep->se_panic || sep->se_tstate != tstate) 823 continue; 824 } 825 if (excl_tstate != -1U) { 826 if (excl_tstate == TSTATE_PANIC) { 827 if (sep->se_panic) 828 continue; 829 } else if (!sep->se_panic && 830 sep->se_tstate == excl_tstate) 831 continue; 832 } 833 834 if (sobj_ops == SOBJ_ALL) { 835 if (sep->se_sobj_ops == 0) 836 continue; 837 } else if (sobj_ops != 0) { 838 if (sobj_ops != sep->se_sobj_ops) 839 continue; 840 } 841 842 if (!(interesting && sep->se_panic)) { 843 if (excl_sobj_ops == SOBJ_ALL) { 844 if (sep->se_sobj_ops != 0) 845 continue; 846 } else if (excl_sobj_ops != 0) { 847 if (excl_sobj_ops == sep->se_sobj_ops) 848 continue; 849 } 850 } 851 852 if (flags & DCMD_PIPE_OUT) { 853 while (sep != NULL) { 854 mdb_printf("%lr\n", sep->se_thread); 855 sep = only_matching ? 856 sep->se_next : sep->se_dup; 857 } 858 continue; 859 } 860 861 if (all || !printed) { 862 mdb_printf("%<u>%-?s %-8s %-?s %8s%</u>\n", 863 "THREAD", "STATE", "SOBJ", "COUNT"); 864 printed = 1; 865 } 866 867 do { 868 char state[20]; 869 char sobj[100]; 870 871 tstate_to_text(cur->se_tstate, cur->se_panic, 872 state, sizeof (state)); 873 sobj_to_text(cur->se_sobj_ops, 874 sobj, sizeof (sobj)); 875 876 if (cur == sep) 877 mdb_printf("%-?p %-8s %-?s %8d\n", 878 cur->se_thread, state, sobj, count); 879 else 880 mdb_printf("%-?p %-8s %-?s %8s\n", 881 cur->se_thread, state, sobj, "-"); 882 883 cur = only_matching ? cur->se_next : cur->se_dup; 884 } while (all && cur != NULL); 885 886 if (sep->se_failed != 0) { 887 char *reason; 888 switch (sep->se_failed) { 889 case FSI_FAIL_NOTINMEMORY: 890 reason = "thread not in memory"; 891 break; 892 case FSI_FAIL_THREADCORRUPT: 893 reason = "thread structure stack info corrupt"; 894 break; 895 case FSI_FAIL_STACKNOTFOUND: 896 reason = "no consistent stack found"; 897 break; 898 default: 899 reason = "unknown failure"; 900 break; 901 } 902 mdb_printf("%?s <%s>\n", "", reason); 903 } 904 905 for (frame = 0; frame < sep->se_depth; frame++) 906 mdb_printf("%?s %a\n", "", sep->se_stack[frame]); 907 if (sep->se_overflow) 908 mdb_printf("%?s ... truncated ...\n", ""); 909 mdb_printf("\n"); 910 } 911 912 if (flags & DCMD_ADDRSPEC) { 913 for (idx = 0; idx < p.pipe_len; idx++) 914 if (seen[idx] == 0) 915 mdb_warn("stacks: %p not in thread list\n", 916 p.pipe_data[idx]); 917 } 918 return (DCMD_OK); 919 } 920