Merge pull request #1474 from unicorn-engine/clangfmt

Import clang-format
This commit is contained in:
lazymio 2021-10-29 13:43:35 +02:00 committed by GitHub
commit 1856e940e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 4975 additions and 4190 deletions

16
.clang-format Normal file
View File

@ -0,0 +1,16 @@
BasedOnStyle: LLVM
IndentWidth: 4
UseTab: Never
BreakBeforeBraces: Linux
AllowShortIfStatementsOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: Empty
AllowShortLoopsOnASingleLine: false
IndentCaseLabels: false
ColumnLimit: 80
SortIncludes: false
AllowShortLambdasOnASingleLine: Inline
AlwaysBreakBeforeMultilineStrings: false
BreakStringLiterals: true
PointerAlignment: Right

8
format.sh Normal file
View File

@ -0,0 +1,8 @@
#!/bin/bash
find . -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";"
find ./msvc -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";"
find ./include -maxdepth 2 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";"
find ./tests/unit -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";"
find ./samples -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";"
find ./qemu "(" -name "unicorn.c" -or -name "unicorn.h" ")" -exec clang-format -i -style=file "{}" ";"

View File

@ -2,7 +2,6 @@
/* 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
@ -15,16 +14,22 @@
// 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)
#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_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 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)
#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_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 ARR_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define READ_QWORD(x) ((uint64_t)x)
#define READ_DWORD(x) (x & 0xffffffff)
@ -36,15 +41,19 @@
#define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | ((b & 0xff) << 8))
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, size_t *result);
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 (*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 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;
@ -52,30 +61,40 @@ typedef struct {
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);
typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr,
const uint8_t *buf, int len);
typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf,
int len);
typedef void (*uc_args_void_t)(void*);
typedef void (*uc_args_void_t)(void *);
typedef void (*uc_args_uc_t)(struct uc_struct*);
typedef void (*uc_args_int_uc_t)(struct uc_struct*);
typedef void (*uc_args_uc_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);
typedef void (*uc_args_uc_long_t)(struct uc_struct *, unsigned long);
typedef void (*uc_args_uc_u64_t)(struct uc_struct *, uint64_t addr);
typedef MemoryRegion* (*uc_args_uc_ram_size_t)(struct uc_struct*, hwaddr begin, size_t size, uint32_t perms);
typedef MemoryRegion *(*uc_args_uc_ram_size_t)(struct uc_struct *, hwaddr begin,
size_t size, uint32_t perms);
typedef MemoryRegion* (*uc_args_uc_ram_size_ptr_t)(struct uc_struct*, hwaddr begin, size_t size, uint32_t perms, void *ptr);
typedef MemoryRegion *(*uc_args_uc_ram_size_ptr_t)(struct uc_struct *,
hwaddr begin, size_t size,
uint32_t perms, void *ptr);
typedef void (*uc_mem_unmap_t)(struct uc_struct*, MemoryRegion *mr);
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);
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)(struct uc_struct *uc, int intno);
@ -84,7 +103,7 @@ typedef bool (*uc_args_int_t)(struct uc_struct *uc, int intno);
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);
typedef bool (*uc_insn_hook_validate)(uint32_t insn_enum);
// init target page
typedef void (*uc_target_page_init)(struct uc_struct *);
@ -96,11 +115,13 @@ typedef void (*uc_softfloat_initialize)(void);
typedef void (*uc_tcg_flush_tlb)(struct uc_struct *uc);
struct hook {
int type; // UC_HOOK_*
int insn; // instruction for HOOK_INSN
int refs; // reference count to free hook stored in multiple lists
bool to_delete; // set to true when the hook is deleted by the user. The destruction of the hook is delayed.
uint64_t begin, end; // only trigger if PC or memory access is in this address (depends on hook type)
int type; // UC_HOOK_*
int insn; // instruction for HOOK_INSN
int refs; // reference count to free hook stored in multiple lists
bool to_delete; // set to true when the hook is deleted by the user. The
// destruction of the hook is delayed.
uint64_t begin, end; // only trigger if PC or memory access is in this
// address (depends on hook type)
void *callback; // a uc_cb_* type
void *user_data;
};
@ -132,31 +153,31 @@ typedef enum uc_hook_idx {
} uc_hook_idx;
// The lowest 6 bits are used for hook type index.
#define UC_HOOK_IDX_MASK ((1<<6)-1)
#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.
#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
#define HOOK_FOREACH_VAR_DECLARE struct list_item *cur
// for loop macro to loop over hook lists
#define HOOK_FOREACH(uc, hh, idx) \
for ( \
cur = (uc)->hook[idx##_IDX].head; \
cur != NULL && ((hh) = (struct hook *)cur->data); \
cur = cur->next)
#define HOOK_FOREACH(uc, hh, idx) \
for (cur = (uc)->hook[idx##_IDX].head; \
cur != NULL && ((hh) = (struct hook *)cur->data); cur = cur->next)
// if statement to check hook bounds
#define HOOK_BOUND_CHECK(hh, addr) \
((((addr) >= (hh)->begin && (addr) <= (hh)->end) \
|| (hh)->begin > (hh)->end) && !((hh)->to_delete))
#define HOOK_BOUND_CHECK(hh, addr) \
((((addr) >= (hh)->begin && (addr) <= (hh)->end) || \
(hh)->begin > (hh)->end) && \
!((hh)->to_delete))
#define HOOK_EXISTS(uc, idx) ((uc)->hook[idx##_IDX].head != NULL)
#define HOOK_EXISTS_BOUNDED(uc, idx, addr) _hook_exists_bounded((uc)->hook[idx##_IDX].head, addr)
#define HOOK_EXISTS_BOUNDED(uc, idx, addr) \
_hook_exists_bounded((uc)->hook[idx##_IDX].head, addr)
static inline bool _hook_exists_bounded(struct list_item *cur, uint64_t addr)
{
@ -168,7 +189,7 @@ static inline bool _hook_exists_bounded(struct list_item *cur, uint64_t addr)
return false;
}
//relloc increment, KEEP THIS A POWER OF 2!
// relloc increment, KEEP THIS A POWER OF 2!
#define MEM_BLOCK_INCR 32
typedef struct TargetPageBits TargetPageBits;
@ -177,7 +198,7 @@ typedef struct TCGContext TCGContext;
struct uc_struct {
uc_arch arch;
uc_mode mode;
uc_err errnum; // qemu/cpu-exec.c
uc_err errnum; // qemu/cpu-exec.c
AddressSpace address_space_memory;
AddressSpace address_space_io;
query_t query;
@ -187,9 +208,10 @@ struct uc_struct {
uc_write_mem_t write_mem;
uc_read_mem_t read_mem;
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_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;
@ -212,21 +234,21 @@ struct uc_struct {
uc_insn_hook_validate insn_hook_validate;
MemoryRegion *system_memory; // qemu/exec.c
MemoryRegion *system_io; // qemu/exec.c
MemoryRegion *system_io; // qemu/exec.c
MemoryRegion io_mem_unassigned; // qemu/exec.c
RAMList ram_list; // 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
BounceBuffer bounce; // qemu/cpu-exec.c
volatile sig_atomic_t exit_request; // qemu/cpu-exec.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/accel/tcg/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;
@ -248,28 +270,33 @@ struct uc_struct {
uc_hook count_hook;
size_t emu_counter; // current counter of uc_emu_start()
size_t emu_count; // save counter of uc_emu_start()
size_t emu_count; // save counter of uc_emu_start()
int size_recur_mem; // size for mem access when in a recursive call
bool init_tcg; // already initialized local TCGv variables?
bool stop_request; // request to immediately stop emulation - for uc_emu_stop()
bool quit_request; // request to quit the current TB, but continue to emulate - for uc_mem_protect()
bool emulation_done; // emulation is done by uc_emu_start()
bool timed_out; // emulation timed out, that can retrieve via uc_query(UC_QUERY_TIMEOUT)
QemuThread timer; // timer for emulation timeout
uint64_t timeout; // timeout for uc_emu_start()
bool init_tcg; // already initialized local TCGv variables?
bool stop_request; // request to immediately stop emulation - for
// uc_emu_stop()
bool quit_request; // request to quit the current TB, but continue to
// emulate - for uc_mem_protect()
bool emulation_done; // emulation is done by uc_emu_start()
bool timed_out; // emulation timed out, that can retrieve via
// uc_query(UC_QUERY_TIMEOUT)
QemuThread timer; // timer for emulation timeout
uint64_t timeout; // timeout for uc_emu_start()
uint64_t invalid_addr; // invalid address to be accessed
int invalid_error; // invalid memory code: 1 = READ, 2 = WRITE, 3 = CODE
uint64_t invalid_addr; // invalid address to be accessed
int invalid_error; // invalid memory code: 1 = READ, 2 = WRITE, 3 = CODE
uint64_t addr_end; // address where emulation stops (@end param of uc_emu_start())
uint64_t addr_end; // address where emulation stops (@end param of
// uc_emu_start())
int thumb; // thumb mode for ARM
int thumb; // thumb mode for ARM
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)
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;
@ -277,26 +304,29 @@ struct uc_struct {
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()?
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.
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_*()
// We also save cpu->jmp_env, so emulation can be reentrant
struct uc_context {
size_t context_size; // size of the real internal context structure
size_t jmp_env_size; // size of cpu->jmp_env
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
size_t context_size; // size of the real internal context structure
size_t jmp_env_size; // size of cpu->jmp_env
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
};
// check if this address is mapped in (via uc_mem_map())
MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address);
MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address);
#endif
/* vim: set ts=4 noet: */

View File

@ -12,7 +12,7 @@ extern "C" {
#endif
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable : 4201)
#endif
//> ARM registers
@ -158,7 +158,7 @@ typedef enum uc_arm_reg {
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
UC_ARM_REG_ENDING, // <-- mark the end of the list or registers
//> alias registers
UC_ARM_REG_R13 = UC_ARM_REG_SP,

View File

@ -12,7 +12,7 @@ extern "C" {
#endif
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable : 4201)
#endif
//> ARM64 registers
@ -281,7 +281,7 @@ typedef enum uc_arm64_reg {
UC_ARM64_REG_V31,
//> pseudo registers
UC_ARM64_REG_PC, // program counter register
UC_ARM64_REG_PC, // program counter register
UC_ARM64_REG_CPACR_EL1,
@ -327,7 +327,7 @@ typedef enum uc_arm64_reg {
UC_ARM64_REG_VBAR_EL2,
UC_ARM64_REG_VBAR_EL3,
UC_ARM64_REG_ENDING, // <-- mark the end of the list of registers
UC_ARM64_REG_ENDING, // <-- mark the end of the list of registers
//> alias registers

View File

@ -12,7 +12,7 @@ extern "C" {
#endif
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable : 4201)
#endif
//> M68K registers
@ -40,7 +40,7 @@ typedef enum uc_m68k_reg {
UC_M68K_REG_SR,
UC_M68K_REG_PC,
UC_M68K_REG_ENDING, // <-- mark the end of the list of registers
UC_M68K_REG_ENDING, // <-- mark the end of the list of registers
} uc_m68k_reg;
#ifdef __cplusplus

View File

@ -16,7 +16,7 @@ extern "C" {
#undef mips
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable : 4201)
#endif
//> MIPS registers
@ -179,7 +179,7 @@ typedef enum UC_MIPS_REG {
UC_MIPS_REG_CP0_USERLOCAL,
UC_MIPS_REG_CP0_STATUS,
UC_MIPS_REG_ENDING, // <-- mark the end of the list or registers
UC_MIPS_REG_ENDING, // <-- mark the end of the list or registers
// alias registers
UC_MIPS_REG_ZERO = UC_MIPS_REG_0,
@ -212,7 +212,8 @@ typedef enum UC_MIPS_REG {
UC_MIPS_REG_K1 = UC_MIPS_REG_27,
UC_MIPS_REG_GP = UC_MIPS_REG_28,
UC_MIPS_REG_SP = UC_MIPS_REG_29,
UC_MIPS_REG_FP = UC_MIPS_REG_30, UC_MIPS_REG_S8 = UC_MIPS_REG_30,
UC_MIPS_REG_FP = UC_MIPS_REG_30,
UC_MIPS_REG_S8 = UC_MIPS_REG_30,
UC_MIPS_REG_RA = UC_MIPS_REG_31,
UC_MIPS_REG_HI0 = UC_MIPS_REG_AC0,

View File

@ -22,16 +22,17 @@ MSVC++ 7.0 _MSC_VER == 1300
MSVC++ 6.0 _MSC_VER == 1200
MSVC++ 5.0 _MSC_VER == 1100
*/
#define MSC_VER_VS2003 1310
#define MSC_VER_VS2005 1400
#define MSC_VER_VS2008 1500
#define MSC_VER_VS2010 1600
#define MSC_VER_VS2012 1700
#define MSC_VER_VS2013 1800
#define MSC_VER_VS2015 1900
#define MSC_VER_VS2003 1310
#define MSC_VER_VS2005 1400
#define MSC_VER_VS2008 1500
#define MSC_VER_VS2010 1600
#define MSC_VER_VS2012 1700
#define MSC_VER_VS2013 1800
#define MSC_VER_VS2015 1900
// handle stdbool.h compatibility
#if !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) && (defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64))
#if !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) && \
(defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64))
// MSVC
// stdbool.h
@ -41,62 +42,65 @@ MSVC++ 5.0 _MSC_VER == 1100
typedef unsigned char bool;
#define false 0
#define true 1
#endif // __cplusplus
#endif // __cplusplus
#else
// VisualStudio 2013+ -> C99 is supported
#include <stdbool.h>
#endif // (_MSC_VER < MSC_VER_VS2013) || defined(_KERNEL_MODE)
#endif // (_MSC_VER < MSC_VER_VS2013) || defined(_KERNEL_MODE)
#else
// not MSVC -> C99 is supported
#include <stdbool.h>
#endif // !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) && (defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64))
#endif // !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__)
// && (defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined
// (_WIN64))
#if (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || defined(_KERNEL_MODE)
// this system does not have stdint.h
typedef signed char int8_t;
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef signed long long int64_t;
typedef unsigned int uint32_t;
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
#ifndef _INTPTR_T_DEFINED
#define _INTPTR_T_DEFINED
#ifdef _WIN64
typedef long long intptr_t;
#else /* _WIN64 */
typedef _W64 int intptr_t;
#endif /* _WIN64 */
#define _INTPTR_T_DEFINED
#ifdef _WIN64
typedef long long intptr_t;
#else /* _WIN64 */
typedef _W64 int intptr_t;
#endif /* _WIN64 */
#endif /* _INTPTR_T_DEFINED */
#ifndef _UINTPTR_T_DEFINED
#define _UINTPTR_T_DEFINED
#ifdef _WIN64
#define _UINTPTR_T_DEFINED
#ifdef _WIN64
typedef unsigned long long uintptr_t;
#else /* _WIN64 */
typedef _W64 unsigned int uintptr_t;
#endif /* _WIN64 */
#else /* _WIN64 */
typedef _W64 unsigned int uintptr_t;
#endif /* _WIN64 */
#endif /* _UINTPTR_T_DEFINED */
#define INT8_MIN (-127i8 - 1)
#define INT16_MIN (-32767i16 - 1)
#define INT32_MIN (-2147483647i32 - 1)
#define INT64_MIN (-9223372036854775807i64 - 1)
#define INT8_MAX 127i8
#define INT16_MAX 32767i16
#define INT32_MAX 2147483647i32
#define INT64_MAX 9223372036854775807i64
#define UINT8_MAX 0xffui8
#define UINT16_MAX 0xffffui16
#define UINT32_MAX 0xffffffffui32
#define UINT64_MAX 0xffffffffffffffffui64
#define INT8_MIN (-127i8 - 1)
#define INT16_MIN (-32767i16 - 1)
#define INT32_MIN (-2147483647i32 - 1)
#define INT64_MIN (-9223372036854775807i64 - 1)
#define INT8_MAX 127i8
#define INT16_MAX 32767i16
#define INT32_MAX 2147483647i32
#define INT64_MAX 9223372036854775807i64
#define UINT8_MAX 0xffui8
#define UINT16_MAX 0xffffui16
#define UINT32_MAX 0xffffffffui32
#define UINT64_MAX 0xffffffffffffffffui64
#else // this system has stdint.h
#include <stdint.h>
#endif // (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || defined(_KERNEL_MODE)
#endif // (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) ||
// defined(_KERNEL_MODE)
// handle inttypes.h compatibility
#if (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2013)) || defined(_KERNEL_MODE)
@ -105,52 +109,53 @@ typedef _W64 unsigned int uintptr_t;
#define __PRI_8_LENGTH_MODIFIER__ "hh"
#define __PRI_64_LENGTH_MODIFIER__ "ll"
#define PRId8 __PRI_8_LENGTH_MODIFIER__ "d"
#define PRIi8 __PRI_8_LENGTH_MODIFIER__ "i"
#define PRIo8 __PRI_8_LENGTH_MODIFIER__ "o"
#define PRIu8 __PRI_8_LENGTH_MODIFIER__ "u"
#define PRIx8 __PRI_8_LENGTH_MODIFIER__ "x"
#define PRIX8 __PRI_8_LENGTH_MODIFIER__ "X"
#define PRId8 __PRI_8_LENGTH_MODIFIER__ "d"
#define PRIi8 __PRI_8_LENGTH_MODIFIER__ "i"
#define PRIo8 __PRI_8_LENGTH_MODIFIER__ "o"
#define PRIu8 __PRI_8_LENGTH_MODIFIER__ "u"
#define PRIx8 __PRI_8_LENGTH_MODIFIER__ "x"
#define PRIX8 __PRI_8_LENGTH_MODIFIER__ "X"
#define PRId16 "hd"
#define PRIi16 "hi"
#define PRIo16 "ho"
#define PRIu16 "hu"
#define PRIx16 "hx"
#define PRIX16 "hX"
#define PRId16 "hd"
#define PRIi16 "hi"
#define PRIo16 "ho"
#define PRIu16 "hu"
#define PRIx16 "hx"
#define PRIX16 "hX"
#if defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012)
#define PRId32 "ld"
#define PRIi32 "li"
#define PRIo32 "lo"
#define PRIu32 "lu"
#define PRIx32 "lx"
#define PRIX32 "lX"
#else // OSX
#define PRId32 "d"
#define PRIi32 "i"
#define PRIo32 "o"
#define PRIu32 "u"
#define PRIx32 "x"
#define PRIX32 "X"
#endif // defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012)
#define PRId32 "ld"
#define PRIi32 "li"
#define PRIo32 "lo"
#define PRIu32 "lu"
#define PRIx32 "lx"
#define PRIX32 "lX"
#else // OSX
#define PRId32 "d"
#define PRIi32 "i"
#define PRIo32 "o"
#define PRIu32 "u"
#define PRIx32 "x"
#define PRIX32 "X"
#endif // defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012)
#if defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012)
// redefine functions from inttypes.h used in cstool
#define strtoull _strtoui64
#endif
#define PRId64 __PRI_64_LENGTH_MODIFIER__ "d"
#define PRIi64 __PRI_64_LENGTH_MODIFIER__ "i"
#define PRIo64 __PRI_64_LENGTH_MODIFIER__ "o"
#define PRIu64 __PRI_64_LENGTH_MODIFIER__ "u"
#define PRIx64 __PRI_64_LENGTH_MODIFIER__ "x"
#define PRIX64 __PRI_64_LENGTH_MODIFIER__ "X"
#define PRId64 __PRI_64_LENGTH_MODIFIER__ "d"
#define PRIi64 __PRI_64_LENGTH_MODIFIER__ "i"
#define PRIo64 __PRI_64_LENGTH_MODIFIER__ "o"
#define PRIu64 __PRI_64_LENGTH_MODIFIER__ "u"
#define PRIx64 __PRI_64_LENGTH_MODIFIER__ "x"
#define PRIX64 __PRI_64_LENGTH_MODIFIER__ "X"
#else
// this system has inttypes.h by default
#include <inttypes.h>
#endif // #if defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2013) || defined(_KERNEL_MODE)
#endif // #if defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2013) ||
// defined(_KERNEL_MODE)
// sys/time.h compatibility
#if defined(_MSC_VER)
@ -174,7 +179,7 @@ static int usleep(uint32_t usec)
if (!timer)
return -1;
due.QuadPart = (-((int64_t) usec)) * 10LL;
due.QuadPart = (-((int64_t)usec)) * 10LL;
if (!SetWaitableTimer(timer, &due, 0, NULL, NULL, 0)) {
CloseHandle(timer);
return -1;
@ -191,23 +196,22 @@ static int usleep(uint32_t usec)
// misc support
#if defined(_MSC_VER)
#ifdef _WIN64
typedef signed __int64 ssize_t;
#ifdef _WIN64
typedef signed __int64 ssize_t;
#else
typedef _W64 signed int ssize_t;
typedef _W64 signed int ssize_t;
#endif
#ifndef va_copy
#define va_copy(d,s) ((d) = (s))
#define va_copy(d, s) ((d) = (s))
#endif
#define strcasecmp _stricmp
#define strcasecmp _stricmp
#if (_MSC_VER < MSC_VER_VS2015)
#define snprintf _snprintf
#define snprintf _snprintf
#endif
#if (_MSC_VER <= MSC_VER_VS2013)
#define strtoll _strtoi64
#define strtoll _strtoi64
#endif
#endif
#endif // UNICORN_PLATFORM_H

View File

@ -12,7 +12,7 @@ extern "C" {
#endif
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable : 4201)
#endif
//> PPC registers

View File

@ -12,7 +12,7 @@ extern "C" {
#endif
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable : 4201)
#endif
//> RISCV registers
@ -53,111 +53,111 @@ typedef enum uc_riscv_reg {
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_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_PC, // PC register
UC_RISCV_REG_ENDING, // <-- mark the end of the list or registers
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_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_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_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

View File

@ -16,7 +16,7 @@ extern "C" {
#undef sparc
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable : 4201)
#endif
//> SPARC registers
@ -71,7 +71,7 @@ typedef enum uc_sparc_reg {
UC_SPARC_REG_F58,
UC_SPARC_REG_F60,
UC_SPARC_REG_F62,
UC_SPARC_REG_FCC0, // Floating condition codes
UC_SPARC_REG_FCC0, // Floating condition codes
UC_SPARC_REG_FCC1,
UC_SPARC_REG_FCC2,
UC_SPARC_REG_FCC3,
@ -91,7 +91,7 @@ typedef enum uc_sparc_reg {
UC_SPARC_REG_I5,
UC_SPARC_REG_FP,
UC_SPARC_REG_I7,
UC_SPARC_REG_ICC, // Integer condition codes
UC_SPARC_REG_ICC, // Integer condition codes
UC_SPARC_REG_L0,
UC_SPARC_REG_L1,
UC_SPARC_REG_L2,
@ -114,9 +114,9 @@ typedef enum uc_sparc_reg {
UC_SPARC_REG_XCC,
// pseudo register
UC_SPARC_REG_PC, // program counter register
UC_SPARC_REG_PC, // program counter register
UC_SPARC_REG_ENDING, // <-- mark the end of the list of registers
UC_SPARC_REG_ENDING, // <-- mark the end of the list of registers
// extras
UC_SPARC_REG_O6 = UC_SPARC_REG_SP,

View File

@ -42,11 +42,11 @@ typedef size_t uc_hook;
#endif
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable:4100)
#pragma warning(disable : 4201)
#pragma warning(disable : 4100)
#ifdef UNICORN_SHARED
#define UNICORN_EXPORT __declspec(dllexport)
#else // defined(UNICORN_STATIC)
#else // defined(UNICORN_STATIC)
#define UNICORN_EXPORT
#endif
#else
@ -62,7 +62,8 @@ typedef size_t uc_hook;
#elif defined(_MSC_VER)
#define UNICORN_DEPRECATED __declspec(deprecated)
#else
#pragma message("WARNING: You need to implement UNICORN_DEPRECATED for this compiler")
#pragma message( \
"WARNING: You need to implement UNICORN_DEPRECATED for this compiler")
#define UNICORN_DEPRECATED
#endif
@ -75,7 +76,6 @@ typedef size_t uc_hook;
#define UC_VERSION_MINOR UC_API_MINOR
#define UC_VERSION_EXTRA 0
/*
Macro to create combined version which can be compared to
result of uc_version() API.
@ -90,14 +90,14 @@ typedef size_t uc_hook;
// Architecture type
typedef enum uc_arch {
UC_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2)
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
UC_ARCH_SPARC, // Sparc architecture
UC_ARCH_M68K, // M68K architecture
UC_ARCH_RISCV, // RISCV architecture
UC_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2)
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
UC_ARCH_SPARC, // Sparc architecture
UC_ARCH_M68K, // M68K architecture
UC_ARCH_RISCV, // RISCV architecture
UC_ARCH_MAX,
} uc_arch;
@ -107,41 +107,42 @@ typedef enum uc_mode {
UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian 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
UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported)
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
UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported)
// arm (32bit) cpu types
UC_MODE_ARM926 = 1 << 7, // ARM926 CPU type
UC_MODE_ARM946 = 1 << 8, // ARM946 CPU type
UC_MODE_ARM1176 = 1 << 9, // ARM1176 CPU type
UC_MODE_ARM926 = 1 << 7, // ARM926 CPU type
UC_MODE_ARM946 = 1 << 8, // ARM946 CPU type
UC_MODE_ARM1176 = 1 << 9, // ARM1176 CPU type
// mips
UC_MODE_MICRO = 1 << 4, // MicroMips mode (currently unsupported)
UC_MODE_MIPS3 = 1 << 5, // Mips III ISA (currently unsupported)
UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA (currently unsupported)
UC_MODE_MIPS32 = 1 << 2, // Mips32 ISA
UC_MODE_MIPS64 = 1 << 3, // Mips64 ISA
UC_MODE_MICRO = 1 << 4, // MicroMips mode (currently unsupported)
UC_MODE_MIPS3 = 1 << 5, // Mips III ISA (currently unsupported)
UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA (currently unsupported)
UC_MODE_MIPS32 = 1 << 2, // Mips32 ISA
UC_MODE_MIPS64 = 1 << 3, // Mips64 ISA
// x86 / x64
UC_MODE_16 = 1 << 1, // 16-bit mode
UC_MODE_32 = 1 << 2, // 32-bit mode
UC_MODE_64 = 1 << 3, // 64-bit mode
UC_MODE_16 = 1 << 1, // 16-bit mode
UC_MODE_32 = 1 << 2, // 32-bit mode
UC_MODE_64 = 1 << 3, // 64-bit mode
// ppc
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)
// ppc
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)
// sparc
UC_MODE_SPARC32 = 1 << 2, // 32-bit mode
UC_MODE_SPARC64 = 1 << 3, // 64-bit mode
UC_MODE_V9 = 1 << 4, // SparcV9 mode (currently unsupported)
UC_MODE_SPARC32 = 1 << 2, // 32-bit 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
UC_MODE_RISCV32 = 1 << 2, // 32-bit mode
UC_MODE_RISCV64 = 1 << 3, // 64-bit mode
// m68k
} uc_mode;
@ -149,39 +150,48 @@ typedef enum uc_mode {
// All type of errors encountered by Unicorn API.
// These are values returned by uc_errno()
typedef enum uc_err {
UC_ERR_OK = 0, // No error: everything was fine
UC_ERR_NOMEM, // Out-Of-Memory error: uc_open(), uc_emulate()
UC_ERR_ARCH, // Unsupported architecture: uc_open()
UC_ERR_HANDLE, // Invalid handle
UC_ERR_MODE, // Invalid/unsupported mode: uc_open()
UC_ERR_VERSION, // Unsupported version (bindings)
UC_ERR_READ_UNMAPPED, // Quit emulation due to READ on unmapped memory: uc_emu_start()
UC_ERR_WRITE_UNMAPPED, // Quit emulation due to WRITE on unmapped memory: uc_emu_start()
UC_ERR_FETCH_UNMAPPED, // Quit emulation due to FETCH on unmapped memory: uc_emu_start()
UC_ERR_HOOK, // Invalid hook type: uc_hook_add()
UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start()
UC_ERR_MAP, // Invalid memory mapping: uc_mem_map()
UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation: uc_emu_start()
UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation: uc_emu_start()
UC_ERR_FETCH_PROT, // Quit emulation due to UC_MEM_FETCH_PROT violation: uc_emu_start()
UC_ERR_ARG, // Inavalid argument provided to uc_xxx function (See specific function API)
UC_ERR_OK = 0, // No error: everything was fine
UC_ERR_NOMEM, // Out-Of-Memory error: uc_open(), uc_emulate()
UC_ERR_ARCH, // Unsupported architecture: uc_open()
UC_ERR_HANDLE, // Invalid handle
UC_ERR_MODE, // Invalid/unsupported mode: uc_open()
UC_ERR_VERSION, // Unsupported version (bindings)
UC_ERR_READ_UNMAPPED, // Quit emulation due to READ on unmapped memory:
// uc_emu_start()
UC_ERR_WRITE_UNMAPPED, // Quit emulation due to WRITE on unmapped memory:
// uc_emu_start()
UC_ERR_FETCH_UNMAPPED, // Quit emulation due to FETCH on unmapped memory:
// uc_emu_start()
UC_ERR_HOOK, // Invalid hook type: uc_hook_add()
UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction:
// uc_emu_start()
UC_ERR_MAP, // Invalid memory mapping: uc_mem_map()
UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation:
// uc_emu_start()
UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation:
// uc_emu_start()
UC_ERR_FETCH_PROT, // Quit emulation due to UC_MEM_FETCH_PROT violation:
// uc_emu_start()
UC_ERR_ARG, // Inavalid argument provided to uc_xxx function (See specific
// function API)
UC_ERR_READ_UNALIGNED, // Unaligned read
UC_ERR_WRITE_UNALIGNED, // Unaligned write
UC_ERR_FETCH_UNALIGNED, // Unaligned fetch
UC_ERR_HOOK_EXIST, // hook for this event already existed
UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start()
UC_ERR_EXCEPTION, // Unhandled CPU exception
UC_ERR_WRITE_UNALIGNED, // Unaligned write
UC_ERR_FETCH_UNALIGNED, // Unaligned fetch
UC_ERR_HOOK_EXIST, // hook for this event already existed
UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start()
UC_ERR_EXCEPTION, // Unhandled CPU exception
} uc_err;
/*
Callback function for tracing code (UC_HOOK_CODE & UC_HOOK_BLOCK)
@address: address where the code is being executed
@size: size of machine instruction(s) being executed, or 0 when size is unknown
@size: size of machine instruction(s) being executed, or 0 when size is
unknown
@user_data: user data passed to tracing APIs.
*/
typedef void (*uc_cb_hookcode_t)(uc_engine *uc, uint64_t address, uint32_t size, void *user_data);
typedef void (*uc_cb_hookcode_t)(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data);
/*
Callback function for tracing interrupts (for uc_hook_intr())
@ -189,14 +199,16 @@ typedef void (*uc_cb_hookcode_t)(uc_engine *uc, uint64_t address, uint32_t size,
@intno: interrupt number
@user_data: user data passed to tracing APIs.
*/
typedef void (*uc_cb_hookintr_t)(uc_engine *uc, uint32_t intno, void *user_data);
typedef void (*uc_cb_hookintr_t)(uc_engine *uc, uint32_t intno,
void *user_data);
/*
Callback function for tracing invalid instructions
@user_data: user data passed to tracing APIs.
@return: return true to continue, or false to stop program (due to invalid instruction).
@return: return true to continue, or false to stop program (due to invalid
instruction).
*/
typedef bool (*uc_cb_hookinsn_invalid_t)(uc_engine *uc, void *user_data);
@ -207,7 +219,8 @@ typedef bool (*uc_cb_hookinsn_invalid_t)(uc_engine *uc, void *user_data);
@size: data size (1/2/4) to be read from this port
@user_data: user data passed to tracing APIs.
*/
typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, void *user_data);
typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size,
void *user_data);
/*
Callback function for OUT instruction of X86
@ -216,7 +229,8 @@ typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, void
@size: data size (1/2/4) to be written to this port
@value: data value to be written to this port
*/
typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data);
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
@ -225,7 +239,8 @@ typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, uint32_
@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);
typedef uint64_t (*uc_cb_mmio_read_t)(uc_engine *uc, uint64_t offset,
unsigned size, void *user_data);
/*
Callback function for MMIO write
@ -235,28 +250,30 @@ typedef uint64_t (*uc_cb_mmio_read_t)(uc_engine *uc, uint64_t offset, unsigned s
@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);
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
UC_MEM_WRITE, // Memory is written to
UC_MEM_FETCH, // Memory is fetched
UC_MEM_READ_UNMAPPED, // Unmapped memory is read from
UC_MEM_WRITE_UNMAPPED, // Unmapped memory is written to
UC_MEM_FETCH_UNMAPPED, // Unmapped memory is fetched
UC_MEM_WRITE_PROT, // Write to write protected, but mapped, memory
UC_MEM_READ_PROT, // Read from read protected, but mapped, memory
UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory
UC_MEM_READ_AFTER, // Memory is read from (successful access)
UC_MEM_READ = 16, // Memory is read from
UC_MEM_WRITE, // Memory is written to
UC_MEM_FETCH, // Memory is fetched
UC_MEM_READ_UNMAPPED, // Unmapped memory is read from
UC_MEM_WRITE_UNMAPPED, // Unmapped memory is written to
UC_MEM_FETCH_UNMAPPED, // Unmapped memory is fetched
UC_MEM_WRITE_PROT, // Write to write protected, but mapped, memory
UC_MEM_READ_PROT, // Read from read protected, but mapped, memory
UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory
UC_MEM_READ_AFTER, // Memory is read from (successful access)
} uc_mem_type;
// All type of hooks for uc_hook_add() API.
typedef enum uc_hook_type {
// Hook all interrupt/syscall events
UC_HOOK_INTR = 1 << 0,
// Hook a particular instruction - only a very small subset of instructions supported here
// Hook a particular instruction - only a very small subset of instructions
// supported here
UC_HOOK_INSN = 1 << 1,
// Hook a range of code
UC_HOOK_CODE = 1 << 2,
@ -288,21 +305,29 @@ typedef enum uc_hook_type {
} uc_hook_type;
// Hook type for all events of unmapped memory access
#define UC_HOOK_MEM_UNMAPPED (UC_HOOK_MEM_READ_UNMAPPED + UC_HOOK_MEM_WRITE_UNMAPPED + UC_HOOK_MEM_FETCH_UNMAPPED)
#define UC_HOOK_MEM_UNMAPPED \
(UC_HOOK_MEM_READ_UNMAPPED + UC_HOOK_MEM_WRITE_UNMAPPED + \
UC_HOOK_MEM_FETCH_UNMAPPED)
// Hook type for all events of illegal protected memory access
#define UC_HOOK_MEM_PROT (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_FETCH_PROT)
#define UC_HOOK_MEM_PROT \
(UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_FETCH_PROT)
// Hook type for all events of illegal read memory access
#define UC_HOOK_MEM_READ_INVALID (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_READ_UNMAPPED)
#define UC_HOOK_MEM_READ_INVALID \
(UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_READ_UNMAPPED)
// Hook type for all events of illegal write memory access
#define UC_HOOK_MEM_WRITE_INVALID (UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_WRITE_UNMAPPED)
#define UC_HOOK_MEM_WRITE_INVALID \
(UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_WRITE_UNMAPPED)
// Hook type for all events of illegal fetch memory access
#define UC_HOOK_MEM_FETCH_INVALID (UC_HOOK_MEM_FETCH_PROT + UC_HOOK_MEM_FETCH_UNMAPPED)
#define UC_HOOK_MEM_FETCH_INVALID \
(UC_HOOK_MEM_FETCH_PROT + UC_HOOK_MEM_FETCH_UNMAPPED)
// Hook type for all events of illegal memory access
#define UC_HOOK_MEM_INVALID (UC_HOOK_MEM_UNMAPPED + UC_HOOK_MEM_PROT)
// Hook type for all events of valid memory access
// NOTE: UC_HOOK_MEM_READ is triggered before UC_HOOK_MEM_READ_PROT and UC_HOOK_MEM_READ_UNMAPPED, so
// this hook may technically trigger on some invalid reads.
#define UC_HOOK_MEM_VALID (UC_HOOK_MEM_READ + UC_HOOK_MEM_WRITE + UC_HOOK_MEM_FETCH)
// NOTE: UC_HOOK_MEM_READ is triggered before UC_HOOK_MEM_READ_PROT and
// UC_HOOK_MEM_READ_UNMAPPED, so
// this hook may technically trigger on some invalid reads.
#define UC_HOOK_MEM_VALID \
(UC_HOOK_MEM_READ + UC_HOOK_MEM_WRITE + UC_HOOK_MEM_FETCH)
/*
Callback function for hooking memory (READ, WRITE & FETCH)
@ -314,7 +339,8 @@ typedef enum uc_hook_type {
@user_data: user data passed to tracing APIs
*/
typedef void (*uc_cb_hookmem_t)(uc_engine *uc, uc_mem_type type,
uint64_t address, int size, int64_t value, void *user_data);
uint64_t address, int size, int64_t value,
void *user_data);
/*
Callback function for handling invalid memory access events (UNMAPPED and
@ -326,21 +352,24 @@ typedef void (*uc_cb_hookmem_t)(uc_engine *uc, uc_mem_type type,
@value: value of data being written to memory, or irrelevant if type = READ.
@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 if the accessed
memory is made accessible with the correct permissions during the hook.
@return: return true to continue, or false to stop program (due to invalid
memory). 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_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,
but the fetch must succeed if execution is to resume.
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, but the fetch must succeed if execution is to resume.
*/
typedef bool (*uc_cb_eventmem_t)(uc_engine *uc, uc_mem_type type,
uint64_t address, int size, int64_t value, void *user_data);
uint64_t address, int size, int64_t value,
void *user_data);
/*
Memory region mapped by uc_mem_map() and uc_mem_map_ptr()
@ -357,8 +386,9 @@ typedef enum uc_query_type {
// Dynamically query current hardware mode.
UC_QUERY_MODE = 1,
UC_QUERY_PAGE_SIZE, // query pagesize of engine
UC_QUERY_ARCH, // query architecture of engine (for ARM to query Thumb mode)
UC_QUERY_TIMEOUT, // query if emulation stops due to timeout (indicated if result = True)
UC_QUERY_ARCH, // query architecture of engine (for ARM to query Thumb mode)
UC_QUERY_TIMEOUT, // query if emulation stops due to timeout (indicated if
// result = True)
} uc_query_type;
// Opaque storage for CPU context, used with uc_context_*()
@ -385,7 +415,6 @@ typedef struct uc_context uc_context;
UNICORN_EXPORT
unsigned int uc_version(unsigned int *major, unsigned int *minor);
/*
Determine if the given architecture is supported by this library.
@ -396,7 +425,6 @@ unsigned int uc_version(unsigned int *major, unsigned int *minor);
UNICORN_EXPORT
bool uc_arch_supported(uc_arch arch);
/*
Create new instance of unicorn engine.
@ -499,7 +527,8 @@ uc_err uc_reg_read(uc_engine *uc, int regid, void *value);
for detailed error).
*/
UNICORN_EXPORT
uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals, int count);
uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals,
int count);
/*
Read multiple register values.
@ -529,7 +558,8 @@ uc_err uc_reg_read_batch(uc_engine *uc, int *regs, void **vals, int count);
for detailed error).
*/
UNICORN_EXPORT
uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t size);
uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes,
size_t size);
/*
Read a range of bytes in memory.
@ -566,7 +596,8 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size);
for detailed error).
*/
UNICORN_EXPORT
uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count);
uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until,
uint64_t timeout, size_t count);
/*
Stop emulation (which was started by uc_emu_start() API.
@ -585,15 +616,17 @@ uc_err uc_emu_stop(uc_engine *uc);
The callback will be run when the hook event is hit.
@uc: handle returned by uc_open()
@hh: hook handle returned from this registration. To be used in uc_hook_del() API
@hh: hook handle returned from this registration. To be used in uc_hook_del()
API
@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 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
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)
NOTE: if @type = UC_HOOK_INSN, this is the instruction ID.
currently, only x86 in, out, syscall, sysenter, cpuid are supported.
@ -603,7 +636,7 @@ uc_err uc_emu_stop(uc_engine *uc);
*/
UNICORN_EXPORT
uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
void *user_data, uint64_t begin, uint64_t end, ...);
void *user_data, uint64_t begin, uint64_t end, ...);
/*
Unregister (remove) a hook callback.
@ -621,11 +654,11 @@ UNICORN_EXPORT
uc_err uc_hook_del(uc_engine *uc, uc_hook hh);
typedef enum uc_prot {
UC_PROT_NONE = 0,
UC_PROT_READ = 1,
UC_PROT_WRITE = 2,
UC_PROT_EXEC = 4,
UC_PROT_ALL = 7,
UC_PROT_NONE = 0,
UC_PROT_READ = 1,
UC_PROT_WRITE = 2,
UC_PROT_EXEC = 4,
UC_PROT_ALL = 7,
} uc_prot;
/*
@ -634,12 +667,14 @@ typedef enum uc_prot {
@uc: handle returned by uc_open()
@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.
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 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.
This must be some combination of UC_PROT_READ | UC_PROT_WRITE |
UC_PROT_EXEC, 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).
@ -653,21 +688,25 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms);
@uc: handle returned by uc_open()
@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.
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 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 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.
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 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
for detailed error).
*/
UNICORN_EXPORT
uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr);
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.
@ -675,15 +714,16 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t per
@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.
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
@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
@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).
*/
@ -698,9 +738,11 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size,
@uc: handle returned by uc_open()
@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.
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 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).
@ -714,18 +756,21 @@ uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size);
@uc: handle returned by uc_open()
@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.
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 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.
This must be some combination of UC_PROT_READ | UC_PROT_WRITE |
UC_PROT_EXEC, 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).
*/
UNICORN_EXPORT
uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t perms);
uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size,
uint32_t perms);
/*
Retrieve all memory regions mapped by uc_mem_map() and uc_mem_map_ptr()
@ -763,9 +808,9 @@ 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 free-ed by uc_context_free(). Calling uc_free() may still work, but the result
is **undefined**.
WARNING: After Unicorn 1.0.1rc5, the memory allocated by uc_context_alloc
should 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).
@ -827,7 +872,8 @@ uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value);
for detailed error).
*/
UNICORN_EXPORT
uc_err uc_context_reg_write_batch(uc_context *ctx, int *regs, void *const *vals, int count);
uc_err uc_context_reg_write_batch(uc_context *ctx, int *regs, void *const *vals,
int count);
/*
Read multiple register values from a context.
@ -841,7 +887,8 @@ uc_err uc_context_reg_write_batch(uc_context *ctx, int *regs, void *const *vals,
for detailed error).
*/
UNICORN_EXPORT
uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, int count);
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.
@ -849,7 +896,8 @@ uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, int co
state saved by uc_context_save().
@uc: handle returned by uc_open()
@context: handle returned by uc_context_alloc that has been used with uc_context_save
@context: handle returned by uc_context_alloc that has been used with
uc_context_save
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error).
@ -857,10 +905,9 @@ uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, int co
UNICORN_EXPORT
uc_err uc_context_restore(uc_engine *uc, uc_context *context);
/*
Return the size needed to store the cpu context. Can be used to allocate a buffer
to contain the cpu context and directly call uc_context_save.
Return the size needed to store the cpu context. Can be used to allocate a
buffer to contain the cpu context and directly call uc_context_save.
@uc: handle returned by uc_open()
@ -869,7 +916,6 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context);
UNICORN_EXPORT
size_t uc_context_size(uc_engine *uc);
/*
Free the context allocated by uc_context_alloc().

View File

@ -16,14 +16,14 @@ extern "C" {
// Memory-Management Register for instructions IDTR, GDTR, LDTR, TR.
// Borrow from SegmentCache in qemu/target-i386/cpu.h
typedef struct uc_x86_mmr {
uint16_t selector; /* not used by GDTR and IDTR */
uint64_t base; /* handle 32 or 64 bit CPUs */
uint16_t selector; /* not used by GDTR and IDTR */
uint64_t base; /* handle 32 or 64 bit CPUs */
uint32_t limit;
uint32_t flags; /* not used by GDTR and IDTR */
uint32_t flags; /* not used by GDTR and IDTR */
} uc_x86_mmr;
// Model-Specific Register structure, use this with UC_X86_REG_MSR (as the register ID) in
// call to uc_reg_write/uc_reg_read() to manipulate MSRs.
// Model-Specific Register structure, use this with UC_X86_REG_MSR (as the
// register ID) in call to uc_reg_write/uc_reg_read() to manipulate MSRs.
typedef struct uc_x86_msr {
uint32_t rid; // MSR id
uint64_t value; // MSR value
@ -35,62 +35,241 @@ typedef void (*uc_cb_insn_syscall_t)(struct uc_struct *uc, void *user_data);
//> X86 registers
typedef enum uc_x86_reg {
UC_X86_REG_INVALID = 0,
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_EBX, UC_X86_REG_ECX, UC_X86_REG_EDI, UC_X86_REG_EDX, UC_X86_REG_EFLAGS,
UC_X86_REG_EIP, 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,
UC_X86_REG_RBP, UC_X86_REG_RBX, UC_X86_REG_RCX, UC_X86_REG_RDI, UC_X86_REG_RDX,
UC_X86_REG_RIP, UC_X86_REG_RSI, UC_X86_REG_RSP, UC_X86_REG_SI,
UC_X86_REG_SIL, UC_X86_REG_SP, UC_X86_REG_SPL, UC_X86_REG_SS, UC_X86_REG_CR0,
UC_X86_REG_CR1, UC_X86_REG_CR2, UC_X86_REG_CR3, UC_X86_REG_CR4, UC_X86_REG_CR8,
UC_X86_REG_DR0, UC_X86_REG_DR1, UC_X86_REG_DR2, UC_X86_REG_DR3, UC_X86_REG_DR4,
UC_X86_REG_DR5, UC_X86_REG_DR6, UC_X86_REG_DR7, UC_X86_REG_FP0, UC_X86_REG_FP1,
UC_X86_REG_FP2, UC_X86_REG_FP3,
UC_X86_REG_FP4, UC_X86_REG_FP5, UC_X86_REG_FP6, UC_X86_REG_FP7,
UC_X86_REG_K0, UC_X86_REG_K1, UC_X86_REG_K2, UC_X86_REG_K3, UC_X86_REG_K4,
UC_X86_REG_K5, UC_X86_REG_K6, UC_X86_REG_K7, UC_X86_REG_MM0, UC_X86_REG_MM1,
UC_X86_REG_MM2, UC_X86_REG_MM3, UC_X86_REG_MM4, UC_X86_REG_MM5, UC_X86_REG_MM6,
UC_X86_REG_MM7, UC_X86_REG_R8, UC_X86_REG_R9, UC_X86_REG_R10, UC_X86_REG_R11,
UC_X86_REG_R12, UC_X86_REG_R13, UC_X86_REG_R14, UC_X86_REG_R15,
UC_X86_REG_ST0, UC_X86_REG_ST1, UC_X86_REG_ST2, UC_X86_REG_ST3,
UC_X86_REG_ST4, UC_X86_REG_ST5, UC_X86_REG_ST6, UC_X86_REG_ST7,
UC_X86_REG_XMM0, UC_X86_REG_XMM1, UC_X86_REG_XMM2, UC_X86_REG_XMM3, UC_X86_REG_XMM4,
UC_X86_REG_XMM5, UC_X86_REG_XMM6, UC_X86_REG_XMM7, UC_X86_REG_XMM8, UC_X86_REG_XMM9,
UC_X86_REG_XMM10, UC_X86_REG_XMM11, UC_X86_REG_XMM12, UC_X86_REG_XMM13, UC_X86_REG_XMM14,
UC_X86_REG_XMM15, UC_X86_REG_XMM16, UC_X86_REG_XMM17, UC_X86_REG_XMM18, UC_X86_REG_XMM19,
UC_X86_REG_XMM20, UC_X86_REG_XMM21, UC_X86_REG_XMM22, UC_X86_REG_XMM23, UC_X86_REG_XMM24,
UC_X86_REG_XMM25, UC_X86_REG_XMM26, UC_X86_REG_XMM27, UC_X86_REG_XMM28, UC_X86_REG_XMM29,
UC_X86_REG_XMM30, UC_X86_REG_XMM31, UC_X86_REG_YMM0, UC_X86_REG_YMM1, UC_X86_REG_YMM2,
UC_X86_REG_YMM3, UC_X86_REG_YMM4, UC_X86_REG_YMM5, UC_X86_REG_YMM6, UC_X86_REG_YMM7,
UC_X86_REG_YMM8, UC_X86_REG_YMM9, UC_X86_REG_YMM10, UC_X86_REG_YMM11, UC_X86_REG_YMM12,
UC_X86_REG_YMM13, UC_X86_REG_YMM14, UC_X86_REG_YMM15, UC_X86_REG_YMM16, UC_X86_REG_YMM17,
UC_X86_REG_YMM18, UC_X86_REG_YMM19, UC_X86_REG_YMM20, UC_X86_REG_YMM21, UC_X86_REG_YMM22,
UC_X86_REG_YMM23, UC_X86_REG_YMM24, UC_X86_REG_YMM25, UC_X86_REG_YMM26, UC_X86_REG_YMM27,
UC_X86_REG_YMM28, UC_X86_REG_YMM29, UC_X86_REG_YMM30, UC_X86_REG_YMM31, UC_X86_REG_ZMM0,
UC_X86_REG_ZMM1, UC_X86_REG_ZMM2, UC_X86_REG_ZMM3, UC_X86_REG_ZMM4, UC_X86_REG_ZMM5,
UC_X86_REG_ZMM6, UC_X86_REG_ZMM7, UC_X86_REG_ZMM8, UC_X86_REG_ZMM9, UC_X86_REG_ZMM10,
UC_X86_REG_ZMM11, UC_X86_REG_ZMM12, UC_X86_REG_ZMM13, UC_X86_REG_ZMM14, UC_X86_REG_ZMM15,
UC_X86_REG_ZMM16, UC_X86_REG_ZMM17, UC_X86_REG_ZMM18, UC_X86_REG_ZMM19, UC_X86_REG_ZMM20,
UC_X86_REG_ZMM21, UC_X86_REG_ZMM22, UC_X86_REG_ZMM23, UC_X86_REG_ZMM24, UC_X86_REG_ZMM25,
UC_X86_REG_ZMM26, UC_X86_REG_ZMM27, UC_X86_REG_ZMM28, UC_X86_REG_ZMM29, UC_X86_REG_ZMM30,
UC_X86_REG_ZMM31, UC_X86_REG_R8B, UC_X86_REG_R9B, UC_X86_REG_R10B, UC_X86_REG_R11B,
UC_X86_REG_R12B, UC_X86_REG_R13B, UC_X86_REG_R14B, UC_X86_REG_R15B, UC_X86_REG_R8D,
UC_X86_REG_R9D, UC_X86_REG_R10D, UC_X86_REG_R11D, UC_X86_REG_R12D, UC_X86_REG_R13D,
UC_X86_REG_R14D, UC_X86_REG_R15D, UC_X86_REG_R8W, UC_X86_REG_R9W, UC_X86_REG_R10W,
UC_X86_REG_R11W, UC_X86_REG_R12W, UC_X86_REG_R13W, UC_X86_REG_R14W, UC_X86_REG_R15W,
UC_X86_REG_IDTR, UC_X86_REG_GDTR, UC_X86_REG_LDTR, UC_X86_REG_TR, UC_X86_REG_FPCW,
UC_X86_REG_FPTAG,
UC_X86_REG_INVALID = 0,
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_EBX,
UC_X86_REG_ECX,
UC_X86_REG_EDI,
UC_X86_REG_EDX,
UC_X86_REG_EFLAGS,
UC_X86_REG_EIP,
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,
UC_X86_REG_RBP,
UC_X86_REG_RBX,
UC_X86_REG_RCX,
UC_X86_REG_RDI,
UC_X86_REG_RDX,
UC_X86_REG_RIP,
UC_X86_REG_RSI,
UC_X86_REG_RSP,
UC_X86_REG_SI,
UC_X86_REG_SIL,
UC_X86_REG_SP,
UC_X86_REG_SPL,
UC_X86_REG_SS,
UC_X86_REG_CR0,
UC_X86_REG_CR1,
UC_X86_REG_CR2,
UC_X86_REG_CR3,
UC_X86_REG_CR4,
UC_X86_REG_CR8,
UC_X86_REG_DR0,
UC_X86_REG_DR1,
UC_X86_REG_DR2,
UC_X86_REG_DR3,
UC_X86_REG_DR4,
UC_X86_REG_DR5,
UC_X86_REG_DR6,
UC_X86_REG_DR7,
UC_X86_REG_FP0,
UC_X86_REG_FP1,
UC_X86_REG_FP2,
UC_X86_REG_FP3,
UC_X86_REG_FP4,
UC_X86_REG_FP5,
UC_X86_REG_FP6,
UC_X86_REG_FP7,
UC_X86_REG_K0,
UC_X86_REG_K1,
UC_X86_REG_K2,
UC_X86_REG_K3,
UC_X86_REG_K4,
UC_X86_REG_K5,
UC_X86_REG_K6,
UC_X86_REG_K7,
UC_X86_REG_MM0,
UC_X86_REG_MM1,
UC_X86_REG_MM2,
UC_X86_REG_MM3,
UC_X86_REG_MM4,
UC_X86_REG_MM5,
UC_X86_REG_MM6,
UC_X86_REG_MM7,
UC_X86_REG_R8,
UC_X86_REG_R9,
UC_X86_REG_R10,
UC_X86_REG_R11,
UC_X86_REG_R12,
UC_X86_REG_R13,
UC_X86_REG_R14,
UC_X86_REG_R15,
UC_X86_REG_ST0,
UC_X86_REG_ST1,
UC_X86_REG_ST2,
UC_X86_REG_ST3,
UC_X86_REG_ST4,
UC_X86_REG_ST5,
UC_X86_REG_ST6,
UC_X86_REG_ST7,
UC_X86_REG_XMM0,
UC_X86_REG_XMM1,
UC_X86_REG_XMM2,
UC_X86_REG_XMM3,
UC_X86_REG_XMM4,
UC_X86_REG_XMM5,
UC_X86_REG_XMM6,
UC_X86_REG_XMM7,
UC_X86_REG_XMM8,
UC_X86_REG_XMM9,
UC_X86_REG_XMM10,
UC_X86_REG_XMM11,
UC_X86_REG_XMM12,
UC_X86_REG_XMM13,
UC_X86_REG_XMM14,
UC_X86_REG_XMM15,
UC_X86_REG_XMM16,
UC_X86_REG_XMM17,
UC_X86_REG_XMM18,
UC_X86_REG_XMM19,
UC_X86_REG_XMM20,
UC_X86_REG_XMM21,
UC_X86_REG_XMM22,
UC_X86_REG_XMM23,
UC_X86_REG_XMM24,
UC_X86_REG_XMM25,
UC_X86_REG_XMM26,
UC_X86_REG_XMM27,
UC_X86_REG_XMM28,
UC_X86_REG_XMM29,
UC_X86_REG_XMM30,
UC_X86_REG_XMM31,
UC_X86_REG_YMM0,
UC_X86_REG_YMM1,
UC_X86_REG_YMM2,
UC_X86_REG_YMM3,
UC_X86_REG_YMM4,
UC_X86_REG_YMM5,
UC_X86_REG_YMM6,
UC_X86_REG_YMM7,
UC_X86_REG_YMM8,
UC_X86_REG_YMM9,
UC_X86_REG_YMM10,
UC_X86_REG_YMM11,
UC_X86_REG_YMM12,
UC_X86_REG_YMM13,
UC_X86_REG_YMM14,
UC_X86_REG_YMM15,
UC_X86_REG_YMM16,
UC_X86_REG_YMM17,
UC_X86_REG_YMM18,
UC_X86_REG_YMM19,
UC_X86_REG_YMM20,
UC_X86_REG_YMM21,
UC_X86_REG_YMM22,
UC_X86_REG_YMM23,
UC_X86_REG_YMM24,
UC_X86_REG_YMM25,
UC_X86_REG_YMM26,
UC_X86_REG_YMM27,
UC_X86_REG_YMM28,
UC_X86_REG_YMM29,
UC_X86_REG_YMM30,
UC_X86_REG_YMM31,
UC_X86_REG_ZMM0,
UC_X86_REG_ZMM1,
UC_X86_REG_ZMM2,
UC_X86_REG_ZMM3,
UC_X86_REG_ZMM4,
UC_X86_REG_ZMM5,
UC_X86_REG_ZMM6,
UC_X86_REG_ZMM7,
UC_X86_REG_ZMM8,
UC_X86_REG_ZMM9,
UC_X86_REG_ZMM10,
UC_X86_REG_ZMM11,
UC_X86_REG_ZMM12,
UC_X86_REG_ZMM13,
UC_X86_REG_ZMM14,
UC_X86_REG_ZMM15,
UC_X86_REG_ZMM16,
UC_X86_REG_ZMM17,
UC_X86_REG_ZMM18,
UC_X86_REG_ZMM19,
UC_X86_REG_ZMM20,
UC_X86_REG_ZMM21,
UC_X86_REG_ZMM22,
UC_X86_REG_ZMM23,
UC_X86_REG_ZMM24,
UC_X86_REG_ZMM25,
UC_X86_REG_ZMM26,
UC_X86_REG_ZMM27,
UC_X86_REG_ZMM28,
UC_X86_REG_ZMM29,
UC_X86_REG_ZMM30,
UC_X86_REG_ZMM31,
UC_X86_REG_R8B,
UC_X86_REG_R9B,
UC_X86_REG_R10B,
UC_X86_REG_R11B,
UC_X86_REG_R12B,
UC_X86_REG_R13B,
UC_X86_REG_R14B,
UC_X86_REG_R15B,
UC_X86_REG_R8D,
UC_X86_REG_R9D,
UC_X86_REG_R10D,
UC_X86_REG_R11D,
UC_X86_REG_R12D,
UC_X86_REG_R13D,
UC_X86_REG_R14D,
UC_X86_REG_R15D,
UC_X86_REG_R8W,
UC_X86_REG_R9W,
UC_X86_REG_R10W,
UC_X86_REG_R11W,
UC_X86_REG_R12W,
UC_X86_REG_R13W,
UC_X86_REG_R14W,
UC_X86_REG_R15W,
UC_X86_REG_IDTR,
UC_X86_REG_GDTR,
UC_X86_REG_LDTR,
UC_X86_REG_TR,
UC_X86_REG_FPCW,
UC_X86_REG_FPTAG,
UC_X86_REG_MSR, // Model-Specific Register
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_ENDING // <-- mark the end of the list of registers
} uc_x86_reg;
//> X86 instructions

View File

@ -5,26 +5,38 @@
#define UC_QEMU_TARGET_ARM_H
// functions to read & write registers
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int armeb_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int armeb_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
int armeb_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int armeb_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
void arm_reg_reset(struct uc_struct *uc);
void arm64_reg_reset(struct uc_struct *uc);
void arm_uc_init(struct uc_struct* uc);
void armeb_uc_init(struct uc_struct* uc);
void arm_uc_init(struct uc_struct *uc);
void armeb_uc_init(struct uc_struct *uc);
void arm64_uc_init(struct uc_struct* uc);
void arm64eb_uc_init(struct uc_struct* uc);
void arm64_uc_init(struct uc_struct *uc);
void arm64eb_uc_init(struct uc_struct *uc);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -6,12 +6,16 @@
#define UC_QEMU_TARGET_I386_H
// functions to read & write registers
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
void x86_reg_reset(struct uc_struct *uc);
void x86_uc_init(struct uc_struct* uc);
void x86_uc_init(struct uc_struct *uc);
#endif

View File

@ -15,7 +15,7 @@ static void m68k_set_pc(struct uc_struct *uc, uint64_t address)
((CPUM68KState *)uc->cpu->env_ptr)->pc = address;
}
static void m68k_release(void* ctx)
static void m68k_release(void *ctx)
{
int i;
TCGContext *tcg_ctx = (TCGContext *)ctx;
@ -51,11 +51,12 @@ static void reg_read(CPUM68KState *env, unsigned int regid, void *value)
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
*(int32_t *)value = env->dregs[regid - UC_M68K_REG_D0];
else {
switch(regid) {
default: break;
case UC_M68K_REG_PC:
*(int32_t *)value = env->pc;
break;
switch (regid) {
default:
break;
case UC_M68K_REG_PC:
*(int32_t *)value = env->pc;
break;
}
}
@ -69,18 +70,20 @@ static void reg_write(CPUM68KState *env, unsigned int regid, const void *value)
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
env->dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value;
else {
switch(regid) {
default: break;
case UC_M68K_REG_PC:
env->pc = *(uint32_t *)value;
break;
switch (regid) {
default:
break;
case UC_M68K_REG_PC:
env->pc = *(uint32_t *)value;
break;
}
}
}
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
{
CPUM68KState* env = &(M68K_CPU(uc->cpu)->env);
CPUM68KState *env = &(M68K_CPU(uc->cpu)->env);
int i;
for (i = 0; i < count; i++) {
@ -92,16 +95,17 @@ int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int cou
return 0;
}
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count)
{
CPUM68KState* env = &(M68K_CPU(uc->cpu)->env);
CPUM68KState *env = &(M68K_CPU(uc->cpu)->env);
int i;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
if (regid == UC_M68K_REG_PC){
if (regid == UC_M68K_REG_PC) {
// force to quit execution and flush TB
uc->quit_request = true;
uc_emu_stop(uc);
@ -112,9 +116,10 @@ int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
}
DEFAULT_VISIBILITY
int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
{
CPUM68KState* env = (CPUM68KState* )ctx->data;
CPUM68KState *env = (CPUM68KState *)ctx->data;
int i;
for (i = 0; i < count; i++) {
@ -127,9 +132,10 @@ int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **val
}
DEFAULT_VISIBILITY
int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
{
CPUM68KState* env = (CPUM68KState* )ctx->data;
CPUM68KState *env = (CPUM68KState *)ctx->data;
int i;
for (i = 0; i < count; i++) {
@ -153,7 +159,7 @@ static int m68k_cpus_init(struct uc_struct *uc, const char *cpu_model)
}
DEFAULT_VISIBILITY
void m68k_uc_init(struct uc_struct* uc)
void m68k_uc_init(struct uc_struct *uc)
{
uc->release = m68k_release;
uc->reg_read = m68k_reg_read;

View File

@ -5,12 +5,16 @@
#define UC_QEMU_TARGET_M68K_H
// functions to read & write registers
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
void m68k_reg_reset(struct uc_struct *uc);
void m68k_uc_init(struct uc_struct* uc);
void m68k_uc_init(struct uc_struct *uc);
#endif

View File

@ -37,7 +37,6 @@ static void mips_set_pc(struct uc_struct *uc, uint64_t address)
((CPUMIPSState *)uc->cpu->env_ptr)->active_tc.PC = address;
}
static void mips_release(void *ctx)
{
int i;
@ -75,20 +74,21 @@ static void reg_read(CPUMIPSState *env, unsigned int regid, void *value)
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
*(mipsreg_t *)value = env->active_tc.gpr[regid - UC_MIPS_REG_0];
else {
switch(regid) {
default: break;
case UC_MIPS_REG_PC:
*(mipsreg_t *)value = env->active_tc.PC;
break;
case UC_MIPS_REG_CP0_CONFIG3:
*(mipsreg_t *)value = env->CP0_Config3;
break;
case UC_MIPS_REG_CP0_STATUS:
*(mipsreg_t *)value = env->CP0_Status;
break;
case UC_MIPS_REG_CP0_USERLOCAL:
*(mipsreg_t *)value = env->active_tc.CP0_UserLocal;
break;
switch (regid) {
default:
break;
case UC_MIPS_REG_PC:
*(mipsreg_t *)value = env->active_tc.PC;
break;
case UC_MIPS_REG_CP0_CONFIG3:
*(mipsreg_t *)value = env->CP0_Config3;
break;
case UC_MIPS_REG_CP0_STATUS:
*(mipsreg_t *)value = env->CP0_Status;
break;
case UC_MIPS_REG_CP0_USERLOCAL:
*(mipsreg_t *)value = env->active_tc.CP0_UserLocal;
break;
}
}
@ -100,31 +100,33 @@ static void reg_write(CPUMIPSState *env, unsigned int regid, const void *value)
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
env->active_tc.gpr[regid - UC_MIPS_REG_0] = *(mipsreg_t *)value;
else {
switch(regid) {
default: break;
case UC_MIPS_REG_PC:
env->active_tc.PC = *(mipsreg_t *)value;
break;
case UC_MIPS_REG_CP0_CONFIG3:
env->CP0_Config3 = *(mipsreg_t *)value;
break;
case UC_MIPS_REG_CP0_STATUS:
// TODO: ALL CP0 REGS
// https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00090-2B-MIPS32PRA-AFP-06.02.pdf
// https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00582-2B-microMIPS32-AFP-05.04.pdf
env->CP0_Status = *(mipsreg_t *)value;
compute_hflags(env);
break;
case UC_MIPS_REG_CP0_USERLOCAL:
env->active_tc.CP0_UserLocal = *(mipsreg_t *)value;
break;
switch (regid) {
default:
break;
case UC_MIPS_REG_PC:
env->active_tc.PC = *(mipsreg_t *)value;
break;
case UC_MIPS_REG_CP0_CONFIG3:
env->CP0_Config3 = *(mipsreg_t *)value;
break;
case UC_MIPS_REG_CP0_STATUS:
// TODO: ALL CP0 REGS
// https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00090-2B-MIPS32PRA-AFP-06.02.pdf
// https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00582-2B-microMIPS32-AFP-05.04.pdf
env->CP0_Status = *(mipsreg_t *)value;
compute_hflags(env);
break;
case UC_MIPS_REG_CP0_USERLOCAL:
env->active_tc.CP0_UserLocal = *(mipsreg_t *)value;
break;
}
}
return;
}
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
{
CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env);
int i;
@ -138,7 +140,8 @@ int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int cou
return 0;
}
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count)
{
CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env);
int i;
@ -147,7 +150,7 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
if(regid == UC_MIPS_REG_PC){
if (regid == UC_MIPS_REG_PC) {
// force to quit execution and flush TB
uc->quit_request = true;
uc_emu_stop(uc);
@ -160,15 +163,19 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
DEFAULT_VISIBILITY
#ifdef TARGET_MIPS64
#ifdef TARGET_WORDS_BIGENDIAN
int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
#else
int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
#endif
#else // if TARGET_MIPS
#ifdef TARGET_WORDS_BIGENDIAN
int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
#else
int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
#endif
#endif
{
@ -187,15 +194,19 @@ DEFAULT_VISIBILITY
DEFAULT_VISIBILITY
#ifdef TARGET_MIPS64
#ifdef TARGET_WORDS_BIGENDIAN
int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
#else
int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
#endif
#else // if TARGET_MIPS
#ifdef TARGET_WORDS_BIGENDIAN
int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
#else
int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
#endif
#endif
{
@ -226,15 +237,15 @@ static int mips_cpus_init(struct uc_struct *uc, const char *cpu_model)
DEFAULT_VISIBILITY
#ifdef TARGET_MIPS64
#ifdef TARGET_WORDS_BIGENDIAN
void mips64_uc_init(struct uc_struct* uc)
void mips64_uc_init(struct uc_struct *uc)
#else
void mips64el_uc_init(struct uc_struct* uc)
void mips64el_uc_init(struct uc_struct *uc)
#endif
#else // if TARGET_MIPS
#ifdef TARGET_WORDS_BIGENDIAN
void mips_uc_init(struct uc_struct* uc)
void mips_uc_init(struct uc_struct *uc)
#else
void mipsel_uc_init(struct uc_struct* uc)
void mipsel_uc_init(struct uc_struct *uc)
#endif
#endif
{

View File

@ -5,22 +5,32 @@
#define UC_QEMU_TARGET_MIPS_H
// functions to read & write registers
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
void mips_reg_reset(struct uc_struct *uc);
void mips_uc_init(struct uc_struct* uc);
void mipsel_uc_init(struct uc_struct* uc);
void mips64_uc_init(struct uc_struct* uc);
void mips64el_uc_init(struct uc_struct* uc);
void mips_uc_init(struct uc_struct *uc);
void mipsel_uc_init(struct uc_struct *uc);
void mips64_uc_init(struct uc_struct *uc);
void mips64el_uc_init(struct uc_struct *uc);
#endif

View File

@ -18,14 +18,14 @@ typedef uint32_t ppcreg_t;
static uint64_t ppc_mem_redirect(uint64_t address)
{
/* // kseg0 range masks off high address bit
if (address >= 0x80000000 && address <= 0x9fffffff)
return address & 0x7fffffff;
/* // kseg0 range masks off high address bit
if (address >= 0x80000000 && address <= 0x9fffffff)
return address & 0x7fffffff;
// kseg1 range masks off top 3 address bits
if (address >= 0xa0000000 && address <= 0xbfffffff) {
return address & 0x1fffffff;
}*/
// kseg1 range masks off top 3 address bits
if (address >= 0xa0000000 && address <= 0xbfffffff) {
return address & 0x1fffffff;
}*/
// no redirect
return address;
@ -59,12 +59,12 @@ static void ppc_release(void *ctx)
for (i = 0; i < 32; i++) {
g_free(tcg_ctx->cpu_gpr[i]);
}
// g_free(tcg_ctx->cpu_PC);
// g_free(tcg_ctx->cpu_PC);
g_free(tcg_ctx->btarget);
g_free(tcg_ctx->bcond);
g_free(tcg_ctx->cpu_dspctrl);
// g_free(tcg_ctx->tb_ctx.tbs);
// g_free(tcg_ctx->tb_ctx.tbs);
ppc_cpu_instance_finalize(tcg_ctx->uc->cpu);
ppc_cpu_unrealize(tcg_ctx->uc->cpu);
@ -84,17 +84,18 @@ static void reg_read(CPUPPCState *env, unsigned int regid, void *value)
if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31)
*(ppcreg_t *)value = env->gpr[regid - UC_PPC_REG_0];
else {
switch(regid) {
default: break;
case UC_PPC_REG_PC:
*(ppcreg_t *)value = env->nip;
break;
/* case UC_PPC_REG_CP0_CONFIG3:
*(mipsreg_t *)value = env->CP0_Config3;
break;
case UC_MIPS_REG_CP0_USERLOCAL:
*(mipsreg_t *)value = env->active_tc.CP0_UserLocal;
break; */
switch (regid) {
default:
break;
case UC_PPC_REG_PC:
*(ppcreg_t *)value = env->nip;
break;
/* case UC_PPC_REG_CP0_CONFIG3:
*(mipsreg_t *)value = env->CP0_Config3;
break;
case UC_MIPS_REG_CP0_USERLOCAL:
*(mipsreg_t *)value = env->active_tc.CP0_UserLocal;
break; */
}
}
@ -106,24 +107,26 @@ static void reg_write(CPUPPCState *env, unsigned int regid, const void *value)
if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31)
env->gpr[regid - UC_PPC_REG_0] = *(ppcreg_t *)value;
else {
switch(regid) {
default: break;
case UC_PPC_REG_PC:
env->nip = *(ppcreg_t *)value;
break;
/* case UC_MIPS_REG_CP0_CONFIG3:
env->CP0_Config3 = *(mipsreg_t *)value;
break;
case UC_MIPS_REG_CP0_USERLOCAL:
env->active_tc.CP0_UserLocal = *(mipsreg_t *)value;
break; */
switch (regid) {
default:
break;
case UC_PPC_REG_PC:
env->nip = *(ppcreg_t *)value;
break;
/* case UC_MIPS_REG_CP0_CONFIG3:
env->CP0_Config3 = *(mipsreg_t *)value;
break;
case UC_MIPS_REG_CP0_USERLOCAL:
env->active_tc.CP0_UserLocal = *(mipsreg_t *)value;
break; */
}
}
return;
}
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
{
CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env);
int i;
@ -137,7 +140,8 @@ int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun
return 0;
}
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count)
{
CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env);
int i;
@ -158,9 +162,11 @@ int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i
DEFAULT_VISIBILITY
#ifdef TARGET_PPC64
int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
#else
int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
#endif
{
CPUPPCState *env = (CPUPPCState *)ctx->data;
@ -177,9 +183,11 @@ int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals
DEFAULT_VISIBILITY
#ifdef TARGET_PPC64
int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
#else
int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
#endif
{
CPUPPCState *env = (CPUPPCState *)ctx->data;
@ -208,9 +216,9 @@ static int ppc_cpus_init(struct uc_struct *uc, const char *cpu_model)
DEFAULT_VISIBILITY
#ifdef TARGET_PPC64
void ppc64_uc_init(struct uc_struct* uc)
void ppc64_uc_init(struct uc_struct *uc)
#else
void ppc_uc_init(struct uc_struct* uc)
void ppc_uc_init(struct uc_struct *uc)
#endif
{
uc->reg_read = ppc_reg_read;

View File

@ -5,16 +5,22 @@
#define UC_QEMU_TARGET_PPC_H
// functions to read & write registers
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
void ppc_reg_reset(struct uc_struct *uc);
void ppc_uc_init(struct uc_struct* uc);
void ppc64_uc_init(struct uc_struct* uc);
void ppc_uc_init(struct uc_struct *uc);
void ppc64_uc_init(struct uc_struct *uc);
#endif

View File

@ -36,99 +36,97 @@ static void riscv_release(void *ctx)
}
}
void riscv_reg_reset(struct uc_struct *uc)
{
}
void riscv_reg_reset(struct uc_struct *uc) {}
static void reg_read(CPURISCVState *env, unsigned int regid, void *value)
{
switch(regid) {
case UC_RISCV_REG_X0:
case UC_RISCV_REG_X1:
case UC_RISCV_REG_X2:
case UC_RISCV_REG_X3:
case UC_RISCV_REG_X4:
case UC_RISCV_REG_X5:
case UC_RISCV_REG_X6:
case UC_RISCV_REG_X7:
case UC_RISCV_REG_X8:
case UC_RISCV_REG_X9:
case UC_RISCV_REG_X10:
case UC_RISCV_REG_X11:
case UC_RISCV_REG_X12:
case UC_RISCV_REG_X13:
case UC_RISCV_REG_X14:
case UC_RISCV_REG_X15:
case UC_RISCV_REG_X16:
case UC_RISCV_REG_X17:
case UC_RISCV_REG_X18:
case UC_RISCV_REG_X19:
case UC_RISCV_REG_X20:
case UC_RISCV_REG_X21:
case UC_RISCV_REG_X22:
case UC_RISCV_REG_X23:
case UC_RISCV_REG_X24:
case UC_RISCV_REG_X25:
case UC_RISCV_REG_X26:
case UC_RISCV_REG_X27:
case UC_RISCV_REG_X28:
case UC_RISCV_REG_X29:
case UC_RISCV_REG_X30:
case UC_RISCV_REG_X31:
switch (regid) {
case UC_RISCV_REG_X0:
case UC_RISCV_REG_X1:
case UC_RISCV_REG_X2:
case UC_RISCV_REG_X3:
case UC_RISCV_REG_X4:
case UC_RISCV_REG_X5:
case UC_RISCV_REG_X6:
case UC_RISCV_REG_X7:
case UC_RISCV_REG_X8:
case UC_RISCV_REG_X9:
case UC_RISCV_REG_X10:
case UC_RISCV_REG_X11:
case UC_RISCV_REG_X12:
case UC_RISCV_REG_X13:
case UC_RISCV_REG_X14:
case UC_RISCV_REG_X15:
case UC_RISCV_REG_X16:
case UC_RISCV_REG_X17:
case UC_RISCV_REG_X18:
case UC_RISCV_REG_X19:
case UC_RISCV_REG_X20:
case UC_RISCV_REG_X21:
case UC_RISCV_REG_X22:
case UC_RISCV_REG_X23:
case UC_RISCV_REG_X24:
case UC_RISCV_REG_X25:
case UC_RISCV_REG_X26:
case UC_RISCV_REG_X27:
case UC_RISCV_REG_X28:
case UC_RISCV_REG_X29:
case UC_RISCV_REG_X30:
case UC_RISCV_REG_X31:
#ifdef TARGET_RISCV64
*(int64_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
*(int64_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
#else
*(int32_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
*(int32_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
#endif
break;
case UC_RISCV_REG_PC:
break;
case UC_RISCV_REG_PC:
#ifdef TARGET_RISCV64
*(int64_t *)value = env->pc;
*(int64_t *)value = env->pc;
#else
*(int32_t *)value = env->pc;
*(int32_t *)value = env->pc;
#endif
break;
break;
case UC_RISCV_REG_F0: // "ft0"
case UC_RISCV_REG_F1: // "ft1"
case UC_RISCV_REG_F2: // "ft2"
case UC_RISCV_REG_F3: // "ft3"
case UC_RISCV_REG_F4: // "ft4"
case UC_RISCV_REG_F5: // "ft5"
case UC_RISCV_REG_F6: // "ft6"
case UC_RISCV_REG_F7: // "ft7"
case UC_RISCV_REG_F8: // "fs0"
case UC_RISCV_REG_F9: // "fs1"
case UC_RISCV_REG_F10: // "fa0"
case UC_RISCV_REG_F11: // "fa1"
case UC_RISCV_REG_F12: // "fa2"
case UC_RISCV_REG_F13: // "fa3"
case UC_RISCV_REG_F14: // "fa4"
case UC_RISCV_REG_F15: // "fa5"
case UC_RISCV_REG_F16: // "fa6"
case UC_RISCV_REG_F17: // "fa7"
case UC_RISCV_REG_F18: // "fs2"
case UC_RISCV_REG_F19: // "fs3"
case UC_RISCV_REG_F20: // "fs4"
case UC_RISCV_REG_F21: // "fs5"
case UC_RISCV_REG_F22: // "fs6"
case UC_RISCV_REG_F23: // "fs7"
case UC_RISCV_REG_F24: // "fs8"
case UC_RISCV_REG_F25: // "fs9"
case UC_RISCV_REG_F26: // "fs10"
case UC_RISCV_REG_F27: // "fs11"
case UC_RISCV_REG_F28: // "ft8"
case UC_RISCV_REG_F29: // "ft9"
case UC_RISCV_REG_F30: // "ft10"
case UC_RISCV_REG_F31: // "ft11"
case UC_RISCV_REG_F0: // "ft0"
case UC_RISCV_REG_F1: // "ft1"
case UC_RISCV_REG_F2: // "ft2"
case UC_RISCV_REG_F3: // "ft3"
case UC_RISCV_REG_F4: // "ft4"
case UC_RISCV_REG_F5: // "ft5"
case UC_RISCV_REG_F6: // "ft6"
case UC_RISCV_REG_F7: // "ft7"
case UC_RISCV_REG_F8: // "fs0"
case UC_RISCV_REG_F9: // "fs1"
case UC_RISCV_REG_F10: // "fa0"
case UC_RISCV_REG_F11: // "fa1"
case UC_RISCV_REG_F12: // "fa2"
case UC_RISCV_REG_F13: // "fa3"
case UC_RISCV_REG_F14: // "fa4"
case UC_RISCV_REG_F15: // "fa5"
case UC_RISCV_REG_F16: // "fa6"
case UC_RISCV_REG_F17: // "fa7"
case UC_RISCV_REG_F18: // "fs2"
case UC_RISCV_REG_F19: // "fs3"
case UC_RISCV_REG_F20: // "fs4"
case UC_RISCV_REG_F21: // "fs5"
case UC_RISCV_REG_F22: // "fs6"
case UC_RISCV_REG_F23: // "fs7"
case UC_RISCV_REG_F24: // "fs8"
case UC_RISCV_REG_F25: // "fs9"
case UC_RISCV_REG_F26: // "fs10"
case UC_RISCV_REG_F27: // "fs11"
case UC_RISCV_REG_F28: // "ft8"
case UC_RISCV_REG_F29: // "ft9"
case UC_RISCV_REG_F30: // "ft10"
case UC_RISCV_REG_F31: // "ft11"
#ifdef TARGET_RISCV64
*(int64_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
*(int64_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
#else
*(int32_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
*(int32_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
#endif
break;
default:
break;
break;
default:
break;
}
return;
@ -136,96 +134,97 @@ static void reg_read(CPURISCVState *env, unsigned int regid, void *value)
static void reg_write(CPURISCVState *env, unsigned int regid, const void *value)
{
switch(regid) {
case UC_RISCV_REG_X0:
case UC_RISCV_REG_X1:
case UC_RISCV_REG_X2:
case UC_RISCV_REG_X3:
case UC_RISCV_REG_X4:
case UC_RISCV_REG_X5:
case UC_RISCV_REG_X6:
case UC_RISCV_REG_X7:
case UC_RISCV_REG_X8:
case UC_RISCV_REG_X9:
case UC_RISCV_REG_X10:
case UC_RISCV_REG_X11:
case UC_RISCV_REG_X12:
case UC_RISCV_REG_X13:
case UC_RISCV_REG_X14:
case UC_RISCV_REG_X15:
case UC_RISCV_REG_X16:
case UC_RISCV_REG_X17:
case UC_RISCV_REG_X18:
case UC_RISCV_REG_X19:
case UC_RISCV_REG_X20:
case UC_RISCV_REG_X21:
case UC_RISCV_REG_X22:
case UC_RISCV_REG_X23:
case UC_RISCV_REG_X24:
case UC_RISCV_REG_X25:
case UC_RISCV_REG_X26:
case UC_RISCV_REG_X27:
case UC_RISCV_REG_X28:
case UC_RISCV_REG_X29:
case UC_RISCV_REG_X30:
case UC_RISCV_REG_X31:
switch (regid) {
case UC_RISCV_REG_X0:
case UC_RISCV_REG_X1:
case UC_RISCV_REG_X2:
case UC_RISCV_REG_X3:
case UC_RISCV_REG_X4:
case UC_RISCV_REG_X5:
case UC_RISCV_REG_X6:
case UC_RISCV_REG_X7:
case UC_RISCV_REG_X8:
case UC_RISCV_REG_X9:
case UC_RISCV_REG_X10:
case UC_RISCV_REG_X11:
case UC_RISCV_REG_X12:
case UC_RISCV_REG_X13:
case UC_RISCV_REG_X14:
case UC_RISCV_REG_X15:
case UC_RISCV_REG_X16:
case UC_RISCV_REG_X17:
case UC_RISCV_REG_X18:
case UC_RISCV_REG_X19:
case UC_RISCV_REG_X20:
case UC_RISCV_REG_X21:
case UC_RISCV_REG_X22:
case UC_RISCV_REG_X23:
case UC_RISCV_REG_X24:
case UC_RISCV_REG_X25:
case UC_RISCV_REG_X26:
case UC_RISCV_REG_X27:
case UC_RISCV_REG_X28:
case UC_RISCV_REG_X29:
case UC_RISCV_REG_X30:
case UC_RISCV_REG_X31:
#ifdef TARGET_RISCV64
env->gpr[regid - UC_RISCV_REG_X0] = *(uint64_t *)value;
env->gpr[regid - UC_RISCV_REG_X0] = *(uint64_t *)value;
#else
env->gpr[regid - UC_RISCV_REG_X0] = *(uint32_t *)value;
env->gpr[regid - UC_RISCV_REG_X0] = *(uint32_t *)value;
#endif
break;
case UC_RISCV_REG_PC:
break;
case UC_RISCV_REG_PC:
#ifdef TARGET_RISCV64
env->pc = *(uint64_t *)value;
env->pc = *(uint64_t *)value;
#else
env->pc = *(uint32_t *)value;
env->pc = *(uint32_t *)value;
#endif
break;
case UC_RISCV_REG_F0: // "ft0"
case UC_RISCV_REG_F1: // "ft1"
case UC_RISCV_REG_F2: // "ft2"
case UC_RISCV_REG_F3: // "ft3"
case UC_RISCV_REG_F4: // "ft4"
case UC_RISCV_REG_F5: // "ft5"
case UC_RISCV_REG_F6: // "ft6"
case UC_RISCV_REG_F7: // "ft7"
case UC_RISCV_REG_F8: // "fs0"
case UC_RISCV_REG_F9: // "fs1"
case UC_RISCV_REG_F10: // "fa0"
case UC_RISCV_REG_F11: // "fa1"
case UC_RISCV_REG_F12: // "fa2"
case UC_RISCV_REG_F13: // "fa3"
case UC_RISCV_REG_F14: // "fa4"
case UC_RISCV_REG_F15: // "fa5"
case UC_RISCV_REG_F16: // "fa6"
case UC_RISCV_REG_F17: // "fa7"
case UC_RISCV_REG_F18: // "fs2"
case UC_RISCV_REG_F19: // "fs3"
case UC_RISCV_REG_F20: // "fs4"
case UC_RISCV_REG_F21: // "fs5"
case UC_RISCV_REG_F22: // "fs6"
case UC_RISCV_REG_F23: // "fs7"
case UC_RISCV_REG_F24: // "fs8"
case UC_RISCV_REG_F25: // "fs9"
case UC_RISCV_REG_F26: // "fs10"
case UC_RISCV_REG_F27: // "fs11"
case UC_RISCV_REG_F28: // "ft8"
case UC_RISCV_REG_F29: // "ft9"
case UC_RISCV_REG_F30: // "ft10"
case UC_RISCV_REG_F31: // "ft11"
break;
case UC_RISCV_REG_F0: // "ft0"
case UC_RISCV_REG_F1: // "ft1"
case UC_RISCV_REG_F2: // "ft2"
case UC_RISCV_REG_F3: // "ft3"
case UC_RISCV_REG_F4: // "ft4"
case UC_RISCV_REG_F5: // "ft5"
case UC_RISCV_REG_F6: // "ft6"
case UC_RISCV_REG_F7: // "ft7"
case UC_RISCV_REG_F8: // "fs0"
case UC_RISCV_REG_F9: // "fs1"
case UC_RISCV_REG_F10: // "fa0"
case UC_RISCV_REG_F11: // "fa1"
case UC_RISCV_REG_F12: // "fa2"
case UC_RISCV_REG_F13: // "fa3"
case UC_RISCV_REG_F14: // "fa4"
case UC_RISCV_REG_F15: // "fa5"
case UC_RISCV_REG_F16: // "fa6"
case UC_RISCV_REG_F17: // "fa7"
case UC_RISCV_REG_F18: // "fs2"
case UC_RISCV_REG_F19: // "fs3"
case UC_RISCV_REG_F20: // "fs4"
case UC_RISCV_REG_F21: // "fs5"
case UC_RISCV_REG_F22: // "fs6"
case UC_RISCV_REG_F23: // "fs7"
case UC_RISCV_REG_F24: // "fs8"
case UC_RISCV_REG_F25: // "fs9"
case UC_RISCV_REG_F26: // "fs10"
case UC_RISCV_REG_F27: // "fs11"
case UC_RISCV_REG_F28: // "ft8"
case UC_RISCV_REG_F29: // "ft9"
case UC_RISCV_REG_F30: // "ft10"
case UC_RISCV_REG_F31: // "ft11"
#ifdef TARGET_RISCV64
env->fpr[regid - UC_RISCV_REG_F0] = *(uint64_t *)value;
env->fpr[regid - UC_RISCV_REG_F0] = *(uint64_t *)value;
#else
env->fpr[regid - UC_RISCV_REG_F0] = *(uint32_t *)value;
env->fpr[regid - UC_RISCV_REG_F0] = *(uint32_t *)value;
#endif
break;
default:
break;
break;
default:
break;
}
}
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
{
CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env);
int i;
@ -239,7 +238,8 @@ int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co
return 0;
}
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count)
{
CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env);
int i;
@ -248,11 +248,11 @@ int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
if(regid == UC_RISCV_REG_PC){
if (regid == UC_RISCV_REG_PC) {
// force to quit execution and flush TB
uc->quit_request = true;
uc_emu_stop(uc);
}
}
}
return 0;
@ -260,10 +260,12 @@ int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
DEFAULT_VISIBILITY
#ifdef TARGET_RISCV32
int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
#else
/* TARGET_RISCV64 */
int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
/* TARGET_RISCV64 */
int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
#endif
{
CPURISCVState *env = (CPURISCVState *)ctx->data;
@ -280,10 +282,12 @@ int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **
DEFAULT_VISIBILITY
#ifdef TARGET_RISCV32
int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
#else
/* TARGET_RISCV64 */
int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
/* TARGET_RISCV64 */
int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
#endif
{
CPURISCVState *env = (CPURISCVState *)ctx->data;
@ -301,14 +305,14 @@ int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *
static bool riscv_stop_interrupt(struct uc_struct *uc, int intno)
{
// detect stop exception
switch(intno){
default:
return false;
case RISCV_EXCP_UNICORN_END:
return true;
case RISCV_EXCP_BREAKPOINT:
uc->invalid_error = UC_ERR_EXCEPTION;
return true;
switch (intno) {
default:
return false;
case RISCV_EXCP_UNICORN_END:
return true;
case RISCV_EXCP_BREAKPOINT:
uc->invalid_error = UC_ERR_EXCEPTION;
return true;
}
}
@ -332,10 +336,10 @@ static int riscv_cpus_init(struct uc_struct *uc, const char *cpu_model)
DEFAULT_VISIBILITY
#ifdef TARGET_RISCV32
void riscv32_uc_init(struct uc_struct* uc)
void riscv32_uc_init(struct uc_struct *uc)
#else
/* TARGET_RISCV64 */
void riscv64_uc_init(struct uc_struct* uc)
/* TARGET_RISCV64 */
void riscv64_uc_init(struct uc_struct *uc)
#endif
{
uc->reg_read = riscv_reg_read;

View File

@ -6,16 +6,22 @@
#define UC_QEMU_TARGET_RISCV_H
// functions to read & write registers
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
void riscv_reg_reset(struct uc_struct *uc);
void riscv32_uc_init(struct uc_struct* uc);
void riscv64_uc_init(struct uc_struct* uc);
void riscv32_uc_init(struct uc_struct *uc);
void riscv64_uc_init(struct uc_struct *uc);
#endif

View File

@ -10,11 +10,11 @@
static bool sparc_stop_interrupt(struct uc_struct *uc, int intno)
{
switch(intno) {
default:
return false;
case TT_ILL_INSN:
return true;
switch (intno) {
default:
return false;
case TT_ILL_INSN:
return true;
}
}
@ -63,15 +63,16 @@ static void reg_read(CPUSPARCState *env, unsigned int regid, void *value)
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
*(int32_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
*(int32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0];
*(int32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0];
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
*(int32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0];
*(int32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0];
else {
switch(regid) {
default: break;
case UC_SPARC_REG_PC:
*(int32_t *)value = env->pc;
break;
switch (regid) {
default:
break;
case UC_SPARC_REG_PC:
*(int32_t *)value = env->pc;
break;
}
}
@ -87,21 +88,23 @@ static void reg_write(CPUSPARCState *env, unsigned int regid, const void *value)
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
env->regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value;
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value;
env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value;
else {
switch(regid) {
default: break;
case UC_SPARC_REG_PC:
env->pc = *(uint32_t *)value;
env->npc = *(uint32_t *)value + 4;
break;
switch (regid) {
default:
break;
case UC_SPARC_REG_PC:
env->pc = *(uint32_t *)value;
env->npc = *(uint32_t *)value + 4;
break;
}
}
return;
}
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
{
CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
int i;
@ -115,7 +118,8 @@ int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co
return 0;
}
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count)
{
CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
int i;
@ -124,7 +128,7 @@ int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
if( regid == UC_SPARC_REG_PC){
if (regid == UC_SPARC_REG_PC) {
// force to quit execution and flush TB
uc->quit_request = true;
uc_emu_stop(uc);
@ -136,7 +140,8 @@ int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
}
DEFAULT_VISIBILITY
int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
{
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
int i;
@ -151,7 +156,8 @@ int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **va
}
DEFAULT_VISIBILITY
int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
{
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
int i;
@ -177,7 +183,7 @@ static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model)
}
DEFAULT_VISIBILITY
void sparc_uc_init(struct uc_struct* uc)
void sparc_uc_init(struct uc_struct *uc)
{
uc->release = sparc_release;
uc->reg_read = sparc_reg_read;

View File

@ -5,16 +5,22 @@
#define UC_QEMU_TARGET_SPARC_H
// functions to read & write registers
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
void sparc_reg_reset(struct uc_struct *uc);
void sparc_uc_init(struct uc_struct* uc);
void sparc64_uc_init(struct uc_struct* uc);
void sparc_uc_init(struct uc_struct *uc);
void sparc64_uc_init(struct uc_struct *uc);
#endif

View File

@ -14,24 +14,24 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA.
*/
#define __STDC_FORMAT_MACROS
#include <unicorn/unicorn.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
static int insts_executed;
// callback for tracing instructions, detect HLT and terminate emulation
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size,
void *user_data)
{
uint8_t opcode;
unsigned char buf[256];
@ -39,61 +39,81 @@ static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_da
insts_executed++;
if (uc_mem_read(uc, addr, buf, size) != UC_ERR_OK) {
printf("not ok - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
printf("not ok - uc_mem_read fail during hook_code callback, addr: "
"0x%" PRIx64 "\n",
addr);
if (uc_emu_stop(uc) != UC_ERR_OK) {
printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
printf("not ok - uc_emu_stop fail during hook_code callback, addr: "
"0x%" PRIx64 "\n",
addr);
_exit(-1);
}
}
opcode = buf[0];
switch (opcode) {
case 0x41: // inc ecx
if (uc_mem_protect(uc, 0x101000, 0x1000, UC_PROT_READ) != UC_ERR_OK) {
printf("not ok - uc_mem_protect fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
_exit(-1);
}
break;
case 0x42: // inc edx
if (uc_mem_unmap(uc, 0x101000, 0x1000) != UC_ERR_OK) {
printf("not ok - uc_mem_unmap fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
_exit(-1);
}
break;
case 0xf4: // hlt
if (uc_emu_stop(uc) != UC_ERR_OK) {
printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
_exit(-1);
}
break;
default: // all others
break;
case 0x41: // inc ecx
if (uc_mem_protect(uc, 0x101000, 0x1000, UC_PROT_READ) != UC_ERR_OK) {
printf("not ok - uc_mem_protect fail during hook_code callback, "
"addr: 0x%" PRIx64 "\n",
addr);
_exit(-1);
}
break;
case 0x42: // inc edx
if (uc_mem_unmap(uc, 0x101000, 0x1000) != UC_ERR_OK) {
printf("not ok - uc_mem_unmap fail during hook_code callback, "
"addr: 0x%" PRIx64 "\n",
addr);
_exit(-1);
}
break;
case 0xf4: // hlt
if (uc_emu_stop(uc) != UC_ERR_OK) {
printf("not ok - uc_emu_stop fail during hook_code callback, addr: "
"0x%" PRIx64 "\n",
addr);
_exit(-1);
}
break;
default: // all others
break;
}
}
// callback for tracing invalid memory access (READ/WRITE/EXEC)
static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
uint64_t addr, int size, int64_t value, void *user_data)
static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, uint64_t addr,
int size, int64_t value, void *user_data)
{
switch(type) {
default:
printf("not ok - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", type, addr);
return false;
case UC_MEM_READ_UNMAPPED:
printf("not ok - Read from invalid memory at 0x%"PRIx64 ", data size = %u\n", addr, size);
return false;
case UC_MEM_WRITE_UNMAPPED:
printf("not ok - Write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
return false;
case UC_MEM_FETCH_PROT:
printf("not ok - Fetch from non-executable memory at 0x%"PRIx64 "\n", addr);
return false;
case UC_MEM_WRITE_PROT:
printf("not ok - Write to non-writeable memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
return false;
case UC_MEM_READ_PROT:
printf("not ok - Read from non-readable memory at 0x%"PRIx64 ", data size = %u\n", addr, size);
return false;
switch (type) {
default:
printf("not ok - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", type,
addr);
return false;
case UC_MEM_READ_UNMAPPED:
printf("not ok - Read from invalid memory at 0x%" PRIx64
", data size = %u\n",
addr, size);
return false;
case UC_MEM_WRITE_UNMAPPED:
printf("not ok - Write to invalid memory at 0x%" PRIx64
", data size = %u, data value = 0x%" PRIx64 "\n",
addr, size, value);
return false;
case UC_MEM_FETCH_PROT:
printf("not ok - Fetch from non-executable memory at 0x%" PRIx64 "\n",
addr);
return false;
case UC_MEM_WRITE_PROT:
printf("not ok - Write to non-writeable memory at 0x%" PRIx64
", data size = %u, data value = 0x%" PRIx64 "\n",
addr, size, value);
return false;
case UC_MEM_READ_PROT:
printf("not ok - Read from non-readable memory at 0x%" PRIx64
", data size = %u\n",
addr, size);
return false;
}
}
@ -107,7 +127,8 @@ static void do_nx_demo(bool cause_fault)
insts_executed = 0;
printf("===================================\n");
printf("# Example of marking memory NX (%s)\n", cause_fault ? "faulting" : "non-faulting");
printf("# Example of marking memory NX (%s)\n",
cause_fault ? "faulting" : "non-faulting");
// Initialize emulator in X86-32bit mode
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
@ -129,14 +150,16 @@ static void do_nx_demo(bool cause_fault)
page2: @2000
jmp page1
*/
memset(code_buf, 0x40, sizeof(code_buf)); // fill with inc eax
memcpy(code_buf + 0x1000 - 5, "\xe9\x00\x10\x00\x00", 5); // jump to 0x102000
memset(code_buf, 0x40, sizeof(code_buf)); // fill with inc eax
memcpy(code_buf + 0x1000 - 5, "\xe9\x00\x10\x00\x00",
5); // jump to 0x102000
memcpy(code_buf + 0x2000, "\xe9\xfb\xef\xff\xff", 5); // jump to 0x101000
code_buf[0x1fff] = 0xf4; //hlt
code_buf[0x1fff] = 0xf4; // hlt
if (cause_fault) {
// insert instruction to trigger U_PROT_EXEC change (see hook_code function)
code_buf[0x1000] = 0x41; // inc ecx at page1
// insert instruction to trigger U_PROT_EXEC change (see hook_code
// function)
code_buf[0x1000] = 0x41; // inc ecx at page1
}
// write machine code to be emulated to memory
@ -146,9 +169,10 @@ static void do_nx_demo(bool cause_fault)
}
// intercept code and invalid memory events
if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK ||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID,
hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) {
if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) !=
UC_ERR_OK ||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL, 1,
0) != UC_ERR_OK) {
printf("not ok - Failed to install hooks\n");
return;
}
@ -157,7 +181,8 @@ static void do_nx_demo(bool cause_fault)
printf("BEGINNING EXECUTION\n");
err = uc_emu_start(uc, 0x100000, 0x103000, 0, 0);
if (err != UC_ERR_OK) {
printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, uc_strerror(err));
printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err,
uc_strerror(err));
printf("FAILED EXECUTION\n");
} else {
printf("SUCCESSFUL EXECUTION\n");
@ -212,11 +237,12 @@ static void do_perms_demo(bool change_perms)
*/
memcpy(code_buf, WRITE_DEMO, sizeof(WRITE_DEMO) - 1);
memset(code_buf + sizeof(WRITE_DEMO) - 1, 0x90, 1000);
code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt
code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt
if (change_perms) {
// write protect memory area [0x101000, 0x101fff]. see hook_code function
code_buf[0] = 0x41; // inc ecx
// write protect memory area [0x101000, 0x101fff]. see hook_code
// function
code_buf[0] = 0x41; // inc ecx
}
// write machine code to be emulated to memory
@ -226,10 +252,10 @@ static void do_perms_demo(bool change_perms)
}
// intercept code and invalid memory events
if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK ||
uc_hook_add(uc, &trace1,
UC_HOOK_MEM_INVALID,
hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) {
if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) !=
UC_ERR_OK ||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL, 1,
0) != UC_ERR_OK) {
printf("not ok - Failed to install hooks\n");
return;
}
@ -239,7 +265,8 @@ static void do_perms_demo(bool change_perms)
err = uc_emu_start(uc, 0x100000, 0x103000, 0, 0);
if (err != UC_ERR_OK) {
printf("FAILED EXECUTION\n");
printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, uc_strerror(err));
printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err,
uc_strerror(err));
} else {
printf("SUCCESSFUL EXECUTION\n");
}
@ -253,11 +280,11 @@ static void perms_test()
{
printf("Permissions demo - step 1: show that area is writeable\n");
do_perms_demo(false);
printf("Permissions demo - step 2: show that code fails when memory marked unwriteable\n");
printf("Permissions demo - step 2: show that code fails when memory marked "
"unwriteable\n");
do_perms_demo(true);
}
static void do_unmap_demo(bool do_unmap)
{
uc_engine *uc;
@ -290,11 +317,11 @@ static void do_unmap_demo(bool do_unmap)
*/
memcpy(code_buf, WRITE_DEMO, sizeof(WRITE_DEMO) - 1);
memset(code_buf + sizeof(WRITE_DEMO) - 1, 0x90, 1000);
code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt
code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt
if (do_unmap) {
// unmap memory area [0x101000, 0x101fff]. see hook_code function
code_buf[0] = 0x42; // inc edx (see hook_code function)
code_buf[0] = 0x42; // inc edx (see hook_code function)
}
// write machine code to be emulated to memory
@ -304,10 +331,10 @@ static void do_unmap_demo(bool do_unmap)
}
// intercept code and invalid memory events
if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK ||
uc_hook_add(uc, &trace1,
UC_HOOK_MEM_INVALID,
hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) {
if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) !=
UC_ERR_OK ||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL, 1,
0) != UC_ERR_OK) {
printf("not ok - Failed to install hooks\n");
return;
}
@ -317,7 +344,8 @@ static void do_unmap_demo(bool do_unmap)
err = uc_emu_start(uc, 0x100000, 0x103000, 0, 0);
if (err != UC_ERR_OK) {
printf("FAILED EXECUTION\n");
printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, uc_strerror(err));
printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err,
uc_strerror(err));
} else {
printf("SUCCESSFUL EXECUTION\n");
}
@ -331,7 +359,8 @@ static void unmap_test()
{
printf("Unmap demo - step 1: show that area is writeable\n");
do_unmap_demo(false);
printf("Unmap demo - step 2: show that code fails when memory is unmapped\n");
printf(
"Unmap demo - step 2: show that code fails when memory is unmapped\n");
do_unmap_demo(true);
}

View File

@ -6,29 +6,37 @@
#include <unicorn/unicorn.h>
#include <string.h>
// code to be emulated
// #define ARM_CODE "\x37\x00\xa0\xe3" // mov r0, #0x37
#define ARM_CODE "\x00\xf0\x20\xe3" // nop
// #define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1, r2, r3
// #define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1,
// r2, r3
#define THUMB_CODE "\x83\xb0" // sub sp, #0xc
#define ARM_THUM_COND_CODE "\x9a\x42\x14\xbf\x68\x22\x4d\x22" // 'cmp r2, r3\nit ne\nmov r2, #0x68\nmov r2, #0x4d'
#define ARM_THUM_COND_CODE \
"\x9a\x42\x14\xbf\x68\x22\x4d\x22" // 'cmp r2, r3\nit ne\nmov r2, #0x68\nmov
// r2, #0x4d'
// code to be emulated
#define ARM_CODE_EB "\xe3\xa0\x00\x37\xe0\x42\x10\x03" // mov r0, #0x37; sub r1, r2, r3
#define THUMB_CODE_EB "\xb0\x83" // sub sp, #0xc
#define ARM_CODE_EB \
"\xe3\xa0\x00\x37\xe0\x42\x10\x03" // mov r0, #0x37; sub r1, r2, r3
#define THUMB_CODE_EB "\xb0\x83" // sub sp, #0xc
// memory address where emulation starts
#define ADDRESS 0x10000
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
address, size);
}
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf(">>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
}
static void test_arm(void)
@ -37,18 +45,18 @@ static void test_arm(void)
uc_err err;
uc_hook trace1, trace2;
int r0 = 0x1234; // R0 register
int r2 = 0x6789; // R1 register
int r3 = 0x3333; // R2 register
int r1; // R1 register
int r0 = 0x1234; // R0 register
int r2 = 0x6789; // R1 register
int r3 = 0x3333; // R2 register
int r1; // R1 register
printf("Emulate ARM code\n");
// Initialize emulator in ARM mode
err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -71,7 +79,7 @@ static void test_arm(void)
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0);
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}
@ -93,15 +101,15 @@ static void test_thumb(void)
uc_err err;
uc_hook trace1, trace2;
int sp = 0x1234; // R0 register
int sp = 0x1234; // R0 register
printf("Emulate THUMB code\n");
// Initialize emulator in ARM mode
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -123,7 +131,7 @@ static void test_thumb(void)
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
// Note we start at ADDRESS | 1 to indicate THUMB mode.
err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE) -1, 0, 0);
err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}
@ -143,18 +151,18 @@ static void test_armeb(void)
uc_err err;
uc_hook trace1, trace2;
int r0 = 0x1234; // R0 register
int r2 = 0x6789; // R1 register
int r3 = 0x3333; // R2 register
int r1; // R1 register
int r0 = 0x1234; // R0 register
int r2 = 0x6789; // R1 register
int r3 = 0x3333; // R2 register
int r1; // R1 register
printf("Emulate ARM Big-Endian code\n");
// Initialize emulator in ARM mode
err = uc_open(UC_ARCH_ARM, UC_MODE_ARM + UC_MODE_BIG_ENDIAN, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -177,7 +185,7 @@ static void test_armeb(void)
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE_EB) -1, 0, 0);
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE_EB) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}
@ -199,15 +207,15 @@ static void test_thumbeb(void)
uc_err err;
uc_hook trace1, trace2;
int sp = 0x1234; // R0 register
int sp = 0x1234; // R0 register
printf("Emulate THUMB Big-Endian code\n");
// Initialize emulator in ARM mode
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB + UC_MODE_BIG_ENDIAN, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -229,7 +237,8 @@ static void test_thumbeb(void)
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
// Note we start at ADDRESS | 1 to indicate THUMB mode.
err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE_EB) -1, 0, 0);
err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE_EB) - 1, 0,
0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}
@ -257,8 +266,8 @@ static void test_thumb_mrs(void)
// Initialize emulator in ARM mode
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -288,14 +297,15 @@ static void test_thumb_mrs(void)
uc_reg_read(uc, UC_ARM_REG_PC, &pc);
printf(">>> PC = 0x%x\n", pc);
if (pc != ADDRESS + 4){
if (pc != ADDRESS + 4) {
printf("Error, PC was 0x%x, expected was 0x%x.\n", pc, ADDRESS + 4);
}
uc_close(uc);
}
static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_out)
static void test_thumb_ite_internal(bool step, uint32_t *r2_out,
uint32_t *r3_out)
{
uc_engine *uc;
uc_err err;
@ -305,14 +315,15 @@ static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_ou
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
uc_mem_write(uc, ADDRESS, ARM_THUM_COND_CODE, sizeof(ARM_THUM_COND_CODE) - 1);
uc_mem_write(uc, ADDRESS, ARM_THUM_COND_CODE,
sizeof(ARM_THUM_COND_CODE) - 1);
uc_reg_write(uc, UC_ARM_REG_SP, &sp);
@ -320,16 +331,19 @@ static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_ou
uc_reg_write(uc, UC_ARM_REG_R3, &r3);
if (!step) {
err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 0);
err = uc_emu_start(uc, ADDRESS | 1,
ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}
} else {
int i, addr = ADDRESS;
for (i = 0; i < sizeof(ARM_THUM_COND_CODE) / 2; i++) {
err = uc_emu_start(uc, addr | 1, ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 1);
err = uc_emu_start(uc, addr | 1,
ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 1);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
printf("Failed on uc_emu_start() with error returned: %u\n",
err);
}
uc_reg_read(uc, UC_ARM_REG_PC, &addr);
}
@ -344,13 +358,13 @@ static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_ou
*r3_out = r3;
}
static void test_thumb_ite()
static void test_thumb_ite()
{
uint32_t r2, r3;
uint32_t step_r2, step_r3;
printf("Emulate a THUMB ITE block as a whole or per instruction.\n");
// Run once.
printf("Running the entire binary.\n");
test_thumb_ite_internal(false, &r2, &r3);

View File

@ -6,48 +6,53 @@
#include <unicorn/unicorn.h>
#include <string.h>
// code to be emulated
#define ARM64_CODE "\xab\x05\x00\xb8\xaf\x05\x40\x38" // str w11, [x13], #0; ldrb w15, [x13], #0
//#define ARM64_CODE_EB "\xb8\x00\x05\xab\x38\x40\x05\xaf" // str w11, [x13]; ldrb w15, [x13]
#define ARM64_CODE \
"\xab\x05\x00\xb8\xaf\x05\x40\x38" // str w11, [x13], #0; ldrb w15, [x13],
// #0
//#define ARM64_CODE_EB "\xb8\x00\x05\xab\x38\x40\x05\xaf" // str w11, [x13];
//ldrb w15, [x13]
#define ARM64_CODE_EB ARM64_CODE
// memory address where emulation starts
#define ADDRESS 0x10000
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
address, size);
}
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf(">>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
}
static void test_arm64_mem_fetch(void)
{
uc_engine* uc;
uc_engine *uc;
uc_err err;
uint64_t x1, sp, x0;
// msr x0, CurrentEL
unsigned char shellcode0[4] = {
64, 66, 56, 213
};
unsigned char shellcode0[4] = {64, 66, 56, 213};
// .text:00000000004002C0 LDR X1, [SP,#arg_0]
unsigned char shellcode[4] = {
0xE1, 0x03, 0x40, 0xF9
};
unsigned char shellcode[4] = {0xE1, 0x03, 0x40, 0xF9};
unsigned shellcode_address = 0x4002C0;
uint64_t data_address = 0x10000000000000;
printf(">>> Emulate ARM64 fetching stack data from high address %"PRIx64"\n", data_address);
printf(">>> Emulate ARM64 fetching stack data from high address %" PRIx64
"\n",
data_address);
// Initialize emulator in ARM mode
err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -60,16 +65,16 @@ static void test_arm64_mem_fetch(void)
uc_mem_write(uc, shellcode_address, shellcode0, 4);
uc_mem_write(uc, shellcode_address + 4, shellcode, 4);
err = uc_emu_start(uc, shellcode_address, shellcode_address+4, 0, 0);
err = uc_emu_start(uc, shellcode_address, shellcode_address + 4, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}
x0 = 0;
uc_reg_read(uc, UC_ARM64_REG_X0, &x0);
printf(">>> x0(Exception Level)=%"PRIx64"\n", x0>>2);
printf(">>> x0(Exception Level)=%" PRIx64 "\n", x0 >> 2);
err = uc_emu_start(uc, shellcode_address+4, shellcode_address+8, 0, 0);
err = uc_emu_start(uc, shellcode_address + 4, shellcode_address + 8, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}
@ -87,17 +92,17 @@ static void test_arm64(void)
uc_err err;
uc_hook trace1, trace2;
int64_t x11 = 0x12345678; // X11 register
int64_t x13 = 0x10000 + 0x8; // X13 register
int64_t x15 = 0x33; // X15 register
int64_t x11 = 0x12345678; // X11 register
int64_t x13 = 0x10000 + 0x8; // X13 register
int64_t x15 = 0x33; // X15 register
printf("Emulate ARM64 code\n");
// Initialize emulator in ARM mode
err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -120,7 +125,7 @@ static void test_arm64(void)
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE) -1, 0, 0);
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}
@ -141,17 +146,17 @@ static void test_arm64eb(void)
uc_err err;
uc_hook trace1, trace2;
int64_t x11 = 0x12345678; // X11 register
int64_t x13 = 0x10000 + 0x8; // X13 register
int64_t x15 = 0x33; // X15 register
int64_t x11 = 0x12345678; // X11 register
int64_t x13 = 0x10000 + 0x8; // X13 register
int64_t x15 = 0x33; // X15 register
printf("Emulate ARM64 Big-Endian code\n");
// Initialize emulator in ARM mode
err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM + UC_MODE_BIG_ENDIAN, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -174,7 +179,7 @@ static void test_arm64eb(void)
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE_EB) -1, 0, 0);
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE_EB) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}
@ -190,7 +195,7 @@ static void test_arm64eb(void)
}
int main(int argc, char **argv, char **envp)
{
{
test_arm64_mem_fetch();
test_arm64();

View File

@ -2,17 +2,15 @@
#include <string.h>
#include <stdio.h>
int syscall_abi[] = {UC_X86_REG_RAX, UC_X86_REG_RDI, UC_X86_REG_RSI,
UC_X86_REG_RDX, UC_X86_REG_R10, UC_X86_REG_R8,
UC_X86_REG_R9};
int syscall_abi[] = {
UC_X86_REG_RAX, UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX,
UC_X86_REG_R10, UC_X86_REG_R8, UC_X86_REG_R9
};
uint64_t vals[7] = {200, 10, 11, 12, 13, 14, 15};
uint64_t vals[7] = { 200, 10, 11, 12, 13, 14, 15 };
// This part of the API is less... clean... because Unicorn supports arbitrary register types.
// So the least intrusive solution is passing individual pointers.
// On the plus side, you only need to make this pointer array once.
// This part of the API is less... clean... because Unicorn supports arbitrary
// register types. So the least intrusive solution is passing individual
// pointers. On the plus side, you only need to make this pointer array once.
void *ptrs[7];
void uc_perror(const char *func, uc_err err)
@ -22,8 +20,12 @@ void uc_perror(const char *func, uc_err err)
#define BASE 0x10000
// mov rax, 100; mov rdi, 1; mov rsi, 2; mov rdx, 3; mov r10, 4; mov r8, 5; mov r9, 6; syscall
#define CODE "\x48\xc7\xc0\x64\x00\x00\x00\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc6\x02\x00\x00\x00\x48\xc7\xc2\x03\x00\x00\x00\x49\xc7\xc2\x04\x00\x00\x00\x49\xc7\xc0\x05\x00\x00\x00\x49\xc7\xc1\x06\x00\x00\x00\x0f\x05"
// mov rax, 100; mov rdi, 1; mov rsi, 2; mov rdx, 3; mov r10, 4; mov r8, 5; mov
// r9, 6; syscall
#define CODE \
"\x48\xc7\xc0\x64\x00\x00\x00\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc6\x02" \
"\x00\x00\x00\x48\xc7\xc2\x03\x00\x00\x00\x49\xc7\xc2\x04\x00\x00\x00\x49" \
"\xc7\xc0\x05\x00\x00\x00\x49\xc7\xc1\x06\x00\x00\x00\x0f\x05"
void hook_syscall(uc_engine *uc, void *user_data)
{
@ -34,7 +36,8 @@ void hook_syscall(uc_engine *uc, void *user_data)
printf("syscall: {");
for (i = 0; i < 7; i++) {
if (i != 0) printf(", ");
if (i != 0)
printf(", ");
printf("%" PRIu64, vals[i]);
}
@ -80,7 +83,8 @@ int main()
printf("reg_read_batch = {");
for (i = 0; i < 7; i++) {
if (i != 0) printf(", ");
if (i != 0)
printf(", ");
printf("%" PRIu64, vals[i]);
}
@ -90,7 +94,8 @@ int main()
printf("\n");
printf("running syscall shellcode\n");
if ((err = uc_hook_add(uc, &sys_hook, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, UC_X86_INS_SYSCALL))) {
if ((err = uc_hook_add(uc, &sys_hook, UC_HOOK_INSN, hook_syscall, NULL, 1,
0, UC_X86_INS_SYSCALL))) {
uc_perror("uc_hook_add", err);
return 1;
}

View File

@ -6,21 +6,25 @@
#include <unicorn/unicorn.h>
#include <string.h>
// code to be emulated
#define M68K_CODE "\x76\xed" // movq #-19, %d3
// memory address where emulation starts
#define ADDRESS 0x10000
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
address, size);
}
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf(">>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
}
static void test_m68k(void)
@ -29,34 +33,34 @@ static void test_m68k(void)
uc_hook trace1, trace2;
uc_err err;
int d0 = 0x0000; // d0 data register
int d1 = 0x0000; // d1 data register
int d2 = 0x0000; // d2 data register
int d3 = 0x0000; // d3 data register
int d4 = 0x0000; // d4 data register
int d5 = 0x0000; // d5 data register
int d6 = 0x0000; // d6 data register
int d7 = 0x0000; // d7 data register
int d0 = 0x0000; // d0 data register
int d1 = 0x0000; // d1 data register
int d2 = 0x0000; // d2 data register
int d3 = 0x0000; // d3 data register
int d4 = 0x0000; // d4 data register
int d5 = 0x0000; // d5 data register
int d6 = 0x0000; // d6 data register
int d7 = 0x0000; // d7 data register
int a0 = 0x0000; // a0 address register
int a1 = 0x0000; // a1 address register
int a2 = 0x0000; // a2 address register
int a3 = 0x0000; // a3 address register
int a4 = 0x0000; // a4 address register
int a5 = 0x0000; // a5 address register
int a6 = 0x0000; // a6 address register
int a7 = 0x0000; // a6 address register
int a0 = 0x0000; // a0 address register
int a1 = 0x0000; // a1 address register
int a2 = 0x0000; // a2 address register
int a3 = 0x0000; // a3 address register
int a4 = 0x0000; // a4 address register
int a5 = 0x0000; // a5 address register
int a6 = 0x0000; // a6 address register
int a7 = 0x0000; // a6 address register
int pc = 0x0000; // program counter
int sr = 0x0000; // status register
int pc = 0x0000; // program counter
int sr = 0x0000; // status register
printf("Emulate M68K code\n");
// Initialize emulator in M68K mode
err = uc_open(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -96,7 +100,7 @@ static void test_m68k(void)
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE)-1, 0, 0);
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}

View File

@ -6,7 +6,6 @@
#include <unicorn/unicorn.h>
#include <string.h>
// code to be emulated
#define MIPS_CODE_EB "\x34\x21\x34\x56" // ori $at, $at, 0x3456;
#define MIPS_CODE_EL "\x56\x34\x21\x34" // ori $at, $at, 0x3456;
@ -14,14 +13,19 @@
// memory address where emulation starts
#define ADDRESS 0x10000
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
address, size);
}
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf(">>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
}
static void test_mips_eb(void)
@ -30,15 +34,15 @@ static void test_mips_eb(void)
uc_err err;
uc_hook trace1, trace2;
int r1 = 0x6789; // R1 register
int r1 = 0x6789; // R1 register
printf("Emulate MIPS code (big-endian)\n");
// Initialize emulator in MIPS mode
err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -61,7 +65,8 @@ static void test_mips_eb(void)
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EB) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err,
uc_strerror(err));
}
// now print out some registers
@ -79,7 +84,7 @@ static void test_mips_el(void)
uc_err err;
uc_hook trace1, trace2;
int r1 = 0x6789; // R1 register
int r1 = 0x6789; // R1 register
printf("===========================\n");
printf("Emulate MIPS code (little-endian)\n");
@ -87,8 +92,8 @@ static void test_mips_el(void)
// Initialize emulator in MIPS mode
err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -111,7 +116,8 @@ static void test_mips_el(void)
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EL) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err,
uc_strerror(err));
}
// now print out some registers

View File

@ -6,22 +6,25 @@
#include <unicorn/unicorn.h>
#include <string.h>
// code to be emulated
#define PPC_CODE "\x7F\x46\x1A\x14" // add r26, r6, r3
// memory address where emulation starts
#define ADDRESS 0x10000
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
address, size);
}
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf(">>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
}
static void test_ppc(void)
@ -30,17 +33,17 @@ static void test_ppc(void)
uc_err err;
uc_hook trace1, trace2;
int r3 = 0x1234; // R3 register
int r6 = 0x6789; // R6 register
int r26 = 0x8877; // R26 register (result)
int r3 = 0x1234; // R3 register
int r6 = 0x6789; // R6 register
int r26 = 0x8877; // R26 register (result)
printf("Emulate PPC code\n");
// Initialize emulator in PPC mode
err = uc_open(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN , &uc);
err = uc_open(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -63,7 +66,7 @@ static void test_ppc(void)
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(PPC_CODE) -1, 0, 0);
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(PPC_CODE) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
return;
@ -79,7 +82,6 @@ static void test_ppc(void)
uc_close(uc);
}
int main(int argc, char **argv, char **envp)
{
test_ppc();

View File

@ -5,7 +5,6 @@
#include <unicorn/unicorn.h>
#include <string.h>
// code to be emulated
#if 0
$ cstool riscv64 1305100093850502
@ -15,23 +14,30 @@ $ cstool riscv64 1305100093850502
//#define RISCV_CODE "\x13\x05\x10\x00\x93\x85\x05\x02\x93\x85\x05\x02"
#define RISCV_CODE "\x13\x05\x10\x00\x93\x85\x05\x02"
// memory address where emulation starts
#define ADDRESS 0x10000
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
address, size);
}
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf(">>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
}
static void hook_code3(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code3(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf(">>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
if (address == ADDRESS) {
printf("stop emulation\n");
uc_emu_stop(uc);
@ -52,8 +58,8 @@ static void test_riscv(void)
// Initialize emulator in RISCV64 mode
err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -106,8 +112,8 @@ static void test_riscv2(void)
// Initialize emulator in RISCV64 mode
err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -171,8 +177,8 @@ static void test_riscv3(void)
// Initialize emulator in RISCV64 mode
err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -226,8 +232,8 @@ static void test_riscv_step(void)
// Initialize emulator in RISCV64 mode
err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -297,8 +303,8 @@ static void test_riscv_timeout(void)
// Initialize emulator in RISCV64 mode
err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -365,8 +371,8 @@ static void test_riscv_sd64(void)
// Initialize emulator in RISCV64 mode
err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -401,13 +407,14 @@ static void test_riscv_sd64(void)
}
static bool hook_memalloc(uc_engine *uc, uc_mem_type type, uint64_t address,
int size, int64_t value, void *user_data)
int size, int64_t value, void *user_data)
{
uint64_t algined_address = address & 0xFFFFFFFFFFFFF000ULL;
int aligned_size = ((int)(size / 0x1000) + 1) * 0x1000;
printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64 "), block size = 0x%x (0x%x)\n",
address, algined_address, size, aligned_size);
printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64
"), block size = 0x%x (0x%x)\n",
address, algined_address, size, aligned_size);
uc_mem_map(uc, algined_address, aligned_size, UC_PROT_ALL);
@ -439,7 +446,8 @@ static void test_recover_from_illegal(void)
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// auto-allocate memory on access
uc_hook_add(uc, &mem_alloc, UC_HOOK_MEM_UNMAPPED, hook_memalloc, NULL, 1, 0);
uc_hook_add(uc, &mem_alloc, UC_HOOK_MEM_UNMAPPED, hook_memalloc, NULL, 1,
0);
// tracing all basic blocks with customized callback
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);
@ -469,8 +477,8 @@ static void test_recover_from_illegal(void)
uc_reg_read(uc, UC_RISCV_REG_A0, &a0);
uc_reg_read(uc, UC_RISCV_REG_A1, &a1);
printf(">>> A0 = 0x%"PRIx64 "\n", a0);
printf(">>> A1 = 0x%"PRIx64 "\n", a1);
printf(">>> A0 = 0x%" PRIx64 "\n", a0);
printf(">>> A1 = 0x%" PRIx64 "\n", a1);
uc_close(uc);
}
@ -495,8 +503,8 @@ static void test_riscv_func_return(void)
// Initialize emulator in RISCV64 mode
err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -527,7 +535,9 @@ static void test_riscv_func_return(void)
uc_reg_read(uc, UC_RISCV_REG_PC, &pc);
if (pc != ra) {
printf("Error after execution: PC is: 0x%"PRIx64 ", expected was 0x%"PRIx64 "\n", pc, ra);
printf("Error after execution: PC is: 0x%" PRIx64
", expected was 0x%" PRIx64 "\n",
pc, ra);
if (pc == 0x10000) {
printf(" PC did not change during execution\n");
}
@ -551,7 +561,9 @@ static void test_riscv_func_return(void)
uc_reg_read(uc, UC_RISCV_REG_PC, &pc);
if (pc != ra) {
printf("Error after execution: PC is: 0x%"PRIx64 ", expected was 0x%"PRIx64 "\n", pc, ra);
printf("Error after execution: PC is: 0x%" PRIx64
", expected was 0x%" PRIx64 "\n",
pc, ra);
if (pc == 0x10004) {
printf(" PC did not change during execution\n");
}

View File

@ -6,7 +6,6 @@
#include <unicorn/unicorn.h>
#include <string.h>
// code to be emulated
#define SPARC_CODE "\x86\x00\x40\x02" // add %g1, %g2, %g3;
//#define SPARC_CODE "\xbb\x70\x00\x00" // illegal code
@ -14,14 +13,19 @@
// memory address where emulation starts
#define ADDRESS 0x10000
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
address, size);
}
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf(">>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
}
static void test_sparc(void)
@ -30,17 +34,17 @@ static void test_sparc(void)
uc_err err;
uc_hook trace1, trace2;
int g1 = 0x1230; // G1 register
int g2 = 0x6789; // G2 register
int g3 = 0x5555; // G3 register
int g1 = 0x1230; // G1 register
int g2 = 0x6789; // G2 register
int g3 = 0x5555; // G3 register
printf("Emulate SPARC code\n");
// Initialize emulator in Sparc mode
err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN, &uc);
err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32 | UC_MODE_BIG_ENDIAN, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
uc_strerror(err));
return;
}
@ -65,8 +69,8 @@ static void test_sparc(void)
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(SPARC_CODE) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u (%s)\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err,
uc_strerror(err));
}
// now print out some registers

View File

@ -6,27 +6,45 @@
#include <unicorn/unicorn.h>
#include <string.h>
// code to be emulated
#define X86_CODE32 "\x41\x4a\x66\x0f\xef\xc1" // INC ecx; DEC edx; PXOR xmm0, xmm1
#define X86_CODE32_JUMP "\xeb\x02\x90\x90\x90\x90\x90\x90" // jmp 4; nop; nop; nop; nop; nop; nop
// #define X86_CODE32_SELF "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41"
#define X86_CODE32 \
"\x41\x4a\x66\x0f\xef\xc1" // INC ecx; DEC edx; PXOR xmm0, xmm1
#define X86_CODE32_JUMP \
"\xeb\x02\x90\x90\x90\x90\x90\x90" // jmp 4; nop; nop; nop; nop; nop; nop
// #define X86_CODE32_SELF
// "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41"
//#define X86_CODE32 "\x51\x51\x51\x51" // PUSH ecx;
#define X86_CODE32_LOOP "\x41\x4a\xeb\xfe" // INC ecx; DEC edx; JMP self-loop
#define X86_CODE32_MEM_WRITE "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov [0xaaaaaaaa], ecx; INC ecx; DEC edx
#define X86_CODE32_MEM_READ "\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx
#define X86_CODE32_MEM_READ_IN_TB "\x40\x8b\x1d\x00\x00\x10\x00\x42" // inc eax; mov ebx, [0x100000]; inc edx
#define X86_CODE32_MEM_WRITE \
"\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov [0xaaaaaaaa], ecx; INC ecx; DEC
// edx
#define X86_CODE32_MEM_READ \
"\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx
#define X86_CODE32_MEM_READ_IN_TB \
"\x40\x8b\x1d\x00\x00\x10\x00\x42" // inc eax; mov ebx, [0x100000]; inc edx
#define X86_CODE32_JMP_INVALID "\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx
#define X86_CODE32_INOUT "\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
#define X86_CODE32_INC "\x40" // INC eax
#define X86_CODE32_JMP_INVALID \
"\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx
#define X86_CODE32_INOUT \
"\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46,
// AL; INC ebx
#define X86_CODE32_INC "\x40" // INC eax
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9"
#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59"
#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90
//\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" //
//<== still crash #define X86_CODE64
//"\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9"
#define X86_CODE64 \
"\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90" \
"\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A" \
"\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5" \
"\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E" \
"\x09\x3C\x59"
#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al
#define X86_CODE64_SYSCALL "\x0f\x05" // SYSCALL
#define X86_MMIO_CODE "\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00" // mov [0x20004], ecx; mov ecx, [0x20004]
#define X86_MMIO_CODE \
"\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00" // mov [0x20004], ecx;
// mov ecx, [0x20004]
/*
* 0x1000 xor dword ptr [edi+0x3], eax ; edi=0x1000, eax=0xbc4177e6
* 0x1003 dw 0x3ea98b13
@ -37,16 +55,21 @@
#define ADDRESS 0x1000000
// callback for tracing basic blocks
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
address, size);
}
// callback for tracing instruction
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
int eflags;
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf(">>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags);
printf(">>> --- EFLAGS is 0x%x\n", eflags);
@ -57,13 +80,16 @@ static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user
}
// callback for tracing instruction
static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
uint64_t rip;
uc_reg_read(uc, UC_X86_REG_RIP, &rip);
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf(">>> RIP is 0x%"PRIx64 "\n", rip);
printf(">>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
printf(">>> RIP is 0x%" PRIx64 "\n", rip);
// Uncomment below code to stop the emulation using uc_emu_stop()
// if (address == 0x1000009)
@ -71,44 +97,48 @@ static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, void *us
}
// callback for tracing memory access (READ or WRITE)
static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
uint64_t address, int size, int64_t value, void *user_data)
static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, uint64_t address,
int size, int64_t value, void *user_data)
{
switch(type) {
default:
// return false to indicate we want to stop emulation
return false;
case UC_MEM_WRITE_UNMAPPED:
printf(">>> Missing memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
address, size, value);
// map this memory in with 2MB in size
uc_mem_map(uc, 0xaaaa0000, 2 * 1024*1024, UC_PROT_ALL);
// return true to indicate we want to continue
return true;
switch (type) {
default:
// return false to indicate we want to stop emulation
return false;
case UC_MEM_WRITE_UNMAPPED:
printf(">>> Missing memory is being WRITE at 0x%" PRIx64
", data size = %u, data value = 0x%" PRIx64 "\n",
address, size, value);
// map this memory in with 2MB in size
uc_mem_map(uc, 0xaaaa0000, 2 * 1024 * 1024, UC_PROT_ALL);
// return true to indicate we want to continue
return true;
}
}
// dummy callback
static bool hook_mem_invalid_dummy(uc_engine *uc, uc_mem_type type,
uint64_t address, int size, int64_t value, void *user_data)
uint64_t address, int size, int64_t value,
void *user_data)
{
// stop emulation
return false;
}
static void hook_mem64(uc_engine *uc, uc_mem_type type,
uint64_t address, int size, int64_t value, void *user_data)
static void hook_mem64(uc_engine *uc, uc_mem_type type, uint64_t address,
int size, int64_t value, void *user_data)
{
switch(type) {
default: break;
case UC_MEM_READ:
printf(">>> Memory is being READ at 0x%"PRIx64 ", data size = %u\n",
address, size);
break;
case UC_MEM_WRITE:
printf(">>> Memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
address, size, value);
break;
switch (type) {
default:
break;
case UC_MEM_READ:
printf(">>> Memory is being READ at 0x%" PRIx64 ", data size = %u\n",
address, size);
break;
case UC_MEM_WRITE:
printf(">>> Memory is being WRITE at 0x%" PRIx64
", data size = %u, data value = 0x%" PRIx64 "\n",
address, size, value);
break;
}
}
@ -120,47 +150,50 @@ static uint32_t hook_in(uc_engine *uc, uint32_t port, int size, void *user_data)
uc_reg_read(uc, UC_X86_REG_EIP, &eip);
printf("--- reading from port 0x%x, size: %u, address: 0x%x\n", port, size, eip);
printf("--- reading from port 0x%x, size: %u, address: 0x%x\n", port, size,
eip);
switch(size) {
default:
return 0; // should never reach this
case 1:
// read 1 byte to AL
return 0xf1;
case 2:
// read 2 byte to AX
return 0xf2;
break;
case 4:
// read 4 byte to EAX
return 0xf4;
switch (size) {
default:
return 0; // should never reach this
case 1:
// read 1 byte to AL
return 0xf1;
case 2:
// read 2 byte to AX
return 0xf2;
break;
case 4:
// read 4 byte to EAX
return 0xf4;
}
}
// callback for OUT instruction (X86).
static void hook_out(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data)
static void hook_out(uc_engine *uc, uint32_t port, int size, uint32_t value,
void *user_data)
{
uint32_t tmp = 0;
uint32_t eip;
uc_reg_read(uc, UC_X86_REG_EIP, &eip);
printf("--- writing to port 0x%x, size: %u, value: 0x%x, address: 0x%x\n", port, size, value, eip);
printf("--- writing to port 0x%x, size: %u, value: 0x%x, address: 0x%x\n",
port, size, value, eip);
// confirm that value is indeed the value of AL/AX/EAX
switch(size) {
default:
return; // should never reach this
case 1:
uc_reg_read(uc, UC_X86_REG_AL, &tmp);
break;
case 2:
uc_reg_read(uc, UC_X86_REG_AX, &tmp);
break;
case 4:
uc_reg_read(uc, UC_X86_REG_EAX, &tmp);
break;
switch (size) {
default:
return; // should never reach this
case 1:
uc_reg_read(uc, UC_X86_REG_AL, &tmp);
break;
case 2:
uc_reg_read(uc, UC_X86_REG_AX, &tmp);
break;
case 4:
uc_reg_read(uc, UC_X86_REG_EAX, &tmp);
break;
}
printf("--- register value = 0x%x\n", tmp);
@ -176,17 +209,18 @@ static void hook_syscall(uc_engine *uc, void *user_data)
rax = 0x200;
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
} else
printf("ERROR: was not expecting rax=0x%"PRIx64 " in syscall\n", rax);
printf("ERROR: was not expecting rax=0x%" PRIx64 " in syscall\n", rax);
}
static bool hook_memalloc(uc_engine *uc, uc_mem_type type, uint64_t address,
int size, int64_t value, void *user_data)
int size, int64_t value, void *user_data)
{
uint64_t algined_address = address & 0xFFFFFFFFFFFFF000ULL;
int aligned_size = ((int)(size / 0x1000) + 1) * 0x1000;
printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64 "), block size = 0x%x (0x%x)\n",
address, algined_address, size, aligned_size);
printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64
"), block size = 0x%x (0x%x)\n",
address, algined_address, size, aligned_size);
uc_mem_map(uc, algined_address, aligned_size, UC_PROT_ALL);
@ -206,8 +240,8 @@ static void test_miss_code(void)
uc_err err;
uc_hook trace1, trace2;
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("Emulate i386 code - missing code\n");
@ -231,8 +265,8 @@ static void test_miss_code(void)
// emulate machine code, without having the code in yet
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -253,8 +287,8 @@ static void test_i386(void)
uint32_t tmp;
uc_hook trace1, trace2;
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
// XMM0 and XMM1 registers, low qword then high qword
uint64_t r_xmm0[2] = {0x08090a0b0c0d0e0f, 0x0001020304050607};
uint64_t r_xmm1[2] = {0x8090a0b0c0d0e0f0, 0x0010203040506070};
@ -292,8 +326,8 @@ static void test_i386(void)
// emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -304,7 +338,7 @@ static void test_i386(void)
uc_reg_read(uc, UC_X86_REG_XMM0, &r_xmm0);
printf(">>> ECX = 0x%x\n", r_ecx);
printf(">>> EDX = 0x%x\n", r_edx);
printf(">>> XMM0 = 0x%.16"PRIx64"%.16"PRIx64"\n", r_xmm0[1], r_xmm0[0]);
printf(">>> XMM0 = 0x%.16" PRIx64 "%.16" PRIx64 "\n", r_xmm0[1], r_xmm0[0]);
// read from memory
if (!uc_mem_read(uc, ADDRESS, &tmp, sizeof(tmp)))
@ -323,8 +357,8 @@ static void test_i386_map_ptr(void)
uc_hook trace1, trace2;
void *mem;
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("===================================\n");
printf("Emulate i386 code - use uc_mem_map_ptr()\n");
@ -364,8 +398,8 @@ static void test_i386_map_ptr(void)
// emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -407,7 +441,7 @@ static void test_i386_jump(void)
// write machine code to be emulated to memory
if (uc_mem_write(uc, ADDRESS, X86_CODE32_JUMP,
sizeof(X86_CODE32_JUMP) - 1)) {
sizeof(X86_CODE32_JUMP) - 1)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
@ -419,10 +453,11 @@ static void test_i386_jump(void)
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS);
// emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JUMP) - 1, 0, 0);
err =
uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JUMP) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
printf(">>> Emulation done. Below is the CPU context\n");
@ -436,8 +471,8 @@ static void test_i386_loop(void)
uc_engine *uc;
uc_err err;
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("===================================\n");
printf("Emulate i386 code that loop forever\n");
@ -453,7 +488,8 @@ static void test_i386_loop(void)
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
if (uc_mem_write(uc, ADDRESS, X86_CODE32_LOOP, sizeof(X86_CODE32_LOOP) - 1)) {
if (uc_mem_write(uc, ADDRESS, X86_CODE32_LOOP,
sizeof(X86_CODE32_LOOP) - 1)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
@ -464,10 +500,11 @@ static void test_i386_loop(void)
// emulate machine code in 2 seconds, so we can quit even
// if the code loops
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_LOOP) - 1, 2 * UC_SECOND_SCALE, 0);
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_LOOP) - 1,
2 * UC_SECOND_SCALE, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -488,8 +525,8 @@ static void test_i386_invalid_mem_read(void)
uc_err err;
uc_hook trace1, trace2;
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("===================================\n");
printf("Emulate i386 code that read from invalid memory\n");
@ -505,7 +542,8 @@ static void test_i386_invalid_mem_read(void)
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ, sizeof(X86_CODE32_MEM_READ) - 1)) {
if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ,
sizeof(X86_CODE32_MEM_READ) - 1)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
@ -521,10 +559,11 @@ static void test_i386_invalid_mem_read(void)
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);
// emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ) - 1, 0, 0);
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ) - 1,
0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -546,8 +585,8 @@ static void test_i386_invalid_mem_write(void)
uc_hook trace1, trace2, trace3;
uint32_t tmp;
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("===================================\n");
printf("Emulate i386 code that write to invalid memory\n");
@ -563,7 +602,8 @@ static void test_i386_invalid_mem_write(void)
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_WRITE, sizeof(X86_CODE32_MEM_WRITE) - 1)) {
if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_WRITE,
sizeof(X86_CODE32_MEM_WRITE) - 1)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
@ -579,13 +619,16 @@ static void test_i386_invalid_mem_write(void)
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);
// intercept invalid memory events
uc_hook_add(uc, &trace3, UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid, NULL, 1, 0);
uc_hook_add(uc, &trace3,
UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED,
hook_mem_invalid, NULL, 1, 0);
// emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, 0, 0);
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1,
0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -617,8 +660,8 @@ static void test_i386_jump_invalid(void)
uc_err err;
uc_hook trace1, trace2;
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("===================================\n");
printf("Emulate i386 code that jumps to invalid memory\n");
@ -634,7 +677,8 @@ static void test_i386_jump_invalid(void)
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
if (uc_mem_write(uc, ADDRESS, X86_CODE32_JMP_INVALID, sizeof(X86_CODE32_JMP_INVALID) - 1)) {
if (uc_mem_write(uc, ADDRESS, X86_CODE32_JMP_INVALID,
sizeof(X86_CODE32_JMP_INVALID) - 1)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
@ -650,10 +694,11 @@ static void test_i386_jump_invalid(void)
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);
// emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JMP_INVALID) - 1, 0, 0);
err = uc_emu_start(uc, ADDRESS,
ADDRESS + sizeof(X86_CODE32_JMP_INVALID) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -673,9 +718,8 @@ static void test_i386_inout(void)
uc_err err;
uc_hook trace1, trace2, trace3, trace4;
int r_eax = 0x1234; // EAX register
int r_ecx = 0x6789; // ECX register
int r_eax = 0x1234; // EAX register
int r_ecx = 0x6789; // ECX register
printf("===================================\n");
printf("Emulate i386 code with IN/OUT instructions\n");
@ -691,7 +735,8 @@ static void test_i386_inout(void)
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
if (uc_mem_write(uc, ADDRESS, X86_CODE32_INOUT, sizeof(X86_CODE32_INOUT) - 1)) {
if (uc_mem_write(uc, ADDRESS, X86_CODE32_INOUT,
sizeof(X86_CODE32_INOUT) - 1)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
@ -709,13 +754,15 @@ static void test_i386_inout(void)
// uc IN instruction
uc_hook_add(uc, &trace3, UC_HOOK_INSN, hook_in, NULL, 1, 0, UC_X86_INS_IN);
// uc OUT instruction
uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, 1, 0, UC_X86_INS_OUT);
uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, 1, 0,
UC_X86_INS_OUT);
// emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INOUT) - 1, 0, 0);
err =
uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INOUT) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -736,7 +783,7 @@ static void test_i386_context_save(void)
uc_context *context;
uc_err err;
int r_eax = 0x1; // EAX register
int r_eax = 0x1; // EAX register
printf("===================================\n");
printf("Save/restore CPU context in opaque blob\n");
@ -765,8 +812,8 @@ static void test_i386_context_save(void)
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INC) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -795,8 +842,8 @@ static void test_i386_context_save(void)
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INC) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -830,7 +877,8 @@ static void test_i386_context_save(void)
}
// now print out some registers
printf(">>> CPU context restored with modification. Below is the CPU context\n");
printf(">>> CPU context restored with modification. Below is the CPU "
"context\n");
uc_reg_read(uc, UC_X86_REG_EAX, &r_eax);
printf(">>> EAX = 0x%x\n", r_eax);
@ -928,7 +976,6 @@ static void test_x86_64(void)
int64_t rsp = ADDRESS + 0x200000;
printf("Emulate x86_64 code\n");
// Initialize emulator in X86-64bit mode
@ -969,7 +1016,8 @@ static void test_x86_64(void)
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);
// tracing all instructions in the range [ADDRESS, ADDRESS+20]
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, ADDRESS, ADDRESS+20);
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, ADDRESS,
ADDRESS + 20);
// tracing all memory WRITE access (with @begin > @end)
uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, 1, 0);
@ -981,8 +1029,8 @@ static void test_x86_64(void)
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -1043,23 +1091,26 @@ static void test_x86_64_syscall(void)
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
if (uc_mem_write(uc, ADDRESS, X86_CODE64_SYSCALL, sizeof(X86_CODE64_SYSCALL) - 1)) {
if (uc_mem_write(uc, ADDRESS, X86_CODE64_SYSCALL,
sizeof(X86_CODE64_SYSCALL) - 1)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
// hook interrupts for syscall
uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, UC_X86_INS_SYSCALL);
uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, 1, 0,
UC_X86_INS_SYSCALL);
// initialize machine registers
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64_SYSCALL) - 1, 0, 0);
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64_SYSCALL) - 1, 0,
0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -1109,8 +1160,8 @@ static void test_x86_16(void)
// finishing all the code.
err = uc_emu_start(uc, 0, sizeof(X86_CODE16) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
@ -1131,12 +1182,13 @@ static void test_i386_invalid_mem_read_in_tb(void)
uc_err err;
uc_hook trace1;
int r_eax = 0x1234; // EAX register
int r_edx = 0x7890; // EDX register
int r_eax = 0x1234; // EAX register
int r_edx = 0x7890; // EDX register
int r_eip = 0;
printf("===================================\n");
printf("Emulate i386 code that read invalid memory in the middle of a TB\n");
printf(
"Emulate i386 code that read invalid memory in the middle of a TB\n");
// Initialize emulator in X86-32bit mode
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
@ -1149,7 +1201,8 @@ static void test_i386_invalid_mem_read_in_tb(void)
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ_IN_TB, sizeof(X86_CODE32_MEM_READ_IN_TB) - 1)) {
if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ_IN_TB,
sizeof(X86_CODE32_MEM_READ_IN_TB) - 1)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
@ -1159,13 +1212,15 @@ static void test_i386_invalid_mem_read_in_tb(void)
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
// Add a dummy callback.
uc_hook_add(uc, &trace1, UC_HOOK_MEM_READ, hook_mem_invalid_dummy, NULL, 1, 0);
uc_hook_add(uc, &trace1, UC_HOOK_MEM_READ, hook_mem_invalid_dummy, NULL, 1,
0);
// Let it crash by design.
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ_IN_TB) - 1, 0, 0);
err = uc_emu_start(uc, ADDRESS,
ADDRESS + sizeof(X86_CODE32_MEM_READ_IN_TB) - 1, 0, 0);
if (err) {
printf("uc_emu_start() failed BY DESIGN with error returned %u: %s\n",
err, uc_strerror(err));
err, uc_strerror(err));
}
printf(">>> Emulation done. Below is the CPU context\n");
@ -1174,21 +1229,24 @@ static void test_i386_invalid_mem_read_in_tb(void)
printf(">>> EIP = 0x%x\n", r_eip);
if (r_eip != ADDRESS + 1) {
printf(">>> ERROR: Wrong PC 0x%x when reading unmapped memory in the middle of TB!\n", r_eip);
printf(">>> ERROR: Wrong PC 0x%x when reading unmapped memory in the "
"middle of TB!\n",
r_eip);
} else {
printf(">>> The PC is correct after reading unmapped memory in the middle of TB.\n");
printf(">>> The PC is correct after reading unmapped memory in the "
"middle of TB.\n");
}
uc_close(uc);
}
static void test_i386_smc_xor()
static void test_i386_smc_xor()
{
uc_engine *uc;
uc_err err;
uint32_t r_edi = ADDRESS; // ECX register
uint32_t r_eax = 0xbc4177e6; // EDX register
uint32_t r_edi = ADDRESS; // ECX register
uint32_t r_eax = 0xbc4177e6; // EDX register
uint32_t result;
printf("===================================\n");
@ -1216,15 +1274,15 @@ static void test_i386_smc_xor()
// **Important Note**
//
// Since SMC code will cause TB regeneration, the XOR in fact would executed
// twice (the first execution won't take effect.). Thus, if you would like to
// use count to control the emulation, the count should be set to 2.
// Since SMC code will cause TB regeneration, the XOR in fact would executed
// twice (the first execution won't take effect.). Thus, if you would like
// to use count to control the emulation, the count should be set to 2.
//
// err = uc_emu_start(uc, ADDRESS, ADDRESS + 3, 0, 0);
err = uc_emu_start(uc, ADDRESS, 0, 0, 2);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
printf(">>> Emulation done. Below is the result.\n");
@ -1232,30 +1290,38 @@ static void test_i386_smc_xor()
uc_mem_read(uc, ADDRESS + 3, (void *)&result, 4);
if (result == (0x3ea98b13 ^ 0xbc4177e6)) {
printf(">>> SMC emulation is correct. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n", result);
printf(">>> SMC emulation is correct. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n",
result);
} else {
printf(">>> SMC emulation is wrong. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n", result);
printf(">>> SMC emulation is wrong. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n",
result);
}
uc_close(uc);
}
static uint64_t mmio_read_callback(uc_engine* uc, uint64_t offset, unsigned size, void* user_data)
static uint64_t mmio_read_callback(uc_engine *uc, uint64_t offset,
unsigned size, void *user_data)
{
printf(">>> Read IO memory at offset 0x%"PRIu64" with 0x%"PRIu32" bytes and return 0x19260817\n", offset, size);
printf(">>> Read IO memory at offset 0x%" PRIu64 " with 0x%" PRIu32
" bytes and return 0x19260817\n",
offset, size);
// The value returned here would be written to ecx.
return 0x19260817;
}
static void mmio_write_callback(uc_engine* uc, uint64_t offset, unsigned size, uint64_t value, void* user_data)
static void mmio_write_callback(uc_engine *uc, uint64_t offset, unsigned size,
uint64_t value, void *user_data)
{
printf(">>> Write value 0x%"PRIu64" to IO memory at offset 0x%"PRIu64" with 0x%"PRIu32" bytes\n", value, offset, size);
printf(">>> Write value 0x%" PRIu64 " to IO memory at offset 0x%" PRIu64
" with 0x%" PRIu32 " bytes\n",
value, offset, size);
return;
}
static void test_i386_mmio()
{
uc_engine* uc;
uc_engine *uc;
int r_ecx = 0xdeadbeef;
uc_err err;
@ -1283,7 +1349,8 @@ static void test_i386_mmio()
return;
}
err = uc_mmio_map(uc, 0x20000, 0x4000, mmio_read_callback, NULL, mmio_write_callback, NULL);
err = uc_mmio_map(uc, 0x20000, 0x4000, mmio_read_callback, NULL,
mmio_write_callback, NULL);
if (err) {
printf("Failed on uc_mmio_map() with error returned: %u\n", err);
return;
@ -1314,8 +1381,7 @@ int main(int argc, char **argv, char **envp)
if (argc == 2) {
if (!strcmp(argv[1], "-16")) {
test_x86_16();
}
else if (!strcmp(argv[1], "-32")) {
} else if (!strcmp(argv[1], "-32")) {
test_miss_code();
test_i386();
test_i386_map_ptr();
@ -1326,17 +1392,14 @@ int main(int argc, char **argv, char **envp)
test_i386_invalid_mem_read();
test_i386_invalid_mem_write();
test_i386_jump_invalid();
//test_i386_invalid_c6c7();
}
else if (!strcmp(argv[1], "-64")) {
// test_i386_invalid_c6c7();
} else if (!strcmp(argv[1], "-64")) {
test_x86_64();
test_x86_64_syscall();
}
else if (!strcmp(argv[1], "-h")) {
} else if (!strcmp(argv[1], "-h")) {
printf("Syntax: %s <-16|-32|-64>\n", argv[0]);
}
}
else {
} else {
test_x86_16();
test_miss_code();
test_i386();
@ -1348,7 +1411,7 @@ int main(int argc, char **argv, char **envp)
test_i386_invalid_mem_read();
test_i386_invalid_mem_write();
test_i386_jump_invalid();
//test_i386_invalid_c6c7();
// test_i386_invalid_c6c7();
test_x86_64();
test_x86_64_syscall();
test_i386_invalid_mem_read_in_tb();

View File

@ -26,62 +26,64 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#pragma pack(push, 1)
struct SegmentDescriptor {
union {
struct {
union {
struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned short limit0;
unsigned short base0;
unsigned char base1;
unsigned char type:4;
unsigned char system:1; /* S flag */
unsigned char dpl:2;
unsigned char present:1; /* P flag */
unsigned char limit1:4;
unsigned char avail:1;
unsigned char is_64_code:1; /* L flag */
unsigned char db:1; /* DB flag */
unsigned char granularity:1; /* G flag */
unsigned char base2;
unsigned short limit0;
unsigned short base0;
unsigned char base1;
unsigned char type : 4;
unsigned char system : 1; /* S flag */
unsigned char dpl : 2;
unsigned char present : 1; /* P flag */
unsigned char limit1 : 4;
unsigned char avail : 1;
unsigned char is_64_code : 1; /* L flag */
unsigned char db : 1; /* DB flag */
unsigned char granularity : 1; /* G flag */
unsigned char base2;
#else
unsigned char base2;
unsigned char granularity:1; /* G flag */
unsigned char db:1; /* DB flag */
unsigned char is_64_code:1; /* L flag */
unsigned char avail:1;
unsigned char limit1:4;
unsigned char present:1; /* P flag */
unsigned char dpl:2;
unsigned char system:1; /* S flag */
unsigned char type:4;
unsigned char base1;
unsigned short base0;
unsigned short limit0;
unsigned char base2;
unsigned char granularity : 1; /* G flag */
unsigned char db : 1; /* DB flag */
unsigned char is_64_code : 1; /* L flag */
unsigned char avail : 1;
unsigned char limit1 : 4;
unsigned char present : 1; /* P flag */
unsigned char dpl : 2;
unsigned char system : 1; /* S flag */
unsigned char type : 4;
unsigned char base1;
unsigned short base0;
unsigned short limit0;
#endif
};
uint64_t desc;
};
};
uint64_t desc;
};
};
#pragma pack(pop)
#define SEGBASE(d) ((uint32_t)((((d).desc >> 16) & 0xffffff) | (((d).desc >> 32) & 0xff000000)))
#define SEGBASE(d) \
((uint32_t)((((d).desc >> 16) & 0xffffff) | \
(((d).desc >> 32) & 0xff000000)))
#define SEGLIMIT(d) ((d).limit0 | (((unsigned int)(d).limit1) << 16))
/**
* Assert that err matches expect
*/
#define uc_assert_err(expect, err) \
do { \
uc_err __err = err; \
if (__err != expect) { \
fprintf(stderr, "%s", uc_strerror(__err)); \
exit(1); \
} \
} while (0)
#define uc_assert_err(expect, err) \
do { \
uc_err __err = err; \
if (__err != expect) { \
fprintf(stderr, "%s", uc_strerror(__err)); \
exit(1); \
} \
} while (0)
/**
* Assert that err is UC_ERR_OK
*/
#define uc_assert_success(err) uc_assert_err(UC_ERR_OK, err)
#define uc_assert_success(err) uc_assert_err(UC_ERR_OK, err)
/**
* Assert that err is anything but UC_ERR_OK
@ -90,55 +92,61 @@ do { \
* as this serves to document which errors a function will return
* in various scenarios.
*/
#define uc_assert_fail(err) \
do { \
uc_err __err = err; \
if (__err == UC_ERR_OK) { \
fprintf(stderr, "%s", uc_strerror(__err)); \
exit(1); \
} \
} while (0)
#define uc_assert_fail(err) \
do { \
uc_err __err = err; \
if (__err == UC_ERR_OK) { \
fprintf(stderr, "%s", uc_strerror(__err)); \
exit(1); \
} \
} while (0)
#define OK(x) uc_assert_success(x)
#define OK(x) uc_assert_success(x)
/******************************************************************************/
static void hook_mem(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data)
static void hook_mem(uc_engine *uc, uc_mem_type type, uint64_t address,
int size, int64_t value, void *user_data)
{
switch(type) {
case UC_MEM_WRITE:
printf("mem write at 0x%"PRIx64 ", size = %u, value = 0x%"PRIx64 "\n", address, size, value);
break;
default: break;
switch (type) {
case UC_MEM_WRITE:
printf("mem write at 0x%" PRIx64 ", size = %u, value = 0x%" PRIx64 "\n",
address, size, value);
break;
default:
break;
}
}
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
printf("Executing at 0x%"PRIx64 ", ilen = 0x%x\n", address, size);
printf("Executing at 0x%" PRIx64 ", ilen = 0x%x\n", address, size);
}
//VERY basic descriptor init function, sets many fields to user space sane defaults
static void init_descriptor(struct SegmentDescriptor *desc, uint32_t base, uint32_t limit, uint8_t is_code)
// VERY basic descriptor init function, sets many fields to user space sane
// defaults
static void init_descriptor(struct SegmentDescriptor *desc, uint32_t base,
uint32_t limit, uint8_t is_code)
{
desc->desc = 0; //clear the descriptor
desc->desc = 0; // clear the descriptor
desc->base0 = base & 0xffff;
desc->base1 = (base >> 16) & 0xff;
desc->base2 = base >> 24;
if (limit > 0xfffff) {
//need Giant granularity
// need Giant granularity
limit >>= 12;
desc->granularity = 1;
}
desc->limit0 = limit & 0xffff;
desc->limit1 = limit >> 16;
//some sane defaults
// some sane defaults
desc->dpl = 3;
desc->present = 1;
desc->db = 1; //32 bit
desc->db = 1; // 32 bit
desc->type = is_code ? 0xb : 3;
desc->system = 1; //code or data
desc->system = 1; // code or data
}
/*
@ -149,7 +157,7 @@ static void hex_dump(unsigned char *ptr, unsigned int len)
if (i != 0 && (i & 0xf) == 0) {
fprintf(stderr, "\n");
}
fprintf(stderr, "%02hhx", ptr[i]);
fprintf(stderr, "%02hhx", ptr[i]);
}
fprintf(stderr, "\n");
}
@ -163,7 +171,7 @@ static void gdt_demo()
uint8_t buf[128];
uc_x86_mmr gdtr;
int i;
/*
bits 32
@ -174,29 +182,33 @@ static void gdt_demo()
mov dword [fs:4], 0x89abcdef
*/
const uint8_t code[] = "\x68\x67\x45\x23\x01\x68\xef\xcd\xab\x89\x64\xc7\x05\x00\x00\x00\x00\x67\x45\x23\x01\x64\xc7\x05\x04\x00\x00\x00\xef\xcd\xab\x89";
const uint8_t code[] =
"\x68\x67\x45\x23\x01\x68\xef\xcd\xab\x89\x64\xc7\x05\x00\x00\x00\x00"
"\x67\x45\x23\x01\x64\xc7\x05\x04\x00\x00\x00\xef\xcd\xab\x89";
const uint64_t code_address = 0x1000000;
const uint64_t stack_address = 0x120000;
const uint64_t gdt_address = 0xc0000000;
const uint64_t fs_address = 0x7efdd000;
struct SegmentDescriptor *gdt = (struct SegmentDescriptor*)calloc(31, sizeof(struct SegmentDescriptor));
struct SegmentDescriptor *gdt = (struct SegmentDescriptor *)calloc(
31, sizeof(struct SegmentDescriptor));
int r_esp = (int)stack_address + 0x1000; // initial esp
int r_esp = (int)stack_address + 0x1000; // initial esp
int r_cs = 0x73;
int r_ss = 0x88; //ring 0
int r_ss = 0x88; // ring 0
int r_ds = 0x7b;
int r_es = 0x7b;
int r_fs = 0x83;
gdtr.base = gdt_address;
gdtr.base = gdt_address;
gdtr.limit = 31 * sizeof(struct SegmentDescriptor) - 1;
init_descriptor(&gdt[14], 0, 0xfffff000, 1); //code segment
init_descriptor(&gdt[15], 0, 0xfffff000, 0); //data segment
init_descriptor(&gdt[16], 0x7efdd000, 0xfff, 0); //one page data segment simulate fs
init_descriptor(&gdt[17], 0, 0xfffff000, 0); //ring 0 data
gdt[17].dpl = 0; //set descriptor privilege level
init_descriptor(&gdt[14], 0, 0xfffff000, 1); // code segment
init_descriptor(&gdt[15], 0, 0xfffff000, 0); // data segment
init_descriptor(&gdt[16], 0x7efdd000, 0xfff,
0); // one page data segment simulate fs
init_descriptor(&gdt[17], 0, 0xfffff000, 0); // ring 0 data
gdt[17].dpl = 0; // set descriptor privilege level
/*
fprintf(stderr, "GDT: \n");
@ -207,9 +219,11 @@ static void gdt_demo()
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
uc_assert_success(err);
uc_hook_add(uc, &hook1, UC_HOOK_CODE, hook_code, NULL, code_address, code_address + sizeof(code) - 1);
uc_hook_add(uc, &hook1, UC_HOOK_CODE, hook_code, NULL, code_address,
code_address + sizeof(code) - 1);
err = uc_hook_add(uc, &hook2, UC_HOOK_MEM_WRITE, hook_mem, NULL, (uint64_t)1, (uint64_t)0);
err = uc_hook_add(uc, &hook2, UC_HOOK_MEM_WRITE, hook_mem, NULL,
(uint64_t)1, (uint64_t)0);
uc_assert_success(err);
// map 1 page of code for this emulation
@ -224,12 +238,13 @@ static void gdt_demo()
err = uc_mem_map(uc, gdt_address, 0x10000, UC_PROT_WRITE | UC_PROT_READ);
uc_assert_success(err);
//set up a GDT BEFORE you manipulate any segment registers
// set up a GDT BEFORE you manipulate any segment registers
err = uc_reg_write(uc, UC_X86_REG_GDTR, &gdtr);
uc_assert_success(err);
// write gdt to be emulated to memory
err = uc_mem_write(uc, gdt_address, gdt, 31 * sizeof(struct SegmentDescriptor));
err = uc_mem_write(uc, gdt_address, gdt,
31 * sizeof(struct SegmentDescriptor));
uc_assert_success(err);
// map 1 page for FS
@ -237,7 +252,7 @@ static void gdt_demo()
uc_assert_success(err);
// write machine code to be emulated to memory
err = uc_mem_write(uc, code_address, code, sizeof(code)-1);
err = uc_mem_write(uc, code_address, code, sizeof(code) - 1);
uc_assert_success(err);
// initialize machine registers
@ -245,7 +260,8 @@ static void gdt_demo()
uc_assert_success(err);
// when setting SS, need rpl == cpl && dpl == cpl
// emulator starts with cpl == 0, so we need a dpl 0 descriptor and rpl 0 selector
// emulator starts with cpl == 0, so we need a dpl 0 descriptor and rpl 0
// selector
err = uc_reg_write(uc, UC_X86_REG_SS, &r_ss);
uc_assert_success(err);
@ -259,7 +275,7 @@ static void gdt_demo()
uc_assert_success(err);
// emulate machine code in infinite time
err = uc_emu_start(uc, code_address, code_address+sizeof(code)-1, 0, 0);
err = uc_emu_start(uc, code_address, code_address + sizeof(code) - 1, 0, 0);
uc_assert_success(err);
// read from memory

View File

@ -6,23 +6,31 @@
#include <unicorn/unicorn.h>
#include <string.h>
// code to be emulated
#define X86_CODE32 "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f"
#define X86_CODE32 \
"\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd" \
"\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c" \
"\x6f"
#define X86_CODE32_SELF "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41\x41\x41\x41\x41"
#define X86_CODE32_SELF \
"\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89" \
"\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31" \
"\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3" \
"\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41\x41\x41\x41\x41"
// memory address where emulation starts
#define ADDRESS 0x1000000
#define MIN(a, b) (a < b? a : b)
#define MIN(a, b) (a < b ? a : b)
// callback for tracing instruction
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
int r_eip;
uint8_t tmp[16];
printf("Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
printf("Tracing instruction at 0x%" PRIx64 ", instruction size = 0x%x\n",
address, size);
uc_reg_read(uc, UC_X86_REG_EIP, &r_eip);
printf("*** EIP = %x ***: ", r_eip);
@ -30,7 +38,7 @@ static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user
size = MIN(sizeof(tmp), size);
if (!uc_mem_read(uc, address, tmp, size)) {
uint32_t i;
for (i=0; i<size; i++) {
for (i = 0; i < size; i++) {
printf("%x ", tmp[i]);
}
printf("\n");
@ -52,33 +60,35 @@ static void hook_intr(uc_engine *uc, uint32_t intno, void *user_data)
uc_reg_read(uc, UC_X86_REG_EAX, &r_eax);
uc_reg_read(uc, UC_X86_REG_EIP, &r_eip);
switch(r_eax) {
default:
printf(">>> 0x%x: interrupt 0x%x, EAX = 0x%x\n", r_eip, intno, r_eax);
break;
case 1: // sys_exit
printf(">>> 0x%x: interrupt 0x%x, SYS_EXIT. quit!\n\n", r_eip, intno);
uc_emu_stop(uc);
break;
case 4: // sys_write
// ECX = buffer address
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
switch (r_eax) {
default:
printf(">>> 0x%x: interrupt 0x%x, EAX = 0x%x\n", r_eip, intno, r_eax);
break;
case 1: // sys_exit
printf(">>> 0x%x: interrupt 0x%x, SYS_EXIT. quit!\n\n", r_eip, intno);
uc_emu_stop(uc);
break;
case 4: // sys_write
// ECX = buffer address
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
// EDX = buffer size
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
// EDX = buffer size
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
// read the buffer in
size = MIN(sizeof(buffer)-1, r_edx);
// read the buffer in
size = MIN(sizeof(buffer) - 1, r_edx);
if (!uc_mem_read(uc, r_ecx, buffer, size)) {
buffer[size] = '\0';
printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u, content = '%s'\n",
r_eip, intno, r_ecx, r_edx, buffer);
} else {
printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u (cannot get content)\n",
r_eip, intno, r_ecx, r_edx);
}
break;
if (!uc_mem_read(uc, r_ecx, buffer, size)) {
buffer[size] = '\0';
printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = "
"%u, content = '%s'\n",
r_eip, intno, r_ecx, r_edx, buffer);
} else {
printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = "
"%u (cannot get content)\n",
r_eip, intno, r_ecx, r_edx);
}
break;
}
}
@ -88,7 +98,7 @@ static void test_i386(void)
uc_err err;
uc_hook trace1, trace2;
int r_esp = ADDRESS + 0x200000; // ESP register
int r_esp = ADDRESS + 0x200000; // ESP register
printf("Emulate i386 code\n");
@ -103,7 +113,8 @@ static void test_i386(void)
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
if (uc_mem_write(uc, ADDRESS, X86_CODE32_SELF, sizeof(X86_CODE32_SELF) - 1)) {
if (uc_mem_write(uc, ADDRESS, X86_CODE32_SELF,
sizeof(X86_CODE32_SELF) - 1)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
@ -120,11 +131,13 @@ static void test_i386(void)
printf("\n>>> Start tracing this Linux code\n");
// emulate machine code in infinite time
// err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF), 0, 12); <--- emulate only 12 instructions
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF) - 1, 0, 0);
// err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF), 0,
// 12); <--- emulate only 12 instructions
err =
uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
printf("\n>>> Emulation done.\n");
@ -137,8 +150,7 @@ int main(int argc, char **argv, char **envp)
if (argc == 2) {
if (!strcmp(argv[1], "-32")) {
test_i386();
}
else if (!strcmp(argv[1], "-h")) {
} else if (!strcmp(argv[1], "-h")) {
printf("Syntax: %s <-32|-64>\n", argv[0]);
}
} else {

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,17 @@
const uint64_t code_start = 0x1000;
const uint64_t code_len = 0x4000;
static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) {
static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode,
const char *code, uint64_t size)
{
OK(uc_open(arch, mode, uc));
OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL));
OK(uc_mem_write(*uc, code_start, code, size));
}
static void test_arm_nop() {
uc_engine* uc;
static void test_arm_nop()
{
uc_engine *uc;
char code[] = "\x00\xf0\x20\xe3"; // nop
int r_r0 = 0x1234;
int r_r2 = 0x6789;
@ -29,8 +32,9 @@ static void test_arm_nop() {
OK(uc_close(uc));
}
static void test_arm_thumb_sub() {
uc_engine* uc;
static void test_arm_thumb_sub()
{
uc_engine *uc;
char code[] = "\x83\xb0"; // sub sp, #0xc
int r_sp = 0x1234;
@ -45,15 +49,18 @@ static void test_arm_thumb_sub() {
OK(uc_close(uc));
}
static void test_armeb_sub() {
uc_engine* uc;
char code[] = "\xe3\xa0\x00\x37\xe0\x42\x10\x03"; // mov r0, #0x37; sub r1, r2, r3
static void test_armeb_sub()
{
uc_engine *uc;
char code[] =
"\xe3\xa0\x00\x37\xe0\x42\x10\x03"; // mov r0, #0x37; sub r1, r2, r3
int r_r0 = 0x1234;
int r_r2 = 0x6789;
int r_r3 = 0x3333;
int r_r1;
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN, code,
sizeof(code) - 1);
OK(uc_reg_write(uc, UC_ARM_REG_R0, &r_r0));
OK(uc_reg_write(uc, UC_ARM_REG_R2, &r_r2));
OK(uc_reg_write(uc, UC_ARM_REG_R3, &r_r3));
@ -73,12 +80,14 @@ static void test_armeb_sub() {
OK(uc_close(uc));
}
static void test_arm_thumbeb_sub() {
uc_engine* uc;
static void test_arm_thumbeb_sub()
{
uc_engine *uc;
char code[] = "\xb0\x83"; // sub sp, #0xc
int r_sp = 0x1234;
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_BIG_ENDIAN, code,
sizeof(code) - 1);
OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp));
OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 0));
@ -89,16 +98,25 @@ static void test_arm_thumbeb_sub() {
OK(uc_close(uc));
}
static void test_arm_thumb_ite_count_callback(uc_engine* uc, uint64_t address, uint32_t size, void* user_data) {
uint64_t* count = (uint64_t*)user_data;
static void test_arm_thumb_ite_count_callback(uc_engine *uc, uint64_t address,
uint32_t size, void *user_data)
{
uint64_t *count = (uint64_t *)user_data;
(*count) += 1;
}
static void test_arm_thumb_ite() {
uc_engine* uc;
static void test_arm_thumb_ite()
{
uc_engine *uc;
uc_hook hook;
char code[] = "\x9a\x42\x15\xbf\x00\x9a\x01\x9a\x78\x23\x15\x23"; // cmp r2, r3; itete ne; ldrne r2, [sp]; ldreq r2, [sp,#4]; movne r3, #0x78; moveq r3, #0x15
char code[] =
"\x9a\x42\x15\xbf\x00\x9a\x01\x9a\x78\x23\x15\x23"; // cmp r2, r3; itete
// ne; ldrne r2,
// [sp]; ldreq r2,
// [sp,#4]; movne
// r3, #0x78; moveq
// r3, #0x15
int r_sp = 0x8000;
int r_r2 = 0;
int r_r3 = 1;
@ -116,7 +134,8 @@ static void test_arm_thumb_ite() {
r_r2 = 0x4d;
OK(uc_mem_write(uc, r_sp + 4, &r_r2, 4));
OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_arm_thumb_ite_count_callback, &count, 1, 0));
OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_arm_thumb_ite_count_callback,
&count, 1, 0));
// Execute four instructions at a time.
OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 0));
@ -146,19 +165,22 @@ static void test_arm_thumb_ite() {
OK(uc_close(uc));
}
static void test_arm_m_thumb_mrs() {
uc_engine* uc;
char code[] = "\xef\xf3\x14\x80\xef\xf3\x00\x81"; // mrs r0, control; mrs r1, apsr
static void test_arm_m_thumb_mrs()
{
uc_engine *uc;
char code[] =
"\xef\xf3\x14\x80\xef\xf3\x00\x81"; // mrs r0, control; mrs r1, apsr
uint32_t r_control = 0b10;
uint32_t r_apsr = (0b10101 << 27);
uint32_t r_r0, r_r1;
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code,
sizeof(code) - 1);
OK(uc_reg_write(uc, UC_ARM_REG_CONTROL, &r_control));
OK(uc_reg_write(uc, UC_ARM_REG_APSR_NZCVQ, &r_apsr));
OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 0));
OK(uc_reg_read(uc, UC_ARM_REG_R0, &r_r0));
OK(uc_reg_read(uc, UC_ARM_REG_R1, &r_r1));
@ -168,8 +190,9 @@ static void test_arm_m_thumb_mrs() {
OK(uc_close(uc));
}
static void test_arm_m_control() {
uc_engine* uc;
static void test_arm_m_control()
{
uc_engine *uc;
int r_control, r_msp, r_psp;
OK(uc_open(UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, &uc));
@ -195,16 +218,19 @@ static void test_arm_m_control() {
OK(uc_reg_read(uc, UC_ARM_REG_R13, &r_msp));
TEST_CHECK(r_psp != r_msp);
TEST_CHECK(r_msp == 0x1000);
OK(uc_close(uc));
}
//
// Some notes:
// Qemu raise a special exception EXCP_EXCEPTION_EXIT to handle the EXC_RETURN. We can't
// help user handle EXC_RETURN since unicorn is designed not to handle any CPU exception.
// Qemu raise a special exception EXCP_EXCEPTION_EXIT to handle the
// EXC_RETURN. We can't help user handle EXC_RETURN since unicorn is designed
// not to handle any CPU exception.
//
static void test_arm_m_exc_return_hook_interrupt(uc_engine* uc, int intno, void* data) {
static void test_arm_m_exc_return_hook_interrupt(uc_engine *uc, int intno,
void *data)
{
int r_pc;
OK(uc_reg_read(uc, UC_ARM_REG_PC, &r_pc));
@ -213,16 +239,19 @@ static void test_arm_m_exc_return_hook_interrupt(uc_engine* uc, int intno, void*
OK(uc_emu_stop(uc));
}
static void test_arm_m_exc_return() {
uc_engine* uc;
static void test_arm_m_exc_return()
{
uc_engine *uc;
char code[] = "\x6f\xf0\x02\x00\x00\x47"; // mov r0, #0xFFFFFFFD; bx r0;
int r_ipsr;
int r_sp = 0x8000;
uc_hook hook;
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code,
sizeof(code) - 1);
OK(uc_mem_map(uc, r_sp - 0x1000, 0x1000, UC_PROT_ALL));
OK(uc_hook_add(uc, &hook, UC_HOOK_INTR, test_arm_m_exc_return_hook_interrupt, NULL, 0, 0));
OK(uc_hook_add(uc, &hook, UC_HOOK_INTR,
test_arm_m_exc_return_hook_interrupt, NULL, 0, 0));
r_sp -= 0x1c;
OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp));
@ -230,20 +259,19 @@ static void test_arm_m_exc_return() {
r_ipsr = 16; // We are in whatever exception.
OK(uc_reg_write(uc, UC_ARM_REG_IPSR, &r_ipsr));
OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 2)); // Just execute 2 instructions.
OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0,
2)); // Just execute 2 instructions.
OK(uc_hook_del(uc, hook));
OK(uc_close(uc));
}
TEST_LIST = {
{ "test_arm_nop", test_arm_nop },
{ "test_arm_thumb_sub", test_arm_thumb_sub },
{ "test_armeb_sub", test_armeb_sub },
{ "test_arm_thumbeb_sub", test_arm_thumbeb_sub },
{ "test_arm_thumb_ite", test_arm_thumb_ite },
{ "test_arm_m_thumb_mrs", test_arm_m_thumb_mrs },
{ "test_arm_m_control", test_arm_m_control },
{ "test_arm_m_exc_return", test_arm_m_exc_return },
{ NULL, NULL }
};
TEST_LIST = {{"test_arm_nop", test_arm_nop},
{"test_arm_thumb_sub", test_arm_thumb_sub},
{"test_armeb_sub", test_armeb_sub},
{"test_arm_thumbeb_sub", test_arm_thumbeb_sub},
{"test_arm_thumb_ite", test_arm_thumb_ite},
{"test_arm_m_thumb_mrs", test_arm_m_thumb_mrs},
{"test_arm_m_control", test_arm_m_control},
{"test_arm_m_exc_return", test_arm_m_exc_return},
{NULL, NULL}};

View File

@ -3,52 +3,51 @@
const uint64_t code_start = 0x1000;
const uint64_t code_len = 0x4000;
static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) {
static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode,
const char *code, uint64_t size)
{
OK(uc_open(arch, mode, uc));
OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL));
OK(uc_mem_write(*uc, code_start, code, size));
}
static void test_arm64_until() {
uc_engine *uc;
char code[] = "\x30\x00\x80\xd2\x11\x04\x80\xd2\x9c\x23\x00\x91";
static void test_arm64_until()
{
uc_engine *uc;
char code[] = "\x30\x00\x80\xd2\x11\x04\x80\xd2\x9c\x23\x00\x91";
/*
mov x16, #1
mov x17, #0x20
add x28, x28, 8
*/
/*
mov x16, #1
mov x17, #0x20
add x28, x28, 8
*/
uint64_t r_x16 = 0x12341234;
uint64_t r_x17 = 0x78907890;
uint64_t r_pc = 0x00000000;
uint64_t r_x28 = 0x12341234;
uint64_t r_x16 = 0x12341234;
uint64_t r_x17 = 0x78907890;
uint64_t r_pc = 0x00000000;
uint64_t r_x28 = 0x12341234;
uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1);
// initialize machine registers
OK(uc_reg_write(uc, UC_ARM64_REG_X16, &r_x16));
OK(uc_reg_write(uc, UC_ARM64_REG_X17, &r_x17));
OK(uc_reg_write(uc, UC_ARM64_REG_X28, &r_x28));
// initialize machine registers
OK(uc_reg_write(uc, UC_ARM64_REG_X16, &r_x16));
OK(uc_reg_write(uc, UC_ARM64_REG_X17, &r_x17));
OK(uc_reg_write(uc, UC_ARM64_REG_X28, &r_x28));
// emulate the three instructions
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 3));
// emulate the three instructions
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 3));
OK(uc_reg_read(uc, UC_ARM64_REG_X16, &r_x16));
OK(uc_reg_read(uc, UC_ARM64_REG_X17, &r_x17));
OK(uc_reg_read(uc, UC_ARM64_REG_X28, &r_x28));
OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc));
OK(uc_reg_read(uc, UC_ARM64_REG_X16, &r_x16));
OK(uc_reg_read(uc, UC_ARM64_REG_X17, &r_x17));
OK(uc_reg_read(uc, UC_ARM64_REG_X28, &r_x28));
OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc));
TEST_CHECK(r_x16 == 0x1);
TEST_CHECK(r_x17 == 0x20);
TEST_CHECK(r_x28 == 0x1234123c);
TEST_CHECK(r_pc == (code_start + sizeof(code) - 1));
TEST_CHECK(r_x16 == 0x1);
TEST_CHECK(r_x17 == 0x20);
TEST_CHECK(r_x28 == 0x1234123c);
TEST_CHECK(r_pc == (code_start + sizeof(code) - 1));
OK(uc_close(uc));
OK(uc_close(uc));
}
TEST_LIST = {
{ "test_arm64_until", test_arm64_until },
{ NULL, NULL }
};
TEST_LIST = {{"test_arm64_until", test_arm64_until}, {NULL, NULL}};

View File

@ -3,6 +3,4 @@
const uint64_t code_start = 0x1000;
const uint64_t code_len = 0x4000;
TEST_LIST = {
{ NULL, NULL }
};
TEST_LIST = {{NULL, NULL}};

View File

@ -1,34 +1,40 @@
#include "unicorn_test.h"
static void test_map_correct() {
uc_engine* uc;
static void test_map_correct()
{
uc_engine *uc;
OK(uc_open (UC_ARCH_X86, UC_MODE_64, &uc));
OK(uc_mem_map (uc, 0x40000, 0x1000 * 16, UC_PROT_ALL)); // [0x40000, 0x50000]
OK(uc_mem_map (uc, 0x60000, 0x1000 * 16, UC_PROT_ALL)); // [0x60000, 0x70000]
OK(uc_mem_map (uc, 0x20000, 0x1000 * 16, UC_PROT_ALL)); // [0x20000, 0x30000]
uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x10000, 0x2000 * 16, UC_PROT_ALL));
uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x25000, 0x1000 * 16, UC_PROT_ALL));
uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x35000, 0x1000 * 16, UC_PROT_ALL));
uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x45000, 0x1000 * 16, UC_PROT_ALL));
uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x55000, 0x2000 * 16, UC_PROT_ALL));
OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc));
OK(uc_mem_map(uc, 0x40000, 0x1000 * 16, UC_PROT_ALL)); // [0x40000, 0x50000]
OK(uc_mem_map(uc, 0x60000, 0x1000 * 16, UC_PROT_ALL)); // [0x60000, 0x70000]
OK(uc_mem_map(uc, 0x20000, 0x1000 * 16, UC_PROT_ALL)); // [0x20000, 0x30000]
uc_assert_err(UC_ERR_MAP,
uc_mem_map(uc, 0x10000, 0x2000 * 16, UC_PROT_ALL));
uc_assert_err(UC_ERR_MAP,
uc_mem_map(uc, 0x25000, 0x1000 * 16, UC_PROT_ALL));
uc_assert_err(UC_ERR_MAP,
uc_mem_map(uc, 0x35000, 0x1000 * 16, UC_PROT_ALL));
uc_assert_err(UC_ERR_MAP,
uc_mem_map(uc, 0x45000, 0x1000 * 16, UC_PROT_ALL));
uc_assert_err(UC_ERR_MAP,
uc_mem_map(uc, 0x55000, 0x2000 * 16, UC_PROT_ALL));
OK(uc_mem_map(uc, 0x35000, 0x5000, UC_PROT_ALL));
OK(uc_mem_map(uc, 0x50000, 0x5000, UC_PROT_ALL));
OK(uc_close(uc));
}
static void test_map_wrapping() {
uc_engine* uc;
static void test_map_wrapping()
{
uc_engine *uc;
OK(uc_open (UC_ARCH_X86, UC_MODE_64, &uc));
uc_assert_err(UC_ERR_ARG, uc_mem_map (uc, (~0ll - 0x4000) & ~0xfff, 0x8000, UC_PROT_ALL));
OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc));
uc_assert_err(UC_ERR_ARG, uc_mem_map(uc, (~0ll - 0x4000) & ~0xfff, 0x8000,
UC_PROT_ALL));
OK(uc_close(uc));
}
TEST_LIST = {
{ "test_map_correct", test_map_correct },
{ "test_map_wrapping", test_map_wrapping },
{ NULL, NULL }
};
TEST_LIST = {{"test_map_correct", test_map_correct},
{"test_map_wrapping", test_map_wrapping},
{NULL, NULL}};

View File

@ -3,18 +3,22 @@
const uint64_t code_start = 0x10000000;
const uint64_t code_len = 0x4000;
static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) {
static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode,
const char *code, uint64_t size)
{
OK(uc_open(arch, mode, uc));
OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL));
OK(uc_mem_write(*uc, code_start, code, size));
}
static void test_mips_el_ori() {
uc_engine* uc;
static void test_mips_el_ori()
{
uc_engine *uc;
char code[] = "\x56\x34\x21\x34"; // ori $at, $at, 0x3456;
int r_r1 = 0x6789;
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code,
sizeof(code) - 1);
OK(uc_reg_write(uc, UC_MIPS_REG_1, &r_r1));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
@ -26,12 +30,14 @@ static void test_mips_el_ori() {
OK(uc_close(uc));
}
static void test_mips_eb_ori() {
uc_engine* uc;
static void test_mips_eb_ori()
{
uc_engine *uc;
char code[] = "\x34\x21\x34\x56"; // ori $at, $at, 0x3456;
int r_r1 = 0x6789;
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code,
sizeof(code) - 1);
OK(uc_reg_write(uc, UC_MIPS_REG_1, &r_r1));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
@ -43,37 +49,43 @@ static void test_mips_eb_ori() {
OK(uc_close(uc));
}
static void test_mips_stop_at_branch() {
uc_engine* uc;
char code[] = "\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop;
static void test_mips_stop_at_branch()
{
uc_engine *uc;
char code[] =
"\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop;
int r_pc = 0x0;
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code,
sizeof(code) - 1);
// Execute one instruction with branch delay slot.
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 1));
OK(uc_reg_read(uc, UC_MIPS_REG_PC, &r_pc));
// Even if we just execute one instruction, the instruction in the
// Even if we just execute one instruction, the instruction in the
// delay slot would also be executed.
TEST_CHECK(r_pc == code_start + 0x8);
OK(uc_close(uc));
}
static void test_mips_stop_at_delay_slot() {
uc_engine* uc;
char code[] = "\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop;
static void test_mips_stop_at_delay_slot()
{
uc_engine *uc;
char code[] =
"\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop;
int r_pc = 0x0;
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code,
sizeof(code) - 1);
// Stop at the delay slot by design.
OK(uc_emu_start(uc, code_start, code_start + 4, 0, 0));
OK(uc_reg_read(uc, UC_MIPS_REG_PC, &r_pc));
// The branch instruction isn't committed and the PC is not updated.
// Users is responsible to restart emulation at the branch instruction.
TEST_CHECK(r_pc == code_start);
@ -81,12 +93,14 @@ static void test_mips_stop_at_delay_slot() {
OK(uc_close(uc));
}
static void test_mips_lwx_exception_issue_1314() {
uc_engine* uc;
static void test_mips_lwx_exception_issue_1314()
{
uc_engine *uc;
char code[] = "\x0a\xc8\x79\x7e"; // lwx $t9, $t9($s3)
int reg;
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code,
sizeof(code) - 1);
OK(uc_mem_map(uc, 0x10000, 0x4000, UC_PROT_ALL));
// Enable DSP
@ -113,10 +127,9 @@ static void test_mips_lwx_exception_issue_1314() {
}
TEST_LIST = {
{ "test_mips_stop_at_branch", test_mips_stop_at_branch },
{ "test_mips_stop_at_delay_slot", test_mips_stop_at_delay_slot},
{ "test_mips_el_ori", test_mips_el_ori},
{ "test_mips_eb_ori", test_mips_eb_ori},
{ "test_mips_lwx_exception_issue_1314", test_mips_lwx_exception_issue_1314},
{ NULL, NULL }
};
{"test_mips_stop_at_branch", test_mips_stop_at_branch},
{"test_mips_stop_at_delay_slot", test_mips_stop_at_delay_slot},
{"test_mips_el_ori", test_mips_el_ori},
{"test_mips_eb_ori", test_mips_eb_ori},
{"test_mips_lwx_exception_issue_1314", test_mips_lwx_exception_issue_1314},
{NULL, NULL}};

View File

@ -3,18 +3,22 @@
const uint64_t code_start = 0x1000;
const uint64_t code_len = 0x4000;
static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) {
static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode,
const char *code, uint64_t size)
{
OK(uc_open(arch, mode, uc));
OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL));
OK(uc_mem_write(*uc, code_start, code, size));
}
static void test_ppc32_add() {
uc_engine* uc;
static void test_ppc32_add()
{
uc_engine *uc;
char code[] = "\x7f\x46\x1a\x14"; // ADD 26, 6, 3
int reg;
uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code,
sizeof(code) - 1);
reg = 42;
OK(uc_reg_write(uc, UC_PPC_REG_3, &reg));
@ -30,7 +34,4 @@ static void test_ppc32_add() {
OK(uc_close(uc));
}
TEST_LIST = {
{ "test_ppc32_add", test_ppc32_add },
{ NULL, NULL}
};
TEST_LIST = {{"test_ppc32_add", test_ppc32_add}, {NULL, NULL}};

View File

@ -3,19 +3,23 @@
const uint64_t code_start = 0x1000;
const uint64_t code_len = 0x4000;
static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) {
static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode,
const char *code, uint64_t size)
{
OK(uc_open(arch, mode, uc));
OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL));
OK(uc_mem_write(*uc, code_start, code, size));
}
static void test_riscv32_nop() {
uc_engine* uc;
static void test_riscv32_nop()
{
uc_engine *uc;
char code[] = "\x13\x00\x00\x00"; // nop
uint32_t r_t0 = 0x1234;
uint32_t r_t1 = 0x5678;
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code,
sizeof(code) - 1);
OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1));
@ -29,13 +33,15 @@ static void test_riscv32_nop() {
OK(uc_close(uc));
}
static void test_riscv64_nop() {
uc_engine* uc;
static void test_riscv64_nop()
{
uc_engine *uc;
char code[] = "\x13\x00\x00\x00"; // nop
uint64_t r_t0 = 0x1234;
uint64_t r_t1 = 0x5678;
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code,
sizeof(code) - 1);
OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1));
@ -49,167 +55,172 @@ static void test_riscv64_nop() {
OK(uc_close(uc));
}
static void test_riscv32_until_pc_update() {
uc_engine *uc;
char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00";
static void test_riscv32_until_pc_update()
{
uc_engine *uc;
char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00";
/*
addi t0, zero, 1
addi t1, zero, 0x20
addi sp, sp, 8
*/
/*
addi t0, zero, 1
addi t1, zero, 0x20
addi sp, sp, 8
*/
uint32_t r_t0 = 0x1234;
uint32_t r_t1 = 0x7890;
uint32_t r_pc = 0x0000;
uint32_t r_sp = 0x1234;
uint32_t r_t0 = 0x1234;
uint32_t r_t1 = 0x7890;
uint32_t r_pc = 0x0000;
uint32_t r_sp = 0x1234;
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code,
sizeof(code) - 1);
// initialize machine registers
OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp));
// initialize machine registers
OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp));
// emulate the three instructions
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
// emulate the three instructions
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp));
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp));
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
TEST_CHECK(r_t0 == 0x1);
TEST_CHECK(r_t1 == 0x20);
TEST_CHECK(r_sp == 0x123c);
TEST_CHECK(r_t0 == 0x1);
TEST_CHECK(r_t1 == 0x20);
TEST_CHECK(r_sp == 0x123c);
TEST_CHECK(r_pc == (code_start + sizeof(code) - 1));
TEST_CHECK(r_pc == (code_start + sizeof(code) - 1));
OK(uc_close(uc));
OK(uc_close(uc));
}
static void test_riscv64_until_pc_update() {
uc_engine *uc;
char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00";
static void test_riscv64_until_pc_update()
{
uc_engine *uc;
char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00";
/*
addi t0, zero, 1
addi t1, zero, 0x20
addi sp, sp, 8
*/
/*
addi t0, zero, 1
addi t1, zero, 0x20
addi sp, sp, 8
*/
uint64_t r_t0 = 0x1234;
uint64_t r_t1 = 0x7890;
uint64_t r_pc = 0x0000;
uint64_t r_sp = 0x1234;
uint64_t r_t0 = 0x1234;
uint64_t r_t1 = 0x7890;
uint64_t r_pc = 0x0000;
uint64_t r_sp = 0x1234;
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code,
sizeof(code) - 1);
// initialize machine registers
OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp));
// initialize machine registers
OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp));
// emulate the three instructions
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
// emulate the three instructions
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp));
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp));
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
TEST_CHECK(r_t0 == 0x1);
TEST_CHECK(r_t1 == 0x20);
TEST_CHECK(r_sp == 0x123c);
TEST_CHECK(r_pc == (code_start + sizeof(code) - 1));
TEST_CHECK(r_t0 == 0x1);
TEST_CHECK(r_t1 == 0x20);
TEST_CHECK(r_sp == 0x123c);
TEST_CHECK(r_pc == (code_start + sizeof(code) - 1));
OK(uc_close(uc));
OK(uc_close(uc));
}
static void test_riscv32_3steps_pc_update() {
uc_engine *uc;
char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00";
static void test_riscv32_3steps_pc_update()
{
uc_engine *uc;
char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00";
/*
addi t0, zero, 1
addi t1, zero, 0x20
addi sp, sp, 8
*/
/*
addi t0, zero, 1
addi t1, zero, 0x20
addi sp, sp, 8
*/
uint32_t r_t0 = 0x1234;
uint32_t r_t1 = 0x7890;
uint32_t r_pc = 0x0000;
uint32_t r_sp = 0x1234;
uint32_t r_t0 = 0x1234;
uint32_t r_t1 = 0x7890;
uint32_t r_pc = 0x0000;
uint32_t r_sp = 0x1234;
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code,
sizeof(code) - 1);
// initialize machine registers
OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp));
// initialize machine registers
OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp));
// emulate the three instructions
OK(uc_emu_start(uc, code_start, -1, 0, 3));
// emulate the three instructions
OK(uc_emu_start(uc, code_start, -1, 0, 3));
OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp));
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp));
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
TEST_CHECK(r_t0 == 0x1);
TEST_CHECK(r_t1 == 0x20);
TEST_CHECK(r_sp == 0x123c);
TEST_CHECK(r_t0 == 0x1);
TEST_CHECK(r_t1 == 0x20);
TEST_CHECK(r_sp == 0x123c);
TEST_CHECK(r_pc == (code_start + sizeof(code) - 1));
TEST_CHECK(r_pc == (code_start + sizeof(code) - 1));
OK(uc_close(uc));
OK(uc_close(uc));
}
static void test_riscv64_3steps_pc_update() {
uc_engine *uc;
char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00";
static void test_riscv64_3steps_pc_update()
{
uc_engine *uc;
char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00";
/*
addi t0, zero, 1
addi t1, zero, 0x20
addi sp, sp, 8
*/
/*
addi t0, zero, 1
addi t1, zero, 0x20
addi sp, sp, 8
*/
uint64_t r_t0 = 0x1234;
uint64_t r_t1 = 0x7890;
uint64_t r_pc = 0x0000;
uint64_t r_sp = 0x1234;
uint64_t r_t0 = 0x1234;
uint64_t r_t1 = 0x7890;
uint64_t r_pc = 0x0000;
uint64_t r_sp = 0x1234;
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1);
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code,
sizeof(code) - 1);
// initialize machine registers
OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp));
// initialize machine registers
OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp));
// emulate the three instructions
OK(uc_emu_start(uc, code_start, -1, 0, 3));
// emulate the three instructions
OK(uc_emu_start(uc, code_start, -1, 0, 3));
OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp));
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0));
OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1));
OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp));
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
TEST_CHECK(r_t0 == 0x1);
TEST_CHECK(r_t1 == 0x20);
TEST_CHECK(r_sp == 0x123c);
TEST_CHECK(r_pc == (code_start + sizeof(code) - 1));
TEST_CHECK(r_t0 == 0x1);
TEST_CHECK(r_t1 == 0x20);
TEST_CHECK(r_sp == 0x123c);
TEST_CHECK(r_pc == (code_start + sizeof(code) - 1));
OK(uc_close(uc));
OK(uc_close(uc));
}
TEST_LIST = {
{ "test_riscv32_nop", test_riscv32_nop },
{ "test_riscv64_nop", test_riscv64_nop },
{ "test_riscv32_3steps_pc_update", test_riscv32_3steps_pc_update },
{ "test_riscv64_3steps_pc_update", test_riscv64_3steps_pc_update },
{ "test_riscv32_until_pc_update", test_riscv32_until_pc_update },
{ "test_riscv64_until_pc_update", test_riscv64_until_pc_update },
{ NULL, NULL }
};
TEST_LIST = {{"test_riscv32_nop", test_riscv32_nop},
{"test_riscv64_nop", test_riscv64_nop},
{"test_riscv32_3steps_pc_update", test_riscv32_3steps_pc_update},
{"test_riscv64_3steps_pc_update", test_riscv64_3steps_pc_update},
{"test_riscv32_until_pc_update", test_riscv32_until_pc_update},
{"test_riscv64_until_pc_update", test_riscv64_until_pc_update},
{NULL, NULL}};

View File

@ -3,6 +3,4 @@
const uint64_t code_start = 0x1000;
const uint64_t code_len = 0x4000;
TEST_LIST = {
{ NULL, NULL }
};
TEST_LIST = {{NULL, NULL}};

View File

@ -3,7 +3,9 @@
const uint64_t code_start = 0x1000;
const uint64_t code_len = 0x4000;
static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) {
static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode,
const char *code, uint64_t size)
{
OK(uc_open(arch, mode, uc));
OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL));
OK(uc_mem_write(*uc, code_start, code, size));
@ -14,22 +16,26 @@ typedef struct _INSN_IN_RESULT {
int size;
} INSN_IN_RESULT;
static void test_x86_in_callback(uc_engine* uc, uint32_t port, int size, void* user_data) {
INSN_IN_RESULT* result = (INSN_IN_RESULT*)user_data;
static void test_x86_in_callback(uc_engine *uc, uint32_t port, int size,
void *user_data)
{
INSN_IN_RESULT *result = (INSN_IN_RESULT *)user_data;
result->port = port;
result->size = size;
}
static void test_x86_in() {
uc_engine* uc;
static void test_x86_in()
{
uc_engine *uc;
uc_hook hook;
char code[] = "\xe5\x10"; // IN eax, 0x10
INSN_IN_RESULT result;
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_in_callback, &result, 1, 0, UC_X86_INS_IN));
OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_in_callback, &result, 1, 0,
UC_X86_INS_IN));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
TEST_CHECK(result.port == 0x10);
TEST_CHECK(result.size == 4);
@ -44,23 +50,27 @@ typedef struct _INSN_OUT_RESULT {
uint32_t value;
} INSN_OUT_RESULT;
static void test_x86_out_callback(uc_engine* uc, uint32_t port, int size, uint32_t value, void* user_data) {
INSN_OUT_RESULT* result = (INSN_OUT_RESULT*)user_data;
static void test_x86_out_callback(uc_engine *uc, uint32_t port, int size,
uint32_t value, void *user_data)
{
INSN_OUT_RESULT *result = (INSN_OUT_RESULT *)user_data;
result->port = port;
result->size = size;
result->value = value;
}
static void test_x86_out() {
uc_engine* uc;
static void test_x86_out()
{
uc_engine *uc;
uc_hook hook;
char code[] = "\xb0\x32\xe6\x46"; // MOV al, 0x32; OUT 0x46, al;
INSN_OUT_RESULT result;
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_out_callback, &result, 1, 0, UC_X86_INS_OUT));
OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_out_callback, &result, 1,
0, UC_X86_INS_OUT));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
TEST_CHECK(result.port == 0x46);
TEST_CHECK(result.size == 1);
@ -82,8 +92,11 @@ typedef struct _MEM_HOOK_RESULTS {
MEM_HOOK_RESULT results[16];
} MEM_HOOK_RESULTS;
static bool test_x86_mem_hook_all_callback(uc_engine* uc, uc_mem_type type, uint64_t address, int size, uint64_t value, void* user_data) {
MEM_HOOK_RESULTS* r = (MEM_HOOK_RESULTS*)user_data;
static bool test_x86_mem_hook_all_callback(uc_engine *uc, uc_mem_type type,
uint64_t address, int size,
uint64_t value, void *user_data)
{
MEM_HOOK_RESULTS *r = (MEM_HOOK_RESULTS *)user_data;
uint64_t count = r->count;
if (count >= 16) {
@ -103,27 +116,28 @@ static bool test_x86_mem_hook_all_callback(uc_engine* uc, uc_mem_type type, uint
return true;
}
static void test_x86_mem_hook_all() {
uc_engine* uc;
static void test_x86_mem_hook_all()
{
uc_engine *uc;
uc_hook hook;
// mov eax, 0xdeadbeef;
// mov [0x8000], eax;
// mov eax, [0x10000];
char code[] = "\xb8\xef\xbe\xad\xde\xa3\x00\x80\x00\x00\xa1\x00\x00\x01\x00";
MEM_HOOK_RESULTS r = { 0 };
MEM_HOOK_RESULT expects[3] = {
{UC_MEM_WRITE, 0x8000, 4, 0xdeadbeef},
{UC_MEM_READ_UNMAPPED, 0x10000, 4, 0},
{UC_MEM_READ, 0x10000, 4, 0}
};
char code[] =
"\xb8\xef\xbe\xad\xde\xa3\x00\x80\x00\x00\xa1\x00\x00\x01\x00";
MEM_HOOK_RESULTS r = {0};
MEM_HOOK_RESULT expects[3] = {{UC_MEM_WRITE, 0x8000, 4, 0xdeadbeef},
{UC_MEM_READ_UNMAPPED, 0x10000, 4, 0},
{UC_MEM_READ, 0x10000, 4, 0}};
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
OK(uc_mem_map(uc, 0x8000, 0x1000, UC_PROT_ALL));
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_VALID | UC_HOOK_MEM_INVALID, test_x86_mem_hook_all_callback, &r, 1, 0));
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_VALID | UC_HOOK_MEM_INVALID,
test_x86_mem_hook_all_callback, &r, 1, 0));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
TEST_CHECK(r.count == 3);
for (int i = 0; i < r.count; i ++) {
for (int i = 0; i < r.count; i++) {
TEST_CHECK(expects[i].type == r.results[i].type);
TEST_CHECK(expects[i].address == r.results[i].address);
TEST_CHECK(expects[i].size == r.results[i].size);
@ -134,9 +148,11 @@ static void test_x86_mem_hook_all() {
OK(uc_close(uc));
}
static void test_x86_inc_dec_pxor() {
uc_engine* uc;
char code[] = "\x41\x4a\x66\x0f\xef\xc1"; // INC ecx; DEC edx; PXOR xmm0, xmm1
static void test_x86_inc_dec_pxor()
{
uc_engine *uc;
char code[] =
"\x41\x4a\x66\x0f\xef\xc1"; // INC ecx; DEC edx; PXOR xmm0, xmm1
int r_ecx = 0x1234;
int r_edx = 0x7890;
uint64_t r_xmm0[2] = {0x08090a0b0c0d0e0f, 0x0001020304050607};
@ -162,9 +178,11 @@ static void test_x86_inc_dec_pxor() {
OK(uc_close(uc));
}
static void test_x86_relative_jump() {
uc_engine* uc;
char code[] = "\xeb\x02\x90\x90\x90\x90\x90\x90"; // jmp 4; nop; nop; nop; nop; nop; nop
static void test_x86_relative_jump()
{
uc_engine *uc;
char code[] = "\xeb\x02\x90\x90\x90\x90\x90\x90"; // jmp 4; nop; nop; nop;
// nop; nop; nop
int r_eip;
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
@ -178,8 +196,9 @@ static void test_x86_relative_jump() {
OK(uc_close(uc));
}
static void test_x86_loop() {
uc_engine* uc;
static void test_x86_loop()
{
uc_engine *uc;
char code[] = "\x41\x4a\xeb\xfe"; // inc ecx; dec edx; jmp $;
int r_ecx = 0x1234;
int r_edx = 0x7890;
@ -188,7 +207,8 @@ static void test_x86_loop() {
OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx));
OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 1 * 1000000, 0));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 1 * 1000000,
0));
OK(uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx));
OK(uc_reg_read(uc, UC_X86_REG_EDX, &r_edx));
@ -199,40 +219,50 @@ static void test_x86_loop() {
OK(uc_close(uc));
}
static void test_x86_invalid_mem_read() {
uc_engine* uc;
static void test_x86_invalid_mem_read()
{
uc_engine *uc;
char code[] = "\x8b\x0d\xaa\xaa\xaa\xaa"; // mov ecx, [0xAAAAAAAA]
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
uc_assert_err(UC_ERR_READ_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
uc_assert_err(
UC_ERR_READ_UNMAPPED,
uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
OK(uc_close(uc));
}
static void test_x86_invalid_mem_write() {
uc_engine* uc;
static void test_x86_invalid_mem_write()
{
uc_engine *uc;
char code[] = "\x89\x0d\xaa\xaa\xaa\xaa"; // mov ecx, [0xAAAAAAAA]
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
uc_assert_err(UC_ERR_WRITE_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
uc_assert_err(
UC_ERR_WRITE_UNMAPPED,
uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
OK(uc_close(uc));
}
static void test_x86_invalid_jump() {
uc_engine* uc;
static void test_x86_invalid_jump()
{
uc_engine *uc;
char code[] = "\xe9\xe9\xee\xee\xee"; // jmp 0xEEEEEEEE
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
uc_assert_err(UC_ERR_FETCH_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
uc_assert_err(
UC_ERR_FETCH_UNMAPPED,
uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
OK(uc_close(uc));
}
static void test_x86_64_syscall_callback(uc_engine* uc, void* user_data) {
static void test_x86_64_syscall_callback(uc_engine *uc, void *user_data)
{
uint64_t rax;
OK(uc_reg_read(uc, UC_X86_REG_RAX, &rax));
@ -240,15 +270,17 @@ static void test_x86_64_syscall_callback(uc_engine* uc, void* user_data) {
TEST_CHECK(rax == 0x100);
}
static void test_x86_64_syscall() {
uc_engine* uc;
static void test_x86_64_syscall()
{
uc_engine *uc;
uc_hook hook;
char code[] = "\x0f\x05"; // syscall
uint64_t r_rax = 0x100;
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_64, code, sizeof(code) - 1);
OK(uc_reg_write(uc, UC_X86_REG_RAX, &r_rax));
OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_64_syscall_callback, NULL, 1, 0, UC_X86_INS_SYSCALL));
OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_64_syscall_callback, NULL,
1, 0, UC_X86_INS_SYSCALL));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
@ -256,8 +288,9 @@ static void test_x86_64_syscall() {
OK(uc_close(uc));
}
static void test_x86_16_add() {
uc_engine* uc;
static void test_x86_16_add()
{
uc_engine *uc;
char code[] = "\x00\x00"; // add byte ptr [bx + si], al
uint16_t r_ax = 7;
uint16_t r_bx = 5;
@ -277,9 +310,10 @@ static void test_x86_16_add() {
OK(uc_close(uc));
}
static void test_x86_reg_save() {
uc_engine* uc;
uc_context* ctx;
static void test_x86_reg_save()
{
uc_engine *uc;
uc_context *ctx;
char code[] = "\x40"; // inc eax
int r_eax = 1;
@ -289,7 +323,7 @@ static void test_x86_reg_save() {
OK(uc_context_alloc(uc, &ctx));
OK(uc_context_save(uc, ctx));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_eax));
TEST_CHECK(r_eax == 2);
@ -302,27 +336,38 @@ static void test_x86_reg_save() {
OK(uc_close(uc));
}
static bool test_x86_invalid_mem_read_stop_in_cb_callback(uc_engine* uc, uc_mem_type type, uint64_t address, int size, uint64_t value, void* user_data) {
// False indicates that we fail to handle this ERROR and let the emulation stop.
static bool
test_x86_invalid_mem_read_stop_in_cb_callback(uc_engine *uc, uc_mem_type type,
uint64_t address, int size,
uint64_t value, void *user_data)
{
// False indicates that we fail to handle this ERROR and let the emulation
// stop.
//
// Note that the memory must be mapped properly if we return true! Check test_x86_mem_hook_all for example.
// Note that the memory must be mapped properly if we return true! Check
// test_x86_mem_hook_all for example.
return false;
}
static void test_x86_invalid_mem_read_stop_in_cb() {
uc_engine* uc;
static void test_x86_invalid_mem_read_stop_in_cb()
{
uc_engine *uc;
uc_hook hook;
char code[] = "\x40\x8b\x1d\x00\x00\x10\x00\x42"; // inc eax; mov ebx, [0x100000]; inc edx
char code[] = "\x40\x8b\x1d\x00\x00\x10\x00\x42"; // inc eax; mov ebx,
// [0x100000]; inc edx
int r_eax = 0x1234;
int r_edx = 0x5678;
int r_eip = 0;
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_READ, test_x86_invalid_mem_read_stop_in_cb_callback, NULL, 1, 0));
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_READ,
test_x86_invalid_mem_read_stop_in_cb_callback, NULL, 1, 0));
OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_eax));
OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx));
uc_assert_err(UC_ERR_READ_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
uc_assert_err(
UC_ERR_READ_UNMAPPED,
uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
// The state of Unicorn should be correct at this time.
OK(uc_reg_read(uc, UC_X86_REG_EIP, &r_eip));
@ -336,8 +381,9 @@ static void test_x86_invalid_mem_read_stop_in_cb() {
OK(uc_close(uc));
}
static void test_x86_x87_fnstenv_callback(uc_engine* uc, uint64_t address, uint32_t size, void* user_data) {
static void test_x86_x87_fnstenv_callback(uc_engine *uc, uint64_t address,
uint32_t size, void *user_data)
{
uint32_t r_eip;
uint32_t r_eax;
uint32_t fnstenv[7];
@ -345,8 +391,8 @@ static void test_x86_x87_fnstenv_callback(uc_engine* uc, uint64_t address, uint3
if (address == code_start + 4) { // The first fnstenv executed
// Save the address of the fld.
OK(uc_reg_read(uc, UC_X86_REG_EIP, &r_eip));
*((uint32_t*)user_data) = r_eip;
*((uint32_t *)user_data) = r_eip;
OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_eax));
OK(uc_mem_read(uc, r_eax, fnstenv, sizeof(fnstenv)));
// Don't update FCS:FIP for fnop.
@ -354,10 +400,13 @@ static void test_x86_x87_fnstenv_callback(uc_engine* uc, uint64_t address, uint3
}
}
static void test_x86_x87_fnstenv() {
uc_engine* uc;
static void test_x86_x87_fnstenv()
{
uc_engine *uc;
uc_hook hook;
char code[] = "\xd9\xd0\xd9\x30\xd9\x00\xd9\x30"; // fnop;fnstenv [eax];fld dword ptr [eax];fnstenv [eax]
char code[] =
"\xd9\xd0\xd9\x30\xd9\x00\xd9\x30"; // fnop;fnstenv [eax];fld dword ptr
// [eax];fnstenv [eax]
uint32_t base = code_start + 3 * code_len;
uint32_t last_eip;
uint32_t fnstenv[7];
@ -366,25 +415,31 @@ static void test_x86_x87_fnstenv() {
OK(uc_mem_map(uc, base, code_len, UC_PROT_ALL));
OK(uc_reg_write(uc, UC_X86_REG_EAX, &base));
OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_x86_x87_fnstenv_callback, &last_eip, 1, 0));
OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_x86_x87_fnstenv_callback,
&last_eip, 1, 0));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
OK(uc_mem_read(uc, base, fnstenv, sizeof(fnstenv)));
//But update FCS:FIP for fld.
// But update FCS:FIP for fld.
TEST_CHECK(fnstenv[3] == last_eip);
OK(uc_close(uc));
}
static uint64_t test_x86_mmio_read_callback(uc_engine* uc, uint64_t offset, unsigned size, void* user_data) {
static uint64_t test_x86_mmio_read_callback(uc_engine *uc, uint64_t offset,
unsigned size, void *user_data)
{
TEST_CHECK(offset == 4);
TEST_CHECK(size == 4);
return 0x19260817;
}
static void test_x86_mmio_write_callback(uc_engine* uc, uint64_t offset, unsigned size, uint64_t value, void* user_data) {
static void test_x86_mmio_write_callback(uc_engine *uc, uint64_t offset,
unsigned size, uint64_t value,
void *user_data)
{
TEST_CHECK(offset == 4);
TEST_CHECK(size == 4);
TEST_CHECK(value == 0xdeadbeef);
@ -392,14 +447,19 @@ static void test_x86_mmio_write_callback(uc_engine* uc, uint64_t offset, unsigne
return;
}
static void test_x86_mmio() {
uc_engine* uc;
static void test_x86_mmio()
{
uc_engine *uc;
int r_ecx = 0xdeadbeef;
char code[] = "\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00"; // mov [0x20004], ecx; mov ecx, [0x20004]
char code[] =
"\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00"; // mov [0x20004],
// ecx; mov ecx,
// [0x20004]
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx));
OK(uc_mmio_map(uc, 0x20000, 0x1000, test_x86_mmio_read_callback, NULL, test_x86_mmio_write_callback, NULL));
OK(uc_mmio_map(uc, 0x20000, 0x1000, test_x86_mmio_read_callback, NULL,
test_x86_mmio_write_callback, NULL));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
@ -410,7 +470,10 @@ static void test_x86_mmio() {
OK(uc_close(uc));
}
static bool test_x86_missing_code_callback(uc_engine* uc, uc_mem_type type, uint64_t address, int size, uint64_t value, void* user_data) {
static bool test_x86_missing_code_callback(uc_engine *uc, uc_mem_type type,
uint64_t address, int size,
uint64_t value, void *user_data)
{
char code[] = "\x41\x4a"; // inc ecx; dec edx;
uint64_t algined_address = address & 0xFFFFFFFFFFFFF000ULL;
int aligned_size = ((int)(size / 0x1000) + 1) * 0x1000;
@ -422,8 +485,9 @@ static bool test_x86_missing_code_callback(uc_engine* uc, uc_mem_type type, uint
return true;
}
static void test_x86_missing_code() {
uc_engine* uc;
static void test_x86_missing_code()
{
uc_engine *uc;
uc_hook hook;
int r_ecx = 0x1234;
int r_edx = 0x7890;
@ -432,7 +496,8 @@ static void test_x86_missing_code() {
OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc));
OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx));
OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx));
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED, test_x86_missing_code_callback, NULL, 1, 0));
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED,
test_x86_missing_code_callback, NULL, 1, 0));
OK(uc_emu_start(uc, code_start, code_start + 2, 0, 0));
@ -445,13 +510,14 @@ static void test_x86_missing_code() {
OK(uc_close(uc));
}
static void test_x86_smc_xor() {
uc_engine* uc;
static void test_x86_smc_xor()
{
uc_engine *uc;
/*
* 0x1000 xor dword ptr [edi+0x3], eax ; edi=0x1000, eax=0xbc4177e6
* 0x1003 dw 0x3ea98b13
*/
char code[] = "\x31\x47\x03\x13\x8b\xa9\x3e";
* 0x1000 xor dword ptr [edi+0x3], eax ; edi=0x1000, eax=0xbc4177e6
* 0x1003 dw 0x3ea98b13
*/
char code[] = "\x31\x47\x03\x13\x8b\xa9\x3e";
int r_edi = code_start;
int r_eax = 0xbc4177e6;
uint32_t result;
@ -469,14 +535,23 @@ static void test_x86_smc_xor() {
OK(uc_close(uc));
}
static uint64_t test_x86_mmio_uc_mem_rw_read_callback(uc_engine* uc, uint64_t offset, unsigned size, void* user_data) {
static uint64_t test_x86_mmio_uc_mem_rw_read_callback(uc_engine *uc,
uint64_t offset,
unsigned size,
void *user_data)
{
TEST_CHECK(offset == 8);
TEST_CHECK(size == 4);
return 0x19260817;
}
static void test_x86_mmio_uc_mem_rw_write_callback(uc_engine* uc, uint64_t offset, unsigned size, uint64_t value, void* user_data) {
static void test_x86_mmio_uc_mem_rw_write_callback(uc_engine *uc,
uint64_t offset,
unsigned size,
uint64_t value,
void *user_data)
{
TEST_CHECK(offset == 4);
TEST_CHECK(size == 4);
TEST_CHECK(value == 0xdeadbeef);
@ -484,39 +559,40 @@ static void test_x86_mmio_uc_mem_rw_write_callback(uc_engine* uc, uint64_t offse
return;
}
static void test_x86_mmio_uc_mem_rw() {
uc_engine* uc;
static void test_x86_mmio_uc_mem_rw()
{
uc_engine *uc;
int data = 0xdeadbeef;
OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc));
OK(uc_mmio_map(uc,
0x20000, 0x1000,
test_x86_mmio_uc_mem_rw_read_callback, NULL,
test_x86_mmio_uc_mem_rw_write_callback, NULL));
OK(uc_mmio_map(uc, 0x20000, 0x1000, test_x86_mmio_uc_mem_rw_read_callback,
NULL, test_x86_mmio_uc_mem_rw_write_callback, NULL));
OK(uc_mem_write(uc, 0x20004, (void*)&data, 4));
OK(uc_mem_read(uc, 0x20008, (void*)&data, 4));
OK(uc_mem_write(uc, 0x20004, (void *)&data, 4));
OK(uc_mem_read(uc, 0x20008, (void *)&data, 4));
TEST_CHECK(data == 0x19260817);
OK(uc_close(uc));
}
static void test_x86_sysenter_hook(uc_engine* uc, void* user) {
*(int*)user = 1;
static void test_x86_sysenter_hook(uc_engine *uc, void *user)
{
*(int *)user = 1;
}
static void test_x86_sysenter() {
uc_engine* uc;
static void test_x86_sysenter()
{
uc_engine *uc;
char code[] = "\x0F\x34"; // sysenter
uc_hook h;
int called = 0;
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_sysenter_hook, &called, 1, 0, UC_X86_INS_SYSENTER));
OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_sysenter_hook, &called, 1, 0,
UC_X86_INS_SYSENTER));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
@ -525,21 +601,24 @@ static void test_x86_sysenter() {
OK(uc_close(uc));
}
static void test_x86_hook_cpuid_callback(uc_engine* uc, void* data) {
static void test_x86_hook_cpuid_callback(uc_engine *uc, void *data)
{
int reg = 7;
OK(uc_reg_write(uc, UC_X86_REG_EAX, &reg));
}
static void test_x86_hook_cpuid() {
uc_engine* uc;
static void test_x86_hook_cpuid()
{
uc_engine *uc;
char code[] = "\x40\x0F\xA2"; // INC EAX; CPUID
uc_hook h;
int reg;
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_hook_cpuid_callback, NULL, 1, 0, UC_X86_INS_CPUID));
OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_hook_cpuid_callback, NULL, 1,
0, UC_X86_INS_CPUID));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
@ -550,26 +629,25 @@ static void test_x86_hook_cpuid() {
OK(uc_close(uc));
}
TEST_LIST = {
{ "test_x86_in", test_x86_in },
{ "test_x86_out", test_x86_out },
{ "test_x86_mem_hook_all", test_x86_mem_hook_all },
{ "test_x86_inc_dec_pxor", test_x86_inc_dec_pxor },
{ "test_x86_relative_jump", test_x86_relative_jump },
{ "test_x86_loop", test_x86_loop },
{ "test_x86_invalid_mem_read", test_x86_invalid_mem_read },
{ "test_x86_invalid_mem_write", test_x86_invalid_mem_write },
{ "test_x86_invalid_jump", test_x86_invalid_jump},
{ "test_x86_64_syscall", test_x86_64_syscall },
{ "test_x86_16_add", test_x86_16_add },
{ "test_x86_reg_save", test_x86_reg_save },
{ "test_x86_invalid_mem_read_stop_in_cb", test_x86_invalid_mem_read_stop_in_cb },
{ "test_x86_x87_fnstenv", test_x86_x87_fnstenv},
{ "test_x86_mmio", test_x86_mmio},
{ "test_x86_missing_code", test_x86_missing_code},
{ "test_x86_smc_xor", test_x86_smc_xor},
{ "test_x86_mmio_uc_mem_rw", test_x86_mmio_uc_mem_rw},
{ "test_x86_sysenter", test_x86_sysenter},
{ "test_x86_hook_cpuid", test_x86_hook_cpuid},
{ NULL, NULL }
};
TEST_LIST = {{"test_x86_in", test_x86_in},
{"test_x86_out", test_x86_out},
{"test_x86_mem_hook_all", test_x86_mem_hook_all},
{"test_x86_inc_dec_pxor", test_x86_inc_dec_pxor},
{"test_x86_relative_jump", test_x86_relative_jump},
{"test_x86_loop", test_x86_loop},
{"test_x86_invalid_mem_read", test_x86_invalid_mem_read},
{"test_x86_invalid_mem_write", test_x86_invalid_mem_write},
{"test_x86_invalid_jump", test_x86_invalid_jump},
{"test_x86_64_syscall", test_x86_64_syscall},
{"test_x86_16_add", test_x86_16_add},
{"test_x86_reg_save", test_x86_reg_save},
{"test_x86_invalid_mem_read_stop_in_cb",
test_x86_invalid_mem_read_stop_in_cb},
{"test_x86_x87_fnstenv", test_x86_x87_fnstenv},
{"test_x86_mmio", test_x86_mmio},
{"test_x86_missing_code", test_x86_missing_code},
{"test_x86_smc_xor", test_x86_smc_xor},
{"test_x86_mmio_uc_mem_rw", test_x86_mmio_uc_mem_rw},
{"test_x86_sysenter", test_x86_sysenter},
{"test_x86_hook_cpuid", test_x86_hook_cpuid},
{NULL, NULL}};

View File

@ -8,17 +8,17 @@
/**
* Assert that err matches expect
*/
#define uc_assert_err(expect, err) \
do { \
uc_err __err = err; \
if (!TEST_CHECK(__err == expect)) { \
TEST_MSG("%s", uc_strerror(__err)); \
} \
} while (0)
#define uc_assert_err(expect, err) \
do { \
uc_err __err = err; \
if (!TEST_CHECK(__err == expect)) { \
TEST_MSG("%s", uc_strerror(__err)); \
} \
} while (0)
/**
* Assert that err is UC_ERR_OK
*/
#define OK(stat) uc_assert_err(UC_ERR_OK, stat)
#define OK(stat) uc_assert_err(UC_ERR_OK, stat)
#endif /* UNICORN_TEST_H */

857
uc.c

File diff suppressed because it is too large Load Diff