diff --git a/components/backtrace/los_backtrace.c b/components/backtrace/los_backtrace.c index 2cfef749..1910be60 100644 --- a/components/backtrace/los_backtrace.c +++ b/components/backtrace/los_backtrace.c @@ -112,15 +112,15 @@ 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(); LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID); *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize; if ((SP < (UINTPTR)taskCB->topOfStack) || (SP >= *stackEnd)) { - PRINT_ERR("msp stack [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); + 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; } } @@ -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,7 +179,172 @@ STATIC INLINE UINTPTR OsAddrIsValid(UINTPTR sp) return pc; } +#elif (LOSCFG_BACKTRACE_TYPE == 2) +STATIC INLINE BOOL OsBackTraceFpCheck(UINT32 value); +#define OS_BACKTRACE_START 1 +#define OS_RA_OFFSET 4 +#define OS_FP_OFFSET 8 +#define OS_FP_ALIGN(value) (((UINT32)(value) & (UINT32)(LOSCFG_STACK_POINT_ALIGN_SIZE - 1)) == 0) +#define OS_FP_CHECK(value) (((UINT32)(value) != FP_INIT_VALUE) && OS_FP_ALIGN(value)) +STATIC INLINE UINTPTR OsFpGet(VOID) +{ + UINTPTR fp = 0; + __asm volatile("mv %0, s0" : "=r"(fp)); + dsb(); + return fp; +} + +VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP) +{ + UNUSED(SP); + UINT32 backFp = OsFpGet(); + UINT32 tmpFp; + UINT32 backRa; + UINT32 count = 0; + UINT32 index = 0; + + if (LR == NULL) { + return; + } + + while (OS_FP_CHECK(backFp)) { + tmpFp = backFp; + backRa = *((UINT32 *)(UINTPTR)(tmpFp - OS_RA_OFFSET)); + backFp = *((UINT32 *)(UINTPTR)(tmpFp - OS_FP_OFFSET)); + if (index++ < jumpCount) { + continue; + } + + LR[count] = backRa; + count++; + if ((count == LRSize) || (backFp == tmpFp) || + (!OsStackDataIsCodeAddr(backRa))) { + break; + } + } + + if (count < LRSize) { + 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) { @@ -218,57 +383,6 @@ VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP) LR[count] = 0; } } -#elif (LOSCFG_BACKTRACE_TYPE == 2) -STATIC INLINE BOOL OsBackTraceFpCheck(UINT32 value); -#define OS_BACKTRACE_START 1 -#define OS_RA_OFFSET 4 -#define OS_FP_OFFSET 8 -#define OS_FP_ALIGN(value) (((UINT32)(value) & (UINT32)(LOSCFG_STACK_POINT_ALIGN_SIZE - 1)) == 0) -#define OS_FP_CHECK(value) (((UINT32)(value) != FP_INIT_VALUE) && OS_FP_ALIGN(value)) - -STATIC INLINE UINTPTR OsFpGet(VOID) -{ - UINTPTR fp = 0; - __asm volatile("mv %0, s0" : "=r"(fp)); - dsb(); - return fp; -} - -VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP) -{ - UNUSED(SP); - UINT32 backFp = OsFpGet(); - UINT32 tmpFp; - UINT32 backRa; - UINT32 count = 0; - UINT32 index = 0; - - if (LR == NULL) { - return; - } - - while (OS_FP_CHECK(backFp)) { - tmpFp = backFp; - backRa = *((UINT32 *)(UINTPTR)(tmpFp - OS_RA_OFFSET)); - backFp = *((UINT32 *)(UINTPTR)(tmpFp - OS_FP_OFFSET)); - if (index++ < jumpCount) { - continue; - } - - LR[count] = backRa; - count++; - if ((count == LRSize) || (backFp == tmpFp) || - (!OsStackDataIsCodeAddr(backRa))) { - break; - } - } - - if (count < LRSize) { - LR[count] = 0; - } -} -#else -#error Unknown backtrace type. #endif VOID LOS_BackTrace(VOID) diff --git a/components/backtrace/los_backtrace.h b/components/backtrace/los_backtrace.h index 70145ec5..b9d1886e 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 default code section start address */ #define CODE_SECTION_START __text_start /* The default 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 011fe472..e3f200ef 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