【完善】函数调用栈识别策略,增加 LR 地址更多有效性检测,提升识别准确性。

Signed-off-by: armink <armink.ztl@gmail.com>
pull/18/merge
armink 6 years ago
parent 9b1158bf12
commit f60c1c48e0

@ -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 */ #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 * 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) { if (!stack_is_overflow) {
/* first depth is PC */ /* first depth is PC */
buffer[depth++] = regs.saved.pc; buffer[depth++] = regs.saved.pc;
/* second depth is from LR, so need decrease a word to PC */ /* fix the LR address in thumb mode */
pc = regs.saved.lr - sizeof(size_t); pc = regs.saved.lr - 1;
if ((pc >= code_start_addr) && (pc <= code_start_addr + code_size) && (depth < CMB_CALL_STACK_MAX_DEPTH) if ((pc >= code_start_addr) && (pc <= code_start_addr + code_size) && (depth < CMB_CALL_STACK_MAX_DEPTH)
&& (depth < size)) { && (depth < size)) {
buffer[depth++] = pc; 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) { if (pc % 2 == 0) {
continue; 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) 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 */ /* the second depth function may be already saved, so need ignore repeat */
if ((depth == 2) && regs_saved_lr_is_valid && (pc == buffer[1])) { if ((depth == 2) && regs_saved_lr_is_valid && (pc == buffer[1])) {
continue; continue;

@ -34,7 +34,7 @@
#include <stdlib.h> #include <stdlib.h>
/* library software version number */ /* 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_M0 0
#define CMB_CPU_ARM_CORTEX_M3 1 #define CMB_CPU_ARM_CORTEX_M3 1

Loading…
Cancel
Save