mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-23 20:57:20 +08:00
update components & lwp. (#7888)
This commit is contained in:
@@ -6,10 +6,15 @@
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-06-02 Jesven the first version
|
||||
* 2023-06-24 WangXiaoyao Support backtrace for non-active thread
|
||||
*/
|
||||
|
||||
#include "mm_aspace.h"
|
||||
#include "mmu.h"
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <backtrace.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define BT_NESTING_MAX 100
|
||||
|
||||
@@ -19,7 +24,7 @@ static int unwind_frame(struct bt_frame *frame)
|
||||
|
||||
if ((fp & 0x7)
|
||||
#ifdef RT_USING_LWP
|
||||
|| fp < KERNEL_VADDR_START
|
||||
|| (rt_kmem_v2p((void *)fp) == ARCH_MAP_FAILED)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
@@ -27,16 +32,18 @@ static int unwind_frame(struct bt_frame *frame)
|
||||
}
|
||||
frame->fp = *(unsigned long *)fp;
|
||||
frame->pc = *(unsigned long *)(fp + 8);
|
||||
|
||||
if ((rt_kmem_v2p((void *)frame->pc) == ARCH_MAP_FAILED))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void walk_unwind(unsigned long pc, unsigned long fp)
|
||||
{
|
||||
struct bt_frame frame;
|
||||
struct bt_frame frame = {fp, 1};
|
||||
unsigned long lr = pc;
|
||||
int nesting = 0;
|
||||
|
||||
frame.fp = fp;
|
||||
while (nesting < BT_NESTING_MAX)
|
||||
{
|
||||
rt_kprintf(" %p", (void *)lr);
|
||||
@@ -51,18 +58,128 @@ static void walk_unwind(unsigned long pc, unsigned long fp)
|
||||
|
||||
void backtrace(unsigned long pc, unsigned long lr, unsigned long fp)
|
||||
{
|
||||
rt_kprintf("please use: addr2line -e rtthread.elf -a -f %p", (void *)pc);
|
||||
walk_unwind(lr, fp);
|
||||
rt_kprintf("please use: addr2line -e rtthread.elf -a -f");
|
||||
if (pc)
|
||||
rt_kprintf(" %p", (void *)pc);
|
||||
|
||||
if (lr && fp)
|
||||
walk_unwind(lr, fp);
|
||||
rt_kprintf("\n");
|
||||
}
|
||||
|
||||
int rt_backtrace(void)
|
||||
{
|
||||
unsigned long pc = (unsigned long)backtrace;
|
||||
unsigned long ra = (unsigned long)__builtin_return_address(0U);
|
||||
unsigned long fr = (unsigned long)__builtin_frame_address(0U);
|
||||
|
||||
backtrace(pc, ra, fr);
|
||||
backtrace(0, ra, fr);
|
||||
return 0;
|
||||
}
|
||||
MSH_CMD_EXPORT_ALIAS(rt_backtrace, bt_test, backtrace test);
|
||||
|
||||
#define ARCH_CONTEXT_FETCH(pctx, id) (*(((unsigned long *)pctx) + (id)))
|
||||
|
||||
int rt_backtrace_thread(rt_thread_t thread)
|
||||
{
|
||||
unsigned long lr;
|
||||
unsigned long fp;
|
||||
|
||||
if (thread == rt_thread_self())
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
lr = ARCH_CONTEXT_FETCH(thread->sp, 3);
|
||||
fp = ARCH_CONTEXT_FETCH(thread->sp, 7);
|
||||
backtrace(0, lr, fp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
|
||||
int rt_backtrace_user_thread(rt_thread_t thread)
|
||||
{
|
||||
unsigned long pc;
|
||||
unsigned long lr;
|
||||
unsigned long fp;
|
||||
unsigned long ctx = (unsigned long)thread->user_ctx.ctx;
|
||||
|
||||
if (ctx > (unsigned long)thread->stack_addr
|
||||
&& ctx < (unsigned long)thread->stack_addr + thread->stack_size)
|
||||
{
|
||||
pc = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 0);
|
||||
lr = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 3);
|
||||
fp = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 7);
|
||||
backtrace(pc, lr, fp);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* RT_USING_SMART */
|
||||
|
||||
static long custom_hex_to_long(const char* hex)
|
||||
{
|
||||
long result = 0;
|
||||
int i = 0;
|
||||
|
||||
// Skip the "0x" prefix
|
||||
if (hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X'))
|
||||
{
|
||||
i = 2;
|
||||
}
|
||||
|
||||
// Convert each hex digit to its decimal value
|
||||
for (; hex[i] != '\0'; i++)
|
||||
{
|
||||
char digit = hex[i];
|
||||
if (digit >= '0' && digit <= '9')
|
||||
{
|
||||
result = result * 16 + (digit - '0');
|
||||
}
|
||||
else if (digit >= 'a' && digit <= 'f')
|
||||
{
|
||||
result = result * 16 + (digit - 'a' + 10);
|
||||
}
|
||||
else if (digit >= 'A' && digit <= 'F')
|
||||
{
|
||||
result = result * 16 + (digit - 'A' + 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid hex digit
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void cmd_backtrace(int argc, char** argv)
|
||||
{
|
||||
long pid;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
rt_kprintf("please use: backtrace pid\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(argv[1], "0x", 2) == 0)
|
||||
{
|
||||
pid = custom_hex_to_long(argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
pid = atol(argv[1]);
|
||||
}
|
||||
if (pid)
|
||||
{
|
||||
rt_kprintf("backtrace %s(0x%lx), from %s\n", ((rt_thread_t)pid)->parent.name, pid, argv[1]);
|
||||
rt_backtrace_thread((rt_thread_t)pid);
|
||||
}
|
||||
}
|
||||
MSH_CMD_EXPORT_ALIAS(cmd_backtrace, backtrace, print backtrace of a thread);
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-06-02 Jesven the first version
|
||||
* 2023-06-24 WangXiaoyao Support backtrace for non-active thread
|
||||
*/
|
||||
|
||||
#ifndef __BACKTRACE_H__
|
||||
#define __BACKTRACE_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
struct bt_frame
|
||||
{
|
||||
unsigned long fp;
|
||||
@@ -20,4 +23,7 @@ struct bt_frame
|
||||
void backtrace(unsigned long pc, unsigned long lr, unsigned long fp);
|
||||
int rt_backtrace(void);
|
||||
|
||||
int rt_backtrace_user_thread(rt_thread_t thread);
|
||||
int rt_backtrace_thread(rt_thread_t thread);
|
||||
|
||||
#endif /*__BACKTRACE_H__*/
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-18 Jesven the first version
|
||||
* 2023-06-24 WangXiaoyao Support backtrace for user thread
|
||||
*/
|
||||
|
||||
#include "rtconfig.h"
|
||||
@@ -375,13 +376,31 @@ rt_hw_context_switch_interrupt:
|
||||
vector_fiq:
|
||||
B .
|
||||
|
||||
.macro SAVE_USER_CTX
|
||||
MRS X1, SPSR_EL1
|
||||
AND X1, X1, 0xf
|
||||
CMP X1, XZR
|
||||
|
||||
BNE 1f
|
||||
BL lwp_uthread_ctx_save
|
||||
LDP X0, X1, [SP]
|
||||
1:
|
||||
.endm
|
||||
|
||||
.globl vector_irq
|
||||
vector_irq:
|
||||
SAVE_CONTEXT
|
||||
STP X0, X1, [SP, #-0x10]! /* X0 is thread sp */
|
||||
|
||||
BL rt_interrupt_enter
|
||||
LDP X0, X1, [SP]
|
||||
#ifdef RT_USING_LWP
|
||||
SAVE_USER_CTX
|
||||
#endif
|
||||
BL rt_hw_trap_irq
|
||||
#ifdef RT_USING_LWP
|
||||
BL lwp_uthread_ctx_restore
|
||||
#endif
|
||||
BL rt_interrupt_leave
|
||||
|
||||
LDP X0, X1, [SP], #0x10
|
||||
@@ -515,7 +534,15 @@ vector_irq_exit:
|
||||
START_POINT(vector_exception)
|
||||
SAVE_CONTEXT
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
#ifdef RT_USING_LWP
|
||||
SAVE_USER_CTX
|
||||
#endif
|
||||
|
||||
BL rt_hw_trap_exception
|
||||
#ifdef RT_USING_LWP
|
||||
BL lwp_uthread_ctx_restore
|
||||
#endif
|
||||
|
||||
LDP X0, X1, [SP], #0x10
|
||||
MOV SP, X0
|
||||
RESTORE_CONTEXT_WITHOUT_MMU_SWITCH
|
||||
@@ -523,6 +550,9 @@ START_POINT_END(vector_exception)
|
||||
|
||||
START_POINT(vector_serror)
|
||||
SAVE_CONTEXT
|
||||
#ifdef RT_USING_LWP
|
||||
SAVE_USER_CTX
|
||||
#endif
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
BL rt_hw_trap_serror
|
||||
b .
|
||||
|
||||
@@ -296,6 +296,19 @@ void rt_hw_trap_exception(struct rt_hw_exp_stack *regs)
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
{
|
||||
rt_thread_t th;
|
||||
|
||||
th = rt_thread_self();
|
||||
if (th && th->lwp)
|
||||
{
|
||||
rt_backtrace_user_thread(th);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
backtrace((unsigned long)regs->pc, (unsigned long)regs->x30, (unsigned long)regs->x29);
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user