diff --git a/components/backtrace/los_backtrace.c b/components/backtrace/los_backtrace.c index db817ade..c9742a1e 100644 --- a/components/backtrace/los_backtrace.c +++ b/components/backtrace/los_backtrace.c @@ -112,7 +112,7 @@ STATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINT { if (SP != 0) { *stackStart = SP; - if ((SP >= CODE_START_ADDR) && (SP < CSTACK_END_ADDR)) { + if ((SP >= CSTACK_START_ADDR) && (SP < CSTACK_END_ADDR)) { *stackEnd = CSTACK_END_ADDR; } else { UINT32 taskID = LOS_CurTaskIDGet(); @@ -120,7 +120,7 @@ STATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINT *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize; if ((SP < (UINTPTR)taskCB->topOfStack) || (SP >= *stackEnd)) { PRINT_ERR("msp statck [0x%x, 0x%x], cur task stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n", - CODE_START_ADDR, CSTACK_END_ADDR, (UINTPTR)taskCB->topOfStack, *stackEnd, SP); + CSTACK_START_ADDR, CSTACK_END_ADDR, (UINTPTR)taskCB->topOfStack, *stackEnd, SP); return LOS_NOK; } } @@ -128,9 +128,9 @@ STATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINT if (HalSpGet() != HalPspGet()) { *stackStart = HalMspGet(); *stackEnd = CSTACK_END_ADDR; - if ((*stackStart < CODE_START_ADDR) || (*stackStart >= CSTACK_END_ADDR)) { + if ((*stackStart < CSTACK_START_ADDR) || (*stackStart >= CSTACK_END_ADDR)) { PRINT_ERR("msp stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n", - CODE_START_ADDR, CSTACK_END_ADDR, *stackStart); + CSTACK_START_ADDR, CSTACK_END_ADDR, *stackStart); return LOS_NOK; } PRINTK("msp, start = %x, end = %x\n", *stackStart, *stackEnd); @@ -179,45 +179,6 @@ STATIC INLINE UINTPTR OsAddrIsValid(UINTPTR sp) return pc; } - -VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP) -{ - if (LR == NULL) { - return; - } - - UINTPTR stackStart; - UINTPTR stackEnd; - UINT32 count = 0; - UINT32 index = 0; - UINTPTR sp; - UINTPTR pc; - UINT32 ret; - - ret = OsStackAddrGet(&stackStart, &stackEnd, SP); - if (ret != LOS_OK) { - return; - } - - /* Traverse the stack space and find the LR address. */ - for (sp = stackStart; sp < stackEnd; sp += sizeof(UINTPTR)) { - pc = OsAddrIsValid(sp); - if ((pc != 0) && (count < LRSize)) { - if (index++ < jumpCount) { - continue; - } - LR[count] = pc; - count++; - if (count == LRSize) { - break; - } - } - } - - if (count < LRSize) { - LR[count] = 0; - } -} #elif (LOSCFG_BACKTRACE_TYPE == 2) STATIC INLINE BOOL OsBackTraceFpCheck(UINT32 value); #define OS_BACKTRACE_START 1 @@ -267,10 +228,163 @@ VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP) LR[count] = 0; } } +#elif (LOSCFG_BACKTRACE_TYPE == 3) +#define OS_BACKTRACE_START 1 +#define OS_JALX_INS_MASK 0x7F +#define OS_JAL_INS_LOW 0x6F +#define OS_JAL_16_INS_MASK 0x2001 +#define OS_JALR_INS_LOW 0x67 +#define OS_JALR_16_INS_MASK 0x9002 +#define OS_JR_16_INS_MASK 0x8002 +#define OS_J_16_INS_MASK 0xA001 + +STATIC INLINE BOOL OsInsIsJump(UINTPTR addr) +{ + UINT16 ins1 = *((UINT16 *)addr); + UINT16 ins2 = *((UINT16 *)(addr + 2)); + + /* Jal ins */ + if (((ins1 & OS_JALX_INS_MASK) == OS_JAL_INS_LOW) || + ((ins1 & OS_JAL_16_INS_MASK) == OS_JAL_16_INS_MASK) || + ((ins2 & OS_JAL_16_INS_MASK) == OS_JAL_16_INS_MASK)) { + return TRUE; + } + + /* Jalr ins */ + if (((ins1 & OS_JALX_INS_MASK) == OS_JALR_INS_LOW) || + ((ins1 & OS_JALR_16_INS_MASK) == OS_JALR_16_INS_MASK) || + ((ins2 & OS_JALR_16_INS_MASK) == OS_JALR_16_INS_MASK)) { + return TRUE; + } + + /* Jr ins */ + if (((ins1 & OS_JR_16_INS_MASK) == OS_JR_16_INS_MASK) || + ((ins2 & OS_JR_16_INS_MASK) == OS_JR_16_INS_MASK)) { + return TRUE; + } + + /* J ins */ + if (((ins1 & OS_J_16_INS_MASK) == OS_J_16_INS_MASK) || + ((ins2 & OS_J_16_INS_MASK) == OS_J_16_INS_MASK)) { + return TRUE; + } + + return FALSE; +} + +STATIC INLINE UINTPTR OsSpGet(VOID) +{ + UINTPTR sp = 0; + __asm volatile("mv %0, sp" : "=r"(sp)); + dsb(); + return sp; +} + +STATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINTPTR SP) +{ + if (SP != 0) { + *stackStart = SP; + if ((SP >= CSTACK_START_ADDR) && (SP < CSTACK_END_ADDR)) { + *stackEnd = CSTACK_END_ADDR; + } else { + UINT32 taskID = LOS_CurTaskIDGet(); + LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID); + *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize; + if ((SP < (UINTPTR)taskCB->topOfStack) || (SP >= *stackEnd)) { + PRINT_ERR("msp statck [0x%x, 0x%x], cur task stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n", + CSTACK_START_ADDR, CSTACK_END_ADDR, (UINTPTR)taskCB->topOfStack, *stackEnd, SP); + return LOS_NOK; + } + } + } else { + if (!LOS_TaskIsRunning()) { + *stackStart = OsSpGet(); + *stackEnd = CSTACK_END_ADDR; + if ((*stackStart < CSTACK_START_ADDR) || (*stackStart >= CSTACK_END_ADDR)) { + PRINT_ERR("msp stack [0x%x, 0x%x], cur sp(0x%x) is overflow!\n", + CSTACK_START_ADDR, CSTACK_END_ADDR, *stackStart); + return LOS_NOK; + } + } else { + *stackStart = OsSpGet(); + UINT32 taskID = LOS_CurTaskIDGet(); + LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID); + *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize; + if ((*stackStart < (UINTPTR)taskCB->topOfStack) || (*stackStart >= *stackEnd)) { + PRINT_ERR("psp stack [0x%x, 0x%x], cur sp(0x%x) is overflow, cur task id is %d!\n", + taskCB->topOfStack, *stackEnd, *stackStart, taskID); + return LOS_NOK; + } + } + } + + return LOS_OK; +} + +STATIC INLINE UINTPTR OsAddrIsValid(UINTPTR sp) +{ + UINTPTR pc; + BOOL ret; + + pc = *((UINTPTR *)sp); + + ret = OsStackDataIsCodeAddr(pc); + if (ret == FALSE) { + return 0; + } + + ret = OsInsIsJump(pc - sizeof(UINTPTR)); + if (ret == FALSE) { + return 0; + } + + return pc; +} #else #error Unknown backtrace type. #endif +#if (LOSCFG_BACKTRACE_TYPE == 1) || (LOSCFG_BACKTRACE_TYPE == 3) +VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP) +{ + if (LR == NULL) { + return; + } + + UINTPTR stackStart; + UINTPTR stackEnd; + UINT32 count = 0; + UINT32 index = 0; + UINTPTR sp; + UINTPTR pc; + UINT32 ret; + + ret = OsStackAddrGet(&stackStart, &stackEnd, SP); + if (ret != LOS_OK) { + return; + } + + /* Traverse the stack space and find the LR address. */ + for (sp = stackStart; sp < stackEnd; sp += sizeof(UINTPTR)) { + pc = OsAddrIsValid(sp); + if ((pc != 0) && (count < LRSize)) { + if (index++ < jumpCount) { + continue; + } + LR[count] = pc; + count++; + if (count == LRSize) { + break; + } + } + } + + if (count < LRSize) { + LR[count] = 0; + } +} +#endif + VOID LOS_BackTrace(VOID) { UINTPTR LR[BACKTRACE_MAX_DEPTH] = {0}; diff --git a/components/backtrace/los_backtrace.h b/components/backtrace/los_backtrace.h index b0d27d43..e62f93da 100644 --- a/components/backtrace/los_backtrace.h +++ b/components/backtrace/los_backtrace.h @@ -115,18 +115,26 @@ extern CHAR *CSTACK_SECTION_END; #else #error Unknown compiler. #endif -#elif (LOSCFG_BACKTRACE_TYPE == 2) +#elif (LOSCFG_BACKTRACE_TYPE == 2) || (LOSCFG_BACKTRACE_TYPE == 3) #if defined(__GNUC__) /* The defalut code section start address */ #define CODE_SECTION_START __text_start /* The defalut code section end address */ #define CODE_SECTION_END __text_end +/* The default C stack section start address */ +#define CSTACK_SECTION_START __except_stack_top +/* The default C stack section end address */ +#define CSTACK_SECTION_END __start_and_irq_stack_top extern CHAR *CODE_SECTION_START; extern CHAR *CODE_SECTION_END; +extern CHAR *CSTACK_SECTION_START; +extern CHAR *CSTACK_SECTION_END; -#define CODE_START_ADDR ((UINTPTR)&CODE_SECTION_START) -#define CODE_END_ADDR ((UINTPTR)&CODE_SECTION_END) +#define CODE_START_ADDR ((UINTPTR)&CODE_SECTION_START) +#define CODE_END_ADDR ((UINTPTR)&CODE_SECTION_END) +#define CSTACK_START_ADDR ((UINTPTR)&CSTACK_SECTION_START) +#define CSTACK_END_ADDR ((UINTPTR)&CSTACK_SECTION_END) #else #error Unknown compiler. #endif diff --git a/kernel/include/los_config.h b/kernel/include/los_config.h index 052c90e7..8340e65a 100644 --- a/kernel/include/los_config.h +++ b/kernel/include/los_config.h @@ -609,8 +609,9 @@ extern UINT8 *m_aucSysMem0; * @ingroup los_config * Configuration backtrace type * 0: Close stack analysis module. - * 1: Call stack analysis for cortex-m series. - * 2: Call stack analysis for risc-v. + * 1: Call stack analysis for cortex-m series by scanning the stack. + * 2: Call stack analysis for risc-v by using frame pointer. + * 3: Call stack analysis for risc-v by scanning the stack. * others: Not currently supported. */ #ifndef LOSCFG_BACKTRACE_TYPE