import Unicorn2

This commit is contained in:
Nguyen Anh Quynh
2021-10-03 22:14:44 +08:00
parent 772558119a
commit aaaea14214
837 changed files with 368717 additions and 200912 deletions

View File

@ -1,5 +1,7 @@
/* Unicorn Emulator Engine */
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015 */
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
#ifndef UC_PRIV_H
#define UC_PRIV_H
@ -14,16 +16,17 @@
// These are masks of supported modes for each cpu/arch.
// They should be updated when changes are made to the uc_mode enum typedef.
#define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS \
|UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|UC_MODE_BIG_ENDIAN|UC_MODE_ARMBE8)
|UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|UC_MODE_BIG_ENDIAN)
#define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN)
#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN)
#define UC_MODE_PPC_MASK (UC_MODE_PPC64|UC_MODE_BIG_ENDIAN)
#define UC_MODE_PPC_MASK (UC_MODE_PPC32|UC_MODE_PPC64|UC_MODE_BIG_ENDIAN)
#define UC_MODE_SPARC_MASK (UC_MODE_SPARC32|UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN)
#define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN)
#define UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN)
#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
#define READ_QWORD(x) ((uint64)x)
#define READ_QWORD(x) ((uint64_t)x)
#define READ_DWORD(x) (x & 0xffffffff)
#define READ_WORD(x) (x & 0xffff)
#define READ_BYTE_H(x) ((x & 0xffff) >> 8)
@ -34,20 +37,19 @@
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
typedef struct ModuleEntry {
void (*init)(void);
QTAILQ_ENTRY(ModuleEntry) node;
module_init_type type;
} ModuleEntry;
typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, size_t *result);
// return 0 on success, -1 on failure
typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
typedef int (*context_reg_read_t)(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
typedef int (*context_reg_write_t)(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
typedef struct {
context_reg_read_t context_reg_read;
context_reg_write_t context_reg_write;
} context_reg_rw_t;
typedef void (*reg_reset_t)(struct uc_struct *uc);
typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, const uint8_t *buf, int len);
@ -57,9 +59,7 @@ typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf, int l
typedef void (*uc_args_void_t)(void*);
typedef void (*uc_args_uc_t)(struct uc_struct*);
typedef int (*uc_args_int_uc_t)(struct uc_struct*);
typedef bool (*uc_args_tcg_enable_t)(struct uc_struct*);
typedef void (*uc_args_int_uc_t)(struct uc_struct*);
typedef void (*uc_args_uc_long_t)(struct uc_struct*, unsigned long);
@ -73,8 +73,12 @@ typedef void (*uc_mem_unmap_t)(struct uc_struct*, MemoryRegion *mr);
typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly);
typedef int (*uc_cpus_init)(struct uc_struct *, const char *);
typedef MemoryRegion* (*uc_memory_map_io_t)(struct uc_struct *uc, ram_addr_t begin, size_t size, uc_cb_mmio_read_t read_cb, uc_cb_mmio_write_t write_cb, void *user_data_read, void *user_data_write);
// which interrupt should make emulation stop?
typedef bool (*uc_args_int_t)(int intno);
typedef bool (*uc_args_int_t)(struct uc_struct *uc, int intno);
// some architecture redirect virtual memory to physical memory like Mips
typedef uint64_t (*uc_mem_redirect_t)(uint64_t address);
@ -82,6 +86,15 @@ typedef uint64_t (*uc_mem_redirect_t)(uint64_t address);
// validate if Unicorn supports hooking a given instruction
typedef bool(*uc_insn_hook_validate)(uint32_t insn_enum);
// init target page
typedef void (*uc_target_page_init)(struct uc_struct *);
// soft float init
typedef void (*uc_softfloat_initialize)(void);
// tcg flush softmmu tlb
typedef void (*uc_tcg_flush_tlb)(struct uc_struct *uc);
struct hook {
int type; // UC_HOOK_*
int insn; // instruction for HOOK_INSN
@ -93,8 +106,12 @@ struct hook {
};
// hook list offsets
//
// The lowest 6 bits are used for hook type index while the others
// are used for hook flags.
//
// mirrors the order of uc_hook_type from include/unicorn/unicorn.h
enum uc_hook_idx {
typedef enum uc_hook_idx {
UC_HOOK_INTR_IDX,
UC_HOOK_INSN_IDX,
UC_HOOK_CODE_IDX,
@ -112,7 +129,16 @@ enum uc_hook_idx {
UC_HOOK_INSN_INVALID_IDX,
UC_HOOK_MAX,
};
} uc_hook_idx;
// The lowest 6 bits are used for hook type index.
#define UC_HOOK_IDX_MASK ((1<<6)-1)
// hook flags
#define UC_HOOK_FLAG_NO_STOP (1 << 6) // Don't stop emulation in this uc_tracecode.
// The rest of bits are reserved for hook flags.
#define UC_HOOK_FLAG_MASK (~(UC_HOOK_IDX_MASK))
#define HOOK_FOREACH_VAR_DECLARE \
struct list_item *cur
@ -145,11 +171,15 @@ static inline bool _hook_exists_bounded(struct list_item *cur, uint64_t addr)
//relloc increment, KEEP THIS A POWER OF 2!
#define MEM_BLOCK_INCR 32
typedef struct TargetPageBits TargetPageBits;
typedef struct TCGContext TCGContext;
struct uc_struct {
uc_arch arch;
uc_mode mode;
uc_err errnum; // qemu/cpu-exec.c
AddressSpace as;
AddressSpace address_space_memory;
AddressSpace address_space_io;
query_t query;
reg_read_t reg_read;
reg_write_t reg_write;
@ -160,56 +190,55 @@ struct uc_struct {
uc_args_void_t release; // release resource when uc_close()
uc_args_uc_u64_t set_pc; // set PC for tracecode
uc_args_int_t stop_interrupt; // check if the interrupt should stop emulation
uc_memory_map_io_t memory_map_io;
uc_args_uc_t init_arch, cpu_exec_init_all;
uc_args_int_uc_t vm_start;
uc_args_tcg_enable_t tcg_enabled;
uc_args_uc_long_t tcg_exec_init;
uc_args_uc_ram_size_t memory_map;
uc_args_uc_ram_size_ptr_t memory_map_ptr;
uc_mem_unmap_t memory_unmap;
uc_readonly_mem_t readonly_mem;
uc_mem_redirect_t mem_redirect;
// TODO: remove current_cpu, as it's a flag for something else ("cpu running"?)
CPUState *cpu, *current_cpu;
uc_cpus_init cpus_init;
uc_target_page_init target_page;
uc_softfloat_initialize softfloat_initialize;
uc_tcg_flush_tlb tcg_flush_tlb;
/* only 1 cpu in unicorn,
do not need current_cpu to handle current running cpu. */
CPUState *cpu;
uc_insn_hook_validate insn_hook_validate;
MemoryRegion *system_memory; // qemu/exec.c
MemoryRegion io_mem_rom; // qemu/exec.c
MemoryRegion io_mem_notdirty; // qemu/exec.c
MemoryRegion *system_io; // qemu/exec.c
MemoryRegion io_mem_unassigned; // qemu/exec.c
MemoryRegion io_mem_watch; // qemu/exec.c
RAMList ram_list; // qemu/exec.c
/* qemu/exec.c */
unsigned int alloc_hint;
/* qemu/exec-vary.c */
TargetPageBits *init_target_page;
BounceBuffer bounce; // qemu/cpu-exec.c
volatile sig_atomic_t exit_request; // qemu/cpu-exec.c
bool global_dirty_log; // qemu/memory.c
/* qemu/accel/tcg/cpu-exec-common.c */
/* always be true after call tcg_exec_init(). */
bool tcg_allowed;
/* This is a multi-level map on the virtual address space.
The bottom level has pointers to PageDesc. */
void **l1_map; // qemu/translate-all.c
void **l1_map; // qemu/accel/tcg/translate-all.c
size_t l1_map_size;
/* qemu/accel/tcg/translate-all.c */
int v_l1_size;
int v_l1_shift;
int v_l2_levels;
/* code generation context */
void *tcg_ctx; // for "TCGContext tcg_ctx" in qemu/translate-all.c
TCGContext *tcg_ctx;
/* memory.c */
unsigned memory_region_transaction_depth;
bool memory_region_update_pending;
bool ioeventfd_update_pending;
QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners;
QTAILQ_HEAD(, AddressSpace) address_spaces;
MachineState *machine_state;
// qom/object.c
GHashTable *type_table;
Type type_interface;
Object *root;
Object *owner;
bool enumerating_types;
// util/module.c
ModuleTypeList init_type_list[MODULE_INIT_MAX];
// hw/intc/apic_common.c
DeviceState *vapic;
int apic_no;
bool mmio_registered;
bool apic_report_tpr_access;
GHashTable *flat_views;
bool memory_region_update_pending;
// linked lists containing hooks per type
struct list hook[UC_HOOK_MAX];
@ -221,8 +250,6 @@ struct uc_struct {
size_t emu_counter; // current counter of uc_emu_start()
size_t emu_count; // save counter of uc_emu_start()
uint64_t block_addr; // save the last block address we hooked
int size_recur_mem; // size for mem access when in a recursive call
bool init_tcg; // already initialized local TCGv variables?
@ -239,19 +266,22 @@ struct uc_struct {
uint64_t addr_end; // address where emulation stops (@end param of uc_emu_start())
int thumb; // thumb mode for ARM
int bswap_code; // For mixed endian mode
// full TCG cache leads to middle-block break in the last translation?
bool block_full;
int size_arg; // what tcg arg slot do we need to update with the size of the block?
MemoryRegion **mapped_blocks;
uint32_t mapped_block_count;
uint32_t mapped_block_cache_index;
void *qemu_thread_data; // to support cross compile to Windows (qemu-thread-win32.c)
uint32_t target_page_size;
uint32_t target_page_align;
uint64_t qemu_host_page_size;
uint64_t qemu_real_host_page_size;
int qemu_icache_linesize;
/* ARCH_REGS_STORAGE_SIZE */
int cpu_context_size;
uint64_t next_pc; // save next PC for some special cases
bool hook_insert; // insert new hook at begin of the hook list (append by default)
bool first_tb; // is this the first Translation-Block ever generated since uc_emu_start()?
struct list saved_contexts; // The contexts saved by this uc_struct.
bool no_exit_request; // Disable check_exit_request temporarily. A workaround to treat the IT block as a whole block.
};
// Metadata stub for the variable-size cpu context used with uc_context_*()
@ -259,7 +289,9 @@ struct uc_struct {
struct uc_context {
size_t context_size; // size of the real internal context structure
size_t jmp_env_size; // size of cpu->jmp_env
struct uc_struct* uc; // the uc_struct which creates this context
uc_mode mode; // the mode of this context (uc may be free-ed already)
uc_arch arch; // the arch of this context (uc may be free-ed already)
struct uc_struct *uc; // the uc_struct which creates this context
char data[0]; // context + cpu->jmp_env
};