#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)
const uint32_t push_reg_code = ARM_BYTE_ORDER(0xfd7bbfa9);
const uint32_t jump_code = ARM_BYTE_ORDER(0xc0033fd6);
const uint32_t pop_reg_code = ARM_BYTE_ORDER(0xfd7bc1a8);
const uint32_t ret_code = ARM_BYTE_ORDER(0xc0035fd6);
static inline uint32_t get_mov_x30_code(uintptr_t val)
{
uint32_t code = 0xd280001e;
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;
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