diff --git a/components/backtrace/los_backtrace.c b/components/backtrace/los_backtrace.c index b1df4f70..ca3cff0a 100755 --- a/components/backtrace/los_backtrace.c +++ b/components/backtrace/los_backtrace.c @@ -45,7 +45,6 @@ WEAK BOOL OsStackDataIsCodeAddr(UINTPTR value) return FALSE; } - #if (LOSCFG_BACKTRACE_TYPE == 1) #define OS_BACKTRACE_START 2 /* Thumb instruction, so the pc must be an odd number */ @@ -587,6 +586,94 @@ VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP) LR[index] = 0; } } +#elif (LOSCFG_BACKTRACE_TYPE == 6) +#define OS_BACKTRACE_START 1 +#define STACK_OFFSET 4 +#define THUMB_OFFSET 2 +#define THUMB_BIT 16 +#define ARM_ALIGN_CODE 4 +#define THUMB_ALIGN_CODE 2 +#define BL_CMD_OFFSET 4 +#define ARM_BL_MASK 0xEB000000 +#define THUMB_BL_MASK 0xF000F000 +#define CLEAR_LOW_BIT_MASK 0xFFFFFFFE + +STATIC INLINE BOOL IsAligned(UINT32 val, UINT32 align) +{ + return ((val & (align - 1)) == 0); +} + +STATIC INLINE UINTPTR OsSpGet(VOID) +{ + UINTPTR SP; + __asm volatile("mov %0, sp" : "=r"(SP)); + return SP; +} + +STATIC INLINE BOOL IsArmValidLr(UINTPTR lr) +{ + return ((*(UINT32 *)(lr - BL_CMD_OFFSET) & ARM_BL_MASK) == ARM_BL_MASK); +} + +STATIC INLINE BOOL IsThumbValidLr(UINTPTR lr) +{ + lr = (*(UINT16 *)(lr - BL_CMD_OFFSET) << THUMB_BIT) + *(UINT16 *)(lr - THUMB_OFFSET); + return ((lr & THUMB_BL_MASK) == THUMB_BL_MASK); +} + +VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP) +{ + UINT32 count = 0; + UINT32 index = 0; + LosTaskCB *taskCB = NULL; + UINT32 taskID; + UINT32 stackStart, stackEnd; + UINTPTR framePtr, tmpFramePtr, linkReg; + + if (LR == NULL) { + return; + } + + if (SP == 0) { + SP = OsSpGet(); + } + + if (LOS_TaskIsRunning()) { + taskID = LOS_CurTaskIDGet(); + taskCB = OS_TCB_FROM_TID(taskID); + stackStart = taskCB->topOfStack; + stackEnd = stackStart + taskCB->stackSize; + } else { + stackStart = CSTACK_START_ADDR; + stackEnd = CSTACK_END_ADDR; + } + + while ((SP > stackStart) && (SP < stackEnd)) { + linkReg = *(UINTPTR *)SP; + if (!OsStackDataIsCodeAddr(linkReg)) { + SP += STACK_OFFSET; + continue; + } + if (((!IsAligned(linkReg, ARM_ALIGN_CODE)) || !IsArmValidLr(linkReg)) && + ((!IsAligned(linkReg - 1, THUMB_ALIGN_CODE)) || !IsThumbValidLr(linkReg - 1))) { + SP += STACK_OFFSET; + continue; + } + if (index >= jumpCount) { + LR[count++] = linkReg & CLEAR_LOW_BIT_MASK; + if (count == LRSize) { + break; + } + } + ++index; + SP += STACK_OFFSET; + } + + /* if linkReg is not enough,clean up the last of the effective LR as the end. */ + if (count < LRSize) { + LR[count] = 0; + } +} #else #error Unknown backtrace type. #endif diff --git a/components/backtrace/los_backtrace.h b/components/backtrace/los_backtrace.h index fabeb2db..adc81a34 100644 --- a/components/backtrace/los_backtrace.h +++ b/components/backtrace/los_backtrace.h @@ -183,6 +183,31 @@ extern CHAR *CSTACK_SECTION_END; #define ALGIN_CODE 2 #define STACK_OFFSET 4 +#elif (LOSCFG_BACKTRACE_TYPE == 6) +extern CHAR *__svc_stack; +extern CHAR *__svc_stack_top; +/* 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 __svc_stack +/* The default C stack section end address */ +#define CSTACK_SECTION_END __svc_stack_top + +extern CHAR *CODE_SECTION_START; +extern CHAR *CODE_SECTION_END; +extern CHAR *CSTACK_SECTION_START; +extern CHAR *CSTACK_SECTION_END; + +/* Default only one code section. In fact, there may be more than one. + You can define more than one and redefine the OsStackDataIsCodeAddr function + to support searching in multiple code sections */ +#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) + #endif /* This function is currently used to register the memory leak check hook, @@ -201,4 +226,5 @@ VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP); } #endif /* __cplusplus */ #endif /* __cplusplus */ -#endif \ No newline at end of file +#endif + diff --git a/kernel/include/los_config.h b/kernel/include/los_config.h index 9c9b6bfb..b21a5ef1 100644 --- a/kernel/include/los_config.h +++ b/kernel/include/los_config.h @@ -741,6 +741,7 @@ extern UINT8 *m_aucSysMem0; * 3: Call stack analysis for risc-v by scanning the stack. * 4: Call stack analysis for xtensa by scanning the stack. * 5: Call stack analysis for c-sky by scanning the stack. + * 6: Call stack analysis for arm9 by scanning the stack. * others: Not currently supported. */ #ifndef LOSCFG_BACKTRACE_TYPE