xref: /illumos-gate/usr/src/cmd/mdb/common/modules/genunix/findstack.c (revision 8e718be9d8b2bb15811a2dc0b61cbb5cc5fa3070)
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