【简介】
我们之前介绍过Cortex M异常解析神器(RA8 Freertos 使用 CmBacktrace 调试死机问题)的使用。CmBacktrace 的一大特色功能是可以根据任务栈中的内容回溯出触发异常时的函数调用栈,我们本次的主题时解析下这部分功能的实现原理。Cmbacktrace 解析函数调用栈的基本原理是检查任务栈中的数据元素是是否在代码段区间,如果在代码段对应的地址的上一条指令如果为BL/BLX 指令的话改该地址就认为是函数调用栈的一个返回地址。上述逻辑的核心一是解析栈里面的代码段的地址的上一条指令是否是BL 跳转指令,对应的代码如下:
/* 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;
}
}以下是BL 指令的编码说明:

从上述描述中可知J1/J2 在Thumb-2 的指令集中为1,和代码的
BL_INS_HIGH 0xF800 BL_INS_LOW 0xF000
以下是本地实际代码中抓取的BL指令的机器码


从上述的BL 的伪代码说明中可知BL 指令做了两件事,1 更新PC指针 2 更新LR返回地址,跳转到对应的函数的时候把LR押入到栈中这也就是为啥在栈中可以找到LR返回地址的信息。

看完了BL指令我们继续看BLX指令,以下是BLX指令的编码说明。

代码中只是去了对应的指令的高八字节来比较,对应的数值定义如下:
#define BLX_INX 0x4700
我要赚赏金
