feat(liteos_m): support backtrace for riscv

Support backtrace for riscv when the compilation option(-fno-omit-frame-pointer) is not turned on.

fix #I3RVXY

Change-Id: Ie7d8a223167e5c540367bc96db646b821dae9fd0
This commit is contained in:
YOUR_NAME 2021-05-25 11:10:28 +08:00
parent e52008ba6e
commit ca1792aa4b
3 changed files with 171 additions and 48 deletions

View File

@ -112,7 +112,7 @@ STATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINT
{ {
if (SP != 0) { if (SP != 0) {
*stackStart = SP; *stackStart = SP;
if ((SP >= CODE_START_ADDR) && (SP < CSTACK_END_ADDR)) { if ((SP >= CSTACK_START_ADDR) && (SP < CSTACK_END_ADDR)) {
*stackEnd = CSTACK_END_ADDR; *stackEnd = CSTACK_END_ADDR;
} else { } else {
UINT32 taskID = LOS_CurTaskIDGet(); UINT32 taskID = LOS_CurTaskIDGet();
@ -120,7 +120,7 @@ STATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINT
*stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize; *stackEnd = (UINTPTR)taskCB->topOfStack + taskCB->stackSize;
if ((SP < (UINTPTR)taskCB->topOfStack) || (SP >= *stackEnd)) { 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", 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; return LOS_NOK;
} }
} }
@ -128,9 +128,9 @@ STATIC INLINE UINT32 OsStackAddrGet(UINTPTR *stackStart, UINTPTR *stackEnd, UINT
if (HalSpGet() != HalPspGet()) { if (HalSpGet() != HalPspGet()) {
*stackStart = HalMspGet(); *stackStart = HalMspGet();
*stackEnd = CSTACK_END_ADDR; *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", 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; return LOS_NOK;
} }
PRINTK("msp, start = %x, end = %x\n", *stackStart, *stackEnd); PRINTK("msp, start = %x, end = %x\n", *stackStart, *stackEnd);
@ -179,45 +179,6 @@ STATIC INLINE UINTPTR OsAddrIsValid(UINTPTR sp)
return pc; 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) #elif (LOSCFG_BACKTRACE_TYPE == 2)
STATIC INLINE BOOL OsBackTraceFpCheck(UINT32 value); STATIC INLINE BOOL OsBackTraceFpCheck(UINT32 value);
#define OS_BACKTRACE_START 1 #define OS_BACKTRACE_START 1
@ -267,10 +228,163 @@ VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 jumpCount, UINTPTR SP)
LR[count] = 0; 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 #else
#error Unknown backtrace type. #error Unknown backtrace type.
#endif #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) VOID LOS_BackTrace(VOID)
{ {
UINTPTR LR[BACKTRACE_MAX_DEPTH] = {0}; UINTPTR LR[BACKTRACE_MAX_DEPTH] = {0};

View File

@ -115,18 +115,26 @@ extern CHAR *CSTACK_SECTION_END;
#else #else
#error Unknown compiler. #error Unknown compiler.
#endif #endif
#elif (LOSCFG_BACKTRACE_TYPE == 2) #elif (LOSCFG_BACKTRACE_TYPE == 2) || (LOSCFG_BACKTRACE_TYPE == 3)
#if defined(__GNUC__) #if defined(__GNUC__)
/* The defalut code section start address */ /* The defalut code section start address */
#define CODE_SECTION_START __text_start #define CODE_SECTION_START __text_start
/* The defalut code section end address */ /* The defalut code section end address */
#define CODE_SECTION_END __text_end #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_START;
extern CHAR *CODE_SECTION_END; 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_START_ADDR ((UINTPTR)&CODE_SECTION_START)
#define CODE_END_ADDR ((UINTPTR)&CODE_SECTION_END) #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 #else
#error Unknown compiler. #error Unknown compiler.
#endif #endif

View File

@ -609,8 +609,9 @@ extern UINT8 *m_aucSysMem0;
* @ingroup los_config * @ingroup los_config
* Configuration backtrace type * Configuration backtrace type
* 0: Close stack analysis module. * 0: Close stack analysis module.
* 1: Call stack analysis for cortex-m series. * 1: Call stack analysis for cortex-m series by scanning the stack.
* 2: Call stack analysis for risc-v. * 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. * others: Not currently supported.
*/ */
#ifndef LOSCFG_BACKTRACE_TYPE #ifndef LOSCFG_BACKTRACE_TYPE