import Unicorn2
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
/* By Dang Hoang Vu <dang.hvu -at- gmail.com>, 2015 */
|
||||
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
|
||||
|
||||
#ifndef UC_QEMU_H
|
||||
#define UC_QEMU_H
|
||||
@ -13,25 +14,23 @@ struct uc_struct;
|
||||
#include "exec/memory.h"
|
||||
|
||||
#include "qemu/thread.h"
|
||||
#include "include/qom/cpu.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
#include "vl.h"
|
||||
|
||||
// This two struct is originally from qemu/include/exec/cpu-all.h
|
||||
// This struct is originally from qemu/include/exec/ramblock.h
|
||||
// Temporarily moved here since there is circular inclusion.
|
||||
typedef struct RAMBlock {
|
||||
struct RAMBlock {
|
||||
struct MemoryRegion *mr;
|
||||
uint8_t *host;
|
||||
ram_addr_t offset;
|
||||
ram_addr_t length;
|
||||
ram_addr_t used_length;
|
||||
ram_addr_t max_length;
|
||||
uint32_t flags;
|
||||
char idstr[256];
|
||||
/* Reads can take either the iothread or the ramlist lock.
|
||||
* Writes must take both locks.
|
||||
*/
|
||||
QTAILQ_ENTRY(RAMBlock) next;
|
||||
int fd;
|
||||
} RAMBlock;
|
||||
/* RCU-enabled, writes protected by the ramlist lock */
|
||||
QLIST_ENTRY(RAMBlock) next;
|
||||
size_t page_size;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
MemoryRegion *mr;
|
||||
@ -40,12 +39,10 @@ typedef struct {
|
||||
hwaddr len;
|
||||
} BounceBuffer;
|
||||
|
||||
// This struct is originally from qemu/include/exec/ramlist.h
|
||||
typedef struct RAMList {
|
||||
/* Protected by the iothread lock. */
|
||||
unsigned long *dirty_memory[DIRTY_MEMORY_NUM];
|
||||
RAMBlock *mru_block;
|
||||
QTAILQ_HEAD(, RAMBlock) blocks;
|
||||
uint32_t version;
|
||||
QLIST_HEAD(, RAMBlock) blocks;
|
||||
} RAMList;
|
||||
|
||||
#endif
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -137,6 +137,27 @@ typedef enum uc_arm_reg {
|
||||
UC_ARM_REG_MSP,
|
||||
UC_ARM_REG_PSP,
|
||||
UC_ARM_REG_CONTROL,
|
||||
UC_ARM_REG_IAPSR,
|
||||
UC_ARM_REG_EAPSR,
|
||||
UC_ARM_REG_XPSR,
|
||||
UC_ARM_REG_EPSR,
|
||||
UC_ARM_REG_IEPSR,
|
||||
UC_ARM_REG_PRIMASK,
|
||||
UC_ARM_REG_BASEPRI,
|
||||
UC_ARM_REG_BASEPRI_MAX,
|
||||
UC_ARM_REG_FAULTMASK,
|
||||
UC_ARM_REG_APSR_NZCVQ,
|
||||
UC_ARM_REG_APSR_G,
|
||||
UC_ARM_REG_APSR_NZCVQG,
|
||||
UC_ARM_REG_IAPSR_NZCVQ,
|
||||
UC_ARM_REG_IAPSR_G,
|
||||
UC_ARM_REG_IAPSR_NZCVQG,
|
||||
UC_ARM_REG_EAPSR_NZCVQ,
|
||||
UC_ARM_REG_EAPSR_G,
|
||||
UC_ARM_REG_EAPSR_NZCVQG,
|
||||
UC_ARM_REG_XPSR_NZCVQ,
|
||||
UC_ARM_REG_XPSR_G,
|
||||
UC_ARM_REG_XPSR_NZCVQG,
|
||||
UC_ARM_REG_ENDING, // <-- mark the end of the list or registers
|
||||
|
||||
//> alias registers
|
||||
|
@ -64,23 +64,6 @@ typedef unsigned int uint32_t;
|
||||
typedef signed long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
typedef signed char int_fast8_t;
|
||||
typedef int int_fast16_t;
|
||||
typedef int int_fast32_t;
|
||||
typedef long long int_fast64_t;
|
||||
typedef unsigned char uint_fast8_t;
|
||||
typedef unsigned int uint_fast16_t;
|
||||
typedef unsigned int uint_fast32_t;
|
||||
typedef unsigned long long uint_fast64_t;
|
||||
|
||||
#if !defined(_W64)
|
||||
#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
#define _W64 __w64
|
||||
#else
|
||||
#define _W64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _INTPTR_T_DEFINED
|
||||
#define _INTPTR_T_DEFINED
|
||||
#ifdef _WIN64
|
||||
@ -111,36 +94,7 @@ typedef _W64 unsigned int uintptr_t;
|
||||
#define UINT16_MAX 0xffffui16
|
||||
#define UINT32_MAX 0xffffffffui32
|
||||
#define UINT64_MAX 0xffffffffffffffffui64
|
||||
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST16_MIN INT32_MIN
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MAX INT32_MAX
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT32_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
#ifdef _WIN64
|
||||
#define INTPTR_MIN INT64_MIN
|
||||
#define INTPTR_MAX INT64_MAX
|
||||
#define UINTPTR_MAX UINT64_MAX
|
||||
#else /* _WIN64 */
|
||||
#define INTPTR_MIN INT32_MIN
|
||||
#define INTPTR_MAX INT32_MAX
|
||||
#define UINTPTR_MAX UINT32_MAX
|
||||
#endif /* _WIN64 */
|
||||
|
||||
#else // this system has stdint.h
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER == MSC_VER_VS2010)
|
||||
#define _INTPTR 2
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#endif // (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || defined(_KERNEL_MODE)
|
||||
|
||||
@ -200,6 +154,7 @@ typedef _W64 unsigned int uintptr_t;
|
||||
|
||||
// sys/time.h compatibility
|
||||
#if defined(_MSC_VER)
|
||||
#include <sys/types.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
|
62
include/unicorn/ppc.h
Normal file
62
include/unicorn/ppc.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* Unicorn Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015-2017 */
|
||||
/* This file is released under LGPL2.
|
||||
See COPYING.LGPL2 in root directory for more details
|
||||
*/
|
||||
|
||||
#ifndef UNICORN_PPC_H
|
||||
#define UNICORN_PPC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4201)
|
||||
#endif
|
||||
|
||||
//> PPC registers
|
||||
typedef enum uc_ppc_reg {
|
||||
UC_PPC_REG_INVALID = 0,
|
||||
//> General purpose registers
|
||||
UC_PPC_REG_PC,
|
||||
|
||||
UC_PPC_REG_0,
|
||||
UC_PPC_REG_1,
|
||||
UC_PPC_REG_2,
|
||||
UC_PPC_REG_3,
|
||||
UC_PPC_REG_4,
|
||||
UC_PPC_REG_5,
|
||||
UC_PPC_REG_6,
|
||||
UC_PPC_REG_7,
|
||||
UC_PPC_REG_8,
|
||||
UC_PPC_REG_9,
|
||||
UC_PPC_REG_10,
|
||||
UC_PPC_REG_11,
|
||||
UC_PPC_REG_12,
|
||||
UC_PPC_REG_13,
|
||||
UC_PPC_REG_14,
|
||||
UC_PPC_REG_15,
|
||||
UC_PPC_REG_16,
|
||||
UC_PPC_REG_17,
|
||||
UC_PPC_REG_18,
|
||||
UC_PPC_REG_19,
|
||||
UC_PPC_REG_20,
|
||||
UC_PPC_REG_21,
|
||||
UC_PPC_REG_22,
|
||||
UC_PPC_REG_23,
|
||||
UC_PPC_REG_24,
|
||||
UC_PPC_REG_25,
|
||||
UC_PPC_REG_26,
|
||||
UC_PPC_REG_27,
|
||||
UC_PPC_REG_28,
|
||||
UC_PPC_REG_29,
|
||||
UC_PPC_REG_30,
|
||||
UC_PPC_REG_31,
|
||||
} uc_ppc_reg;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
167
include/unicorn/riscv.h
Normal file
167
include/unicorn/riscv.h
Normal file
@ -0,0 +1,167 @@
|
||||
/* Unicorn Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015-2020 */
|
||||
/* This file is released under LGPL2.
|
||||
See COPYING.LGPL2 in root directory for more details
|
||||
*/
|
||||
|
||||
#ifndef UNICORN_RISCV_H
|
||||
#define UNICORN_RISCV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4201)
|
||||
#endif
|
||||
|
||||
//> RISCV registers
|
||||
typedef enum uc_riscv_reg {
|
||||
UC_RISCV_REG_INVALID = 0,
|
||||
//> General purpose registers
|
||||
UC_RISCV_REG_X0,
|
||||
UC_RISCV_REG_X1,
|
||||
UC_RISCV_REG_X2,
|
||||
UC_RISCV_REG_X3,
|
||||
UC_RISCV_REG_X4,
|
||||
UC_RISCV_REG_X5,
|
||||
UC_RISCV_REG_X6,
|
||||
UC_RISCV_REG_X7,
|
||||
UC_RISCV_REG_X8,
|
||||
UC_RISCV_REG_X9,
|
||||
UC_RISCV_REG_X10,
|
||||
UC_RISCV_REG_X11,
|
||||
UC_RISCV_REG_X12,
|
||||
UC_RISCV_REG_X13,
|
||||
UC_RISCV_REG_X14,
|
||||
UC_RISCV_REG_X15,
|
||||
UC_RISCV_REG_X16,
|
||||
UC_RISCV_REG_X17,
|
||||
UC_RISCV_REG_X18,
|
||||
UC_RISCV_REG_X19,
|
||||
UC_RISCV_REG_X20,
|
||||
UC_RISCV_REG_X21,
|
||||
UC_RISCV_REG_X22,
|
||||
UC_RISCV_REG_X23,
|
||||
UC_RISCV_REG_X24,
|
||||
UC_RISCV_REG_X25,
|
||||
UC_RISCV_REG_X26,
|
||||
UC_RISCV_REG_X27,
|
||||
UC_RISCV_REG_X28,
|
||||
UC_RISCV_REG_X29,
|
||||
UC_RISCV_REG_X30,
|
||||
UC_RISCV_REG_X31,
|
||||
|
||||
//> Floating-point registers
|
||||
UC_RISCV_REG_F0, // "ft0"
|
||||
UC_RISCV_REG_F1, // "ft1"
|
||||
UC_RISCV_REG_F2, // "ft2"
|
||||
UC_RISCV_REG_F3, // "ft3"
|
||||
UC_RISCV_REG_F4, // "ft4"
|
||||
UC_RISCV_REG_F5, // "ft5"
|
||||
UC_RISCV_REG_F6, // "ft6"
|
||||
UC_RISCV_REG_F7, // "ft7"
|
||||
UC_RISCV_REG_F8, // "fs0"
|
||||
UC_RISCV_REG_F9, // "fs1"
|
||||
UC_RISCV_REG_F10, // "fa0"
|
||||
UC_RISCV_REG_F11, // "fa1"
|
||||
UC_RISCV_REG_F12, // "fa2"
|
||||
UC_RISCV_REG_F13, // "fa3"
|
||||
UC_RISCV_REG_F14, // "fa4"
|
||||
UC_RISCV_REG_F15, // "fa5"
|
||||
UC_RISCV_REG_F16, // "fa6"
|
||||
UC_RISCV_REG_F17, // "fa7"
|
||||
UC_RISCV_REG_F18, // "fs2"
|
||||
UC_RISCV_REG_F19, // "fs3"
|
||||
UC_RISCV_REG_F20, // "fs4"
|
||||
UC_RISCV_REG_F21, // "fs5"
|
||||
UC_RISCV_REG_F22, // "fs6"
|
||||
UC_RISCV_REG_F23, // "fs7"
|
||||
UC_RISCV_REG_F24, // "fs8"
|
||||
UC_RISCV_REG_F25, // "fs9"
|
||||
UC_RISCV_REG_F26, // "fs10"
|
||||
UC_RISCV_REG_F27, // "fs11"
|
||||
UC_RISCV_REG_F28, // "ft8"
|
||||
UC_RISCV_REG_F29, // "ft9"
|
||||
UC_RISCV_REG_F30, // "ft10"
|
||||
UC_RISCV_REG_F31, // "ft11"
|
||||
|
||||
UC_RISCV_REG_PC, // PC register
|
||||
|
||||
UC_RISCV_REG_ENDING, // <-- mark the end of the list or registers
|
||||
|
||||
//> Alias registers
|
||||
UC_RISCV_REG_ZERO = UC_RISCV_REG_X0, // "zero"
|
||||
UC_RISCV_REG_RA = UC_RISCV_REG_X1, // "ra"
|
||||
UC_RISCV_REG_SP = UC_RISCV_REG_X2, // "sp"
|
||||
UC_RISCV_REG_GP = UC_RISCV_REG_X3, // "gp"
|
||||
UC_RISCV_REG_TP = UC_RISCV_REG_X4, // "tp"
|
||||
UC_RISCV_REG_T0 = UC_RISCV_REG_X5, // "t0"
|
||||
UC_RISCV_REG_T1 = UC_RISCV_REG_X6, // "t1"
|
||||
UC_RISCV_REG_T2 = UC_RISCV_REG_X7, // "t2"
|
||||
UC_RISCV_REG_S0 = UC_RISCV_REG_X8, // "s0"
|
||||
UC_RISCV_REG_FP = UC_RISCV_REG_X8, // "fp"
|
||||
UC_RISCV_REG_S1 = UC_RISCV_REG_X9, // "s1"
|
||||
UC_RISCV_REG_A0 = UC_RISCV_REG_X10, // "a0"
|
||||
UC_RISCV_REG_A1 = UC_RISCV_REG_X11, // "a1"
|
||||
UC_RISCV_REG_A2 = UC_RISCV_REG_X12, // "a2"
|
||||
UC_RISCV_REG_A3 = UC_RISCV_REG_X13, // "a3"
|
||||
UC_RISCV_REG_A4 = UC_RISCV_REG_X14, // "a4"
|
||||
UC_RISCV_REG_A5 = UC_RISCV_REG_X15, // "a5"
|
||||
UC_RISCV_REG_A6 = UC_RISCV_REG_X16, // "a6"
|
||||
UC_RISCV_REG_A7 = UC_RISCV_REG_X17, // "a7"
|
||||
UC_RISCV_REG_S2 = UC_RISCV_REG_X18, // "s2"
|
||||
UC_RISCV_REG_S3 = UC_RISCV_REG_X19, // "s3"
|
||||
UC_RISCV_REG_S4 = UC_RISCV_REG_X20, // "s4"
|
||||
UC_RISCV_REG_S5 = UC_RISCV_REG_X21, // "s5"
|
||||
UC_RISCV_REG_S6 = UC_RISCV_REG_X22, // "s6"
|
||||
UC_RISCV_REG_S7 = UC_RISCV_REG_X23, // "s7"
|
||||
UC_RISCV_REG_S8 = UC_RISCV_REG_X24, // "s8"
|
||||
UC_RISCV_REG_S9 = UC_RISCV_REG_X25, // "s9"
|
||||
UC_RISCV_REG_S10 = UC_RISCV_REG_X26, // "s10"
|
||||
UC_RISCV_REG_S11 = UC_RISCV_REG_X27, // "s11"
|
||||
UC_RISCV_REG_T3 = UC_RISCV_REG_X28, // "t3"
|
||||
UC_RISCV_REG_T4 = UC_RISCV_REG_X29, // "t4"
|
||||
UC_RISCV_REG_T5 = UC_RISCV_REG_X30, // "t5"
|
||||
UC_RISCV_REG_T6 = UC_RISCV_REG_X31, // "t6"
|
||||
|
||||
UC_RISCV_REG_FT0 = UC_RISCV_REG_F0, // "ft0"
|
||||
UC_RISCV_REG_FT1 = UC_RISCV_REG_F1, // "ft1"
|
||||
UC_RISCV_REG_FT2 = UC_RISCV_REG_F2, // "ft2"
|
||||
UC_RISCV_REG_FT3 = UC_RISCV_REG_F3, // "ft3"
|
||||
UC_RISCV_REG_FT4 = UC_RISCV_REG_F4, // "ft4"
|
||||
UC_RISCV_REG_FT5 = UC_RISCV_REG_F5, // "ft5"
|
||||
UC_RISCV_REG_FT6 = UC_RISCV_REG_F6, // "ft6"
|
||||
UC_RISCV_REG_FT7 = UC_RISCV_REG_F7, // "ft7"
|
||||
UC_RISCV_REG_FS0 = UC_RISCV_REG_F8, // "fs0"
|
||||
UC_RISCV_REG_FS1 = UC_RISCV_REG_F9, // "fs1"
|
||||
|
||||
UC_RISCV_REG_FA0 = UC_RISCV_REG_F10, // "fa0"
|
||||
UC_RISCV_REG_FA1 = UC_RISCV_REG_F11, // "fa1"
|
||||
UC_RISCV_REG_FA2 = UC_RISCV_REG_F12, // "fa2"
|
||||
UC_RISCV_REG_FA3 = UC_RISCV_REG_F13, // "fa3"
|
||||
UC_RISCV_REG_FA4 = UC_RISCV_REG_F14, // "fa4"
|
||||
UC_RISCV_REG_FA5 = UC_RISCV_REG_F15, // "fa5"
|
||||
UC_RISCV_REG_FA6 = UC_RISCV_REG_F16, // "fa6"
|
||||
UC_RISCV_REG_FA7 = UC_RISCV_REG_F17, // "fa7"
|
||||
UC_RISCV_REG_FS2 = UC_RISCV_REG_F18, // "fs2"
|
||||
UC_RISCV_REG_FS3 = UC_RISCV_REG_F19, // "fs3"
|
||||
UC_RISCV_REG_FS4 = UC_RISCV_REG_F20, // "fs4"
|
||||
UC_RISCV_REG_FS5 = UC_RISCV_REG_F21, // "fs5"
|
||||
UC_RISCV_REG_FS6 = UC_RISCV_REG_F22, // "fs6"
|
||||
UC_RISCV_REG_FS7 = UC_RISCV_REG_F23, // "fs7"
|
||||
UC_RISCV_REG_FS8 = UC_RISCV_REG_F24, // "fs8"
|
||||
UC_RISCV_REG_FS9 = UC_RISCV_REG_F25, // "fs9"
|
||||
UC_RISCV_REG_FS10 = UC_RISCV_REG_F26, // "fs10"
|
||||
UC_RISCV_REG_FS11 = UC_RISCV_REG_F27, // "fs11"
|
||||
UC_RISCV_REG_FT8 = UC_RISCV_REG_F28, // "ft8"
|
||||
UC_RISCV_REG_FT9 = UC_RISCV_REG_F29, // "ft9"
|
||||
UC_RISCV_REG_FT10 = UC_RISCV_REG_F30, // "ft10"
|
||||
UC_RISCV_REG_FT11 = UC_RISCV_REG_F31, // "ft11"
|
||||
} uc_riscv_reg;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -32,6 +32,8 @@ typedef size_t uc_hook;
|
||||
#include "arm64.h"
|
||||
#include "mips.h"
|
||||
#include "sparc.h"
|
||||
#include "ppc.h"
|
||||
#include "riscv.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DEFAULT_VISIBILITY __attribute__((visibility("default")))
|
||||
@ -65,13 +67,13 @@ typedef size_t uc_hook;
|
||||
#endif
|
||||
|
||||
// Unicorn API version
|
||||
#define UC_API_MAJOR 1
|
||||
#define UC_API_MAJOR 2
|
||||
#define UC_API_MINOR 0
|
||||
|
||||
// Unicorn package version
|
||||
#define UC_VERSION_MAJOR UC_API_MAJOR
|
||||
#define UC_VERSION_MINOR UC_API_MINOR
|
||||
#define UC_VERSION_EXTRA 3
|
||||
#define UC_VERSION_EXTRA 0
|
||||
|
||||
|
||||
/*
|
||||
@ -92,9 +94,10 @@ typedef enum uc_arch {
|
||||
UC_ARCH_ARM64, // ARM-64, also called AArch64
|
||||
UC_ARCH_MIPS, // Mips architecture
|
||||
UC_ARCH_X86, // X86 architecture (including x86 & x86-64)
|
||||
UC_ARCH_PPC, // PowerPC architecture (currently unsupported)
|
||||
UC_ARCH_PPC, // PowerPC architecture
|
||||
UC_ARCH_SPARC, // Sparc architecture
|
||||
UC_ARCH_M68K, // M68K architecture
|
||||
UC_ARCH_RISCV, // RISCV architecture
|
||||
UC_ARCH_MAX,
|
||||
} uc_arch;
|
||||
|
||||
@ -106,7 +109,7 @@ typedef enum uc_mode {
|
||||
// arm / arm64
|
||||
UC_MODE_ARM = 0, // ARM mode
|
||||
UC_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2)
|
||||
UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series (currently unsupported)
|
||||
UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series
|
||||
UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported)
|
||||
|
||||
// arm (32bit) cpu types
|
||||
@ -114,9 +117,6 @@ typedef enum uc_mode {
|
||||
UC_MODE_ARM946 = 1 << 8, // ARM946 CPU type
|
||||
UC_MODE_ARM1176 = 1 << 9, // ARM1176 CPU type
|
||||
|
||||
// ARM BE8
|
||||
UC_MODE_ARMBE8 = 1 << 10, // Big-endian data and Little-endian code
|
||||
|
||||
// mips
|
||||
UC_MODE_MICRO = 1 << 4, // MicroMips mode (currently unsupported)
|
||||
UC_MODE_MIPS3 = 1 << 5, // Mips III ISA (currently unsupported)
|
||||
@ -130,7 +130,7 @@ typedef enum uc_mode {
|
||||
UC_MODE_64 = 1 << 3, // 64-bit mode
|
||||
|
||||
// ppc
|
||||
UC_MODE_PPC32 = 1 << 2, // 32-bit mode (currently unsupported)
|
||||
UC_MODE_PPC32 = 1 << 2, // 32-bit mode
|
||||
UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported)
|
||||
UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (currently unsupported)
|
||||
|
||||
@ -139,6 +139,10 @@ typedef enum uc_mode {
|
||||
UC_MODE_SPARC64 = 1 << 3, // 64-bit mode
|
||||
UC_MODE_V9 = 1 << 4, // SparcV9 mode (currently unsupported)
|
||||
|
||||
// riscv
|
||||
UC_MODE_RISCV32 = 1 << 2, // 32-bit mode
|
||||
UC_MODE_RISCV64 = 1 << 3, // 64-bit mode
|
||||
|
||||
// m68k
|
||||
} uc_mode;
|
||||
|
||||
@ -214,6 +218,26 @@ typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, void
|
||||
*/
|
||||
typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data);
|
||||
|
||||
/*
|
||||
Callback function for MMIO read
|
||||
|
||||
@offset: offset to the base address of the IO memory.
|
||||
@size: data size to read
|
||||
@user_data: user data passed to uc_mmio_map()
|
||||
*/
|
||||
typedef uint64_t (*uc_cb_mmio_read_t)(uc_engine *uc, uint64_t offset, unsigned size, void *user_data);
|
||||
|
||||
/*
|
||||
Callback function for MMIO write
|
||||
|
||||
@offset: offset to the base address of the IO memory.
|
||||
@size: data size to write
|
||||
@value: data value to be written
|
||||
@user_data: user data passed to uc_mmio_map()
|
||||
*/
|
||||
typedef void (*uc_cb_mmio_write_t)(uc_engine *uc, uint64_t offset, unsigned size, uint64_t value, void *user_data);
|
||||
|
||||
|
||||
// All type of memory accesses for UC_HOOK_MEM_*
|
||||
typedef enum uc_mem_type {
|
||||
UC_MEM_READ = 16, // Memory is read from
|
||||
@ -303,13 +327,13 @@ typedef void (*uc_cb_hookmem_t)(uc_engine *uc, uc_mem_type type,
|
||||
@user_data: user data passed to tracing APIs
|
||||
|
||||
@return: return true to continue, or false to stop program (due to invalid memory).
|
||||
NOTE: returning true to continue execution will only work if the accessed
|
||||
NOTE: returning true to continue execution will only work if if the accessed
|
||||
memory is made accessible with the correct permissions during the hook.
|
||||
|
||||
|
||||
In the event of a UC_MEM_READ_UNMAPPED or UC_MEM_WRITE_UNMAPPED callback,
|
||||
the memory should be uc_mem_map()-ed with the correct permissions, and the
|
||||
instruction will then read or write to the address as it was supposed to.
|
||||
|
||||
|
||||
In the event of a UC_MEM_FETCH_UNMAPPED callback, the memory can be mapped
|
||||
in as executable, in which case execution will resume from the fetched address.
|
||||
The instruction pointer may be written to in order to change where execution resumes,
|
||||
@ -416,7 +440,7 @@ UNICORN_EXPORT
|
||||
uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result);
|
||||
|
||||
/*
|
||||
Report the last error number when some API function fails.
|
||||
Report the last error number when some API function fail.
|
||||
Like glibc's errno, uc_errno might not retain its old value once accessed.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@ -528,12 +552,12 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size);
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@begin: address where emulation starts
|
||||
@until: address where emulation stops (i.e. when this address is hit)
|
||||
@until: address where emulation stops (i.e when this address is hit)
|
||||
@timeout: duration to emulate the code (in microseconds). When this value is 0,
|
||||
we will emulate the code in infinite time, until the code is finished.
|
||||
@count: the number of instructions to be emulated. When this value is 0,
|
||||
we will emulate all the code available, until the code is finished.
|
||||
|
||||
|
||||
NOTE: The internal states of the engine is guranteed to be correct if and only
|
||||
if uc_emu_start returns without any errors or errors have been handled in
|
||||
the callbacks.
|
||||
@ -562,12 +586,12 @@ uc_err uc_emu_stop(uc_engine *uc);
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@hh: hook handle returned from this registration. To be used in uc_hook_del() API
|
||||
@type: hook type, refer to uc_hook_type enum
|
||||
@type: hook type
|
||||
@callback: callback to be run when instruction is hit
|
||||
@user_data: user-defined data. This will be passed to callback function in its
|
||||
last argument @user_data
|
||||
@begin: start address of the area where the callback is in effect (inclusive)
|
||||
@end: end address of the area where the callback is in effect (inclusive)
|
||||
@begin: start address of the area where the callback is effect (inclusive)
|
||||
@end: end address of the area where the callback is effect (inclusive)
|
||||
NOTE 1: the callback is called only if related address is in range [@begin, @end]
|
||||
NOTE 2: if @begin > @end, callback is called whenever this hook type is triggered
|
||||
@...: variable arguments (depending on @type)
|
||||
@ -584,7 +608,7 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
|
||||
Unregister (remove) a hook callback.
|
||||
This API removes the hook callback registered by uc_hook_add().
|
||||
NOTE: this should be called only when you no longer want to trace.
|
||||
After this, @hh is invalid, and no longer usable.
|
||||
After this, @hh is invalid, and nolonger usable.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@hh: handle returned by uc_hook_add()
|
||||
@ -611,7 +635,7 @@ typedef enum uc_prot {
|
||||
@address: starting address of the new memory region to be mapped in.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
|
||||
@size: size of the new memory region to be mapped in.
|
||||
This size must be a multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
@perms: Permissions for the newly mapped region.
|
||||
This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
|
||||
or this will return with UC_ERR_ARG error.
|
||||
@ -630,12 +654,12 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms);
|
||||
@address: starting address of the new memory region to be mapped in.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
|
||||
@size: size of the new memory region to be mapped in.
|
||||
This size must be a multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
@perms: Permissions for the newly mapped region.
|
||||
This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
|
||||
or this will return with UC_ERR_ARG error.
|
||||
@ptr: pointer to host memory backing the newly mapped memory. This host memory is
|
||||
expected to be of equal or larger size than provided, and be mapped with at
|
||||
expected to be an equal or larger size than provided, and be mapped with at
|
||||
least PROT_READ | PROT_WRITE. If it is not, the resulting behavior is undefined.
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
@ -644,6 +668,29 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms);
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr);
|
||||
|
||||
/*
|
||||
Map MMIO in for emulation.
|
||||
This API adds a MMIO region that can be used by emulation.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@address: starting address of the new MMIO region to be mapped in.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
|
||||
@size: size of the new MMIO region to be mapped in.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
@read_cb: function for handling reads from this MMIO region.
|
||||
@user_data_read: user-defined data. This will be passed to @read_cb function in its
|
||||
last argument @user_data
|
||||
@write_cb: function for handling writes to this MMIO region.
|
||||
@user_data_write: user-defined data. This will be passed to @write_cb function in its
|
||||
last argument @user_data
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size,
|
||||
uc_cb_mmio_read_t read_cb, void *user_data_read,
|
||||
uc_cb_mmio_write_t write_cb, void *user_data_write);
|
||||
|
||||
/*
|
||||
Unmap a region of emulation memory.
|
||||
This API deletes a memory mapping from the emulation memory space.
|
||||
@ -652,7 +699,7 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t per
|
||||
@address: starting address of the memory region to be unmapped.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
|
||||
@size: size of the memory region to be modified.
|
||||
This size must be a multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@ -668,7 +715,7 @@ uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size);
|
||||
@address: starting address of the memory region to be modified.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
|
||||
@size: size of the memory region to be modified.
|
||||
This size must be a multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
@perms: New permissions for the mapped region.
|
||||
This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
|
||||
or this will return with UC_ERR_ARG error.
|
||||
@ -682,8 +729,8 @@ uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t per
|
||||
/*
|
||||
Retrieve all memory regions mapped by uc_mem_map() and uc_mem_map_ptr()
|
||||
This API allocates memory for @regions, and user must free this memory later
|
||||
by uc_free() to avoid leaking memory.
|
||||
NOTE: memory regions may be split by uc_mem_unmap()
|
||||
by free() to avoid leaking memory.
|
||||
NOTE: memory regions may be splitted by uc_mem_unmap()
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@regions: pointer to an array of uc_mem_region struct. This is allocated by
|
||||
@ -703,9 +750,9 @@ uc_err uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count);
|
||||
differing arches or modes.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@context: pointer to a uc_context*. This will be updated with the pointer to
|
||||
@context: pointer to a uc_engine*. This will be updated with the pointer to
|
||||
the new context on successful return of this function.
|
||||
Later, this allocated memory must be freed with uc_context_free().
|
||||
Later, this allocated memory must be freed with uc_free().
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@ -716,7 +763,7 @@ uc_err uc_context_alloc(uc_engine *uc, uc_context **context);
|
||||
/*
|
||||
Free the memory allocated by uc_mem_regions.
|
||||
WARNING: After Unicorn 1.0.1rc5, the memory allocated by uc_context_alloc should
|
||||
be freed by uc_context_free(). Calling uc_free() may still work, but the result
|
||||
be free-ed by uc_context_free(). Calling uc_free() may still work, but the result
|
||||
is **undefined**.
|
||||
|
||||
@mem: memory allocated by uc_mem_regions (returned in *regions).
|
||||
@ -741,6 +788,60 @@ uc_err uc_free(void *mem);
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_save(uc_engine *uc, uc_context *context);
|
||||
|
||||
/*
|
||||
Write value to a register of a context.
|
||||
|
||||
@ctx: handle returned by uc_context_alloc()
|
||||
@regid: register ID that is to be modified.
|
||||
@value: pointer to the value that will set to register @regid
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value);
|
||||
|
||||
/*
|
||||
Read register value from a context.
|
||||
|
||||
@ctx: handle returned by uc_context_alloc()
|
||||
@regid: register ID that is to be retrieved.
|
||||
@value: pointer to a variable storing the register value.
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value);
|
||||
|
||||
/*
|
||||
Write multiple register values to registers of a context.
|
||||
|
||||
@ctx: handle returned by uc_context_alloc()
|
||||
@regs: array of register IDs to store
|
||||
@value: pointer to array of register values
|
||||
@count: length of both *regs and *vals
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_write_batch(uc_context *ctx, int *regs, void *const *vals, int count);
|
||||
|
||||
/*
|
||||
Read multiple register values from a context.
|
||||
|
||||
@ctx: handle returned by uc_context_alloc()
|
||||
@regs: array of register IDs to retrieve
|
||||
@value: pointer to array of values to hold registers
|
||||
@count: length of both *regs and *vals
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, int count);
|
||||
|
||||
/*
|
||||
Restore the current CPU context from a saved copy.
|
||||
This API should be used to roll the CPU context back to a previous
|
||||
|
@ -39,7 +39,7 @@ typedef enum uc_x86_reg {
|
||||
UC_X86_REG_AH, UC_X86_REG_AL, UC_X86_REG_AX, UC_X86_REG_BH, UC_X86_REG_BL,
|
||||
UC_X86_REG_BP, UC_X86_REG_BPL, UC_X86_REG_BX, UC_X86_REG_CH, UC_X86_REG_CL,
|
||||
UC_X86_REG_CS, UC_X86_REG_CX, UC_X86_REG_DH, UC_X86_REG_DI, UC_X86_REG_DIL,
|
||||
UC_X86_REG_DL, UC_X86_REG_DS, UC_X86_REG_DX, UC_X86_REG_EAX, UC_X86_REG_EBP,
|
||||
UC_X86_REG_DL, UC_X86_REG_DS, UC_X86_REG_DX, UC_X86_REG_EAX, UC_X86_REG_EBP,
|
||||
UC_X86_REG_EBX, UC_X86_REG_ECX, UC_X86_REG_EDI, UC_X86_REG_EDX, UC_X86_REG_EFLAGS,
|
||||
UC_X86_REG_EIP, UC_X86_REG_EIZ, UC_X86_REG_ES, UC_X86_REG_ESI, UC_X86_REG_ESP,
|
||||
UC_X86_REG_FPSW, UC_X86_REG_FS, UC_X86_REG_GS, UC_X86_REG_IP, UC_X86_REG_RAX,
|
||||
@ -91,6 +91,8 @@ typedef enum uc_x86_reg {
|
||||
UC_X86_REG_MXCSR,
|
||||
UC_X86_REG_FS_BASE, // Base regs for x86_64
|
||||
UC_X86_REG_GS_BASE,
|
||||
UC_X86_REG_FLAGS,
|
||||
UC_X86_REG_RFLAGS,
|
||||
UC_X86_REG_ENDING // <-- mark the end of the list of registers
|
||||
} uc_x86_reg;
|
||||
|
||||
|
Reference in New Issue
Block a user