Hhehongzhemockcpp patch
af7c8d3c创建于 2025年12月26日历史提交

#ifndef __MOCKCPP_JMP_CODE_AARCH64_H__
#define __MOCKCPP_JMP_CODE_AARCH64_H__

#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <asm/unistd.h>
#include <sys/ioctl.h>
#include <unistd.h>

MOCKCPP_NS_START

struct l2cache_addr_range
{
  uintptr_t start;
  uintptr_t end;
};

MOCKCPP_NS_END

#define ADDR_ALIGN_UP(addr) ((((addr) + ((4096) - 1)) & (~((4096) - 1))) & 0xffffffffffffffff)
#define ADDR_ALIGN_DOWN(addr) (((addr) & (~((4096) - 1))) & 0xffffffffffffffff)
#define OUTER_CACHE_INV_RANGE _IOWR('S', 0x00, struct l2cache_addr_range)

#define OUTER_CACHE_CLEAN_RANGE _IOWR('S', 0x01, struct l2cache_addr_range)

#define OUTER_CACHE_FLUSH_RANGE _IOWR('S', 0x02, struct l2cache_addr_range)

#define L1_INV_I_CACHE _IOWR('S', 0x03, struct l2cache_addr_range)

#define D_TO_I_CACHEFLUSH_RANGE _IOWR('S', 0x04, struct l2cache_addr_range)

const unsigned char jmpCodeTemplate[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

#define ARM_BYTE_ORDER(x)   ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24)
// stp x29, x30, [sp,#-16]! 将x29(fp)、x30(lr)压栈,sp指针下移16字节(栈向低地址增长)
const uint32_t push_reg_code = ARM_BYTE_ORDER(0xfd7bbfa9);
// blr x30 跳转到寄存器x30中存储的目标函数地址执行(函数调用),
// 同时将返回地址(当前指令的下一条指令地址)存入链接寄存器x30
const uint32_t jump_code = ARM_BYTE_ORDER(0xc0033fd6);
// ldp x29, x30, [sp],#16 出栈恢复帧指针(x29)和返回地址(x30),并释放栈空间
const uint32_t pop_reg_code = ARM_BYTE_ORDER(0xfd7bc1a8);
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)

#define FLUSH_CACHE(from, length) do {                                      \
    struct l2cache_addr_range usr_data;                                     \
    usr_data.start = ADDR_ALIGN_DOWN((unsigned long long)from);             \
    usr_data.end = ADDR_ALIGN_UP((unsigned long long)from) + length;        \
    __builtin___clear_cache((void *)usr_data.start, (void *)usr_data.end);  \
} while (0)

#endif