已关闭
mockcpp在aarch64环境下出现非法指令,异常内存访问,长跳转指令错误,需要修改代码 #1
wangtao创建于  3月4日关闭于  3月9日
wangtao
3月4日 创建

根据mockcpp源码,在jmpaarch文件中,跳转指令需要使用强制跳转,并且范围要大,建议参考如下代码。

#define ARM_BYTE_ORDER(x) ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24)
const uint32_t push_reg_code = ARM_BYTE_ORDER(0xfd7bbfa9); // stp x29, x30, [sp,#-16]! 先把sp指针减去16,然后,把寄存器x29和x30这两个64位寄存器存放到sp所指的地址处
const uint32_t jump_code = ARM_BYTE_ORDER(0xc0033fd6); // blr x30 跳转到装函数,执行后返回到此处的下一条指令以回复寄存器的内容
const uint32_t pop_reg_code = ARM_BYTE_ORDER(0xfd7bc1a8); // ldp x29, x30, [sp],#16 把sp所指内存地址处的16字节内容拷贝到寄存器x29和x30中,然后把sp加上16。这样,栈空间就恢复了
const uint32_t ret_code = ARM_BYTE_ORDER(0xc0035fd6); // ret
static inline uint32_t get_mov_x30_code(uintptr_t val)
{
uint32_t code = 0xd280001e; // mov 指令是 11010010 100 + 16bit val + 5bit reg id
val = (val & 0xffff) << 5;
code |= (uint32_t)val;
return code;
}

static inline uint32_t get_movk_x30_code(uintptr_t val, uint32_t pos)
{
uint32_t code = 0xf280001e; // movk 指令是 11110010 1 + 2bit offset + 16bit val + 5bit reg id
pos &= 0x3;
val = ((val >> (16 * pos)) & 0xffff) << 5;
code |= (uint32_t)val;
pos = pos << 21;
code |= pos;
return code;
}
#define SET_JMP_CODE(base, from, to) do {
uint32_t *d_ptr = (uint32_t *)base;
d_ptr[0] = push_reg_code;
d_ptr[1] = get_mov_x30_code((uintptr_t)to);
d_ptr[2] = get_movk_x30_code((uintptr_t)to, 1);
d_ptr[3] = get_movk_x30_code((uintptr_t)to, 2);
d_ptr[4] = get_movk_x30_code((uintptr_t)to, 3);
d_ptr[5] = jump_code;
d_ptr[6] = pop_reg_code;
d_ptr[7] = ret_code;
} while(0)

likedislike
wangtao
3月4日 评论:

5cc1c173e166413789a2f68ed541ae0f.patch
基于以上代码,生成补丁,请验证

likedislike
wangtao
3月4日 评论:
wangtao
3月5日 评论:

使用如上方法,需要修改32字节的代码段,对于空的小函数,可能代码段会小于32字节,因此需要增加编译选项<<<STREQUAL: ${CMAKE_SYSTEM_PROCESSOR}, aarch64>:-falign-functions=32>,向上对齐到32字节,防止修改到下一个函数,产生异常。

likedislike
Wwangtao
3月9日 关闭了 issue