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)
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)
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 }
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
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;
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);
|
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)
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)
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 }
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
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;
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);
|