From 4abadfa0c4f86f22352aa5ab9ebbb4f687125a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=A4=A9=E9=BE=99=20=28Armink=29?= Date: Sun, 20 Aug 2023 13:28:04 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=AE=8C=E5=96=84=E3=80=91RTOS=20?= =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E7=9A=84=E8=AF=86=E5=88=AB=E5=87=86=E7=A1=AE?= =?UTF-8?q?=E6=80=A7=E3=80=82=E6=94=B9=E8=89=AF=20addr2line=20=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cm_backtrace/Languages/en-US/cmb_en_US.h | 2 +- cm_backtrace/Languages/zh-CN/cmb_zh_CN.h | 2 +- cm_backtrace/Languages/zh-CN/cmb_zh_CN_UTF8.h | 2 +- cm_backtrace/cm_backtrace.c | 88 +++++++++++++------ cm_backtrace/cmb_cfg.h | 4 +- cm_backtrace/cmb_def.h | 18 ++-- 6 files changed, 80 insertions(+), 36 deletions(-) diff --git a/cm_backtrace/Languages/en-US/cmb_en_US.h b/cm_backtrace/Languages/en-US/cmb_en_US.h index a172b88..a8d5fdf 100644 --- a/cm_backtrace/Languages/en-US/cmb_en_US.h +++ b/cm_backtrace/Languages/en-US/cmb_en_US.h @@ -36,7 +36,7 @@ [PRINT_MAIN_STACK_INFO] = "====== Main stack information ======", [PRINT_THREAD_STACK_OVERFLOW] = "Error: Thread stack(%08x) was overflow", [PRINT_MAIN_STACK_OVERFLOW] = "Error: Main stack(%08x) was overflow", -[PRINT_CALL_STACK_INFO] = "Show more call stack info by run: addr2line -e %s%s -a -f %s", +[PRINT_CALL_STACK_INFO] = "Show more call stack info by run: addr2line -e %s%s -afpiC %.*s", [PRINT_CALL_STACK_ERR] = "Dump call stack has an error", [PRINT_FAULT_ON_THREAD] = "Fault on thread %s", [PRINT_FAULT_ON_HANDLER] = "Fault on interrupt or bare metal(no OS) environment", diff --git a/cm_backtrace/Languages/zh-CN/cmb_zh_CN.h b/cm_backtrace/Languages/zh-CN/cmb_zh_CN.h index 1065422..be80e34 100644 --- a/cm_backtrace/Languages/zh-CN/cmb_zh_CN.h +++ b/cm_backtrace/Languages/zh-CN/cmb_zh_CN.h @@ -36,7 +36,7 @@ [PRINT_MAIN_STACK_INFO] = "============ 主堆栈信息 ============", [PRINT_THREAD_STACK_OVERFLOW] = "错误:线程栈(%08x)发生溢出", [PRINT_MAIN_STACK_OVERFLOW] = "错误:主栈(%08x)发生溢出", -[PRINT_CALL_STACK_INFO] = "查看更多函数调用栈信息,请运行:addr2line -e %s%s -a -f %s", +[PRINT_CALL_STACK_INFO] = "查看更多函数调用栈信息,请运行:addr2line -e %s%s -afpiC %.*s", [PRINT_CALL_STACK_ERR] = "获取函数调用栈失败", [PRINT_FAULT_ON_THREAD] = "在线程(%s)中发生错误异常", [PRINT_FAULT_ON_HANDLER] = "在中断或裸机环境下发生错误异常", diff --git a/cm_backtrace/Languages/zh-CN/cmb_zh_CN_UTF8.h b/cm_backtrace/Languages/zh-CN/cmb_zh_CN_UTF8.h index 040b68f..886755c 100644 --- a/cm_backtrace/Languages/zh-CN/cmb_zh_CN_UTF8.h +++ b/cm_backtrace/Languages/zh-CN/cmb_zh_CN_UTF8.h @@ -36,7 +36,7 @@ [PRINT_MAIN_STACK_INFO] = "============ 涓诲爢鏍堜俊鎭 ============", [PRINT_THREAD_STACK_OVERFLOW] = "閿欒锛氱嚎绋嬫爤(%08x)鍙戠敓婧㈠嚭", [PRINT_MAIN_STACK_OVERFLOW] = "閿欒锛氫富鏍(%08x)鍙戠敓婧㈠嚭", -[PRINT_CALL_STACK_INFO] = "鏌ョ湅鏇村鍑芥暟璋冪敤鏍堜俊鎭紝璇疯繍琛岋細addr2line -e %s%s -a -f %s", +[PRINT_CALL_STACK_INFO] = "鏌ョ湅鏇村鍑芥暟璋冪敤鏍堜俊鎭紝璇疯繍琛岋細addr2line -e %s%s -afpiC %.*s", [PRINT_CALL_STACK_ERR] = "鑾峰彇鍑芥暟璋冪敤鏍堝け璐", [PRINT_FAULT_ON_THREAD] = "鍦ㄧ嚎绋(%s)涓彂鐢熼敊璇紓甯", [PRINT_FAULT_ON_HANDLER] = "鍦ㄤ腑鏂垨瑁告満鐜涓嬪彂鐢熼敊璇紓甯", diff --git a/cm_backtrace/cm_backtrace.c b/cm_backtrace/cm_backtrace.c index d2b3f6c..4157c22 100644 --- a/cm_backtrace/cm_backtrace.c +++ b/cm_backtrace/cm_backtrace.c @@ -117,9 +117,9 @@ static const char * const print_info[] = { #endif }; -static char fw_name[CMB_NAME_MAX] = {0}; -static char hw_ver[CMB_NAME_MAX] = {0}; -static char sw_ver[CMB_NAME_MAX] = {0}; +static char fw_name[CMB_NAME_MAX + 1] = {0}; +static char hw_ver[CMB_NAME_MAX + 1] = {0}; +static char sw_ver[CMB_NAME_MAX + 1] = {0}; static uint32_t main_stack_start_addr = 0; static size_t main_stack_size = 0; static uint32_t code_start_addr = 0; @@ -187,24 +187,25 @@ void cm_backtrace_firmware_info(void) { * @param start_addr stack start address * @param size stack size */ -static void get_cur_thread_stack_info(uint32_t sp, uint32_t *start_addr, size_t *size) { +static void get_cur_thread_stack_info(uint32_t *sp, uint32_t *start_addr, size_t *size) { CMB_ASSERT(start_addr); CMB_ASSERT(size); #if (CMB_OS_PLATFORM_TYPE == CMB_OS_PLATFORM_RTT) *start_addr = (uint32_t) rt_thread_self()->stack_addr; *size = rt_thread_self()->stack_size; + *sp = (uint32_t)rt_thread_self()->sp; #elif (CMB_OS_PLATFORM_TYPE == CMB_OS_PLATFORM_UCOSII) extern OS_TCB *OSTCBCur; *start_addr = (uint32_t) OSTCBCur->OSTCBStkBottom; *size = OSTCBCur->OSTCBStkSize * sizeof(OS_STK); #elif (CMB_OS_PLATFORM_TYPE == CMB_OS_PLATFORM_UCOSIII) - extern OS_TCB *OSTCBCurPtr; - + extern OS_TCB *OSTCBCurPtr; + *start_addr = (uint32_t) OSTCBCurPtr->StkBasePtr; *size = OSTCBCurPtr->StkSize * sizeof(CPU_STK_SIZE); -#elif (CMB_OS_PLATFORM_TYPE == CMB_OS_PLATFORM_FREERTOS) +#elif (CMB_OS_PLATFORM_TYPE == CMB_OS_PLATFORM_FREERTOS) *start_addr = (uint32_t)vTaskStackAddr(); *size = vTaskStackSize() * sizeof( StackType_t ); #elif (CMB_OS_PLATFORM_TYPE == CMB_OS_PLATFORM_RTX5) @@ -230,8 +231,8 @@ static const char *get_cur_thread_name(void) { #endif /* OS_TASK_NAME_SIZE > 0 || OS_TASK_NAME_EN > 0 */ #elif (CMB_OS_PLATFORM_TYPE == CMB_OS_PLATFORM_UCOSIII) - extern OS_TCB *OSTCBCurPtr; - + extern OS_TCB *OSTCBCurPtr; + return (const char *)OSTCBCurPtr->NamePtr; #elif (CMB_OS_PLATFORM_TYPE == CMB_OS_PLATFORM_FREERTOS) return vTaskName(); @@ -248,6 +249,8 @@ static const char *get_cur_thread_name(void) { * dump current stack information */ static void dump_stack(uint32_t stack_start_addr, size_t stack_size, uint32_t *stack_pointer) { + uint32_t deep = CMB_DUMP_STACK_DEPTH_SIZE; + if (stack_is_overflow) { if (on_thread_before_fault) { cmb_println(print_info[PRINT_THREAD_STACK_OVERFLOW], stack_pointer); @@ -261,7 +264,7 @@ static void dump_stack(uint32_t stack_start_addr, size_t stack_size, uint32_t *s } } cmb_println(print_info[PRINT_THREAD_STACK_INFO]); - for (; (uint32_t) stack_pointer < stack_start_addr + stack_size; stack_pointer++) { + for (; (uint32_t) stack_pointer < stack_start_addr + stack_size && deep; stack_pointer++, deep--) { cmb_println(" addr: %08x data: %08x", stack_pointer, *stack_pointer); } cmb_println("===================================="); @@ -288,6 +291,31 @@ static bool disassembly_ins_is_bl_blx(uint32_t addr) { } } +size_t cm_backtrace_call_stack_any(uint32_t *buffer, size_t size, uint32_t sp, uint32_t stack_start_addr, uint32_t stack_size) +{ + uint32_t pc; + size_t depth = 0; + /* copy called function address */ + for (; sp < stack_start_addr + stack_size; sp += sizeof(size_t)) { + /* the *sp value may be LR, so need decrease a word to PC */ + pc = *((uint32_t *) sp) - sizeof(size_t); + /* the Cortex-M using thumb instruction, so the pc must be an odd number */ + if (pc % 2 == 0) { + continue; + } + /* fix the PC address in thumb mode */ + pc = *((uint32_t *) sp) - 1; + if ((pc >= code_start_addr + sizeof(size_t)) && (pc <= code_start_addr + code_size) && (depth < CMB_CALL_STACK_MAX_DEPTH) + /* check the the instruction before PC address is 'BL' or 'BLX' */ + && disassembly_ins_is_bl_blx(pc - sizeof(size_t)) && (depth < size)) { + /* the second depth function may be already saved, so need ignore repeat */ + buffer[depth++] = pc; + } + } + + return depth; +} + /** * backtrace function call stack * @@ -299,6 +327,10 @@ static bool disassembly_ins_is_bl_blx(uint32_t addr) { */ size_t cm_backtrace_call_stack(uint32_t *buffer, size_t size, uint32_t sp) { uint32_t stack_start_addr = main_stack_start_addr, pc; + +#ifdef CMB_USING_OS_PLATFORM + uint32_t tcb_sp; +#endif size_t depth = 0, stack_size = main_stack_size; bool regs_saved_lr_is_valid = false; @@ -318,23 +350,19 @@ size_t cm_backtrace_call_stack(uint32_t *buffer, size_t size, uint32_t sp) { #ifdef CMB_USING_OS_PLATFORM /* program is running on thread before fault */ if (on_thread_before_fault) { - get_cur_thread_stack_info(sp, &stack_start_addr, &stack_size); + get_cur_thread_stack_info(&tcb_sp, &stack_start_addr, &stack_size); } } else { /* OS environment */ if (cmb_get_sp() == cmb_get_psp()) { - get_cur_thread_stack_info(sp, &stack_start_addr, &stack_size); + get_cur_thread_stack_info(&tcb_sp, &stack_start_addr, &stack_size); } #endif /* CMB_USING_OS_PLATFORM */ } if (stack_is_overflow) { - if (sp < stack_start_addr) { - sp = stack_start_addr; - } else if (sp > stack_start_addr + stack_size) { - sp = stack_start_addr + stack_size; - } + sp = stack_start_addr; } /* copy called function address */ @@ -378,8 +406,8 @@ static void print_call_stack(uint32_t sp) { } if (cur_depth) { - call_stack_info[cur_depth * (8 + 1) - 1] = '\0'; - cmb_println(print_info[PRINT_CALL_STACK_INFO], fw_name, CMB_ELF_FILE_EXTENSION_NAME, call_stack_info); + cmb_println(print_info[PRINT_CALL_STACK_INFO], fw_name, CMB_ELF_FILE_EXTENSION_NAME, cur_depth * (8 + 1), + call_stack_info); } else { cmb_println(print_info[PRINT_CALL_STACK_ERR]); } @@ -391,12 +419,13 @@ static void print_call_stack(uint32_t sp) { * @param sp the stack pointer when on assert occurred */ void cm_backtrace_assert(uint32_t sp) { - CMB_ASSERT(init_ok); - #ifdef CMB_USING_OS_PLATFORM + uint32_t tcb_sp; uint32_t cur_stack_pointer = cmb_get_sp(); #endif + CMB_ASSERT(init_ok); + cmb_println(""); cm_backtrace_firmware_info(); @@ -415,7 +444,7 @@ void cm_backtrace_assert(uint32_t sp) { #ifdef CMB_USING_DUMP_STACK_INFO uint32_t stack_start_addr; size_t stack_size; - get_cur_thread_stack_info(sp, &stack_start_addr, &stack_size); + get_cur_thread_stack_info(&tcb_sp, &stack_start_addr, &stack_size); dump_stack(stack_start_addr, stack_size, (uint32_t *) sp); #endif /* CMB_USING_DUMP_STACK_INFO */ @@ -570,7 +599,7 @@ static uint32_t statck_del_fpu_regs(uint32_t fault_handler_lr, uint32_t sp) { * @param fault_handler_sp the stack pointer on fault handler */ void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp) { - uint32_t stack_pointer = fault_handler_sp, saved_regs_addr = stack_pointer; + uint32_t stack_pointer = fault_handler_sp, saved_regs_addr = stack_pointer, tcb_stack_pointer = 0; const char *regs_name[] = { "R0 ", "R1 ", "R2 ", "R3 ", "R12", "LR ", "PC ", "PSR" }; #ifdef CMB_USING_DUMP_STACK_INFO @@ -595,7 +624,7 @@ void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp) { saved_regs_addr = stack_pointer = cmb_get_psp(); #ifdef CMB_USING_DUMP_STACK_INFO - get_cur_thread_stack_info(stack_pointer, &stack_start_addr, &stack_size); + get_cur_thread_stack_info(&tcb_stack_pointer, &stack_start_addr, &stack_size); #endif /* CMB_USING_DUMP_STACK_INFO */ } else { @@ -617,14 +646,21 @@ void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp) { #ifdef CMB_USING_DUMP_STACK_INFO /* check stack overflow */ if (stack_pointer < stack_start_addr || stack_pointer > stack_start_addr + stack_size) { + cmb_println("stack_pointer: 0x%08x, stack_start_addr: 0x%08x, stack_end_addr: 0x%08x", stack_pointer, stack_start_addr, + stack_start_addr + stack_size); stack_is_overflow = true; +#if (CMB_OS_PLATFORM_TYPE == CMB_OS_PLATFORM_RTT) + if (on_thread_before_fault) { + /* change the stack start adder to TCB->sp when stack is overflow */ + stack_pointer = tcb_stack_pointer; + } +#endif } /* dump stack information */ dump_stack(stack_start_addr, stack_size, (uint32_t *) stack_pointer); #endif /* CMB_USING_DUMP_STACK_INFO */ - /* the stack frame may be get failed when it is overflow */ - if (!stack_is_overflow) { + { /* dump register */ cmb_println(print_info[PRINT_REGS_TITLE]); diff --git a/cm_backtrace/cmb_cfg.h b/cm_backtrace/cmb_cfg.h index 3ca90e6..a622ed8 100644 --- a/cm_backtrace/cmb_cfg.h +++ b/cm_backtrace/cmb_cfg.h @@ -38,9 +38,9 @@ /* OS platform type, must config when CMB_USING_OS_PLATFORM is enable */ /* #define CMB_OS_PLATFORM_TYPE CMB_OS_PLATFORM_RTT or CMB_OS_PLATFORM_UCOSII or CMB_OS_PLATFORM_UCOSIII or CMB_OS_PLATFORM_FREERTOS or CMB_OS_PLATFORM_RTX5 */ /* cpu platform type, must config by user */ -#define CMB_CPU_PLATFORM_TYPE /* CMB_CPU_ARM_CORTEX_M0 or CMB_CPU_ARM_CORTEX_M3 or CMB_CPU_ARM_CORTEX_M4 or CMB_CPU_ARM_CORTEX_M7 */ +#define CMB_CPU_PLATFORM_TYPE /* CMB_CPU_ARM_CORTEX_M0 or CMB_CPU_ARM_CORTEX_M3 or CMB_CPU_ARM_CORTEX_M4 or CMB_CPU_ARM_CORTEX_M7 or CMB_CPU_ARM_CORTEX_M33 */ /* enable dump stack information */ /* #define CMB_USING_DUMP_STACK_INFO */ /* language of print information */ -/* #define CMB_PRINT_LANGUAGE CMB_PRINT_LANGUAGE_ENGLISH(default) or CMB_PRINT_LANGUAGE_CHINESE */ +/* #define CMB_PRINT_LANGUAGE CMB_PRINT_LANGUAGE_ENGLISH(default) or CMB_PRINT_LANGUAGE_CHINESE or CMB_PRINT_LANGUAGE_CHINESE_UTF8 */ #endif /* _CMB_CFG_H_ */ diff --git a/cm_backtrace/cmb_def.h b/cm_backtrace/cmb_def.h index 07b5405..d01dad1 100644 --- a/cm_backtrace/cmb_def.h +++ b/cm_backtrace/cmb_def.h @@ -34,7 +34,7 @@ #include /* library software version number */ -#define CMB_SW_VERSION "1.4.1" +#define CMB_SW_VERSION "1.4.2" #define CMB_CPU_ARM_CORTEX_M0 0 #define CMB_CPU_ARM_CORTEX_M3 1 @@ -102,9 +102,17 @@ #error "not supported compiler" #endif -/* supported function call stack max depth, default is 16 */ +/* supported function call stack max depth, default is 32 */ #ifndef CMB_CALL_STACK_MAX_DEPTH -#define CMB_CALL_STACK_MAX_DEPTH 16 +#define CMB_CALL_STACK_MAX_DEPTH 32 +#endif + +/* + * The maximum print depth in case of exception prevents + * too much stack information from printing and insufficient log space + */ +#ifndef CMB_DUMP_STACK_DEPTH_SIZE +#define CMB_DUMP_STACK_DEPTH_SIZE (16) #endif /* system handler control and state register */ @@ -302,7 +310,7 @@ if (!(EXPR)) \ } /* ELF(Executable and Linking Format) file extension name for each compiler */ -#if defined(__ARMCC_VERSION) +#if defined(__CC_ARM) || defined(__CLANG_ARM) || defined(__ARMCC_VERSION) #define CMB_ELF_FILE_EXTENSION_NAME ".axf" #elif defined(__ICCARM__) #define CMB_ELF_FILE_EXTENSION_NAME ".out" @@ -358,7 +366,7 @@ if (!(EXPR)) \ mov r0, sp bx lr } -#elif defined(__clang__) +#elif defined(__CLANG_ARM) __attribute__( (always_inline) ) static __inline uint32_t cmb_get_msp(void) { uint32_t result; __asm volatile ("mrs %0, msp" : "=r" (result) );