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