1 /*
2  * Copyright (c) 2024 Meta Platforms
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "kernel_shell.h"
8 
9 #include <zephyr/debug/symtab.h>
10 #include <zephyr/kernel.h>
11 
print_trace_address(void * arg,unsigned long ra)12 static bool print_trace_address(void *arg, unsigned long ra)
13 {
14 	const struct shell *sh = arg;
15 #ifdef CONFIG_SYMTAB
16 	uint32_t offset = 0;
17 	const char *name = symtab_find_symbol_name(ra, &offset);
18 
19 	shell_print(sh, "ra: %p [%s+0x%x]", (void *)ra, name, offset);
20 #else
21 	shell_print(sh, "ra: %p", (void *)ra);
22 #endif
23 
24 	return true;
25 }
26 
cmd_kernel_thread_unwind(const struct shell * sh,size_t argc,char ** argv)27 static int cmd_kernel_thread_unwind(const struct shell *sh, size_t argc, char **argv)
28 {
29 	struct k_thread *thread;
30 	int err = 0;
31 
32 	if (argc == 1) {
33 		thread = arch_current_thread();
34 	} else {
35 		thread = UINT_TO_POINTER(shell_strtoull(argv[1], 16, &err));
36 		if (err != 0) {
37 			shell_error(sh, "Unable to parse thread ID %s (err %d)", argv[1], err);
38 			return err;
39 		}
40 
41 		if (!z_thread_is_valid(thread)) {
42 			shell_error(sh, "Invalid thread id %p", (void *)thread);
43 			return -EINVAL;
44 		}
45 	}
46 	shell_print(sh, "Unwinding %p %s", (void *)thread, thread->name);
47 
48 	arch_stack_walk(print_trace_address, (void *)sh, thread, NULL);
49 
50 	return 0;
51 }
52 
53 KERNEL_THREAD_CMD_ARG_ADD(unwind, NULL, "Unwind a thread.", cmd_kernel_thread_unwind, 1, 1);
54