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