diff --git a/cm_backtrace/cm_backtrace.c b/cm_backtrace/cm_backtrace.c index 1bd2d8a..056244a 100644 --- a/cm_backtrace/cm_backtrace.c +++ b/cm_backtrace/cm_backtrace.c @@ -329,6 +329,26 @@ static void dump_stack(uint32_t stack_start_addr, size_t stack_size, uint32_t *s } #endif /* CMB_USING_DUMP_STACK_INFO */ +/* check the disassembly instruction is 'BL' or 'BLX' */ +static bool disassembly_ins_is_bl_blx(uint32_t addr) { + uint16_t ins1 = *((uint16_t *)addr); + uint16_t ins2 = *((uint16_t *)(addr + 2)); + +#define BL_INS_MASK 0xF800 +#define BL_INS_HIGH 0xF800 +#define BL_INS_LOW 0xF000 +#define BLX_INX_MASK 0xFF00 +#define BLX_INX 0x4700 + + if ((ins2 & BL_INS_MASK) == BL_INS_HIGH && (ins1 & BL_INS_MASK) == BL_INS_LOW) { + return true; + } else if ((ins2 & BLX_INX_MASK) == BLX_INX) { + return true; + } else { + return false; + } +} + /** * backtrace function call stack * @@ -347,8 +367,8 @@ size_t cm_backtrace_call_stack(uint32_t *buffer, size_t size, uint32_t sp) { if (!stack_is_overflow) { /* first depth is PC */ buffer[depth++] = regs.saved.pc; - /* second depth is from LR, so need decrease a word to PC */ - pc = regs.saved.lr - sizeof(size_t); + /* fix the LR address in thumb mode */ + pc = regs.saved.lr - 1; if ((pc >= code_start_addr) && (pc <= code_start_addr + code_size) && (depth < CMB_CALL_STACK_MAX_DEPTH) && (depth < size)) { buffer[depth++] = pc; @@ -386,8 +406,11 @@ size_t cm_backtrace_call_stack(uint32_t *buffer, size_t size, uint32_t sp) { if (pc % 2 == 0) { continue; } + /* fix the PC address in thumb mode */ + pc = *((uint32_t *) sp) - 1; if ((pc >= code_start_addr) && (pc <= code_start_addr + code_size) && (depth < CMB_CALL_STACK_MAX_DEPTH) - && (depth < size)) { + /* 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 */ if ((depth == 2) && regs_saved_lr_is_valid && (pc == buffer[1])) { continue; diff --git a/cm_backtrace/cmb_def.h b/cm_backtrace/cmb_def.h index 91aa4a2..513de68 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.3.0" +#define CMB_SW_VERSION "1.3.99" #define CMB_CPU_ARM_CORTEX_M0 0 #define CMB_CPU_ARM_CORTEX_M3 1