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