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 }