实现代码
c
#ifdef RT_USING_FINSH
#include <finsh.h>
#endif
#define LED3_PIN GET_PIN(C, 13)
#if defined(__GNUC__) && defined(RT_USING_FINSH)
static void thread_stack_call_fun(int argc, char **argv)
{
struct rt_object_information *info;
rt_list_t *node;
int max_depth = RT_BACKTRACE_LEVEL_MAX_NR;
int dump_all = 0;
const char *target_name = RT_NULL;
if (argc > 1)
{
if (rt_strcmp(argv[1], "-a") == 0)
dump_all = 1;
else
target_name = argv[1];
if (argc > 2)
max_depth = atoi(argv[2]);
}
info = rt_object_get_information(RT_Object_Class_Thread);
if (!info)
{
rt_kprintf("Failed to get thread object information\n");
return;
}
for (node = info->object_list.next; node != &info->object_list; node = node->next)
{
rt_thread_t thread = rt_list_entry(node, struct rt_thread, parent.list);
rt_ubase_t *sp;
rt_ubase_t *stack_start;
rt_ubase_t *stack_end;
int count = 0;
if (target_name && rt_strcmp(thread->parent.name, target_name) != 0)
continue;
rt_kprintf("\n========== thread: %s ==========\n", thread->parent.name);
if (thread->sp == RT_NULL)
{
rt_kprintf(" (no stack info)\n");
continue;
}
stack_start = (rt_ubase_t *)thread->stack_addr;
stack_end = (rt_ubase_t *)((rt_ubase_t)thread->stack_addr + thread->stack_size);
sp = (rt_ubase_t *)thread->sp;
rt_kprintf(" stack: %p - %p, sp: %p, size: %d\n",
stack_start, stack_end, sp, thread->stack_size);
if (!dump_all)
{
rt_kprintf(" (use -a to dump all stack, now only scan from sp to stack end)\n");
}
{
rt_ubase_t *scan_start = sp;
rt_ubase_t *scan_end = dump_all ? stack_end : (sp + 128);
if (scan_end > stack_end)
scan_end = stack_end;
rt_kprintf(" call stack (addr2line -e rtthread.elf -a -f):\n");
for (rt_ubase_t *p = scan_start; p < scan_end && count < max_depth; p++)
{
rt_ubase_t val = *p;
if (val >= 0x08000000 && val <= 0x08080000)
{
rt_kprintf(" 0x%08lx", val);
count++;
}
}
if (count == 0)
rt_kprintf(" (empty)");
rt_kprintf("\n");
}
if (target_name)
break;
}
}
MSH_CMD_EXPORT(thread_stack_call_fun, dump threads stack for addr2line);
#endif
如何使用
示例输出:
========== thread: tidle ==========
stack: 0x20000f08 - 0x20001308, sp: 0x200012f0, size: 1024
call stack (addr2line -e rtthread.elf -a -f):
0x0800abcd 0x0800cdef
把输出的地址复制出来,在 PC 命令行中执行:
addr2line -e rtthread.elf -a -f 0x0800abcd 0x0800cdef
查看函数名和源码位置。
带参数用法:
│命令 │说明 │
│thread_stack_call_fun │列出所有线程栈中的调用地址 │
│thread_stack_call_fun -a │扫描整个栈空间(默认只扫 sp 后 128 字节) │
│thread_stack_call_fun tidle │只看指定线程 │
│thread_stack_call_fun tidle 10 │只看指定线程,最多输出 10 个地址 |