From e62b0ef255994591e7ea6a96577ddf8f4ad05eaa Mon Sep 17 00:00:00 2001 From: lazymio Date: Fri, 29 Oct 2021 12:44:49 +0200 Subject: [PATCH] Add clang-format and format code to qemu code style --- .clang-format | 16 + include/uc_priv.h | 186 +- include/unicorn/arm.h | 4 +- include/unicorn/arm64.h | 6 +- include/unicorn/m68k.h | 4 +- include/unicorn/mips.h | 7 +- include/unicorn/platform.h | 168 +- include/unicorn/ppc.h | 2 +- include/unicorn/riscv.h | 200 +- include/unicorn/sparc.h | 10 +- include/unicorn/unicorn.h | 344 +-- include/unicorn/x86.h | 289 ++- qemu/target/arm/unicorn.h | 44 +- qemu/target/i386/unicorn.c | 2602 +++++++++++----------- qemu/target/i386/unicorn.h | 14 +- qemu/target/m68k/unicorn.c | 48 +- qemu/target/m68k/unicorn.h | 14 +- qemu/target/mips/unicorn.c | 107 +- qemu/target/mips/unicorn.h | 38 +- qemu/target/ppc/unicorn.c | 86 +- qemu/target/ppc/unicorn.h | 22 +- qemu/target/riscv/unicorn.c | 360 +-- qemu/target/riscv/unicorn.h | 22 +- qemu/target/sparc/unicorn.c | 56 +- qemu/target/sparc/unicorn.h | 22 +- samples/mem_apis.c | 179 +- samples/sample_arm.c | 100 +- samples/sample_arm64.c | 71 +- samples/sample_batch_reg.c | 33 +- samples/sample_m68k.c | 56 +- samples/sample_mips.c | 32 +- samples/sample_ppc.c | 30 +- samples/sample_riscv.c | 72 +- samples/sample_sparc.c | 30 +- samples/sample_x86.c | 429 ++-- samples/sample_x86_32_gdt_and_seg_regs.c | 184 +- samples/shellcode.c | 90 +- tests/unit/acutest.h | 1369 ++++++------ tests/unit/test_arm.c | 118 +- tests/unit/test_arm64.c | 67 +- tests/unit/test_m68k.c | 4 +- tests/unit/test_mem.c | 46 +- tests/unit/test_mips.c | 71 +- tests/unit/test_ppc.c | 17 +- tests/unit/test_riscv.c | 269 +-- tests/unit/test_sparc.c | 4 +- tests/unit/test_x86.c | 342 +-- tests/unit/unicorn_test.h | 16 +- uc.c | 857 +++---- 49 files changed, 4967 insertions(+), 4190 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..04e13156 --- /dev/null +++ b/.clang-format @@ -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 diff --git a/include/uc_priv.h b/include/uc_priv.h index 8c564396..bcdf9059 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -2,7 +2,6 @@ /* By Nguyen Anh Quynh , 2015 */ /* Modified for Unicorn Engine by Chen Huitao, 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: */ diff --git a/include/unicorn/arm.h b/include/unicorn/arm.h index 9ce7b0b3..5bd72d63 100644 --- a/include/unicorn/arm.h +++ b/include/unicorn/arm.h @@ -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, diff --git a/include/unicorn/arm64.h b/include/unicorn/arm64.h index 0f66518d..256b2a50 100644 --- a/include/unicorn/arm64.h +++ b/include/unicorn/arm64.h @@ -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 diff --git a/include/unicorn/m68k.h b/include/unicorn/m68k.h index 80e8b920..01cb0af1 100644 --- a/include/unicorn/m68k.h +++ b/include/unicorn/m68k.h @@ -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 diff --git a/include/unicorn/mips.h b/include/unicorn/mips.h index df54893f..b8d203f9 100644 --- a/include/unicorn/mips.h +++ b/include/unicorn/mips.h @@ -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, diff --git a/include/unicorn/platform.h b/include/unicorn/platform.h index 1d5dc314..385d1e03 100644 --- a/include/unicorn/platform.h +++ b/include/unicorn/platform.h @@ -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 -#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 -#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 -#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 -#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 diff --git a/include/unicorn/ppc.h b/include/unicorn/ppc.h index 9fded44c..a6181834 100644 --- a/include/unicorn/ppc.h +++ b/include/unicorn/ppc.h @@ -12,7 +12,7 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif //> PPC registers diff --git a/include/unicorn/riscv.h b/include/unicorn/riscv.h index 42a26627..a058ebab 100644 --- a/include/unicorn/riscv.h +++ b/include/unicorn/riscv.h @@ -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 diff --git a/include/unicorn/sparc.h b/include/unicorn/sparc.h index 08e05386..f9ec729d 100644 --- a/include/unicorn/sparc.h +++ b/include/unicorn/sparc.h @@ -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, diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index d7780e56..0d217bd4 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -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(). diff --git a/include/unicorn/x86.h b/include/unicorn/x86.h index 9533a72f..1f9b740e 100644 --- a/include/unicorn/x86.h +++ b/include/unicorn/x86.h @@ -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 diff --git a/qemu/target/arm/unicorn.h b/qemu/target/arm/unicorn.h index be5e23fc..270444bd 100644 --- a/qemu/target/arm/unicorn.h +++ b/qemu/target/arm/unicorn.h @@ -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 diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index eef1e471..404f8444 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -6,18 +6,18 @@ #include "sysemu/cpus.h" #include "cpu.h" #include "unicorn_common.h" -#include /* needed for uc_x86_mmr */ +#include /* needed for uc_x86_mmr */ #include "unicorn.h" -#define FPST(n) (env->fpregs[(env->fpstt + (n)) & 7].d) +#define FPST(n) (env->fpregs[(env->fpstt + (n)) & 7].d) #define X86_NON_CS_FLAGS (DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK) static void load_seg_16_helper(CPUX86State *env, int seg, uint32_t selector) { - cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff, X86_NON_CS_FLAGS); + cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff, + X86_NON_CS_FLAGS); } - void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f); floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper); @@ -28,7 +28,7 @@ static void x86_set_pc(struct uc_struct *uc, uint64_t address) { if (uc->mode == UC_MODE_16) { int16_t cs = (uint16_t)X86_CPU(uc->cpu)->env.segs[R_CS].selector; - ((CPUX86State *)uc->cpu->env_ptr)->eip = address - cs*16; + ((CPUX86State *)uc->cpu->env_ptr)->eip = address - cs * 16; } else ((CPUX86State *)uc->cpu->env_ptr)->eip = address; } @@ -59,11 +59,16 @@ void x86_reg_reset(struct uc_struct *uc) { CPUArchState *env = uc->cpu->env_ptr; - env->features[FEAT_1_EDX] = CPUID_CX8 | CPUID_CMOV | CPUID_SSE2 | CPUID_FXSR | CPUID_SSE | CPUID_CLFLUSH; - env->features[FEAT_1_ECX] = CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_AES | CPUID_EXT_CX16; + env->features[FEAT_1_EDX] = CPUID_CX8 | CPUID_CMOV | CPUID_SSE2 | + CPUID_FXSR | CPUID_SSE | CPUID_CLFLUSH; + env->features[FEAT_1_ECX] = CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 | + CPUID_EXT_SSE42 | CPUID_EXT_AES | + CPUID_EXT_CX16; env->features[FEAT_8000_0001_EDX] = CPUID_EXT2_3DNOW | CPUID_EXT2_RDTSCP; - env->features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM | CPUID_EXT3_ABM | CPUID_EXT3_SKINIT | CPUID_EXT3_CR8LEG; - env->features[FEAT_7_0_EBX] = CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP; + env->features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM | CPUID_EXT3_ABM | + CPUID_EXT3_SKINIT | CPUID_EXT3_CR8LEG; + env->features[FEAT_7_0_EBX] = CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | + CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP; memset(env->regs, 0, sizeof(env->regs)); memset(env->segs, 0, sizeof(env->segs)); @@ -81,7 +86,7 @@ void x86_reg_reset(struct uc_struct *uc) env->fpstt = 0; /* top of stack index */ env->fpus = 0; env->fpuc = 0; - memset(env->fptags, 0, sizeof(env->fptags)); /* 0 = valid, 1 = empty */ + memset(env->fptags, 0, sizeof(env->fptags)); /* 0 = valid, 1 = empty */ env->mxcsr = 0; memset(env->xmm_regs, 0, sizeof(env->xmm_regs)); @@ -129,43 +134,44 @@ void x86_reg_reset(struct uc_struct *uc) // TODO: reset other registers in CPUX86State qemu/target-i386/cpu.h // properly initialize internal setup for each mode - switch(uc->mode) { - default: - break; - case UC_MODE_16: - env->hflags = 0; - env->cr[0] = 0; - //undo the damage done by the memset of env->segs above - //for R_CS, not quite the same as x86_cpu_reset - cpu_x86_load_seg_cache(env, R_CS, 0, 0, 0xffff, - DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | + switch (uc->mode) { + default: + break; + case UC_MODE_16: + env->hflags = 0; + env->cr[0] = 0; + // undo the damage done by the memset of env->segs above + // for R_CS, not quite the same as x86_cpu_reset + cpu_x86_load_seg_cache(env, R_CS, 0, 0, 0xffff, + DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); - //remainder yields same state as x86_cpu_reset - load_seg_16_helper(env, R_DS, 0); - load_seg_16_helper(env, R_ES, 0); - load_seg_16_helper(env, R_SS, 0); - load_seg_16_helper(env, R_FS, 0); - load_seg_16_helper(env, R_GS, 0); + // remainder yields same state as x86_cpu_reset + load_seg_16_helper(env, R_DS, 0); + load_seg_16_helper(env, R_ES, 0); + load_seg_16_helper(env, R_SS, 0); + load_seg_16_helper(env, R_FS, 0); + load_seg_16_helper(env, R_GS, 0); - break; - case UC_MODE_32: - env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_OSFXSR_MASK; - cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode - break; - case UC_MODE_64: - env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_LMA_MASK | HF_OSFXSR_MASK; - env->hflags &= ~(HF_ADDSEG_MASK); - env->efer |= MSR_EFER_LMA | MSR_EFER_LME; // extended mode activated - cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode - /* If we are operating in 64bit mode then add the Long Mode flag - * to the CPUID feature flag - */ - env->features[FEAT_8000_0001_EDX] |= CPUID_EXT2_LM; - break; + break; + case UC_MODE_32: + env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_OSFXSR_MASK; + cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode + break; + case UC_MODE_64: + env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | + HF_LMA_MASK | HF_OSFXSR_MASK; + env->hflags &= ~(HF_ADDSEG_MASK); + env->efer |= MSR_EFER_LMA | MSR_EFER_LME; // extended mode activated + cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode + /* If we are operating in 64bit mode then add the Long Mode flag + * to the CPUID feature flag + */ + env->features[FEAT_8000_0001_EDX] |= CPUID_EXT2_LM; + break; } } -static int x86_msr_read(CPUX86State *env, uc_x86_msr *msr) +static int x86_msr_read(CPUX86State *env, uc_x86_msr *msr) { uint64_t ecx = env->regs[R_ECX]; uint64_t eax = env->regs[R_EAX]; @@ -175,14 +181,14 @@ static int x86_msr_read(CPUX86State *env, uc_x86_msr *msr) helper_rdmsr(env); msr->value = ((uint32_t)env->regs[R_EAX]) | - ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); + ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); env->regs[R_EAX] = eax; env->regs[R_ECX] = ecx; env->regs[R_EDX] = edx; - /* The implementation doesn't throw exception or return an error if there is one, so - * we will return 0. */ + /* The implementation doesn't throw exception or return an error if there is + * one, so we will return 0. */ return 0; } @@ -201,1258 +207,1249 @@ static int x86_msr_write(CPUX86State *env, uc_x86_msr *msr) env->regs[R_EAX] = eax; env->regs[R_EDX] = edx; - /* The implementation doesn't throw exception or return an error if there is one, so - * we will return 0. */ + /* The implementation doesn't throw exception or return an error if there is + * one, so we will return 0. */ return 0; } -static void reg_read(CPUX86State *env, unsigned int regid, void *value, uc_mode mode) +static void reg_read(CPUX86State *env, unsigned int regid, void *value, + uc_mode mode) { - switch(regid) { - default: - break; - case UC_X86_REG_FP0: - case UC_X86_REG_FP1: - case UC_X86_REG_FP2: - case UC_X86_REG_FP3: - case UC_X86_REG_FP4: - case UC_X86_REG_FP5: - case UC_X86_REG_FP6: - case UC_X86_REG_FP7: - { - floatx80 reg = env->fpregs[regid - UC_X86_REG_FP0].d; - cpu_get_fp80(value, (uint16_t*)((char*)value+sizeof(uint64_t)), reg); - } - return; - case UC_X86_REG_FPSW: - { - uint16_t fpus = env->fpus; - fpus = fpus & ~0x3800; - fpus |= ( env->fpstt & 0x7 ) << 11; - *(uint16_t*) value = fpus; - } - return; - case UC_X86_REG_FPCW: - *(uint16_t*) value = env->fpuc; - return; - case UC_X86_REG_FPTAG: - { - #define EXPD(fp) (fp.l.upper & 0x7fff) - #define MANTD(fp) (fp.l.lower) - #define MAXEXPD 0x7fff - int fptag, exp, i; - uint64_t mant; - CPU_LDoubleU tmp; - fptag = 0; - for (i = 7; i >= 0; i--) { - fptag <<= 2; - if (env->fptags[i]) { - fptag |= 3; - } else { - tmp.d = env->fpregs[i].d; - exp = EXPD(tmp); - mant = MANTD(tmp); - if (exp == 0 && mant == 0) { - /* zero */ - fptag |= 1; - } else if (exp == 0 || exp == MAXEXPD - || (mant & (1LL << 63)) == 0) { - /* NaNs, infinity, denormal */ - fptag |= 2; - } - } + switch (regid) { + default: + break; + case UC_X86_REG_FP0: + case UC_X86_REG_FP1: + case UC_X86_REG_FP2: + case UC_X86_REG_FP3: + case UC_X86_REG_FP4: + case UC_X86_REG_FP5: + case UC_X86_REG_FP6: + case UC_X86_REG_FP7: { + floatx80 reg = env->fpregs[regid - UC_X86_REG_FP0].d; + cpu_get_fp80(value, (uint16_t *)((char *)value + sizeof(uint64_t)), + reg); + } + return; + case UC_X86_REG_FPSW: { + uint16_t fpus = env->fpus; + fpus = fpus & ~0x3800; + fpus |= (env->fpstt & 0x7) << 11; + *(uint16_t *)value = fpus; + } + return; + case UC_X86_REG_FPCW: + *(uint16_t *)value = env->fpuc; + return; + case UC_X86_REG_FPTAG: { +#define EXPD(fp) (fp.l.upper & 0x7fff) +#define MANTD(fp) (fp.l.lower) +#define MAXEXPD 0x7fff + int fptag, exp, i; + uint64_t mant; + CPU_LDoubleU tmp; + fptag = 0; + for (i = 7; i >= 0; i--) { + fptag <<= 2; + if (env->fptags[i]) { + fptag |= 3; + } else { + tmp.d = env->fpregs[i].d; + exp = EXPD(tmp); + mant = MANTD(tmp); + if (exp == 0 && mant == 0) { + /* zero */ + fptag |= 1; + } else if (exp == 0 || exp == MAXEXPD || + (mant & (1LL << 63)) == 0) { + /* NaNs, infinity, denormal */ + fptag |= 2; } - *(uint16_t*) value = fptag; - } - return; - case UC_X86_REG_XMM0: - case UC_X86_REG_XMM1: - case UC_X86_REG_XMM2: - case UC_X86_REG_XMM3: - case UC_X86_REG_XMM4: - case UC_X86_REG_XMM5: - case UC_X86_REG_XMM6: - case UC_X86_REG_XMM7: - { - float64 *dst = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - dst[0] = reg->_d[0]; - dst[1] = reg->_d[1]; - return; - } - case UC_X86_REG_ST0: - case UC_X86_REG_ST1: - case UC_X86_REG_ST2: - case UC_X86_REG_ST3: - case UC_X86_REG_ST4: - case UC_X86_REG_ST5: - case UC_X86_REG_ST6: - case UC_X86_REG_ST7: - { - // value must be big enough to keep 80 bits (10 bytes) - memcpy(value, &FPST(regid - UC_X86_REG_ST0), 10); - return; - } - case UC_X86_REG_YMM0: - case UC_X86_REG_YMM1: - case UC_X86_REG_YMM2: - case UC_X86_REG_YMM3: - case UC_X86_REG_YMM4: - case UC_X86_REG_YMM5: - case UC_X86_REG_YMM6: - case UC_X86_REG_YMM7: - case UC_X86_REG_YMM8: - case UC_X86_REG_YMM9: - case UC_X86_REG_YMM10: - case UC_X86_REG_YMM11: - case UC_X86_REG_YMM12: - case UC_X86_REG_YMM13: - case UC_X86_REG_YMM14: - case UC_X86_REG_YMM15: - { - float64 *dst = (float64*)value; - XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; - XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; - dst[0] = lo_reg->_d[0]; - dst[1] = lo_reg->_d[1]; - dst[2] = hi_reg->_d[0]; - dst[3] = hi_reg->_d[1]; - return; } + } + *(uint16_t *)value = fptag; + } + return; + case UC_X86_REG_XMM0: + case UC_X86_REG_XMM1: + case UC_X86_REG_XMM2: + case UC_X86_REG_XMM3: + case UC_X86_REG_XMM4: + case UC_X86_REG_XMM5: + case UC_X86_REG_XMM6: + case UC_X86_REG_XMM7: { + float64 *dst = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + dst[0] = reg->_d[0]; + dst[1] = reg->_d[1]; + return; + } + case UC_X86_REG_ST0: + case UC_X86_REG_ST1: + case UC_X86_REG_ST2: + case UC_X86_REG_ST3: + case UC_X86_REG_ST4: + case UC_X86_REG_ST5: + case UC_X86_REG_ST6: + case UC_X86_REG_ST7: { + // value must be big enough to keep 80 bits (10 bytes) + memcpy(value, &FPST(regid - UC_X86_REG_ST0), 10); + return; + } + case UC_X86_REG_YMM0: + case UC_X86_REG_YMM1: + case UC_X86_REG_YMM2: + case UC_X86_REG_YMM3: + case UC_X86_REG_YMM4: + case UC_X86_REG_YMM5: + case UC_X86_REG_YMM6: + case UC_X86_REG_YMM7: + case UC_X86_REG_YMM8: + case UC_X86_REG_YMM9: + case UC_X86_REG_YMM10: + case UC_X86_REG_YMM11: + case UC_X86_REG_YMM12: + case UC_X86_REG_YMM13: + case UC_X86_REG_YMM14: + case UC_X86_REG_YMM15: { + float64 *dst = (float64 *)value; + XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; + XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; + dst[0] = lo_reg->_d[0]; + dst[1] = lo_reg->_d[1]; + dst[2] = hi_reg->_d[0]; + dst[3] = hi_reg->_d[1]; + return; + } } - switch(mode) { + switch (mode) { + default: + break; + case UC_MODE_16: + switch (regid) { default: break; - case UC_MODE_16: - switch(regid) { - default: break; - case UC_X86_REG_ES: - *(int16_t *)value = env->segs[R_ES].selector; - return; - case UC_X86_REG_SS: - *(int16_t *)value = env->segs[R_SS].selector; - return; - case UC_X86_REG_DS: - *(int16_t *)value = env->segs[R_DS].selector; - return; - case UC_X86_REG_FS: - *(int16_t *)value = env->segs[R_FS].selector; - return; - case UC_X86_REG_GS: - *(int16_t *)value = env->segs[R_GS].selector; - return; - case UC_X86_REG_FS_BASE: - *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; - return; - } - // fall-thru - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - *(int32_t *)value = env->cr[regid - UC_X86_REG_CR0]; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - *(int32_t *)value = env->dr[regid - UC_X86_REG_DR0]; - break; - case UC_X86_REG_FLAGS: - *(int16_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_EFLAGS: - *(int32_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_EAX: - *(int32_t *)value = env->regs[R_EAX]; - break; - case UC_X86_REG_AX: - *(int16_t *)value = READ_WORD(env->regs[R_EAX]); - break; - case UC_X86_REG_AH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); - break; - case UC_X86_REG_AL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); - break; - case UC_X86_REG_EBX: - *(int32_t *)value = env->regs[R_EBX]; - break; - case UC_X86_REG_BX: - *(int16_t *)value = READ_WORD(env->regs[R_EBX]); - break; - case UC_X86_REG_BH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); - break; - case UC_X86_REG_BL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); - break; - case UC_X86_REG_ECX: - *(int32_t *)value = env->regs[R_ECX]; - break; - case UC_X86_REG_CX: - *(int16_t *)value = READ_WORD(env->regs[R_ECX]); - break; - case UC_X86_REG_CH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); - break; - case UC_X86_REG_CL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); - break; - case UC_X86_REG_EDX: - *(int32_t *)value = env->regs[R_EDX]; - break; - case UC_X86_REG_DX: - *(int16_t *)value = READ_WORD(env->regs[R_EDX]); - break; - case UC_X86_REG_DH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); - break; - case UC_X86_REG_DL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); - break; - case UC_X86_REG_ESP: - *(int32_t *)value = env->regs[R_ESP]; - break; - case UC_X86_REG_SP: - *(int16_t *)value = READ_WORD(env->regs[R_ESP]); - break; - case UC_X86_REG_EBP: - *(int32_t *)value = env->regs[R_EBP]; - break; - case UC_X86_REG_BP: - *(int16_t *)value = READ_WORD(env->regs[R_EBP]); - break; - case UC_X86_REG_ESI: - *(int32_t *)value = env->regs[R_ESI]; - break; - case UC_X86_REG_SI: - *(int16_t *)value = READ_WORD(env->regs[R_ESI]); - break; - case UC_X86_REG_EDI: - *(int32_t *)value = env->regs[R_EDI]; - break; - case UC_X86_REG_DI: - *(int16_t *)value = READ_WORD(env->regs[R_EDI]); - break; - case UC_X86_REG_EIP: - *(int32_t *)value = env->eip; - break; - case UC_X86_REG_IP: - *(int16_t *)value = READ_WORD(env->eip); - break; - case UC_X86_REG_CS: - *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; - break; - case UC_X86_REG_DS: - *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; - break; - case UC_X86_REG_SS: - *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; - break; - case UC_X86_REG_ES: - *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; - break; - case UC_X86_REG_FS: - *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; - break; - case UC_X86_REG_GS: - *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; - break; - case UC_X86_REG_IDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->idt.base; - break; - case UC_X86_REG_GDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->gdt.base; - break; - case UC_X86_REG_LDTR: - ((uc_x86_mmr *)value)->limit = env->ldt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->ldt.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; - ((uc_x86_mmr *)value)->flags = env->ldt.flags; - break; - case UC_X86_REG_TR: - ((uc_x86_mmr *)value)->limit = env->tr.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->tr.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; - ((uc_x86_mmr *)value)->flags = env->tr.flags; - break; - case UC_X86_REG_MSR: - x86_msr_read(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - *(uint32_t *)value = env->mxcsr; - break; - case UC_X86_REG_FS_BASE: - *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; - break; - } + case UC_X86_REG_ES: + *(int16_t *)value = env->segs[R_ES].selector; + return; + case UC_X86_REG_SS: + *(int16_t *)value = env->segs[R_SS].selector; + return; + case UC_X86_REG_DS: + *(int16_t *)value = env->segs[R_DS].selector; + return; + case UC_X86_REG_FS: + *(int16_t *)value = env->segs[R_FS].selector; + return; + case UC_X86_REG_GS: + *(int16_t *)value = env->segs[R_GS].selector; + return; + case UC_X86_REG_FS_BASE: + *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; + return; + } + // fall-thru + case UC_MODE_32: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + *(int32_t *)value = env->cr[regid - UC_X86_REG_CR0]; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + *(int32_t *)value = env->dr[regid - UC_X86_REG_DR0]; + break; + case UC_X86_REG_FLAGS: + *(int16_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_EFLAGS: + *(int32_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_EAX: + *(int32_t *)value = env->regs[R_EAX]; + break; + case UC_X86_REG_AX: + *(int16_t *)value = READ_WORD(env->regs[R_EAX]); + break; + case UC_X86_REG_AH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); + break; + case UC_X86_REG_AL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); + break; + case UC_X86_REG_EBX: + *(int32_t *)value = env->regs[R_EBX]; + break; + case UC_X86_REG_BX: + *(int16_t *)value = READ_WORD(env->regs[R_EBX]); + break; + case UC_X86_REG_BH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); + break; + case UC_X86_REG_BL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); + break; + case UC_X86_REG_ECX: + *(int32_t *)value = env->regs[R_ECX]; + break; + case UC_X86_REG_CX: + *(int16_t *)value = READ_WORD(env->regs[R_ECX]); + break; + case UC_X86_REG_CH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); + break; + case UC_X86_REG_CL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); + break; + case UC_X86_REG_EDX: + *(int32_t *)value = env->regs[R_EDX]; + break; + case UC_X86_REG_DX: + *(int16_t *)value = READ_WORD(env->regs[R_EDX]); + break; + case UC_X86_REG_DH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); + break; + case UC_X86_REG_DL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); + break; + case UC_X86_REG_ESP: + *(int32_t *)value = env->regs[R_ESP]; + break; + case UC_X86_REG_SP: + *(int16_t *)value = READ_WORD(env->regs[R_ESP]); + break; + case UC_X86_REG_EBP: + *(int32_t *)value = env->regs[R_EBP]; + break; + case UC_X86_REG_BP: + *(int16_t *)value = READ_WORD(env->regs[R_EBP]); + break; + case UC_X86_REG_ESI: + *(int32_t *)value = env->regs[R_ESI]; + break; + case UC_X86_REG_SI: + *(int16_t *)value = READ_WORD(env->regs[R_ESI]); + break; + case UC_X86_REG_EDI: + *(int32_t *)value = env->regs[R_EDI]; + break; + case UC_X86_REG_DI: + *(int16_t *)value = READ_WORD(env->regs[R_EDI]); + break; + case UC_X86_REG_EIP: + *(int32_t *)value = env->eip; + break; + case UC_X86_REG_IP: + *(int16_t *)value = READ_WORD(env->eip); + break; + case UC_X86_REG_CS: + *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; + break; + case UC_X86_REG_DS: + *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; + break; + case UC_X86_REG_SS: + *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; + break; + case UC_X86_REG_ES: + *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; + break; + case UC_X86_REG_FS: + *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; + break; + case UC_X86_REG_GS: + *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; + break; + case UC_X86_REG_IDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->idt.base; + break; + case UC_X86_REG_GDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->gdt.base; + break; + case UC_X86_REG_LDTR: + ((uc_x86_mmr *)value)->limit = env->ldt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->ldt.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; + ((uc_x86_mmr *)value)->flags = env->ldt.flags; + break; + case UC_X86_REG_TR: + ((uc_x86_mmr *)value)->limit = env->tr.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->tr.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; + ((uc_x86_mmr *)value)->flags = env->tr.flags; + break; + case UC_X86_REG_MSR: + x86_msr_read(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + *(uint32_t *)value = env->mxcsr; + break; + case UC_X86_REG_FS_BASE: + *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; + break; + } + break; #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - *(int64_t *)value = env->cr[regid - UC_X86_REG_CR0]; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - *(int64_t *)value = env->dr[regid - UC_X86_REG_DR0]; - break; - case UC_X86_REG_FLAGS: - *(int16_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_EFLAGS: - *(int32_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_RFLAGS: - *(int64_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_RAX: - *(uint64_t *)value = env->regs[R_EAX]; - break; - case UC_X86_REG_EAX: - *(int32_t *)value = READ_DWORD(env->regs[R_EAX]); - break; - case UC_X86_REG_AX: - *(int16_t *)value = READ_WORD(env->regs[R_EAX]); - break; - case UC_X86_REG_AH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); - break; - case UC_X86_REG_AL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); - break; - case UC_X86_REG_RBX: - *(uint64_t *)value = env->regs[R_EBX]; - break; - case UC_X86_REG_EBX: - *(int32_t *)value = READ_DWORD(env->regs[R_EBX]); - break; - case UC_X86_REG_BX: - *(int16_t *)value = READ_WORD(env->regs[R_EBX]); - break; - case UC_X86_REG_BH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); - break; - case UC_X86_REG_BL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); - break; - case UC_X86_REG_RCX: - *(uint64_t *)value = env->regs[R_ECX]; - break; - case UC_X86_REG_ECX: - *(int32_t *)value = READ_DWORD(env->regs[R_ECX]); - break; - case UC_X86_REG_CX: - *(int16_t *)value = READ_WORD(env->regs[R_ECX]); - break; - case UC_X86_REG_CH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); - break; - case UC_X86_REG_CL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); - break; - case UC_X86_REG_RDX: - *(uint64_t *)value = env->regs[R_EDX]; - break; - case UC_X86_REG_EDX: - *(int32_t *)value = READ_DWORD(env->regs[R_EDX]); - break; - case UC_X86_REG_DX: - *(int16_t *)value = READ_WORD(env->regs[R_EDX]); - break; - case UC_X86_REG_DH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); - break; - case UC_X86_REG_DL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); - break; - case UC_X86_REG_RSP: - *(uint64_t *)value = env->regs[R_ESP]; - break; - case UC_X86_REG_ESP: - *(int32_t *)value = READ_DWORD(env->regs[R_ESP]); - break; - case UC_X86_REG_SP: - *(int16_t *)value = READ_WORD(env->regs[R_ESP]); - break; - case UC_X86_REG_SPL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ESP]); - break; - case UC_X86_REG_RBP: - *(uint64_t *)value = env->regs[R_EBP]; - break; - case UC_X86_REG_EBP: - *(int32_t *)value = READ_DWORD(env->regs[R_EBP]); - break; - case UC_X86_REG_BP: - *(int16_t *)value = READ_WORD(env->regs[R_EBP]); - break; - case UC_X86_REG_BPL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EBP]); - break; - case UC_X86_REG_RSI: - *(uint64_t *)value = env->regs[R_ESI]; - break; - case UC_X86_REG_ESI: - *(int32_t *)value = READ_DWORD(env->regs[R_ESI]); - break; - case UC_X86_REG_SI: - *(int16_t *)value = READ_WORD(env->regs[R_ESI]); - break; - case UC_X86_REG_SIL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ESI]); - break; - case UC_X86_REG_RDI: - *(uint64_t *)value = env->regs[R_EDI]; - break; - case UC_X86_REG_EDI: - *(int32_t *)value = READ_DWORD(env->regs[R_EDI]); - break; - case UC_X86_REG_DI: - *(int16_t *)value = READ_WORD(env->regs[R_EDI]); - break; - case UC_X86_REG_DIL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EDI]); - break; - case UC_X86_REG_RIP: - *(uint64_t *)value = env->eip; - break; - case UC_X86_REG_EIP: - *(int32_t *)value = READ_DWORD(env->eip); - break; - case UC_X86_REG_IP: - *(int16_t *)value = READ_WORD(env->eip); - break; - case UC_X86_REG_CS: - *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; - break; - case UC_X86_REG_DS: - *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; - break; - case UC_X86_REG_SS: - *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; - break; - case UC_X86_REG_ES: - *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; - break; - case UC_X86_REG_FS: - *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; - break; - case UC_X86_REG_GS: - *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; - break; - case UC_X86_REG_R8: - *(int64_t *)value = READ_QWORD(env->regs[8]); - break; - case UC_X86_REG_R8D: - *(int32_t *)value = READ_DWORD(env->regs[8]); - break; - case UC_X86_REG_R8W: - *(int16_t *)value = READ_WORD(env->regs[8]); - break; - case UC_X86_REG_R8B: - *(int8_t *)value = READ_BYTE_L(env->regs[8]); - break; - case UC_X86_REG_R9: - *(int64_t *)value = READ_QWORD(env->regs[9]); - break; - case UC_X86_REG_R9D: - *(int32_t *)value = READ_DWORD(env->regs[9]); - break; - case UC_X86_REG_R9W: - *(int16_t *)value = READ_WORD(env->regs[9]); - break; - case UC_X86_REG_R9B: - *(int8_t *)value = READ_BYTE_L(env->regs[9]); - break; - case UC_X86_REG_R10: - *(int64_t *)value = READ_QWORD(env->regs[10]); - break; - case UC_X86_REG_R10D: - *(int32_t *)value = READ_DWORD(env->regs[10]); - break; - case UC_X86_REG_R10W: - *(int16_t *)value = READ_WORD(env->regs[10]); - break; - case UC_X86_REG_R10B: - *(int8_t *)value = READ_BYTE_L(env->regs[10]); - break; - case UC_X86_REG_R11: - *(int64_t *)value = READ_QWORD(env->regs[11]); - break; - case UC_X86_REG_R11D: - *(int32_t *)value = READ_DWORD(env->regs[11]); - break; - case UC_X86_REG_R11W: - *(int16_t *)value = READ_WORD(env->regs[11]); - break; - case UC_X86_REG_R11B: - *(int8_t *)value = READ_BYTE_L(env->regs[11]); - break; - case UC_X86_REG_R12: - *(int64_t *)value = READ_QWORD(env->regs[12]); - break; - case UC_X86_REG_R12D: - *(int32_t *)value = READ_DWORD(env->regs[12]); - break; - case UC_X86_REG_R12W: - *(int16_t *)value = READ_WORD(env->regs[12]); - break; - case UC_X86_REG_R12B: - *(int8_t *)value = READ_BYTE_L(env->regs[12]); - break; - case UC_X86_REG_R13: - *(int64_t *)value = READ_QWORD(env->regs[13]); - break; - case UC_X86_REG_R13D: - *(int32_t *)value = READ_DWORD(env->regs[13]); - break; - case UC_X86_REG_R13W: - *(int16_t *)value = READ_WORD(env->regs[13]); - break; - case UC_X86_REG_R13B: - *(int8_t *)value = READ_BYTE_L(env->regs[13]); - break; - case UC_X86_REG_R14: - *(int64_t *)value = READ_QWORD(env->regs[14]); - break; - case UC_X86_REG_R14D: - *(int32_t *)value = READ_DWORD(env->regs[14]); - break; - case UC_X86_REG_R14W: - *(int16_t *)value = READ_WORD(env->regs[14]); - break; - case UC_X86_REG_R14B: - *(int8_t *)value = READ_BYTE_L(env->regs[14]); - break; - case UC_X86_REG_R15: - *(int64_t *)value = READ_QWORD(env->regs[15]); - break; - case UC_X86_REG_R15D: - *(int32_t *)value = READ_DWORD(env->regs[15]); - break; - case UC_X86_REG_R15W: - *(int16_t *)value = READ_WORD(env->regs[15]); - break; - case UC_X86_REG_R15B: - *(int8_t *)value = READ_BYTE_L(env->regs[15]); - break; - case UC_X86_REG_IDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; - ((uc_x86_mmr *)value)->base = env->idt.base; - break; - case UC_X86_REG_GDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; - ((uc_x86_mmr *)value)->base = env->gdt.base; - break; - case UC_X86_REG_LDTR: - ((uc_x86_mmr *)value)->limit = env->ldt.limit; - ((uc_x86_mmr *)value)->base = env->ldt.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; - ((uc_x86_mmr *)value)->flags = env->ldt.flags; - break; - case UC_X86_REG_TR: - ((uc_x86_mmr *)value)->limit = env->tr.limit; - ((uc_x86_mmr *)value)->base = env->tr.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; - ((uc_x86_mmr *)value)->flags = env->tr.flags; - break; - case UC_X86_REG_MSR: - x86_msr_read(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - *(uint32_t *)value = env->mxcsr; - break; - case UC_X86_REG_XMM8: - case UC_X86_REG_XMM9: - case UC_X86_REG_XMM10: - case UC_X86_REG_XMM11: - case UC_X86_REG_XMM12: - case UC_X86_REG_XMM13: - case UC_X86_REG_XMM14: - case UC_X86_REG_XMM15: - { - float64 *dst = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - dst[0] = reg->_d[0]; - dst[1] = reg->_d[1]; - break; - } - case UC_X86_REG_FS_BASE: - *(uint64_t *)value = (uint64_t)env->segs[R_FS].base; - break; - case UC_X86_REG_GS_BASE: - *(uint64_t *)value = (uint64_t)env->segs[R_GS].base; - break; - } + case UC_MODE_64: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + *(int64_t *)value = env->cr[regid - UC_X86_REG_CR0]; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + *(int64_t *)value = env->dr[regid - UC_X86_REG_DR0]; + break; + case UC_X86_REG_FLAGS: + *(int16_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_EFLAGS: + *(int32_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_RFLAGS: + *(int64_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_RAX: + *(uint64_t *)value = env->regs[R_EAX]; + break; + case UC_X86_REG_EAX: + *(int32_t *)value = READ_DWORD(env->regs[R_EAX]); + break; + case UC_X86_REG_AX: + *(int16_t *)value = READ_WORD(env->regs[R_EAX]); + break; + case UC_X86_REG_AH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); + break; + case UC_X86_REG_AL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); + break; + case UC_X86_REG_RBX: + *(uint64_t *)value = env->regs[R_EBX]; + break; + case UC_X86_REG_EBX: + *(int32_t *)value = READ_DWORD(env->regs[R_EBX]); + break; + case UC_X86_REG_BX: + *(int16_t *)value = READ_WORD(env->regs[R_EBX]); + break; + case UC_X86_REG_BH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); + break; + case UC_X86_REG_BL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); + break; + case UC_X86_REG_RCX: + *(uint64_t *)value = env->regs[R_ECX]; + break; + case UC_X86_REG_ECX: + *(int32_t *)value = READ_DWORD(env->regs[R_ECX]); + break; + case UC_X86_REG_CX: + *(int16_t *)value = READ_WORD(env->regs[R_ECX]); + break; + case UC_X86_REG_CH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); + break; + case UC_X86_REG_CL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); + break; + case UC_X86_REG_RDX: + *(uint64_t *)value = env->regs[R_EDX]; + break; + case UC_X86_REG_EDX: + *(int32_t *)value = READ_DWORD(env->regs[R_EDX]); + break; + case UC_X86_REG_DX: + *(int16_t *)value = READ_WORD(env->regs[R_EDX]); + break; + case UC_X86_REG_DH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); + break; + case UC_X86_REG_DL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); + break; + case UC_X86_REG_RSP: + *(uint64_t *)value = env->regs[R_ESP]; + break; + case UC_X86_REG_ESP: + *(int32_t *)value = READ_DWORD(env->regs[R_ESP]); + break; + case UC_X86_REG_SP: + *(int16_t *)value = READ_WORD(env->regs[R_ESP]); + break; + case UC_X86_REG_SPL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ESP]); + break; + case UC_X86_REG_RBP: + *(uint64_t *)value = env->regs[R_EBP]; + break; + case UC_X86_REG_EBP: + *(int32_t *)value = READ_DWORD(env->regs[R_EBP]); + break; + case UC_X86_REG_BP: + *(int16_t *)value = READ_WORD(env->regs[R_EBP]); + break; + case UC_X86_REG_BPL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EBP]); + break; + case UC_X86_REG_RSI: + *(uint64_t *)value = env->regs[R_ESI]; + break; + case UC_X86_REG_ESI: + *(int32_t *)value = READ_DWORD(env->regs[R_ESI]); + break; + case UC_X86_REG_SI: + *(int16_t *)value = READ_WORD(env->regs[R_ESI]); + break; + case UC_X86_REG_SIL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ESI]); + break; + case UC_X86_REG_RDI: + *(uint64_t *)value = env->regs[R_EDI]; + break; + case UC_X86_REG_EDI: + *(int32_t *)value = READ_DWORD(env->regs[R_EDI]); + break; + case UC_X86_REG_DI: + *(int16_t *)value = READ_WORD(env->regs[R_EDI]); + break; + case UC_X86_REG_DIL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EDI]); + break; + case UC_X86_REG_RIP: + *(uint64_t *)value = env->eip; + break; + case UC_X86_REG_EIP: + *(int32_t *)value = READ_DWORD(env->eip); + break; + case UC_X86_REG_IP: + *(int16_t *)value = READ_WORD(env->eip); + break; + case UC_X86_REG_CS: + *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; + break; + case UC_X86_REG_DS: + *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; + break; + case UC_X86_REG_SS: + *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; + break; + case UC_X86_REG_ES: + *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; + break; + case UC_X86_REG_FS: + *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; + break; + case UC_X86_REG_GS: + *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; + break; + case UC_X86_REG_R8: + *(int64_t *)value = READ_QWORD(env->regs[8]); + break; + case UC_X86_REG_R8D: + *(int32_t *)value = READ_DWORD(env->regs[8]); + break; + case UC_X86_REG_R8W: + *(int16_t *)value = READ_WORD(env->regs[8]); + break; + case UC_X86_REG_R8B: + *(int8_t *)value = READ_BYTE_L(env->regs[8]); + break; + case UC_X86_REG_R9: + *(int64_t *)value = READ_QWORD(env->regs[9]); + break; + case UC_X86_REG_R9D: + *(int32_t *)value = READ_DWORD(env->regs[9]); + break; + case UC_X86_REG_R9W: + *(int16_t *)value = READ_WORD(env->regs[9]); + break; + case UC_X86_REG_R9B: + *(int8_t *)value = READ_BYTE_L(env->regs[9]); + break; + case UC_X86_REG_R10: + *(int64_t *)value = READ_QWORD(env->regs[10]); + break; + case UC_X86_REG_R10D: + *(int32_t *)value = READ_DWORD(env->regs[10]); + break; + case UC_X86_REG_R10W: + *(int16_t *)value = READ_WORD(env->regs[10]); + break; + case UC_X86_REG_R10B: + *(int8_t *)value = READ_BYTE_L(env->regs[10]); + break; + case UC_X86_REG_R11: + *(int64_t *)value = READ_QWORD(env->regs[11]); + break; + case UC_X86_REG_R11D: + *(int32_t *)value = READ_DWORD(env->regs[11]); + break; + case UC_X86_REG_R11W: + *(int16_t *)value = READ_WORD(env->regs[11]); + break; + case UC_X86_REG_R11B: + *(int8_t *)value = READ_BYTE_L(env->regs[11]); + break; + case UC_X86_REG_R12: + *(int64_t *)value = READ_QWORD(env->regs[12]); + break; + case UC_X86_REG_R12D: + *(int32_t *)value = READ_DWORD(env->regs[12]); + break; + case UC_X86_REG_R12W: + *(int16_t *)value = READ_WORD(env->regs[12]); + break; + case UC_X86_REG_R12B: + *(int8_t *)value = READ_BYTE_L(env->regs[12]); + break; + case UC_X86_REG_R13: + *(int64_t *)value = READ_QWORD(env->regs[13]); + break; + case UC_X86_REG_R13D: + *(int32_t *)value = READ_DWORD(env->regs[13]); + break; + case UC_X86_REG_R13W: + *(int16_t *)value = READ_WORD(env->regs[13]); + break; + case UC_X86_REG_R13B: + *(int8_t *)value = READ_BYTE_L(env->regs[13]); + break; + case UC_X86_REG_R14: + *(int64_t *)value = READ_QWORD(env->regs[14]); + break; + case UC_X86_REG_R14D: + *(int32_t *)value = READ_DWORD(env->regs[14]); + break; + case UC_X86_REG_R14W: + *(int16_t *)value = READ_WORD(env->regs[14]); + break; + case UC_X86_REG_R14B: + *(int8_t *)value = READ_BYTE_L(env->regs[14]); + break; + case UC_X86_REG_R15: + *(int64_t *)value = READ_QWORD(env->regs[15]); + break; + case UC_X86_REG_R15D: + *(int32_t *)value = READ_DWORD(env->regs[15]); + break; + case UC_X86_REG_R15W: + *(int16_t *)value = READ_WORD(env->regs[15]); + break; + case UC_X86_REG_R15B: + *(int8_t *)value = READ_BYTE_L(env->regs[15]); + break; + case UC_X86_REG_IDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; + ((uc_x86_mmr *)value)->base = env->idt.base; + break; + case UC_X86_REG_GDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; + ((uc_x86_mmr *)value)->base = env->gdt.base; + break; + case UC_X86_REG_LDTR: + ((uc_x86_mmr *)value)->limit = env->ldt.limit; + ((uc_x86_mmr *)value)->base = env->ldt.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; + ((uc_x86_mmr *)value)->flags = env->ldt.flags; + break; + case UC_X86_REG_TR: + ((uc_x86_mmr *)value)->limit = env->tr.limit; + ((uc_x86_mmr *)value)->base = env->tr.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; + ((uc_x86_mmr *)value)->flags = env->tr.flags; + break; + case UC_X86_REG_MSR: + x86_msr_read(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + *(uint32_t *)value = env->mxcsr; + break; + case UC_X86_REG_XMM8: + case UC_X86_REG_XMM9: + case UC_X86_REG_XMM10: + case UC_X86_REG_XMM11: + case UC_X86_REG_XMM12: + case UC_X86_REG_XMM13: + case UC_X86_REG_XMM14: + case UC_X86_REG_XMM15: { + float64 *dst = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + dst[0] = reg->_d[0]; + dst[1] = reg->_d[1]; + break; + } + case UC_X86_REG_FS_BASE: + *(uint64_t *)value = (uint64_t)env->segs[R_FS].base; + break; + case UC_X86_REG_GS_BASE: + *(uint64_t *)value = (uint64_t)env->segs[R_GS].base; + break; + } + break; #endif } return; } -static int reg_write(CPUX86State *env, unsigned int regid, const void *value, uc_mode mode) +static int reg_write(CPUX86State *env, unsigned int regid, const void *value, + uc_mode mode) { int ret; - - switch(regid) { - default: - break; - case UC_X86_REG_FP0: - case UC_X86_REG_FP1: - case UC_X86_REG_FP2: - case UC_X86_REG_FP3: - case UC_X86_REG_FP4: - case UC_X86_REG_FP5: - case UC_X86_REG_FP6: - case UC_X86_REG_FP7: - { - uint64_t mant = *(uint64_t*) value; - uint16_t upper = *(uint16_t*) ((char*)value + sizeof(uint64_t)); - env->fpregs[regid - UC_X86_REG_FP0].d = cpu_set_fp80(mant, upper); - } - return 0; - case UC_X86_REG_FPSW: - { - uint16_t fpus = *(uint16_t*) value; - env->fpus = fpus & ~0x3800; - env->fpstt = (fpus >> 11) & 0x7; - } - return 0; - case UC_X86_REG_FPCW: - cpu_set_fpuc(env, *(uint16_t *)value); - return 0; - case UC_X86_REG_FPTAG: - { - int i; - uint16_t fptag = *(uint16_t*) value; - for (i = 0; i < 8; i++) { - env->fptags[i] = ((fptag & 3) == 3); - fptag >>= 2; - } - return 0; - } - break; - case UC_X86_REG_XMM0: - case UC_X86_REG_XMM1: - case UC_X86_REG_XMM2: - case UC_X86_REG_XMM3: - case UC_X86_REG_XMM4: - case UC_X86_REG_XMM5: - case UC_X86_REG_XMM6: - case UC_X86_REG_XMM7: - { - float64 *src = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - reg->_d[0] = src[0]; - reg->_d[1] = src[1]; - return 0; - } - case UC_X86_REG_ST0: - case UC_X86_REG_ST1: - case UC_X86_REG_ST2: - case UC_X86_REG_ST3: - case UC_X86_REG_ST4: - case UC_X86_REG_ST5: - case UC_X86_REG_ST6: - case UC_X86_REG_ST7: - { - // value must be big enough to keep 80 bits (10 bytes) - memcpy(&FPST(regid - UC_X86_REG_ST0), value, 10); - return 0; - } - case UC_X86_REG_YMM0: - case UC_X86_REG_YMM1: - case UC_X86_REG_YMM2: - case UC_X86_REG_YMM3: - case UC_X86_REG_YMM4: - case UC_X86_REG_YMM5: - case UC_X86_REG_YMM6: - case UC_X86_REG_YMM7: - case UC_X86_REG_YMM8: - case UC_X86_REG_YMM9: - case UC_X86_REG_YMM10: - case UC_X86_REG_YMM11: - case UC_X86_REG_YMM12: - case UC_X86_REG_YMM13: - case UC_X86_REG_YMM14: - case UC_X86_REG_YMM15: - { - float64 *src = (float64*)value; - XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; - XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; - lo_reg->_d[0] = src[0]; - lo_reg->_d[1] = src[1]; - hi_reg->_d[0] = src[2]; - hi_reg->_d[1] = src[3]; - return 0; - } + switch (regid) { + default: + break; + case UC_X86_REG_FP0: + case UC_X86_REG_FP1: + case UC_X86_REG_FP2: + case UC_X86_REG_FP3: + case UC_X86_REG_FP4: + case UC_X86_REG_FP5: + case UC_X86_REG_FP6: + case UC_X86_REG_FP7: { + uint64_t mant = *(uint64_t *)value; + uint16_t upper = *(uint16_t *)((char *)value + sizeof(uint64_t)); + env->fpregs[regid - UC_X86_REG_FP0].d = cpu_set_fp80(mant, upper); + } + return 0; + case UC_X86_REG_FPSW: { + uint16_t fpus = *(uint16_t *)value; + env->fpus = fpus & ~0x3800; + env->fpstt = (fpus >> 11) & 0x7; + } + return 0; + case UC_X86_REG_FPCW: + cpu_set_fpuc(env, *(uint16_t *)value); + return 0; + case UC_X86_REG_FPTAG: { + int i; + uint16_t fptag = *(uint16_t *)value; + for (i = 0; i < 8; i++) { + env->fptags[i] = ((fptag & 3) == 3); + fptag >>= 2; + } + + return 0; + } break; + case UC_X86_REG_XMM0: + case UC_X86_REG_XMM1: + case UC_X86_REG_XMM2: + case UC_X86_REG_XMM3: + case UC_X86_REG_XMM4: + case UC_X86_REG_XMM5: + case UC_X86_REG_XMM6: + case UC_X86_REG_XMM7: { + float64 *src = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + reg->_d[0] = src[0]; + reg->_d[1] = src[1]; + return 0; + } + case UC_X86_REG_ST0: + case UC_X86_REG_ST1: + case UC_X86_REG_ST2: + case UC_X86_REG_ST3: + case UC_X86_REG_ST4: + case UC_X86_REG_ST5: + case UC_X86_REG_ST6: + case UC_X86_REG_ST7: { + // value must be big enough to keep 80 bits (10 bytes) + memcpy(&FPST(regid - UC_X86_REG_ST0), value, 10); + return 0; + } + case UC_X86_REG_YMM0: + case UC_X86_REG_YMM1: + case UC_X86_REG_YMM2: + case UC_X86_REG_YMM3: + case UC_X86_REG_YMM4: + case UC_X86_REG_YMM5: + case UC_X86_REG_YMM6: + case UC_X86_REG_YMM7: + case UC_X86_REG_YMM8: + case UC_X86_REG_YMM9: + case UC_X86_REG_YMM10: + case UC_X86_REG_YMM11: + case UC_X86_REG_YMM12: + case UC_X86_REG_YMM13: + case UC_X86_REG_YMM14: + case UC_X86_REG_YMM15: { + float64 *src = (float64 *)value; + XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; + XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; + lo_reg->_d[0] = src[0]; + lo_reg->_d[1] = src[1]; + hi_reg->_d[0] = src[2]; + hi_reg->_d[1] = src[3]; + return 0; + } } - switch(mode) { + switch (mode) { + default: + break; + + case UC_MODE_16: + switch (regid) { default: break; - - case UC_MODE_16: - switch(regid) { - default: break; - case UC_X86_REG_ES: - load_seg_16_helper(env, R_ES, *(uint16_t *)value); - return 0; - case UC_X86_REG_SS: - load_seg_16_helper(env, R_SS, *(uint16_t *)value); - return 0; - case UC_X86_REG_DS: - load_seg_16_helper(env, R_DS, *(uint16_t *)value); - return 0; - case UC_X86_REG_FS: - load_seg_16_helper(env, R_FS, *(uint16_t *)value); - return 0; - case UC_X86_REG_GS: - load_seg_16_helper(env, R_GS, *(uint16_t *)value); - return 0; - } - // fall-thru - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - env->cr[regid - UC_X86_REG_CR0] = *(uint32_t *)value; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - env->dr[regid - UC_X86_REG_DR0] = *(uint32_t *)value; - break; - case UC_X86_REG_FLAGS: - cpu_load_eflags(env, *(uint16_t*)value, -1); - break; - case UC_X86_REG_EFLAGS: - cpu_load_eflags(env, *(uint32_t *)value, -1); - break; - case UC_X86_REG_EAX: - env->regs[R_EAX] = *(uint32_t *)value; - break; - case UC_X86_REG_AX: - WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); - break; - case UC_X86_REG_AH: - WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_AL: - WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_EBX: - env->regs[R_EBX] = *(uint32_t *)value; - break; - case UC_X86_REG_BX: - WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); - break; - case UC_X86_REG_BH: - WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_BL: - WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_ECX: - env->regs[R_ECX] = *(uint32_t *)value; - break; - case UC_X86_REG_CX: - WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); - break; - case UC_X86_REG_CH: - WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_CL: - WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_EDX: - env->regs[R_EDX] = *(uint32_t *)value; - break; - case UC_X86_REG_DX: - WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); - break; - case UC_X86_REG_DH: - WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_DL: - WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_ESP: - env->regs[R_ESP] = *(uint32_t *)value; - break; - case UC_X86_REG_SP: - WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); - break; - case UC_X86_REG_EBP: - env->regs[R_EBP] = *(uint32_t *)value; - break; - case UC_X86_REG_BP: - WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); - break; - case UC_X86_REG_ESI: - env->regs[R_ESI] = *(uint32_t *)value; - break; - case UC_X86_REG_SI: - WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); - break; - case UC_X86_REG_EDI: - env->regs[R_EDI] = *(uint32_t *)value; - break; - case UC_X86_REG_DI: - WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); - break; - case UC_X86_REG_EIP: - env->eip = *(uint32_t *)value; - break; - case UC_X86_REG_IP: - env->eip = *(uint16_t *)value; - break; - case UC_X86_REG_CS: - ret = uc_check_cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); - break; - case UC_X86_REG_DS: - ret = uc_check_cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); - break; - case UC_X86_REG_SS: - ret = uc_check_cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); - break; - case UC_X86_REG_ES: - ret = uc_check_cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); - break; - case UC_X86_REG_FS: - ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - break; - case UC_X86_REG_GS: - ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - break; - case UC_X86_REG_IDTR: - env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->idt.base = (uint32_t)((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_GDTR: - env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->gdt.base = (uint32_t)((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_LDTR: - env->ldt.limit = ((uc_x86_mmr *)value)->limit; - env->ldt.base = (uint32_t)((uc_x86_mmr *)value)->base; - env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->ldt.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_TR: - env->tr.limit = ((uc_x86_mmr *)value)->limit; - env->tr.base = (uint32_t)((uc_x86_mmr *)value)->base; - env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->tr.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_MSR: - x86_msr_write(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - cpu_set_mxcsr(env, *(uint32_t *)value); - break; - /* - // Don't think base registers are a "thing" on x86 - case UC_X86_REG_FS_BASE: - env->segs[R_FS].base = *(uint32_t *)value; - continue; - case UC_X86_REG_GS_BASE: - env->segs[R_GS].base = *(uint32_t *)value; - continue; - */ - } + case UC_X86_REG_ES: + load_seg_16_helper(env, R_ES, *(uint16_t *)value); + return 0; + case UC_X86_REG_SS: + load_seg_16_helper(env, R_SS, *(uint16_t *)value); + return 0; + case UC_X86_REG_DS: + load_seg_16_helper(env, R_DS, *(uint16_t *)value); + return 0; + case UC_X86_REG_FS: + load_seg_16_helper(env, R_FS, *(uint16_t *)value); + return 0; + case UC_X86_REG_GS: + load_seg_16_helper(env, R_GS, *(uint16_t *)value); + return 0; + } + // fall-thru + case UC_MODE_32: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + env->cr[regid - UC_X86_REG_CR0] = *(uint32_t *)value; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + env->dr[regid - UC_X86_REG_DR0] = *(uint32_t *)value; + break; + case UC_X86_REG_FLAGS: + cpu_load_eflags(env, *(uint16_t *)value, -1); + break; + case UC_X86_REG_EFLAGS: + cpu_load_eflags(env, *(uint32_t *)value, -1); + break; + case UC_X86_REG_EAX: + env->regs[R_EAX] = *(uint32_t *)value; + break; + case UC_X86_REG_AX: + WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); + break; + case UC_X86_REG_AH: + WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_AL: + WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_EBX: + env->regs[R_EBX] = *(uint32_t *)value; + break; + case UC_X86_REG_BX: + WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); + break; + case UC_X86_REG_BH: + WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_BL: + WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_ECX: + env->regs[R_ECX] = *(uint32_t *)value; + break; + case UC_X86_REG_CX: + WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); + break; + case UC_X86_REG_CH: + WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_CL: + WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_EDX: + env->regs[R_EDX] = *(uint32_t *)value; + break; + case UC_X86_REG_DX: + WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); + break; + case UC_X86_REG_DH: + WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_DL: + WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_ESP: + env->regs[R_ESP] = *(uint32_t *)value; + break; + case UC_X86_REG_SP: + WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); + break; + case UC_X86_REG_EBP: + env->regs[R_EBP] = *(uint32_t *)value; + break; + case UC_X86_REG_BP: + WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); + break; + case UC_X86_REG_ESI: + env->regs[R_ESI] = *(uint32_t *)value; + break; + case UC_X86_REG_SI: + WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); + break; + case UC_X86_REG_EDI: + env->regs[R_EDI] = *(uint32_t *)value; + break; + case UC_X86_REG_DI: + WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); + break; + case UC_X86_REG_EIP: + env->eip = *(uint32_t *)value; + break; + case UC_X86_REG_IP: + env->eip = *(uint16_t *)value; + break; + case UC_X86_REG_CS: + ret = uc_check_cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); + break; + case UC_X86_REG_DS: + ret = uc_check_cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); + break; + case UC_X86_REG_SS: + ret = uc_check_cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); + break; + case UC_X86_REG_ES: + ret = uc_check_cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); + break; + case UC_X86_REG_FS: + ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + break; + case UC_X86_REG_GS: + ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + break; + case UC_X86_REG_IDTR: + env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->idt.base = (uint32_t)((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_GDTR: + env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->gdt.base = (uint32_t)((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_LDTR: + env->ldt.limit = ((uc_x86_mmr *)value)->limit; + env->ldt.base = (uint32_t)((uc_x86_mmr *)value)->base; + env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->ldt.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_TR: + env->tr.limit = ((uc_x86_mmr *)value)->limit; + env->tr.base = (uint32_t)((uc_x86_mmr *)value)->base; + env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->tr.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_MSR: + x86_msr_write(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + cpu_set_mxcsr(env, *(uint32_t *)value); + break; + /* + // Don't think base registers are a "thing" on x86 + case UC_X86_REG_FS_BASE: + env->segs[R_FS].base = *(uint32_t *)value; + continue; + case UC_X86_REG_GS_BASE: + env->segs[R_GS].base = *(uint32_t *)value; + continue; + */ + } + break; #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - env->cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - env->dr[regid - UC_X86_REG_DR0] = *(uint64_t *)value; - break; - case UC_X86_REG_FLAGS: - cpu_load_eflags(env, *(uint16_t*)value, -1); - break; - case UC_X86_REG_EFLAGS: - cpu_load_eflags(env, *(uint32_t *)value, -1); - break; - case UC_X86_REG_RFLAGS: - cpu_load_eflags(env, *(uint64_t *)value, -1); - break; - case UC_X86_REG_RAX: - env->regs[R_EAX] = *(uint64_t *)value; - break; - case UC_X86_REG_EAX: - WRITE_DWORD(env->regs[R_EAX], *(uint32_t *)value); - break; - case UC_X86_REG_AX: - WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); - break; - case UC_X86_REG_AH: - WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_AL: - WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_RBX: - env->regs[R_EBX] = *(uint64_t *)value; - break; - case UC_X86_REG_EBX: - WRITE_DWORD(env->regs[R_EBX], *(uint32_t *)value); - break; - case UC_X86_REG_BX: - WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); - break; - case UC_X86_REG_BH: - WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_BL: - WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_RCX: - env->regs[R_ECX] = *(uint64_t *)value; - break; - case UC_X86_REG_ECX: - WRITE_DWORD(env->regs[R_ECX], *(uint32_t *)value); - break; - case UC_X86_REG_CX: - WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); - break; - case UC_X86_REG_CH: - WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_CL: - WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_RDX: - env->regs[R_EDX] = *(uint64_t *)value; - break; - case UC_X86_REG_EDX: - WRITE_DWORD(env->regs[R_EDX], *(uint32_t *)value); - break; - case UC_X86_REG_DX: - WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); - break; - case UC_X86_REG_DH: - WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_DL: - WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_RSP: - env->regs[R_ESP] = *(uint64_t *)value; - break; - case UC_X86_REG_ESP: - WRITE_DWORD(env->regs[R_ESP], *(uint32_t *)value); - break; - case UC_X86_REG_SP: - WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); - break; - case UC_X86_REG_SPL: - WRITE_BYTE_L(env->regs[R_ESP], *(uint8_t *)value); - break; - case UC_X86_REG_RBP: - env->regs[R_EBP] = *(uint64_t *)value; - break; - case UC_X86_REG_EBP: - WRITE_DWORD(env->regs[R_EBP], *(uint32_t *)value); - break; - case UC_X86_REG_BP: - WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); - break; - case UC_X86_REG_BPL: - WRITE_BYTE_L(env->regs[R_EBP], *(uint8_t *)value); - break; - case UC_X86_REG_RSI: - env->regs[R_ESI] = *(uint64_t *)value; - break; - case UC_X86_REG_ESI: - WRITE_DWORD(env->regs[R_ESI], *(uint32_t *)value); - break; - case UC_X86_REG_SI: - WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); - break; - case UC_X86_REG_SIL: - WRITE_BYTE_L(env->regs[R_ESI], *(uint8_t *)value); - break; - case UC_X86_REG_RDI: - env->regs[R_EDI] = *(uint64_t *)value; - break; - case UC_X86_REG_EDI: - WRITE_DWORD(env->regs[R_EDI], *(uint32_t *)value); - break; - case UC_X86_REG_DI: - WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); - break; - case UC_X86_REG_DIL: - WRITE_BYTE_L(env->regs[R_EDI], *(uint8_t *)value); - break; - case UC_X86_REG_RIP: - env->eip = *(uint64_t *)value; - break; - case UC_X86_REG_EIP: - env->eip = *(uint32_t *)value; - break; - case UC_X86_REG_IP: - WRITE_WORD(env->eip, *(uint16_t *)value); - break; - case UC_X86_REG_CS: - env->segs[R_CS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_DS: - env->segs[R_DS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_SS: - env->segs[R_SS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_ES: - env->segs[R_ES].selector = *(uint16_t *)value; - break; - case UC_X86_REG_FS: - ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - break; - case UC_X86_REG_GS: - ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - break; - case UC_X86_REG_R8: - env->regs[8] = *(uint64_t *)value; - break; - case UC_X86_REG_R8D: - WRITE_DWORD(env->regs[8], *(uint32_t *)value); - break; - case UC_X86_REG_R8W: - WRITE_WORD(env->regs[8], *(uint16_t *)value); - break; - case UC_X86_REG_R8B: - WRITE_BYTE_L(env->regs[8], *(uint8_t *)value); - break; - case UC_X86_REG_R9: - env->regs[9] = *(uint64_t *)value; - break; - case UC_X86_REG_R9D: - WRITE_DWORD(env->regs[9], *(uint32_t *)value); - break; - case UC_X86_REG_R9W: - WRITE_WORD(env->regs[9], *(uint16_t *)value); - break; - case UC_X86_REG_R9B: - WRITE_BYTE_L(env->regs[9], *(uint8_t *)value); - break; - case UC_X86_REG_R10: - env->regs[10] = *(uint64_t *)value; - break; - case UC_X86_REG_R10D: - WRITE_DWORD(env->regs[10], *(uint32_t *)value); - break; - case UC_X86_REG_R10W: - WRITE_WORD(env->regs[10], *(uint16_t *)value); - break; - case UC_X86_REG_R10B: - WRITE_BYTE_L(env->regs[10], *(uint8_t *)value); - break; - case UC_X86_REG_R11: - env->regs[11] = *(uint64_t *)value; - break; - case UC_X86_REG_R11D: - WRITE_DWORD(env->regs[11], *(uint32_t *)value); - break; - case UC_X86_REG_R11W: - WRITE_WORD(env->regs[11], *(uint16_t *)value); - break; - case UC_X86_REG_R11B: - WRITE_BYTE_L(env->regs[11], *(uint8_t *)value); - break; - case UC_X86_REG_R12: - env->regs[12] = *(uint64_t *)value; - break; - case UC_X86_REG_R12D: - WRITE_DWORD(env->regs[12], *(uint32_t *)value); - break; - case UC_X86_REG_R12W: - WRITE_WORD(env->regs[12], *(uint16_t *)value); - break; - case UC_X86_REG_R12B: - WRITE_BYTE_L(env->regs[12], *(uint8_t *)value); - break; - case UC_X86_REG_R13: - env->regs[13] = *(uint64_t *)value; - break; - case UC_X86_REG_R13D: - WRITE_DWORD(env->regs[13], *(uint32_t *)value); - break; - case UC_X86_REG_R13W: - WRITE_WORD(env->regs[13], *(uint16_t *)value); - break; - case UC_X86_REG_R13B: - WRITE_BYTE_L(env->regs[13], *(uint8_t *)value); - break; - case UC_X86_REG_R14: - env->regs[14] = *(uint64_t *)value; - break; - case UC_X86_REG_R14D: - WRITE_DWORD(env->regs[14], *(uint32_t *)value); - break; - case UC_X86_REG_R14W: - WRITE_WORD(env->regs[14], *(uint16_t *)value); - break; - case UC_X86_REG_R14B: - WRITE_BYTE_L(env->regs[14], *(uint8_t *)value); - break; - case UC_X86_REG_R15: - env->regs[15] = *(uint64_t *)value; - break; - case UC_X86_REG_R15D: - WRITE_DWORD(env->regs[15], *(uint32_t *)value); - break; - case UC_X86_REG_R15W: - WRITE_WORD(env->regs[15], *(uint16_t *)value); - break; - case UC_X86_REG_R15B: - WRITE_BYTE_L(env->regs[15], *(uint8_t *)value); - break; - case UC_X86_REG_IDTR: - env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->idt.base = ((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_GDTR: - env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->gdt.base = ((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_LDTR: - env->ldt.limit = ((uc_x86_mmr *)value)->limit; - env->ldt.base = ((uc_x86_mmr *)value)->base; - env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->ldt.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_TR: - env->tr.limit = ((uc_x86_mmr *)value)->limit; - env->tr.base = ((uc_x86_mmr *)value)->base; - env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->tr.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_MSR: - x86_msr_write(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - cpu_set_mxcsr(env, *(uint32_t *)value); - break; - case UC_X86_REG_XMM8: - case UC_X86_REG_XMM9: - case UC_X86_REG_XMM10: - case UC_X86_REG_XMM11: - case UC_X86_REG_XMM12: - case UC_X86_REG_XMM13: - case UC_X86_REG_XMM14: - case UC_X86_REG_XMM15: - { - float64 *src = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - reg->_d[0] = src[0]; - reg->_d[1] = src[1]; - break; - } - case UC_X86_REG_FS_BASE: - env->segs[R_FS].base = *(uint64_t *)value; - return 0; - case UC_X86_REG_GS_BASE: - env->segs[R_GS].base = *(uint64_t *)value; - return 0; - } + case UC_MODE_64: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + env->cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + env->dr[regid - UC_X86_REG_DR0] = *(uint64_t *)value; + break; + case UC_X86_REG_FLAGS: + cpu_load_eflags(env, *(uint16_t *)value, -1); + break; + case UC_X86_REG_EFLAGS: + cpu_load_eflags(env, *(uint32_t *)value, -1); + break; + case UC_X86_REG_RFLAGS: + cpu_load_eflags(env, *(uint64_t *)value, -1); + break; + case UC_X86_REG_RAX: + env->regs[R_EAX] = *(uint64_t *)value; + break; + case UC_X86_REG_EAX: + WRITE_DWORD(env->regs[R_EAX], *(uint32_t *)value); + break; + case UC_X86_REG_AX: + WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); + break; + case UC_X86_REG_AH: + WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_AL: + WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_RBX: + env->regs[R_EBX] = *(uint64_t *)value; + break; + case UC_X86_REG_EBX: + WRITE_DWORD(env->regs[R_EBX], *(uint32_t *)value); + break; + case UC_X86_REG_BX: + WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); + break; + case UC_X86_REG_BH: + WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_BL: + WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_RCX: + env->regs[R_ECX] = *(uint64_t *)value; + break; + case UC_X86_REG_ECX: + WRITE_DWORD(env->regs[R_ECX], *(uint32_t *)value); + break; + case UC_X86_REG_CX: + WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); + break; + case UC_X86_REG_CH: + WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_CL: + WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_RDX: + env->regs[R_EDX] = *(uint64_t *)value; + break; + case UC_X86_REG_EDX: + WRITE_DWORD(env->regs[R_EDX], *(uint32_t *)value); + break; + case UC_X86_REG_DX: + WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); + break; + case UC_X86_REG_DH: + WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_DL: + WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_RSP: + env->regs[R_ESP] = *(uint64_t *)value; + break; + case UC_X86_REG_ESP: + WRITE_DWORD(env->regs[R_ESP], *(uint32_t *)value); + break; + case UC_X86_REG_SP: + WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); + break; + case UC_X86_REG_SPL: + WRITE_BYTE_L(env->regs[R_ESP], *(uint8_t *)value); + break; + case UC_X86_REG_RBP: + env->regs[R_EBP] = *(uint64_t *)value; + break; + case UC_X86_REG_EBP: + WRITE_DWORD(env->regs[R_EBP], *(uint32_t *)value); + break; + case UC_X86_REG_BP: + WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); + break; + case UC_X86_REG_BPL: + WRITE_BYTE_L(env->regs[R_EBP], *(uint8_t *)value); + break; + case UC_X86_REG_RSI: + env->regs[R_ESI] = *(uint64_t *)value; + break; + case UC_X86_REG_ESI: + WRITE_DWORD(env->regs[R_ESI], *(uint32_t *)value); + break; + case UC_X86_REG_SI: + WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); + break; + case UC_X86_REG_SIL: + WRITE_BYTE_L(env->regs[R_ESI], *(uint8_t *)value); + break; + case UC_X86_REG_RDI: + env->regs[R_EDI] = *(uint64_t *)value; + break; + case UC_X86_REG_EDI: + WRITE_DWORD(env->regs[R_EDI], *(uint32_t *)value); + break; + case UC_X86_REG_DI: + WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); + break; + case UC_X86_REG_DIL: + WRITE_BYTE_L(env->regs[R_EDI], *(uint8_t *)value); + break; + case UC_X86_REG_RIP: + env->eip = *(uint64_t *)value; + break; + case UC_X86_REG_EIP: + env->eip = *(uint32_t *)value; + break; + case UC_X86_REG_IP: + WRITE_WORD(env->eip, *(uint16_t *)value); + break; + case UC_X86_REG_CS: + env->segs[R_CS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_DS: + env->segs[R_DS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_SS: + env->segs[R_SS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_ES: + env->segs[R_ES].selector = *(uint16_t *)value; + break; + case UC_X86_REG_FS: + ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + break; + case UC_X86_REG_GS: + ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + break; + case UC_X86_REG_R8: + env->regs[8] = *(uint64_t *)value; + break; + case UC_X86_REG_R8D: + WRITE_DWORD(env->regs[8], *(uint32_t *)value); + break; + case UC_X86_REG_R8W: + WRITE_WORD(env->regs[8], *(uint16_t *)value); + break; + case UC_X86_REG_R8B: + WRITE_BYTE_L(env->regs[8], *(uint8_t *)value); + break; + case UC_X86_REG_R9: + env->regs[9] = *(uint64_t *)value; + break; + case UC_X86_REG_R9D: + WRITE_DWORD(env->regs[9], *(uint32_t *)value); + break; + case UC_X86_REG_R9W: + WRITE_WORD(env->regs[9], *(uint16_t *)value); + break; + case UC_X86_REG_R9B: + WRITE_BYTE_L(env->regs[9], *(uint8_t *)value); + break; + case UC_X86_REG_R10: + env->regs[10] = *(uint64_t *)value; + break; + case UC_X86_REG_R10D: + WRITE_DWORD(env->regs[10], *(uint32_t *)value); + break; + case UC_X86_REG_R10W: + WRITE_WORD(env->regs[10], *(uint16_t *)value); + break; + case UC_X86_REG_R10B: + WRITE_BYTE_L(env->regs[10], *(uint8_t *)value); + break; + case UC_X86_REG_R11: + env->regs[11] = *(uint64_t *)value; + break; + case UC_X86_REG_R11D: + WRITE_DWORD(env->regs[11], *(uint32_t *)value); + break; + case UC_X86_REG_R11W: + WRITE_WORD(env->regs[11], *(uint16_t *)value); + break; + case UC_X86_REG_R11B: + WRITE_BYTE_L(env->regs[11], *(uint8_t *)value); + break; + case UC_X86_REG_R12: + env->regs[12] = *(uint64_t *)value; + break; + case UC_X86_REG_R12D: + WRITE_DWORD(env->regs[12], *(uint32_t *)value); + break; + case UC_X86_REG_R12W: + WRITE_WORD(env->regs[12], *(uint16_t *)value); + break; + case UC_X86_REG_R12B: + WRITE_BYTE_L(env->regs[12], *(uint8_t *)value); + break; + case UC_X86_REG_R13: + env->regs[13] = *(uint64_t *)value; + break; + case UC_X86_REG_R13D: + WRITE_DWORD(env->regs[13], *(uint32_t *)value); + break; + case UC_X86_REG_R13W: + WRITE_WORD(env->regs[13], *(uint16_t *)value); + break; + case UC_X86_REG_R13B: + WRITE_BYTE_L(env->regs[13], *(uint8_t *)value); + break; + case UC_X86_REG_R14: + env->regs[14] = *(uint64_t *)value; + break; + case UC_X86_REG_R14D: + WRITE_DWORD(env->regs[14], *(uint32_t *)value); + break; + case UC_X86_REG_R14W: + WRITE_WORD(env->regs[14], *(uint16_t *)value); + break; + case UC_X86_REG_R14B: + WRITE_BYTE_L(env->regs[14], *(uint8_t *)value); + break; + case UC_X86_REG_R15: + env->regs[15] = *(uint64_t *)value; + break; + case UC_X86_REG_R15D: + WRITE_DWORD(env->regs[15], *(uint32_t *)value); + break; + case UC_X86_REG_R15W: + WRITE_WORD(env->regs[15], *(uint16_t *)value); + break; + case UC_X86_REG_R15B: + WRITE_BYTE_L(env->regs[15], *(uint8_t *)value); + break; + case UC_X86_REG_IDTR: + env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->idt.base = ((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_GDTR: + env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->gdt.base = ((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_LDTR: + env->ldt.limit = ((uc_x86_mmr *)value)->limit; + env->ldt.base = ((uc_x86_mmr *)value)->base; + env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->ldt.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_TR: + env->tr.limit = ((uc_x86_mmr *)value)->limit; + env->tr.base = ((uc_x86_mmr *)value)->base; + env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->tr.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_MSR: + x86_msr_write(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + cpu_set_mxcsr(env, *(uint32_t *)value); + break; + case UC_X86_REG_XMM8: + case UC_X86_REG_XMM9: + case UC_X86_REG_XMM10: + case UC_X86_REG_XMM11: + case UC_X86_REG_XMM12: + case UC_X86_REG_XMM13: + case UC_X86_REG_XMM14: + case UC_X86_REG_XMM15: { + float64 *src = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + reg->_d[0] = src[0]; + reg->_d[1] = src[1]; + break; + } + case UC_X86_REG_FS_BASE: + env->segs[R_FS].base = *(uint64_t *)value; + return 0; + case UC_X86_REG_GS_BASE: + env->segs[R_GS].base = *(uint64_t *)value; + return 0; + } + break; #endif } return 0; } -int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUX86State *env = &(X86_CPU(uc->cpu)->env); int i; @@ -1466,9 +1463,10 @@ int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun return 0; } -int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { - CPUX86State* env = &(X86_CPU(uc->cpu)->env); + CPUX86State *env = &(X86_CPU(uc->cpu)->env); int i; int ret; @@ -1476,37 +1474,37 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i unsigned int regid = regs[i]; const void *value = vals[i]; ret = reg_write(env, regid, value, uc->mode); - if (ret){ + if (ret) { return ret; } - switch(uc->mode) { + switch (uc->mode) { + default: + break; + case UC_MODE_32: + switch (regid) { default: break; - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_EIP: - case UC_X86_REG_IP: - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - } + case UC_X86_REG_EIP: + case UC_X86_REG_IP: + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + } #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_RIP: - case UC_X86_REG_EIP: - case UC_X86_REG_IP: - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - } + case UC_MODE_64: + switch (regid) { + default: + break; + case UC_X86_REG_RIP: + case UC_X86_REG_EIP: + case UC_X86_REG_IP: + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + } #endif } } @@ -1515,7 +1513,8 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i } DEFAULT_VISIBILITY -int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) { CPUX86State *env = (CPUX86State *)ctx->data; int i; @@ -1530,7 +1529,8 @@ int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals } DEFAULT_VISIBILITY -int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) { CPUX86State *env = (CPUX86State *)ctx->data; int i; @@ -1540,7 +1540,7 @@ int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *cons unsigned int regid = regs[i]; const void *value = vals[i]; ret = reg_write(env, regid, value, ctx->mode); - if (ret){ + if (ret) { return ret; } } @@ -1550,22 +1550,20 @@ int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *cons static bool x86_stop_interrupt(struct uc_struct *uc, int intno) { - switch(intno) { - default: - return false; - case EXCP06_ILLOP: - return true; + switch (intno) { + default: + return false; + case EXCP06_ILLOP: + return true; } } static bool x86_insn_hook_validate(uint32_t insn_enum) { - //for x86 we can only hook IN, OUT, and SYSCALL - if (insn_enum != UC_X86_INS_IN - && insn_enum != UC_X86_INS_OUT - && insn_enum != UC_X86_INS_SYSCALL - && insn_enum != UC_X86_INS_SYSENTER - && insn_enum != UC_X86_INS_CPUID) { + // for x86 we can only hook IN, OUT, and SYSCALL + if (insn_enum != UC_X86_INS_IN && insn_enum != UC_X86_INS_OUT && + insn_enum != UC_X86_INS_SYSCALL && insn_enum != UC_X86_INS_SYSENTER && + insn_enum != UC_X86_INS_CPUID) { return false; } return true; @@ -1585,7 +1583,7 @@ static int x86_cpus_init(struct uc_struct *uc, const char *cpu_model) } DEFAULT_VISIBILITY -void x86_uc_init(struct uc_struct* uc) +void x86_uc_init(struct uc_struct *uc) { uc->reg_read = x86_reg_read; uc->reg_write = x86_reg_write; diff --git a/qemu/target/i386/unicorn.h b/qemu/target/i386/unicorn.h index b07be9d2..7c456cfb 100644 --- a/qemu/target/i386/unicorn.h +++ b/qemu/target/i386/unicorn.h @@ -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 diff --git a/qemu/target/m68k/unicorn.c b/qemu/target/m68k/unicorn.c index 1b9c5b14..72ce6ce5 100644 --- a/qemu/target/m68k/unicorn.c +++ b/qemu/target/m68k/unicorn.c @@ -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; diff --git a/qemu/target/m68k/unicorn.h b/qemu/target/m68k/unicorn.h index 2eeeaae8..ebd5c310 100644 --- a/qemu/target/m68k/unicorn.h +++ b/qemu/target/m68k/unicorn.h @@ -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 diff --git a/qemu/target/mips/unicorn.c b/qemu/target/mips/unicorn.c index 2c9dae5f..c2840828 100644 --- a/qemu/target/mips/unicorn.c +++ b/qemu/target/mips/unicorn.c @@ -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 { diff --git a/qemu/target/mips/unicorn.h b/qemu/target/mips/unicorn.h index 6179a3c3..5a806522 100644 --- a/qemu/target/mips/unicorn.h +++ b/qemu/target/mips/unicorn.h @@ -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 diff --git a/qemu/target/ppc/unicorn.c b/qemu/target/ppc/unicorn.c index 66b7da7d..99438c27 100644 --- a/qemu/target/ppc/unicorn.c +++ b/qemu/target/ppc/unicorn.c @@ -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; diff --git a/qemu/target/ppc/unicorn.h b/qemu/target/ppc/unicorn.h index ef3bcf6e..2afaa3a0 100644 --- a/qemu/target/ppc/unicorn.h +++ b/qemu/target/ppc/unicorn.h @@ -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 diff --git a/qemu/target/riscv/unicorn.c b/qemu/target/riscv/unicorn.c index 4bf9f2b7..c66a5c9a 100644 --- a/qemu/target/riscv/unicorn.c +++ b/qemu/target/riscv/unicorn.c @@ -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; diff --git a/qemu/target/riscv/unicorn.h b/qemu/target/riscv/unicorn.h index 58371737..6add9369 100644 --- a/qemu/target/riscv/unicorn.h +++ b/qemu/target/riscv/unicorn.h @@ -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 diff --git a/qemu/target/sparc/unicorn.c b/qemu/target/sparc/unicorn.c index aad52ebb..4733ac99 100644 --- a/qemu/target/sparc/unicorn.c +++ b/qemu/target/sparc/unicorn.c @@ -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; diff --git a/qemu/target/sparc/unicorn.h b/qemu/target/sparc/unicorn.h index 2e90e0e3..1f9818aa 100644 --- a/qemu/target/sparc/unicorn.h +++ b/qemu/target/sparc/unicorn.h @@ -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 diff --git a/samples/mem_apis.c b/samples/mem_apis.c index 767e6aec..57756f3c 100644 --- a/samples/mem_apis.c +++ b/samples/mem_apis.c @@ -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 #include #include #include #include - 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); } diff --git a/samples/sample_arm.c b/samples/sample_arm.c index bda2d0b0..ac25e598 100644 --- a/samples/sample_arm.c +++ b/samples/sample_arm.c @@ -6,29 +6,37 @@ #include #include - // 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); diff --git a/samples/sample_arm64.c b/samples/sample_arm64.c index 74ea4e05..16db549f 100644 --- a/samples/sample_arm64.c +++ b/samples/sample_arm64.c @@ -6,48 +6,53 @@ #include #include - // 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(); diff --git a/samples/sample_batch_reg.c b/samples/sample_batch_reg.c index b1b51b6d..8b5736f4 100644 --- a/samples/sample_batch_reg.c +++ b/samples/sample_batch_reg.c @@ -2,17 +2,15 @@ #include #include +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; } diff --git a/samples/sample_m68k.c b/samples/sample_m68k.c index 49e47e5b..ed58f9fe 100644 --- a/samples/sample_m68k.c +++ b/samples/sample_m68k.c @@ -6,21 +6,25 @@ #include #include - // 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); } diff --git a/samples/sample_mips.c b/samples/sample_mips.c index ef26af11..3bcafafd 100644 --- a/samples/sample_mips.c +++ b/samples/sample_mips.c @@ -6,7 +6,6 @@ #include #include - // 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 diff --git a/samples/sample_ppc.c b/samples/sample_ppc.c index 12dbbd3f..cd09ae5e 100644 --- a/samples/sample_ppc.c +++ b/samples/sample_ppc.c @@ -6,22 +6,25 @@ #include #include - // 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(); diff --git a/samples/sample_riscv.c b/samples/sample_riscv.c index 73bdf98d..6e36f53a 100644 --- a/samples/sample_riscv.c +++ b/samples/sample_riscv.c @@ -5,7 +5,6 @@ #include #include - // 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"); } diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index 04c2a359..f7609282 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -6,7 +6,6 @@ #include #include - // 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 diff --git a/samples/sample_x86.c b/samples/sample_x86.c index 6732e076..3b9d280f 100644 --- a/samples/sample_x86.c +++ b/samples/sample_x86.c @@ -6,27 +6,45 @@ #include #include - // 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(); diff --git a/samples/sample_x86_32_gdt_and_seg_regs.c b/samples/sample_x86_32_gdt_and_seg_regs.c index e6023f8e..1ffd8892 100644 --- a/samples/sample_x86_32_gdt_and_seg_regs.c +++ b/samples/sample_x86_32_gdt_and_seg_regs.c @@ -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 diff --git a/samples/shellcode.c b/samples/shellcode.c index e0a72c75..9094dc07 100644 --- a/samples/shellcode.c +++ b/samples/shellcode.c @@ -6,23 +6,31 @@ #include #include - // 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>> 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 { diff --git a/tests/unit/acutest.h b/tests/unit/acutest.h index 376748bd..6b4d596d 100644 --- a/tests/unit/acutest.h +++ b/tests/unit/acutest.h @@ -27,7 +27,6 @@ #ifndef ACUTEST_H #define ACUTEST_H - /************************ *** Public interface *** ************************/ @@ -59,8 +58,7 @@ * * Note the list has to be ended with a zeroed record. */ -#define TEST_LIST const struct acutest_test_ acutest_list_[] - +#define TEST_LIST const struct acutest_test_ acutest_list_[] /* Macros for testing whether an unit test succeeds or fails. These macros * can be used arbitrarily in functions implementing the unit tests. @@ -81,9 +79,9 @@ * TEST_CHECK(ptr->member2 > 200); * } */ -#define TEST_CHECK_(cond,...) acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__) -#define TEST_CHECK(cond) acutest_check_((cond), __FILE__, __LINE__, "%s", #cond) - +#define TEST_CHECK_(cond, ...) \ + acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__) +#define TEST_CHECK(cond) acutest_check_((cond), __FILE__, __LINE__, "%s", #cond) /* These macros are the same as TEST_CHECK_ and TEST_CHECK except that if the * condition fails, the currently executed unit test is immediately aborted. @@ -100,17 +98,16 @@ * effects to the outside world (e.g. communicating with some server, inserting * into a database etc.). */ -#define TEST_ASSERT_(cond,...) \ +#define TEST_ASSERT_(cond, ...) \ do { \ - if(!acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__)) \ + if (!acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__)) \ acutest_abort_(); \ - } while(0) + } while (0) #define TEST_ASSERT(cond) \ do { \ - if(!acutest_check_((cond), __FILE__, __LINE__, "%s", #cond)) \ + if (!acutest_check_((cond), __FILE__, __LINE__, "%s", #cond)) \ acutest_abort_(); \ - } while(0) - + } while (0) #ifdef __cplusplus /* Macros to verify that the code (the 1st argument) throws exception of given @@ -134,15 +131,16 @@ try { \ code; \ msg_ = "No exception thrown."; \ - } catch(exctype const&) { \ - exc_ok_= true; \ - } catch(...) { \ + } catch (exctype const &) { \ + exc_ok_ = true; \ + } catch (...) { \ msg_ = "Unexpected exception thrown."; \ } \ - acutest_check_(exc_ok_, __FILE__, __LINE__, #code " throws " #exctype);\ - if(msg_ != NULL) \ + acutest_check_(exc_ok_, __FILE__, __LINE__, \ + #code " throws " #exctype); \ + if (msg_ != NULL) \ acutest_message_("%s", msg_); \ - } while(0) + } while (0) #define TEST_EXCEPTION_(code, exctype, ...) \ do { \ bool exc_ok_ = false; \ @@ -150,17 +148,16 @@ try { \ code; \ msg_ = "No exception thrown."; \ - } catch(exctype const&) { \ - exc_ok_= true; \ - } catch(...) { \ + } catch (exctype const &) { \ + exc_ok_ = true; \ + } catch (...) { \ msg_ = "Unexpected exception thrown."; \ } \ acutest_check_(exc_ok_, __FILE__, __LINE__, __VA_ARGS__); \ - if(msg_ != NULL) \ + if (msg_ != NULL) \ acutest_message_("%s", msg_); \ - } while(0) -#endif /* #ifdef __cplusplus */ - + } while (0) +#endif /* #ifdef __cplusplus */ /* Sometimes it is useful to split execution of more complex unit tests to some * smaller parts and associate those parts with some names. @@ -180,18 +177,16 @@ * implicitly the previous one. To end the test case explicitly (e.g. to end * the last test case after exiting the loop), you may use TEST_CASE(NULL). */ -#define TEST_CASE_(...) acutest_case_(__VA_ARGS__) -#define TEST_CASE(name) acutest_case_("%s", name) - +#define TEST_CASE_(...) acutest_case_(__VA_ARGS__) +#define TEST_CASE(name) acutest_case_("%s", name) /* Maximal output per TEST_CASE call. Longer messages are cut. * You may define another limit prior including "acutest.h" */ #ifndef TEST_CASE_MAXSIZE - #define TEST_CASE_MAXSIZE 64 +#define TEST_CASE_MAXSIZE 64 #endif - /* printf-like macro for outputting an extra information about a failure. * * Intended use is to output some computed output versus the expected value, @@ -213,17 +208,15 @@ * The macro can deal with multi-line output fairly well. It also automatically * adds a final new-line if there is none present. */ -#define TEST_MSG(...) acutest_message_(__VA_ARGS__) - +#define TEST_MSG(...) acutest_message_(__VA_ARGS__) /* Maximal output per TEST_MSG call. Longer messages are cut. * You may define another limit prior including "acutest.h" */ #ifndef TEST_MSG_MAXSIZE - #define TEST_MSG_MAXSIZE 1024 +#define TEST_MSG_MAXSIZE 1024 #endif - /* Macro for dumping a block of memory. * * Its intended use is very similar to what TEST_MSG is for, but instead of @@ -235,16 +228,15 @@ * TEST_DUMP("Expected:", addr_expected, size_expected); * TEST_DUMP("Produced:", addr_produced, size_produced); */ -#define TEST_DUMP(title, addr, size) acutest_dump_(title, addr, size) +#define TEST_DUMP(title, addr, size) acutest_dump_(title, addr, size) /* Maximal output per TEST_DUMP call (in bytes to dump). Longer blocks are cut. * You may define another limit prior including "acutest.h" */ #ifndef TEST_DUMP_MAXSIZE - #define TEST_DUMP_MAXSIZE 1024 +#define TEST_DUMP_MAXSIZE 1024 #endif - /* Common test initialiation/clean-up * * In some test suites, it may be needed to perform some sort of the same @@ -258,14 +250,13 @@ * Examples of various ways how to use the macro TEST_INIT: * * #define TEST_INIT my_init_func(); - * #define TEST_INIT my_init_func() // Works even without the semicolon - * #define TEST_INIT setlocale(LC_ALL, NULL); - * #define TEST_INIT { setlocale(LC_ALL, NULL); my_init_func(); } + * #define TEST_INIT my_init_func() // Works even without the + * semicolon #define TEST_INIT setlocale(LC_ALL, NULL); #define TEST_INIT + * { setlocale(LC_ALL, NULL); my_init_func(); } * * TEST_FINI is to be used in the same way. */ - /********************** *** Implementation *** **********************/ @@ -280,76 +271,76 @@ #include #if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) - #define ACUTEST_UNIX_ 1 - #include - #include - #include - #include - #include - #include - #include +#define ACUTEST_UNIX_ 1 +#include +#include +#include +#include +#include +#include +#include - #if defined CLOCK_PROCESS_CPUTIME_ID && defined CLOCK_MONOTONIC - #define ACUTEST_HAS_POSIX_TIMER_ 1 - #endif +#if defined CLOCK_PROCESS_CPUTIME_ID && defined CLOCK_MONOTONIC +#define ACUTEST_HAS_POSIX_TIMER_ 1 +#endif #endif #if defined(_gnu_linux_) || defined(__linux__) - #define ACUTEST_LINUX_ 1 - #include - #include +#define ACUTEST_LINUX_ 1 +#include +#include #endif #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) - #define ACUTEST_WIN_ 1 - #include - #include +#define ACUTEST_WIN_ 1 +#include +#include #endif #if defined(__APPLE__) - #define ACUTEST_MACOS_ - #include - #include - #include - #include - #include +#define ACUTEST_MACOS_ +#include +#include +#include +#include +#include #endif #ifdef __cplusplus - #include +#include #endif #ifdef __has_include - #if __has_include() - #include - #endif +#if __has_include() +#include +#endif #endif -/* Enable the use of the non-standard keyword __attribute__ to silence warnings under some compilers */ +/* Enable the use of the non-standard keyword __attribute__ to silence warnings + * under some compilers */ #if defined(__GNUC__) || defined(__clang__) - #define ACUTEST_ATTRIBUTE_(attr) __attribute__((attr)) +#define ACUTEST_ATTRIBUTE_(attr) __attribute__((attr)) #else - #define ACUTEST_ATTRIBUTE_(attr) +#define ACUTEST_ATTRIBUTE_(attr) #endif /* Note our global private identifiers end with '_' to mitigate risk of clash * with the unit tests implementation. */ #ifdef __cplusplus - extern "C" { +extern "C" { #endif #ifdef _MSC_VER - /* In the multi-platform code like ours, we cannot use the non-standard - * "safe" functions from Microsoft C lib like e.g. sprintf_s() instead of - * standard sprintf(). Hence, lets disable the warning C4996. */ - #pragma warning(push) - #pragma warning(disable: 4996) +/* In the multi-platform code like ours, we cannot use the non-standard + * "safe" functions from Microsoft C lib like e.g. sprintf_s() instead of + * standard sprintf(). Hence, lets disable the warning C4996. */ +#pragma warning(push) +#pragma warning(disable : 4996) #endif - struct acutest_test_ { - const char* name; + const char *name; void (*func)(void); }; @@ -366,18 +357,17 @@ enum { extern const struct acutest_test_ acutest_list_[]; -int acutest_check_(int cond, const char* file, int line, const char* fmt, ...); -void acutest_case_(const char* fmt, ...); -void acutest_message_(const char* fmt, ...); -void acutest_dump_(const char* title, const void* addr, size_t size); +int acutest_check_(int cond, const char *file, int line, const char *fmt, ...); +void acutest_case_(const char *fmt, ...); +void acutest_message_(const char *fmt, ...); +void acutest_dump_(const char *title, const void *addr, size_t size); void acutest_abort_(void) ACUTEST_ATTRIBUTE_(noreturn); - #ifndef TEST_NO_MAIN -static char* acutest_argv0_ = NULL; +static char *acutest_argv0_ = NULL; static size_t acutest_list_size_ = 0; -static struct acutest_test_data_* acutest_test_data_ = NULL; +static struct acutest_test_data_ *acutest_test_data_ = NULL; static size_t acutest_count_ = 0; static int acutest_no_exec_ = -1; static int acutest_no_summary_ = 0; @@ -392,7 +382,7 @@ static FILE *acutest_xml_output_ = NULL; static int acutest_stat_failed_units_ = 0; static int acutest_stat_run_units_ = 0; -static const struct acutest_test_* acutest_current_test_ = NULL; +static const struct acutest_test_ *acutest_current_test_ = NULL; static int acutest_current_index_ = 0; static char acutest_case_name_[TEST_CASE_MAXSIZE] = ""; static int acutest_test_already_logged_ = 0; @@ -405,132 +395,116 @@ static int acutest_timer_ = 0; static int acutest_abort_has_jmp_buf_ = 0; static jmp_buf acutest_abort_jmp_buf_; - -static void -acutest_cleanup_(void) +static void acutest_cleanup_(void) { - free((void*) acutest_test_data_); + free((void *)acutest_test_data_); } -static void ACUTEST_ATTRIBUTE_(noreturn) -acutest_exit_(int exit_code) +static void ACUTEST_ATTRIBUTE_(noreturn) acutest_exit_(int exit_code) { acutest_cleanup_(); exit(exit_code); } #if defined ACUTEST_WIN_ - typedef LARGE_INTEGER acutest_timer_type_; - static LARGE_INTEGER acutest_timer_freq_; - static acutest_timer_type_ acutest_timer_start_; - static acutest_timer_type_ acutest_timer_end_; +typedef LARGE_INTEGER acutest_timer_type_; +static LARGE_INTEGER acutest_timer_freq_; +static acutest_timer_type_ acutest_timer_start_; +static acutest_timer_type_ acutest_timer_end_; - static void - acutest_timer_init_(void) - { - QueryPerformanceFrequency(´st_timer_freq_); - } +static void acutest_timer_init_(void) +{ + QueryPerformanceFrequency(´st_timer_freq_); +} - static void - acutest_timer_get_time_(LARGE_INTEGER* ts) - { - QueryPerformanceCounter(ts); - } +static void acutest_timer_get_time_(LARGE_INTEGER *ts) +{ + QueryPerformanceCounter(ts); +} - static double - acutest_timer_diff_(LARGE_INTEGER start, LARGE_INTEGER end) - { - double duration = (double)(end.QuadPart - start.QuadPart); - duration /= (double)acutest_timer_freq_.QuadPart; - return duration; - } +static double acutest_timer_diff_(LARGE_INTEGER start, LARGE_INTEGER end) +{ + double duration = (double)(end.QuadPart - start.QuadPart); + duration /= (double)acutest_timer_freq_.QuadPart; + return duration; +} - static void - acutest_timer_print_diff_(void) - { - printf("%.6lf secs", acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); - } +static void acutest_timer_print_diff_(void) +{ + printf("%.6lf secs", + acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); +} #elif defined ACUTEST_HAS_POSIX_TIMER_ - static clockid_t acutest_timer_id_; - typedef struct timespec acutest_timer_type_; - static acutest_timer_type_ acutest_timer_start_; - static acutest_timer_type_ acutest_timer_end_; +static clockid_t acutest_timer_id_; +typedef struct timespec acutest_timer_type_; +static acutest_timer_type_ acutest_timer_start_; +static acutest_timer_type_ acutest_timer_end_; - static void - acutest_timer_init_(void) - { - if(acutest_timer_ == 1) - acutest_timer_id_ = CLOCK_MONOTONIC; - else if(acutest_timer_ == 2) - acutest_timer_id_ = CLOCK_PROCESS_CPUTIME_ID; - } +static void acutest_timer_init_(void) +{ + if (acutest_timer_ == 1) + acutest_timer_id_ = CLOCK_MONOTONIC; + else if (acutest_timer_ == 2) + acutest_timer_id_ = CLOCK_PROCESS_CPUTIME_ID; +} - static void - acutest_timer_get_time_(struct timespec* ts) - { - clock_gettime(acutest_timer_id_, ts); - } +static void acutest_timer_get_time_(struct timespec *ts) +{ + clock_gettime(acutest_timer_id_, ts); +} - static double - acutest_timer_diff_(struct timespec start, struct timespec end) - { - double endns; - double startns; +static double acutest_timer_diff_(struct timespec start, struct timespec end) +{ + double endns; + double startns; - endns = end.tv_sec; - endns *= 1e9; - endns += end.tv_nsec; + endns = end.tv_sec; + endns *= 1e9; + endns += end.tv_nsec; - startns = start.tv_sec; - startns *= 1e9; - startns += start.tv_nsec; + startns = start.tv_sec; + startns *= 1e9; + startns += start.tv_nsec; - return ((endns - startns)/ 1e9); - } + return ((endns - startns) / 1e9); +} - static void - acutest_timer_print_diff_(void) - { - printf("%.6lf secs", - acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); - } +static void acutest_timer_print_diff_(void) +{ + printf("%.6lf secs", + acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); +} #else - typedef int acutest_timer_type_; - static acutest_timer_type_ acutest_timer_start_; - static acutest_timer_type_ acutest_timer_end_; +typedef int acutest_timer_type_; +static acutest_timer_type_ acutest_timer_start_; +static acutest_timer_type_ acutest_timer_end_; - void - acutest_timer_init_(void) - {} +void acutest_timer_init_(void) {} - static void - acutest_timer_get_time_(int* ts) - { - (void) ts; - } +static void acutest_timer_get_time_(int *ts) +{ + (void)ts; +} - static double - acutest_timer_diff_(int start, int end) - { - (void) start; - (void) end; - return 0.0; - } +static double acutest_timer_diff_(int start, int end) +{ + (void)start; + (void)end; + return 0.0; +} - static void - acutest_timer_print_diff_(void) - {} +static void acutest_timer_print_diff_(void) {} #endif -#define ACUTEST_COLOR_DEFAULT_ 0 -#define ACUTEST_COLOR_GREEN_ 1 -#define ACUTEST_COLOR_RED_ 2 -#define ACUTEST_COLOR_DEFAULT_INTENSIVE_ 3 -#define ACUTEST_COLOR_GREEN_INTENSIVE_ 4 -#define ACUTEST_COLOR_RED_INTENSIVE_ 5 +#define ACUTEST_COLOR_DEFAULT_ 0 +#define ACUTEST_COLOR_GREEN_ 1 +#define ACUTEST_COLOR_RED_ 2 +#define ACUTEST_COLOR_DEFAULT_INTENSIVE_ 3 +#define ACUTEST_COLOR_GREEN_INTENSIVE_ 4 +#define ACUTEST_COLOR_RED_INTENSIVE_ 5 -static int ACUTEST_ATTRIBUTE_(format (printf, 2, 3)) -acutest_colored_printf_(int color, const char* fmt, ...) +static int ACUTEST_ATTRIBUTE_(format(printf, 2, 3)) + acutest_colored_printf_(int color, const char *fmt, ...) { va_list args; char buffer[256]; @@ -539,22 +513,34 @@ acutest_colored_printf_(int color, const char* fmt, ...) va_start(args, fmt); vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); - buffer[sizeof(buffer)-1] = '\0'; + buffer[sizeof(buffer) - 1] = '\0'; - if(!acutest_colorize_) { + if (!acutest_colorize_) { return printf("%s", buffer); } #if defined ACUTEST_UNIX_ { - const char* col_str; - switch(color) { - case ACUTEST_COLOR_GREEN_: col_str = "\033[0;32m"; break; - case ACUTEST_COLOR_RED_: col_str = "\033[0;31m"; break; - case ACUTEST_COLOR_GREEN_INTENSIVE_: col_str = "\033[1;32m"; break; - case ACUTEST_COLOR_RED_INTENSIVE_: col_str = "\033[1;31m"; break; - case ACUTEST_COLOR_DEFAULT_INTENSIVE_: col_str = "\033[1m"; break; - default: col_str = "\033[0m"; break; + const char *col_str; + switch (color) { + case ACUTEST_COLOR_GREEN_: + col_str = "\033[0;32m"; + break; + case ACUTEST_COLOR_RED_: + col_str = "\033[0;31m"; + break; + case ACUTEST_COLOR_GREEN_INTENSIVE_: + col_str = "\033[1;32m"; + break; + case ACUTEST_COLOR_RED_INTENSIVE_: + col_str = "\033[1;31m"; + break; + case ACUTEST_COLOR_DEFAULT_INTENSIVE_: + col_str = "\033[1m"; + break; + default: + col_str = "\033[0m"; + break; } printf("%s", col_str); n = printf("%s", buffer); @@ -570,15 +556,28 @@ acutest_colored_printf_(int color, const char* fmt, ...) h = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(h, &info); - switch(color) { - case ACUTEST_COLOR_GREEN_: attr = FOREGROUND_GREEN; break; - case ACUTEST_COLOR_RED_: attr = FOREGROUND_RED; break; - case ACUTEST_COLOR_GREEN_INTENSIVE_: attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY; break; - case ACUTEST_COLOR_RED_INTENSIVE_: attr = FOREGROUND_RED | FOREGROUND_INTENSITY; break; - case ACUTEST_COLOR_DEFAULT_INTENSIVE_: attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; break; - default: attr = 0; break; + switch (color) { + case ACUTEST_COLOR_GREEN_: + attr = FOREGROUND_GREEN; + break; + case ACUTEST_COLOR_RED_: + attr = FOREGROUND_RED; + break; + case ACUTEST_COLOR_GREEN_INTENSIVE_: + attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY; + break; + case ACUTEST_COLOR_RED_INTENSIVE_: + attr = FOREGROUND_RED | FOREGROUND_INTENSITY; + break; + case ACUTEST_COLOR_DEFAULT_INTENSIVE_: + attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_INTENSITY; + break; + default: + attr = 0; + break; } - if(attr != 0) + if (attr != 0) SetConsoleTextAttribute(h, attr); n = printf("%s", buffer); SetConsoleTextAttribute(h, info.wAttributes); @@ -590,48 +589,50 @@ acutest_colored_printf_(int color, const char* fmt, ...) #endif } -static void -acutest_begin_test_line_(const struct acutest_test_* test) +static void acutest_begin_test_line_(const struct acutest_test_ *test) { - if(!acutest_tap_) { - if(acutest_verbose_level_ >= 3) { - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Test %s:\n", test->name); + if (!acutest_tap_) { + if (acutest_verbose_level_ >= 3) { + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Test %s:\n", test->name); acutest_test_already_logged_++; - } else if(acutest_verbose_level_ >= 1) { + } else if (acutest_verbose_level_ >= 1) { int n; char spaces[48]; - n = acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Test %s... ", test->name); + n = acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Test %s... ", test->name); memset(spaces, ' ', sizeof(spaces)); - if(n < (int) sizeof(spaces)) - printf("%.*s", (int) sizeof(spaces) - n, spaces); + if (n < (int)sizeof(spaces)) + printf("%.*s", (int)sizeof(spaces) - n, spaces); } else { acutest_test_already_logged_ = 1; } } } -static void -acutest_finish_test_line_(int result) +static void acutest_finish_test_line_(int result) { - if(acutest_tap_) { - const char* str = (result == 0) ? "ok" : "not ok"; + if (acutest_tap_) { + const char *str = (result == 0) ? "ok" : "not ok"; - printf("%s %d - %s\n", str, acutest_current_index_ + 1, acutest_current_test_->name); + printf("%s %d - %s\n", str, acutest_current_index_ + 1, + acutest_current_test_->name); - if(result == 0 && acutest_timer_) { + if (result == 0 && acutest_timer_) { printf("# Duration: "); acutest_timer_print_diff_(); printf("\n"); } } else { - int color = (result == 0) ? ACUTEST_COLOR_GREEN_INTENSIVE_ : ACUTEST_COLOR_RED_INTENSIVE_; - const char* str = (result == 0) ? "OK" : "FAILED"; + int color = (result == 0) ? ACUTEST_COLOR_GREEN_INTENSIVE_ + : ACUTEST_COLOR_RED_INTENSIVE_; + const char *str = (result == 0) ? "OK" : "FAILED"; printf("[ "); acutest_colored_printf_(color, "%s", str); printf(" ]"); - if(result == 0 && acutest_timer_) { + if (result == 0 && acutest_timer_) { printf(" "); acutest_timer_print_diff_(); } @@ -640,37 +641,36 @@ acutest_finish_test_line_(int result) } } -static void -acutest_line_indent_(int level) +static void acutest_line_indent_(int level) { static const char spaces[] = " "; int n = level * 2; - if(acutest_tap_ && n > 0) { + if (acutest_tap_ && n > 0) { n--; printf("#"); } - while(n > 16) { + while (n > 16) { printf("%s", spaces); n -= 16; } printf("%.*s", n, spaces); } -int ACUTEST_ATTRIBUTE_(format (printf, 4, 5)) -acutest_check_(int cond, const char* file, int line, const char* fmt, ...) +int ACUTEST_ATTRIBUTE_(format(printf, 4, 5)) + acutest_check_(int cond, const char *file, int line, const char *fmt, ...) { const char *result_str; int result_color; int verbose_level; - if(cond) { + if (cond) { result_str = "ok"; result_color = ACUTEST_COLOR_GREEN_; verbose_level = 3; } else { - if(!acutest_test_already_logged_ && acutest_current_test_ != NULL) + if (!acutest_test_already_logged_ && acutest_current_test_ != NULL) acutest_finish_test_line_(-1); result_str = "failed"; @@ -680,30 +680,31 @@ acutest_check_(int cond, const char* file, int line, const char* fmt, ...) acutest_test_already_logged_++; } - if(acutest_verbose_level_ >= verbose_level) { + if (acutest_verbose_level_ >= verbose_level) { va_list args; - if(!acutest_case_already_logged_ && acutest_case_name_[0]) { + if (!acutest_case_already_logged_ && acutest_case_name_[0]) { acutest_line_indent_(1); - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", acutest_case_name_); + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Case %s:\n", acutest_case_name_); acutest_test_already_logged_++; acutest_case_already_logged_++; } acutest_line_indent_(acutest_case_name_[0] ? 2 : 1); - if(file != NULL) { + if (file != NULL) { #ifdef ACUTEST_WIN_ - const char* lastsep1 = strrchr(file, '\\'); - const char* lastsep2 = strrchr(file, '/'); - if(lastsep1 == NULL) - lastsep1 = file-1; - if(lastsep2 == NULL) - lastsep2 = file-1; + const char *lastsep1 = strrchr(file, '\\'); + const char *lastsep2 = strrchr(file, '/'); + if (lastsep1 == NULL) + lastsep1 = file - 1; + if (lastsep2 == NULL) + lastsep2 = file - 1; file = (lastsep1 > lastsep2 ? lastsep1 : lastsep2) + 1; #else - const char* lastsep = strrchr(file, '/'); - if(lastsep != NULL) - file = lastsep+1; + const char *lastsep = strrchr(file, '/'); + if (lastsep != NULL) + file = lastsep + 1; #endif printf("%s:%d: Check ", file, line); } @@ -722,20 +723,20 @@ acutest_check_(int cond, const char* file, int line, const char* fmt, ...) return !acutest_cond_failed_; } -void ACUTEST_ATTRIBUTE_(format (printf, 1, 2)) -acutest_case_(const char* fmt, ...) +void ACUTEST_ATTRIBUTE_(format(printf, 1, 2)) + acutest_case_(const char *fmt, ...) { va_list args; - if(acutest_verbose_level_ < 2) + if (acutest_verbose_level_ < 2) return; - if(acutest_case_name_[0]) { + if (acutest_case_name_[0]) { acutest_case_already_logged_ = 0; acutest_case_name_[0] = '\0'; } - if(fmt == NULL) + if (fmt == NULL) return; va_start(args, fmt); @@ -743,90 +744,90 @@ acutest_case_(const char* fmt, ...) va_end(args); acutest_case_name_[sizeof(acutest_case_name_) - 1] = '\0'; - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", acutest_case_name_); + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", + acutest_case_name_); acutest_test_already_logged_++; acutest_case_already_logged_++; } } -void ACUTEST_ATTRIBUTE_(format (printf, 1, 2)) -acutest_message_(const char* fmt, ...) +void ACUTEST_ATTRIBUTE_(format(printf, 1, 2)) + acutest_message_(const char *fmt, ...) { char buffer[TEST_MSG_MAXSIZE]; - char* line_beg; - char* line_end; + char *line_beg; + char *line_end; va_list args; - if(acutest_verbose_level_ < 2) + if (acutest_verbose_level_ < 2) return; /* We allow extra message only when something is already wrong in the * current test. */ - if(acutest_current_test_ == NULL || !acutest_cond_failed_) + if (acutest_current_test_ == NULL || !acutest_cond_failed_) return; va_start(args, fmt); vsnprintf(buffer, TEST_MSG_MAXSIZE, fmt, args); va_end(args); - buffer[TEST_MSG_MAXSIZE-1] = '\0'; + buffer[TEST_MSG_MAXSIZE - 1] = '\0'; line_beg = buffer; - while(1) { + while (1) { line_end = strchr(line_beg, '\n'); - if(line_end == NULL) + if (line_end == NULL) break; acutest_line_indent_(acutest_case_name_[0] ? 3 : 2); printf("%.*s\n", (int)(line_end - line_beg), line_beg); line_beg = line_end + 1; } - if(line_beg[0] != '\0') { + if (line_beg[0] != '\0') { acutest_line_indent_(acutest_case_name_[0] ? 3 : 2); printf("%s\n", line_beg); } } -void -acutest_dump_(const char* title, const void* addr, size_t size) +void acutest_dump_(const char *title, const void *addr, size_t size) { static const size_t BYTES_PER_LINE = 16; size_t line_beg; size_t truncate = 0; - if(acutest_verbose_level_ < 2) + if (acutest_verbose_level_ < 2) return; /* We allow extra message only when something is already wrong in the * current test. */ - if(acutest_current_test_ == NULL || !acutest_cond_failed_) + if (acutest_current_test_ == NULL || !acutest_cond_failed_) return; - if(size > TEST_DUMP_MAXSIZE) { + if (size > TEST_DUMP_MAXSIZE) { truncate = size - TEST_DUMP_MAXSIZE; size = TEST_DUMP_MAXSIZE; } acutest_line_indent_(acutest_case_name_[0] ? 3 : 2); - printf((title[strlen(title)-1] == ':') ? "%s\n" : "%s:\n", title); + printf((title[strlen(title) - 1] == ':') ? "%s\n" : "%s:\n", title); - for(line_beg = 0; line_beg < size; line_beg += BYTES_PER_LINE) { + for (line_beg = 0; line_beg < size; line_beg += BYTES_PER_LINE) { size_t line_end = line_beg + BYTES_PER_LINE; size_t off; acutest_line_indent_(acutest_case_name_[0] ? 4 : 3); printf("%08lx: ", (unsigned long)line_beg); - for(off = line_beg; off < line_end; off++) { - if(off < size) - printf(" %02x", ((const unsigned char*)addr)[off]); + for (off = line_beg; off < line_end; off++) { + if (off < size) + printf(" %02x", ((const unsigned char *)addr)[off]); else printf(" "); } printf(" "); - for(off = line_beg; off < line_end; off++) { - unsigned char byte = ((const unsigned char*)addr)[off]; - if(off < size) + for (off = line_beg; off < line_end; off++) { + unsigned char byte = ((const unsigned char *)addr)[off]; + if (off < size) printf("%c", (iscntrl(byte) ? '.' : byte)); else break; @@ -835,135 +836,128 @@ acutest_dump_(const char* title, const void* addr, size_t size) printf("\n"); } - if(truncate > 0) { + if (truncate > 0) { acutest_line_indent_(acutest_case_name_[0] ? 4 : 3); - printf(" ... (and more %u bytes)\n", (unsigned) truncate); + printf(" ... (and more %u bytes)\n", (unsigned)truncate); } } /* This is called just before each test */ -static void -acutest_init_(const char *test_name) +static void acutest_init_(const char *test_name) { #ifdef TEST_INIT - TEST_INIT - ; /* Allow for a single unterminated function call */ + TEST_INIT; /* Allow for a single unterminated function call */ #endif /* Suppress any warnings about unused variable. */ - (void) test_name; + (void)test_name; } /* This is called after each test */ -static void -acutest_fini_(const char *test_name) +static void acutest_fini_(const char *test_name) { #ifdef TEST_FINI - TEST_FINI - ; /* Allow for a single unterminated function call */ + TEST_FINI; /* Allow for a single unterminated function call */ #endif /* Suppress any warnings about unused variable. */ - (void) test_name; + (void)test_name; } -void -acutest_abort_(void) +void acutest_abort_(void) { - if(acutest_abort_has_jmp_buf_) { + if (acutest_abort_has_jmp_buf_) { longjmp(acutest_abort_jmp_buf_, 1); } else { - if(acutest_current_test_ != NULL) + if (acutest_current_test_ != NULL) acutest_fini_(acutest_current_test_->name); abort(); } } -static void -acutest_list_names_(void) +static void acutest_list_names_(void) { - const struct acutest_test_* test; + const struct acutest_test_ *test; printf("Unit tests:\n"); - for(test = ´st_list_[0]; test->func != NULL; test++) + for (test = ´st_list_[0]; test->func != NULL; test++) printf(" %s\n", test->name); } -static void -acutest_remember_(int i) +static void acutest_remember_(int i) { - if(acutest_test_data_[i].flags & ACUTEST_FLAG_RUN_) + if (acutest_test_data_[i].flags & ACUTEST_FLAG_RUN_) return; acutest_test_data_[i].flags |= ACUTEST_FLAG_RUN_; acutest_count_++; } -static void -acutest_set_success_(int i, int success) +static void acutest_set_success_(int i, int success) { - acutest_test_data_[i].flags |= success ? ACUTEST_FLAG_SUCCESS_ : ACUTEST_FLAG_FAILURE_; + acutest_test_data_[i].flags |= + success ? ACUTEST_FLAG_SUCCESS_ : ACUTEST_FLAG_FAILURE_; } -static void -acutest_set_duration_(int i, double duration) +static void acutest_set_duration_(int i, double duration) { acutest_test_data_[i].duration = duration; } -static int -acutest_name_contains_word_(const char* name, const char* pattern) +static int acutest_name_contains_word_(const char *name, const char *pattern) { static const char word_delim[] = " \t-_/.,:;"; - const char* substr; + const char *substr; size_t pattern_len; pattern_len = strlen(pattern); substr = strstr(name, pattern); - while(substr != NULL) { - int starts_on_word_boundary = (substr == name || strchr(word_delim, substr[-1]) != NULL); - int ends_on_word_boundary = (substr[pattern_len] == '\0' || strchr(word_delim, substr[pattern_len]) != NULL); + while (substr != NULL) { + int starts_on_word_boundary = + (substr == name || strchr(word_delim, substr[-1]) != NULL); + int ends_on_word_boundary = + (substr[pattern_len] == '\0' || + strchr(word_delim, substr[pattern_len]) != NULL); - if(starts_on_word_boundary && ends_on_word_boundary) + if (starts_on_word_boundary && ends_on_word_boundary) return 1; - substr = strstr(substr+1, pattern); + substr = strstr(substr + 1, pattern); } return 0; } -static int -acutest_lookup_(const char* pattern) +static int acutest_lookup_(const char *pattern) { int i; int n = 0; /* Try exact match. */ - for(i = 0; i < (int) acutest_list_size_; i++) { - if(strcmp(acutest_list_[i].name, pattern) == 0) { + for (i = 0; i < (int)acutest_list_size_; i++) { + if (strcmp(acutest_list_[i].name, pattern) == 0) { acutest_remember_(i); n++; break; } } - if(n > 0) + if (n > 0) return n; /* Try word match. */ - for(i = 0; i < (int) acutest_list_size_; i++) { - if(acutest_name_contains_word_(acutest_list_[i].name, pattern)) { + for (i = 0; i < (int)acutest_list_size_; i++) { + if (acutest_name_contains_word_(acutest_list_[i].name, pattern)) { acutest_remember_(i); n++; } } - if(n > 0) + if (n > 0) return n; /* Try relaxed match. */ - for(i = 0; i < (int) acutest_list_size_; i++) { - if(strstr(acutest_list_[i].name, pattern) != NULL) { + for (i = 0; i < (int)acutest_list_size_; i++) { + if (strstr(acutest_list_[i].name, pattern) != NULL) { acutest_remember_(i); n++; } @@ -972,21 +966,20 @@ acutest_lookup_(const char* pattern) return n; } - /* Called if anything goes bad in Acutest, or if the unit test ends in other * way then by normal returning from its function (e.g. exception or some * abnormal child process termination). */ -static void ACUTEST_ATTRIBUTE_(format (printf, 1, 2)) -acutest_error_(const char* fmt, ...) +static void ACUTEST_ATTRIBUTE_(format(printf, 1, 2)) + acutest_error_(const char *fmt, ...) { - if(acutest_verbose_level_ == 0) + if (acutest_verbose_level_ == 0) return; - if(acutest_verbose_level_ >= 2) { + if (acutest_verbose_level_ >= 2) { va_list args; acutest_line_indent_(1); - if(acutest_verbose_level_ >= 3) + if (acutest_verbose_level_ >= 3) acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "ERROR: "); va_start(args, fmt); vprintf(fmt, args); @@ -994,14 +987,13 @@ acutest_error_(const char* fmt, ...) printf("\n"); } - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { printf("\n"); } } /* Call directly the given test unit function. */ -static int -acutest_do_run_(const struct acutest_test_* test, int index) +static int acutest_do_run_(const struct acutest_test_ *test, int index) { int status = -1; @@ -1022,9 +1014,9 @@ acutest_do_run_(const struct acutest_test_* test, int index) fflush(stdout); fflush(stderr); - if(!acutest_worker_) { + if (!acutest_worker_) { acutest_abort_has_jmp_buf_ = 1; - if(setjmp(acutest_abort_jmp_buf_) != 0) { + if (setjmp(acutest_abort_jmp_buf_) != 0) { acutest_was_aborted_ = 1; goto aborted; } @@ -1032,56 +1024,58 @@ acutest_do_run_(const struct acutest_test_* test, int index) acutest_timer_get_time_(´st_timer_start_); test->func(); -aborted: + aborted: acutest_abort_has_jmp_buf_ = 0; acutest_timer_get_time_(´st_timer_end_); - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); - if(acutest_test_failures_ == 0) { - acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, "SUCCESS: "); + if (acutest_test_failures_ == 0) { + acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, + "SUCCESS: "); printf("All conditions have passed.\n"); - if(acutest_timer_) { + if (acutest_timer_) { acutest_line_indent_(1); printf("Duration: "); acutest_timer_print_diff_(); printf("\n"); } } else { - acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: "); - if(!acutest_was_aborted_) { + acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, + "FAILED: "); + if (!acutest_was_aborted_) { printf("%d condition%s %s failed.\n", - acutest_test_failures_, - (acutest_test_failures_ == 1) ? "" : "s", - (acutest_test_failures_ == 1) ? "has" : "have"); + acutest_test_failures_, + (acutest_test_failures_ == 1) ? "" : "s", + (acutest_test_failures_ == 1) ? "has" : "have"); } else { printf("Aborted.\n"); } } printf("\n"); - } else if(acutest_verbose_level_ >= 1 && acutest_test_failures_ == 0) { + } else if (acutest_verbose_level_ >= 1 && acutest_test_failures_ == 0) { acutest_finish_test_line_(0); } status = (acutest_test_failures_ == 0) ? 0 : -1; #ifdef __cplusplus - } catch(std::exception& e) { - const char* what = e.what(); + } catch (std::exception &e) { + const char *what = e.what(); acutest_check_(0, NULL, 0, "Threw std::exception"); - if(what != NULL) + if (what != NULL) acutest_message_("std::exception::what(): %s", what); - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: "); printf("C++ exception.\n\n"); } - } catch(...) { + } catch (...) { acutest_check_(0, NULL, 0, "Threw an exception"); - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: "); printf("C++ exception.\n\n"); @@ -1099,8 +1093,8 @@ aborted: /* Trigger the unit test. If possible (and not suppressed) it starts a child * process who calls acutest_do_run_(), otherwise it calls acutest_do_run_() * directly. */ -static void -acutest_run_(const struct acutest_test_* test, int index, int master_index) +static void acutest_run_(const struct acutest_test_ *test, int index, + int master_index) { int failed = 1; acutest_timer_type_ start, end; @@ -1109,7 +1103,7 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) acutest_test_already_logged_ = 0; acutest_timer_get_time_(&start); - if(!acutest_no_exec_) { + if (!acutest_no_exec_) { #if defined(ACUTEST_UNIX_) @@ -1121,10 +1115,10 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) fflush(stderr); pid = fork(); - if(pid == (pid_t)-1) { + if (pid == (pid_t)-1) { acutest_error_("Cannot fork. %s [%d]", strerror(errno), errno); failed = 1; - } else if(pid == 0) { + } else if (pid == 0) { /* Child: Do the test. */ acutest_worker_ = 1; failed = (acutest_do_run_(test, index) != 0); @@ -1132,29 +1126,54 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) } else { /* Parent: Wait until child terminates and analyze its exit code. */ waitpid(pid, &exit_code, 0); - if(WIFEXITED(exit_code)) { - switch(WEXITSTATUS(exit_code)) { - case 0: failed = 0; break; /* test has passed. */ - case 1: /* noop */ break; /* "normal" failure. */ - default: acutest_error_("Unexpected exit code [%d]", WEXITSTATUS(exit_code)); + if (WIFEXITED(exit_code)) { + switch (WEXITSTATUS(exit_code)) { + case 0: + failed = 0; + break; /* test has passed. */ + case 1: /* noop */ + break; /* "normal" failure. */ + default: + acutest_error_("Unexpected exit code [%d]", + WEXITSTATUS(exit_code)); } - } else if(WIFSIGNALED(exit_code)) { + } else if (WIFSIGNALED(exit_code)) { char tmp[32]; - const char* signame; - switch(WTERMSIG(exit_code)) { - case SIGINT: signame = "SIGINT"; break; - case SIGHUP: signame = "SIGHUP"; break; - case SIGQUIT: signame = "SIGQUIT"; break; - case SIGABRT: signame = "SIGABRT"; break; - case SIGKILL: signame = "SIGKILL"; break; - case SIGSEGV: signame = "SIGSEGV"; break; - case SIGILL: signame = "SIGILL"; break; - case SIGTERM: signame = "SIGTERM"; break; - default: sprintf(tmp, "signal %d", WTERMSIG(exit_code)); signame = tmp; break; + const char *signame; + switch (WTERMSIG(exit_code)) { + case SIGINT: + signame = "SIGINT"; + break; + case SIGHUP: + signame = "SIGHUP"; + break; + case SIGQUIT: + signame = "SIGQUIT"; + break; + case SIGABRT: + signame = "SIGABRT"; + break; + case SIGKILL: + signame = "SIGKILL"; + break; + case SIGSEGV: + signame = "SIGSEGV"; + break; + case SIGILL: + signame = "SIGILL"; + break; + case SIGTERM: + signame = "SIGTERM"; + break; + default: + sprintf(tmp, "signal %d", WTERMSIG(exit_code)); + signame = tmp; + break; } acutest_error_("Test interrupted by %s.", signame); } else { - acutest_error_("Test ended in an unexpected way [%d].", exit_code); + acutest_error_("Test ended in an unexpected way [%d].", + exit_code); } } @@ -1167,29 +1186,38 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) /* Windows has no fork(). So we propagate all info into the child * through a command line arguments. */ - _snprintf(buffer, sizeof(buffer)-1, - "%s --worker=%d %s --no-exec --no-summary %s --verbose=%d --color=%s -- \"%s\"", - acutest_argv0_, index, acutest_timer_ ? "--time" : "", - acutest_tap_ ? "--tap" : "", acutest_verbose_level_, - acutest_colorize_ ? "always" : "never", - test->name); + _snprintf(buffer, sizeof(buffer) - 1, + "%s --worker=%d %s --no-exec --no-summary %s --verbose=%d " + "--color=%s -- \"%s\"", + acutest_argv0_, index, acutest_timer_ ? "--time" : "", + acutest_tap_ ? "--tap" : "", acutest_verbose_level_, + acutest_colorize_ ? "always" : "never", test->name); memset(&startupInfo, 0, sizeof(startupInfo)); startupInfo.cb = sizeof(STARTUPINFO); - if(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo)) { + if (CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, + &startupInfo, &processInfo)) { WaitForSingleObject(processInfo.hProcess, INFINITE); GetExitCodeProcess(processInfo.hProcess, &exitCode); CloseHandle(processInfo.hThread); CloseHandle(processInfo.hProcess); failed = (exitCode != 0); - if(exitCode > 1) { - switch(exitCode) { - case 3: acutest_error_("Aborted."); break; - case 0xC0000005: acutest_error_("Access violation."); break; - default: acutest_error_("Test ended in an unexpected way [%lu].", exitCode); break; + if (exitCode > 1) { + switch (exitCode) { + case 3: + acutest_error_("Aborted."); + break; + case 0xC0000005: + acutest_error_("Access violation."); + break; + default: + acutest_error_("Test ended in an unexpected way [%lu].", + exitCode); + break; } } } else { - acutest_error_("Cannot create unit test subprocess [%ld].", GetLastError()); + acutest_error_("Cannot create unit test subprocess [%ld].", + GetLastError()); failed = 1; } @@ -1209,7 +1237,7 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) acutest_current_test_ = NULL; acutest_stat_run_units_++; - if(failed) + if (failed) acutest_stat_failed_units_++; acutest_set_success_(master_index, !failed); @@ -1218,12 +1246,13 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) #if defined(ACUTEST_WIN_) /* Callback for SEH events. */ -static LONG CALLBACK -acutest_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) +static LONG CALLBACK acutest_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) { acutest_check_(0, NULL, 0, "Unhandled SEH exception"); - acutest_message_("Exception code: 0x%08lx", ptrs->ExceptionRecord->ExceptionCode); - acutest_message_("Exception address: 0x%p", ptrs->ExceptionRecord->ExceptionAddress); + acutest_message_("Exception code: 0x%08lx", + ptrs->ExceptionRecord->ExceptionCode); + acutest_message_("Exception address: 0x%p", + ptrs->ExceptionRecord->ExceptionAddress); fflush(stdout); fflush(stderr); @@ -1232,38 +1261,37 @@ acutest_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) } #endif +#define ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ 0x0001 +#define ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ 0x0002 -#define ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ 0x0001 -#define ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ 0x0002 - -#define ACUTEST_CMDLINE_OPTID_NONE_ 0 -#define ACUTEST_CMDLINE_OPTID_UNKNOWN_ (-0x7fffffff + 0) -#define ACUTEST_CMDLINE_OPTID_MISSINGARG_ (-0x7fffffff + 1) -#define ACUTEST_CMDLINE_OPTID_BOGUSARG_ (-0x7fffffff + 2) +#define ACUTEST_CMDLINE_OPTID_NONE_ 0 +#define ACUTEST_CMDLINE_OPTID_UNKNOWN_ (-0x7fffffff + 0) +#define ACUTEST_CMDLINE_OPTID_MISSINGARG_ (-0x7fffffff + 1) +#define ACUTEST_CMDLINE_OPTID_BOGUSARG_ (-0x7fffffff + 2) typedef struct acutest_test_CMDLINE_OPTION_ { char shortname; - const char* longname; + const char *longname; int id; unsigned flags; } ACUTEST_CMDLINE_OPTION_; -static int -acutest_cmdline_handle_short_opt_group_(const ACUTEST_CMDLINE_OPTION_* options, - const char* arggroup, - int (*callback)(int /*optval*/, const char* /*arg*/)) +static int acutest_cmdline_handle_short_opt_group_( + const ACUTEST_CMDLINE_OPTION_ *options, const char *arggroup, + int (*callback)(int /*optval*/, const char * /*arg*/)) { - const ACUTEST_CMDLINE_OPTION_* opt; + const ACUTEST_CMDLINE_OPTION_ *opt; int i; int ret = 0; - for(i = 0; arggroup[i] != '\0'; i++) { - for(opt = options; opt->id != 0; opt++) { - if(arggroup[i] == opt->shortname) + for (i = 0; arggroup[i] != '\0'; i++) { + for (opt = options; opt->id != 0; opt++) { + if (arggroup[i] == opt->shortname) break; } - if(opt->id != 0 && !(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { + if (opt->id != 0 && + !(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { ret = callback(opt->id, NULL); } else { /* Unknown option. */ @@ -1271,106 +1299,116 @@ acutest_cmdline_handle_short_opt_group_(const ACUTEST_CMDLINE_OPTION_* options, badoptname[0] = '-'; badoptname[1] = arggroup[i]; badoptname[2] = '\0'; - ret = callback((opt->id != 0 ? ACUTEST_CMDLINE_OPTID_MISSINGARG_ : ACUTEST_CMDLINE_OPTID_UNKNOWN_), - badoptname); + ret = callback((opt->id != 0 ? ACUTEST_CMDLINE_OPTID_MISSINGARG_ + : ACUTEST_CMDLINE_OPTID_UNKNOWN_), + badoptname); } - if(ret != 0) + if (ret != 0) break; } return ret; } -#define ACUTEST_CMDLINE_AUXBUF_SIZE_ 32 +#define ACUTEST_CMDLINE_AUXBUF_SIZE_ 32 -static int -acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_* options, int argc, char** argv, - int (*callback)(int /*optval*/, const char* /*arg*/)) +static int acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_ *options, + int argc, char **argv, + int (*callback)(int /*optval*/, + const char * /*arg*/)) { - const ACUTEST_CMDLINE_OPTION_* opt; - char auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_+1]; + const ACUTEST_CMDLINE_OPTION_ *opt; + char auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_ + 1]; int after_doubledash = 0; int i = 1; int ret = 0; auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_] = '\0'; - while(i < argc) { - if(after_doubledash || strcmp(argv[i], "-") == 0) { + while (i < argc) { + if (after_doubledash || strcmp(argv[i], "-") == 0) { /* Non-option argument. */ ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]); - } else if(strcmp(argv[i], "--") == 0) { - /* End of options. All the remaining members are non-option arguments. */ + } else if (strcmp(argv[i], "--") == 0) { + /* End of options. All the remaining members are non-option + * arguments. */ after_doubledash = 1; - } else if(argv[i][0] != '-') { + } else if (argv[i][0] != '-') { /* Non-option argument. */ ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]); } else { - for(opt = options; opt->id != 0; opt++) { - if(opt->longname != NULL && strncmp(argv[i], "--", 2) == 0) { + for (opt = options; opt->id != 0; opt++) { + if (opt->longname != NULL && strncmp(argv[i], "--", 2) == 0) { size_t len = strlen(opt->longname); - if(strncmp(argv[i]+2, opt->longname, len) == 0) { + if (strncmp(argv[i] + 2, opt->longname, len) == 0) { /* Regular long option. */ - if(argv[i][2+len] == '\0') { + if (argv[i][2 + len] == '\0') { /* with no argument provided. */ - if(!(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) + if (!(opt->flags & + ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) ret = callback(opt->id, NULL); else - ret = callback(ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); + ret = callback( + ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); break; - } else if(argv[i][2+len] == '=') { + } else if (argv[i][2 + len] == '=') { /* with an argument provided. */ - if(opt->flags & (ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ | ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { - ret = callback(opt->id, argv[i]+2+len+1); + if (opt->flags & + (ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ | + ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { + ret = callback(opt->id, argv[i] + 2 + len + 1); } else { sprintf(auxbuf, "--%s", opt->longname); - ret = callback(ACUTEST_CMDLINE_OPTID_BOGUSARG_, auxbuf); + ret = callback(ACUTEST_CMDLINE_OPTID_BOGUSARG_, + auxbuf); } break; } else { continue; } } - } else if(opt->shortname != '\0' && argv[i][0] == '-') { - if(argv[i][1] == opt->shortname) { + } else if (opt->shortname != '\0' && argv[i][0] == '-') { + if (argv[i][1] == opt->shortname) { /* Regular short option. */ - if(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_) { - if(argv[i][2] != '\0') - ret = callback(opt->id, argv[i]+2); - else if(i+1 < argc) + if (opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_) { + if (argv[i][2] != '\0') + ret = callback(opt->id, argv[i] + 2); + else if (i + 1 < argc) ret = callback(opt->id, argv[++i]); else - ret = callback(ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); + ret = callback( + ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); break; } else { ret = callback(opt->id, NULL); /* There might be more (argument-less) short options * grouped together. */ - if(ret == 0 && argv[i][2] != '\0') - ret = acutest_cmdline_handle_short_opt_group_(options, argv[i]+2, callback); + if (ret == 0 && argv[i][2] != '\0') + ret = acutest_cmdline_handle_short_opt_group_( + options, argv[i] + 2, callback); break; } } } } - if(opt->id == 0) { /* still not handled? */ - if(argv[i][0] != '-') { + if (opt->id == 0) { /* still not handled? */ + if (argv[i][0] != '-') { /* Non-option argument. */ ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]); } else { /* Unknown option. */ - char* badoptname = argv[i]; + char *badoptname = argv[i]; - if(strncmp(badoptname, "--", 2) == 0) { + if (strncmp(badoptname, "--", 2) == 0) { /* Strip any argument from the long option. */ - char* assignment = strchr(badoptname, '='); - if(assignment != NULL) { + char *assignment = strchr(badoptname, '='); + if (assignment != NULL) { size_t len = assignment - badoptname; - if(len > ACUTEST_CMDLINE_AUXBUF_SIZE_) + if (len > ACUTEST_CMDLINE_AUXBUF_SIZE_) len = ACUTEST_CMDLINE_AUXBUF_SIZE_; strncpy(auxbuf, badoptname, len); auxbuf[len] = '\0'; @@ -1383,7 +1421,7 @@ acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_* options, int argc, char** a } } - if(ret != 0) + if (ret != 0) return ret; i++; } @@ -1391,28 +1429,34 @@ acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_* options, int argc, char** a return ret; } -static void -acutest_help_(void) +static void acutest_help_(void) { printf("Usage: %s [options] [test...]\n", acutest_argv0_); printf("\n"); - printf("Run the specified unit tests; or if the option '--skip' is used, run all\n"); - printf("tests in the suite but those listed. By default, if no tests are specified\n"); + printf("Run the specified unit tests; or if the option '--skip' is used, " + "run all\n"); + printf("tests in the suite but those listed. By default, if no tests are " + "specified\n"); printf("on the command line, all unit tests in the suite are run.\n"); printf("\n"); printf("Options:\n"); - printf(" -s, --skip Execute all unit tests but the listed ones\n"); - printf(" --exec[=WHEN] If supported, execute unit tests as child processes\n"); - printf(" (WHEN is one of 'auto', 'always', 'never')\n"); + printf( + " -s, --skip Execute all unit tests but the listed ones\n"); + printf(" --exec[=WHEN] If supported, execute unit tests as child " + "processes\n"); + printf(" (WHEN is one of 'auto', 'always', " + "'never')\n"); printf(" -E, --no-exec Same as --exec=never\n"); #if defined ACUTEST_WIN_ printf(" -t, --time Measure test duration\n"); #elif defined ACUTEST_HAS_POSIX_TIMER_ printf(" -t, --time Measure test duration (real time)\n"); - printf(" --time=TIMER Measure test duration, using given timer\n"); + printf( + " --time=TIMER Measure test duration, using given timer\n"); printf(" (TIMER is one of 'real', 'cpu')\n"); #endif - printf(" --no-summary Suppress printing of test results summary\n"); + printf( + " --no-summary Suppress printing of test results summary\n"); printf(" --tap Produce TAP-compliant output\n"); printf(" (See https://testanything.org/)\n"); printf(" -x, --xml-output=FILE Enable XUnit output to the given file\n"); @@ -1420,213 +1464,232 @@ acutest_help_(void) printf(" -v, --verbose Make output more verbose\n"); printf(" --verbose=LEVEL Set verbose level to LEVEL:\n"); printf(" 0 ... Be silent\n"); - printf(" 1 ... Output one line per test (and summary)\n"); - printf(" 2 ... As 1 and failed conditions (this is default)\n"); - printf(" 3 ... As 1 and all conditions (and extended summary)\n"); + printf(" 1 ... Output one line per test (and " + "summary)\n"); + printf(" 2 ... As 1 and failed conditions (this " + "is default)\n"); + printf(" 3 ... As 1 and all conditions (and " + "extended summary)\n"); printf(" -q, --quiet Same as --verbose=0\n"); printf(" --color[=WHEN] Enable colorized output\n"); - printf(" (WHEN is one of 'auto', 'always', 'never')\n"); + printf(" (WHEN is one of 'auto', 'always', " + "'never')\n"); printf(" --no-color Same as --color=never\n"); printf(" -h, --help Display this help and exit\n"); - if(acutest_list_size_ < 16) { + if (acutest_list_size_ < 16) { printf("\n"); acutest_list_names_(); } } static const ACUTEST_CMDLINE_OPTION_ acutest_cmdline_options_[] = { - { 's', "skip", 's', 0 }, - { 0, "exec", 'e', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 'E', "no-exec", 'E', 0 }, + {'s', "skip", 's', 0}, + {0, "exec", 'e', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {'E', "no-exec", 'E', 0}, #if defined ACUTEST_WIN_ - { 't', "time", 't', 0 }, - { 0, "timer", 't', 0 }, /* kept for compatibility */ + {'t', "time", 't', 0}, + {0, "timer", 't', 0}, /* kept for compatibility */ #elif defined ACUTEST_HAS_POSIX_TIMER_ - { 't', "time", 't', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 0, "timer", 't', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, /* kept for compatibility */ + {'t', "time", 't', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {0, "timer", 't', + ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, /* kept for compatibility */ #endif - { 0, "no-summary", 'S', 0 }, - { 0, "tap", 'T', 0 }, - { 'l', "list", 'l', 0 }, - { 'v', "verbose", 'v', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 'q', "quiet", 'q', 0 }, - { 0, "color", 'c', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 0, "no-color", 'C', 0 }, - { 'h', "help", 'h', 0 }, - { 0, "worker", 'w', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ }, /* internal */ - { 'x', "xml-output", 'x', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ }, - { 0, NULL, 0, 0 } -}; + {0, "no-summary", 'S', 0}, + {0, "tap", 'T', 0}, + {'l', "list", 'l', 0}, + {'v', "verbose", 'v', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {'q', "quiet", 'q', 0}, + {0, "color", 'c', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {0, "no-color", 'C', 0}, + {'h', "help", 'h', 0}, + {0, "worker", 'w', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_}, /* internal */ + {'x', "xml-output", 'x', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_}, + {0, NULL, 0, 0}}; -static int -acutest_cmdline_callback_(int id, const char* arg) +static int acutest_cmdline_callback_(int id, const char *arg) { - switch(id) { - case 's': - acutest_skip_mode_ = 1; - break; + switch (id) { + case 's': + acutest_skip_mode_ = 1; + break; - case 'e': - if(arg == NULL || strcmp(arg, "always") == 0) { - acutest_no_exec_ = 0; - } else if(strcmp(arg, "never") == 0) { - acutest_no_exec_ = 1; - } else if(strcmp(arg, "auto") == 0) { - /*noop*/ - } else { - fprintf(stderr, "%s: Unrecognized argument '%s' for option --exec.\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - } - break; - - case 'E': + case 'e': + if (arg == NULL || strcmp(arg, "always") == 0) { + acutest_no_exec_ = 0; + } else if (strcmp(arg, "never") == 0) { acutest_no_exec_ = 1; - break; + } else if (strcmp(arg, "auto") == 0) { + /*noop*/ + } else { + fprintf(stderr, + "%s: Unrecognized argument '%s' for option --exec.\n", + acutest_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + } + break; - case 't': -#if defined ACUTEST_WIN_ || defined ACUTEST_HAS_POSIX_TIMER_ - if(arg == NULL || strcmp(arg, "real") == 0) { - acutest_timer_ = 1; - #ifndef ACUTEST_WIN_ - } else if(strcmp(arg, "cpu") == 0) { - acutest_timer_ = 2; - #endif - } else { - fprintf(stderr, "%s: Unrecognized argument '%s' for option --time.\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - } + case 'E': + acutest_no_exec_ = 1; + break; + + case 't': +#if defined ACUTEST_WIN_ || defined ACUTEST_HAS_POSIX_TIMER_ + if (arg == NULL || strcmp(arg, "real") == 0) { + acutest_timer_ = 1; +#ifndef ACUTEST_WIN_ + } else if (strcmp(arg, "cpu") == 0) { + acutest_timer_ = 2; #endif - break; + } else { + fprintf(stderr, + "%s: Unrecognized argument '%s' for option --time.\n", + acutest_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + } +#endif + break; - case 'S': - acutest_no_summary_ = 1; - break; + case 'S': + acutest_no_summary_ = 1; + break; - case 'T': - acutest_tap_ = 1; - break; + case 'T': + acutest_tap_ = 1; + break; - case 'l': - acutest_list_names_(); - acutest_exit_(0); - break; + case 'l': + acutest_list_names_(); + acutest_exit_(0); + break; - case 'v': - acutest_verbose_level_ = (arg != NULL ? atoi(arg) : acutest_verbose_level_+1); - break; + case 'v': + acutest_verbose_level_ = + (arg != NULL ? atoi(arg) : acutest_verbose_level_ + 1); + break; - case 'q': - acutest_verbose_level_ = 0; - break; + case 'q': + acutest_verbose_level_ = 0; + break; - case 'c': - if(arg == NULL || strcmp(arg, "always") == 0) { - acutest_colorize_ = 1; - } else if(strcmp(arg, "never") == 0) { - acutest_colorize_ = 0; - } else if(strcmp(arg, "auto") == 0) { - /*noop*/ - } else { - fprintf(stderr, "%s: Unrecognized argument '%s' for option --color.\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - } - break; - - case 'C': + case 'c': + if (arg == NULL || strcmp(arg, "always") == 0) { + acutest_colorize_ = 1; + } else if (strcmp(arg, "never") == 0) { acutest_colorize_ = 0; - break; - - case 'h': - acutest_help_(); - acutest_exit_(0); - break; - - case 'w': - acutest_worker_ = 1; - acutest_worker_index_ = atoi(arg); - break; - case 'x': - acutest_xml_output_ = fopen(arg, "w"); - if (!acutest_xml_output_) { - fprintf(stderr, "Unable to open '%s': %s\n", arg, strerror(errno)); - acutest_exit_(2); - } - break; - - case 0: - if(acutest_lookup_(arg) == 0) { - fprintf(stderr, "%s: Unrecognized unit test '%s'\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --list' for list of unit tests.\n", acutest_argv0_); - acutest_exit_(2); - } - break; - - case ACUTEST_CMDLINE_OPTID_UNKNOWN_: - fprintf(stderr, "Unrecognized command line option '%s'.\n", arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); + } else if (strcmp(arg, "auto") == 0) { + /*noop*/ + } else { + fprintf(stderr, + "%s: Unrecognized argument '%s' for option --color.\n", + acutest_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); acutest_exit_(2); - break; + } + break; - case ACUTEST_CMDLINE_OPTID_MISSINGARG_: - fprintf(stderr, "The command line option '%s' requires an argument.\n", arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - break; + case 'C': + acutest_colorize_ = 0; + break; - case ACUTEST_CMDLINE_OPTID_BOGUSARG_: - fprintf(stderr, "The command line option '%s' does not expect an argument.\n", arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); + case 'h': + acutest_help_(); + acutest_exit_(0); + break; + + case 'w': + acutest_worker_ = 1; + acutest_worker_index_ = atoi(arg); + break; + case 'x': + acutest_xml_output_ = fopen(arg, "w"); + if (!acutest_xml_output_) { + fprintf(stderr, "Unable to open '%s': %s\n", arg, strerror(errno)); acutest_exit_(2); - break; + } + break; + + case 0: + if (acutest_lookup_(arg) == 0) { + fprintf(stderr, "%s: Unrecognized unit test '%s'\n", acutest_argv0_, + arg); + fprintf(stderr, "Try '%s --list' for list of unit tests.\n", + acutest_argv0_); + acutest_exit_(2); + } + break; + + case ACUTEST_CMDLINE_OPTID_UNKNOWN_: + fprintf(stderr, "Unrecognized command line option '%s'.\n", arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + break; + + case ACUTEST_CMDLINE_OPTID_MISSINGARG_: + fprintf(stderr, "The command line option '%s' requires an argument.\n", + arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + break; + + case ACUTEST_CMDLINE_OPTID_BOGUSARG_: + fprintf(stderr, + "The command line option '%s' does not expect an argument.\n", + arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + break; } return 0; } - #ifdef ACUTEST_LINUX_ -static int -acutest_is_tracer_present_(void) +static int acutest_is_tracer_present_(void) { /* Must be large enough so the line 'TracerPid: ${PID}' can fit in. */ static const int OVERLAP = 32; - char buf[256+OVERLAP+1]; + char buf[256 + OVERLAP + 1]; int tracer_present = 0; int fd; size_t n_read = 0; fd = open("/proc/self/status", O_RDONLY); - if(fd == -1) + if (fd == -1) return 0; - while(1) { + while (1) { static const char pattern[] = "TracerPid:"; - const char* field; + const char *field; - while(n_read < sizeof(buf) - 1) { + while (n_read < sizeof(buf) - 1) { ssize_t n; n = read(fd, buf + n_read, sizeof(buf) - 1 - n_read); - if(n <= 0) + if (n <= 0) break; n_read += n; } buf[n_read] = '\0'; field = strstr(buf, pattern); - if(field != NULL && field < buf + sizeof(buf) - OVERLAP) { - pid_t tracer_pid = (pid_t) atoi(field + sizeof(pattern) - 1); + if (field != NULL && field < buf + sizeof(buf) - OVERLAP) { + pid_t tracer_pid = (pid_t)atoi(field + sizeof(pattern) - 1); tracer_present = (tracer_pid != 0); break; } - if(n_read == sizeof(buf)-1) { - memmove(buf, buf + sizeof(buf)-1 - OVERLAP, OVERLAP); + if (n_read == sizeof(buf) - 1) { + memmove(buf, buf + sizeof(buf) - 1 - OVERLAP, OVERLAP); n_read = OVERLAP; } else { break; @@ -1639,8 +1702,7 @@ acutest_is_tracer_present_(void) #endif #ifdef ACUTEST_MACOS_ -static bool -acutest_AmIBeingDebugged(void) +static bool acutest_AmIBeingDebugged(void) { int junk; int mib[4]; @@ -1664,12 +1726,11 @@ acutest_AmIBeingDebugged(void) assert(junk == 0); // We're being debugged if the P_TRACED flag is set. - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + return ((info.kp_proc.p_flag & P_TRACED) != 0); } #endif -int -main(int argc, char** argv) +int main(int argc, char **argv) { int i; @@ -1678,28 +1739,30 @@ main(int argc, char** argv) #if defined ACUTEST_UNIX_ acutest_colorize_ = isatty(STDOUT_FILENO); #elif defined ACUTEST_WIN_ - #if defined _BORLANDC_ +#if defined _BORLANDC_ acutest_colorize_ = isatty(_fileno(stdout)); - #else +#else acutest_colorize_ = _isatty(_fileno(stdout)); - #endif +#endif #else acutest_colorize_ = 0; #endif /* Count all test units */ acutest_list_size_ = 0; - for(i = 0; acutest_list_[i].func != NULL; i++) + for (i = 0; acutest_list_[i].func != NULL; i++) acutest_list_size_++; - acutest_test_data_ = (struct acutest_test_data_*)calloc(acutest_list_size_, sizeof(struct acutest_test_data_)); - if(acutest_test_data_ == NULL) { + acutest_test_data_ = (struct acutest_test_data_ *)calloc( + acutest_list_size_, sizeof(struct acutest_test_data_)); + if (acutest_test_data_ == NULL) { fprintf(stderr, "Out of memory.\n"); acutest_exit_(2); } /* Parse options */ - acutest_cmdline_read_(acutest_cmdline_options_, argc, argv, acutest_cmdline_callback_); + acutest_cmdline_read_(acutest_cmdline_options_, argc, argv, + acutest_cmdline_callback_); /* Initialize the proper timer. */ acutest_timer_init_(); @@ -1712,83 +1775,89 @@ main(int argc, char** argv) #endif /* By default, we want to run all tests. */ - if(acutest_count_ == 0) { - for(i = 0; acutest_list_[i].func != NULL; i++) + if (acutest_count_ == 0) { + for (i = 0; acutest_list_[i].func != NULL; i++) acutest_remember_(i); } /* Guess whether we want to run unit tests as child processes. */ - if(acutest_no_exec_ < 0) { + if (acutest_no_exec_ < 0) { acutest_no_exec_ = 0; - if(acutest_count_ <= 1) { + if (acutest_count_ <= 1) { acutest_no_exec_ = 1; } else { #ifdef ACUTEST_WIN_ - if(IsDebuggerPresent()) + if (IsDebuggerPresent()) acutest_no_exec_ = 1; #endif #ifdef ACUTEST_LINUX_ - if(acutest_is_tracer_present_()) + if (acutest_is_tracer_present_()) acutest_no_exec_ = 1; #endif #ifdef ACUTEST_MACOS_ - if(acutest_AmIBeingDebugged()) + if (acutest_AmIBeingDebugged()) acutest_no_exec_ = 1; #endif #ifdef RUNNING_ON_VALGRIND - /* RUNNING_ON_VALGRIND is provided by optionally included */ - if(RUNNING_ON_VALGRIND) + /* RUNNING_ON_VALGRIND is provided by optionally included + * */ + if (RUNNING_ON_VALGRIND) acutest_no_exec_ = 1; #endif } } - if(acutest_tap_) { + if (acutest_tap_) { /* TAP requires we know test result ("ok", "not ok") before we output * anything about the test, and this gets problematic for larger verbose * levels. */ - if(acutest_verbose_level_ > 2) + if (acutest_verbose_level_ > 2) acutest_verbose_level_ = 2; /* TAP harness should provide some summary. */ acutest_no_summary_ = 1; - if(!acutest_worker_) - printf("1..%d\n", (int) acutest_count_); + if (!acutest_worker_) + printf("1..%d\n", (int)acutest_count_); } int index = acutest_worker_index_; - for(i = 0; acutest_list_[i].func != NULL; i++) { + for (i = 0; acutest_list_[i].func != NULL; i++) { int run = (acutest_test_data_[i].flags & ACUTEST_FLAG_RUN_); if (acutest_skip_mode_) /* Run all tests except those listed. */ run = !run; - if(run) + if (run) acutest_run_(´st_list_[i], index++, i); } /* Write a summary */ - if(!acutest_no_summary_ && acutest_verbose_level_ >= 1) { - if(acutest_verbose_level_ >= 3) { - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Summary:\n"); + if (!acutest_no_summary_ && acutest_verbose_level_ >= 1) { + if (acutest_verbose_level_ >= 3) { + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Summary:\n"); - printf(" Count of all unit tests: %4d\n", (int) acutest_list_size_); - printf(" Count of run unit tests: %4d\n", acutest_stat_run_units_); - printf(" Count of failed unit tests: %4d\n", acutest_stat_failed_units_); - printf(" Count of skipped unit tests: %4d\n", (int) acutest_list_size_ - acutest_stat_run_units_); + printf(" Count of all unit tests: %4d\n", + (int)acutest_list_size_); + printf(" Count of run unit tests: %4d\n", + acutest_stat_run_units_); + printf(" Count of failed unit tests: %4d\n", + acutest_stat_failed_units_); + printf(" Count of skipped unit tests: %4d\n", + (int)acutest_list_size_ - acutest_stat_run_units_); } - if(acutest_stat_failed_units_ == 0) { + if (acutest_stat_failed_units_ == 0) { acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, "SUCCESS:"); printf(" All unit tests have passed.\n"); } else { acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED:"); printf(" %d of %d unit tests %s failed.\n", - acutest_stat_failed_units_, acutest_stat_run_units_, - (acutest_stat_failed_units_ == 1) ? "has" : "have"); + acutest_stat_failed_units_, acutest_stat_run_units_, + (acutest_stat_failed_units_ == 1) ? "has" : "have"); } - if(acutest_verbose_level_ >= 3) + if (acutest_verbose_level_ >= 3) printf("\n"); } @@ -1801,16 +1870,23 @@ main(int argc, char** argv) #else const char *suite_name = argv[0]; #endif - fprintf(acutest_xml_output_, "\n"); - fprintf(acutest_xml_output_, "\n", - suite_name, (int)acutest_list_size_, acutest_stat_failed_units_, acutest_stat_failed_units_, - (int)acutest_list_size_ - acutest_stat_run_units_); - for(i = 0; acutest_list_[i].func != NULL; i++) { + fprintf(acutest_xml_output_, + "\n"); + fprintf(acutest_xml_output_, + "\n", + suite_name, (int)acutest_list_size_, acutest_stat_failed_units_, + acutest_stat_failed_units_, + (int)acutest_list_size_ - acutest_stat_run_units_); + for (i = 0; acutest_list_[i].func != NULL; i++) { struct acutest_test_data_ *details = ´st_test_data_[i]; - fprintf(acutest_xml_output_, " \n", acutest_list_[i].name, details->duration); + fprintf(acutest_xml_output_, + " \n", + acutest_list_[i].name, details->duration); if (details->flags & ACUTEST_FLAG_FAILURE_) fprintf(acutest_xml_output_, " \n"); - if (!(details->flags & ACUTEST_FLAG_FAILURE_) && !(details->flags & ACUTEST_FLAG_SUCCESS_)) + if (!(details->flags & ACUTEST_FLAG_FAILURE_) && + !(details->flags & ACUTEST_FLAG_SUCCESS_)) fprintf(acutest_xml_output_, " \n"); fprintf(acutest_xml_output_, " \n"); } @@ -1823,15 +1899,14 @@ main(int argc, char** argv) return (acutest_stat_failed_units_ == 0) ? 0 : 1; } - -#endif /* #ifndef TEST_NO_MAIN */ +#endif /* #ifndef TEST_NO_MAIN */ #ifdef _MSC_VER - #pragma warning(pop) +#pragma warning(pop) #endif #ifdef __cplusplus - } /* extern "C" */ +} /* extern "C" */ #endif -#endif /* #ifndef ACUTEST_H */ +#endif /* #ifndef ACUTEST_H */ diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index 6a609243..4bfd3127 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -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 } -}; \ No newline at end of file +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}}; \ No newline at end of file diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 59333f4d..302945db 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -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}}; diff --git a/tests/unit/test_m68k.c b/tests/unit/test_m68k.c index 972d24c6..4c2505f4 100644 --- a/tests/unit/test_m68k.c +++ b/tests/unit/test_m68k.c @@ -3,6 +3,4 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -TEST_LIST = { - { NULL, NULL } -}; \ No newline at end of file +TEST_LIST = {{NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index 008ec146..987a3ae3 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -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}}; diff --git a/tests/unit/test_mips.c b/tests/unit/test_mips.c index bfff4cad..61699e5d 100644 --- a/tests/unit/test_mips.c +++ b/tests/unit/test_mips.c @@ -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 } -}; \ No newline at end of file + {"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}}; \ No newline at end of file diff --git a/tests/unit/test_ppc.c b/tests/unit/test_ppc.c index c457bd70..41fed7c4 100644 --- a/tests/unit/test_ppc.c +++ b/tests/unit/test_ppc.c @@ -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, ®)); @@ -30,7 +34,4 @@ static void test_ppc32_add() { OK(uc_close(uc)); } -TEST_LIST = { - { "test_ppc32_add", test_ppc32_add }, - { NULL, NULL} -}; \ No newline at end of file +TEST_LIST = {{"test_ppc32_add", test_ppc32_add}, {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_riscv.c b/tests/unit/test_riscv.c index 8617e631..24fb87e1 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -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}}; diff --git a/tests/unit/test_sparc.c b/tests/unit/test_sparc.c index 972d24c6..4c2505f4 100644 --- a/tests/unit/test_sparc.c +++ b/tests/unit/test_sparc.c @@ -3,6 +3,4 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -TEST_LIST = { - { NULL, NULL } -}; \ No newline at end of file +TEST_LIST = {{NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 17d346ef..ab9eca6f 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -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, ®)); } -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 } -}; \ No newline at end of file +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}}; \ No newline at end of file diff --git a/tests/unit/unicorn_test.h b/tests/unit/unicorn_test.h index e3a45c02..8c47310c 100644 --- a/tests/unit/unicorn_test.h +++ b/tests/unit/unicorn_test.h @@ -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 */ diff --git a/uc.c b/uc.c index f41e8306..07ae921f 100644 --- a/uc.c +++ b/uc.c @@ -10,7 +10,7 @@ #include #endif -#include // nanosleep +#include // nanosleep #include #include "uc_priv.h" @@ -37,100 +37,105 @@ unsigned int uc_version(unsigned int *major, unsigned int *minor) return (UC_API_MAJOR << 8) + UC_API_MINOR; } - UNICORN_EXPORT uc_err uc_errno(uc_engine *uc) { return uc->errnum; } - UNICORN_EXPORT const char *uc_strerror(uc_err code) { - switch(code) { - default: - return "Unknown error code"; - case UC_ERR_OK: - return "OK (UC_ERR_OK)"; - case UC_ERR_NOMEM: - return "No memory available or memory not present (UC_ERR_NOMEM)"; - case UC_ERR_ARCH: - return "Invalid/unsupported architecture (UC_ERR_ARCH)"; - case UC_ERR_HANDLE: - return "Invalid handle (UC_ERR_HANDLE)"; - case UC_ERR_MODE: - return "Invalid mode (UC_ERR_MODE)"; - case UC_ERR_VERSION: - return "Different API version between core & binding (UC_ERR_VERSION)"; - case UC_ERR_READ_UNMAPPED: - return "Invalid memory read (UC_ERR_READ_UNMAPPED)"; - case UC_ERR_WRITE_UNMAPPED: - return "Invalid memory write (UC_ERR_WRITE_UNMAPPED)"; - case UC_ERR_FETCH_UNMAPPED: - return "Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)"; - case UC_ERR_HOOK: - return "Invalid hook type (UC_ERR_HOOK)"; - case UC_ERR_INSN_INVALID: - return "Invalid instruction (UC_ERR_INSN_INVALID)"; - case UC_ERR_MAP: - return "Invalid memory mapping (UC_ERR_MAP)"; - case UC_ERR_WRITE_PROT: - return "Write to write-protected memory (UC_ERR_WRITE_PROT)"; - case UC_ERR_READ_PROT: - return "Read from non-readable memory (UC_ERR_READ_PROT)"; - case UC_ERR_FETCH_PROT: - return "Fetch from non-executable memory (UC_ERR_FETCH_PROT)"; - case UC_ERR_ARG: - return "Invalid argument (UC_ERR_ARG)"; - case UC_ERR_READ_UNALIGNED: - return "Read from unaligned memory (UC_ERR_READ_UNALIGNED)"; - case UC_ERR_WRITE_UNALIGNED: - return "Write to unaligned memory (UC_ERR_WRITE_UNALIGNED)"; - case UC_ERR_FETCH_UNALIGNED: - return "Fetch from unaligned memory (UC_ERR_FETCH_UNALIGNED)"; - case UC_ERR_RESOURCE: - return "Insufficient resource (UC_ERR_RESOURCE)"; - case UC_ERR_EXCEPTION: - return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; + switch (code) { + default: + return "Unknown error code"; + case UC_ERR_OK: + return "OK (UC_ERR_OK)"; + case UC_ERR_NOMEM: + return "No memory available or memory not present (UC_ERR_NOMEM)"; + case UC_ERR_ARCH: + return "Invalid/unsupported architecture (UC_ERR_ARCH)"; + case UC_ERR_HANDLE: + return "Invalid handle (UC_ERR_HANDLE)"; + case UC_ERR_MODE: + return "Invalid mode (UC_ERR_MODE)"; + case UC_ERR_VERSION: + return "Different API version between core & binding (UC_ERR_VERSION)"; + case UC_ERR_READ_UNMAPPED: + return "Invalid memory read (UC_ERR_READ_UNMAPPED)"; + case UC_ERR_WRITE_UNMAPPED: + return "Invalid memory write (UC_ERR_WRITE_UNMAPPED)"; + case UC_ERR_FETCH_UNMAPPED: + return "Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)"; + case UC_ERR_HOOK: + return "Invalid hook type (UC_ERR_HOOK)"; + case UC_ERR_INSN_INVALID: + return "Invalid instruction (UC_ERR_INSN_INVALID)"; + case UC_ERR_MAP: + return "Invalid memory mapping (UC_ERR_MAP)"; + case UC_ERR_WRITE_PROT: + return "Write to write-protected memory (UC_ERR_WRITE_PROT)"; + case UC_ERR_READ_PROT: + return "Read from non-readable memory (UC_ERR_READ_PROT)"; + case UC_ERR_FETCH_PROT: + return "Fetch from non-executable memory (UC_ERR_FETCH_PROT)"; + case UC_ERR_ARG: + return "Invalid argument (UC_ERR_ARG)"; + case UC_ERR_READ_UNALIGNED: + return "Read from unaligned memory (UC_ERR_READ_UNALIGNED)"; + case UC_ERR_WRITE_UNALIGNED: + return "Write to unaligned memory (UC_ERR_WRITE_UNALIGNED)"; + case UC_ERR_FETCH_UNALIGNED: + return "Fetch from unaligned memory (UC_ERR_FETCH_UNALIGNED)"; + case UC_ERR_RESOURCE: + return "Insufficient resource (UC_ERR_RESOURCE)"; + case UC_ERR_EXCEPTION: + return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; } } - UNICORN_EXPORT bool uc_arch_supported(uc_arch arch) { switch (arch) { #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: return true; + case UC_ARCH_ARM: + return true; #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: return true; + case UC_ARCH_ARM64: + return true; #endif #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: return true; + case UC_ARCH_M68K: + return true; #endif #ifdef UNICORN_HAS_MIPS - case UC_ARCH_MIPS: return true; + case UC_ARCH_MIPS: + return true; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: return true; + case UC_ARCH_PPC: + return true; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: return true; + case UC_ARCH_SPARC: + return true; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: return true; + case UC_ARCH_X86: + return true; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: return true; + case UC_ARCH_RISCV: + return true; #endif - /* Invalid or disabled arch */ - default: return false; + /* Invalid or disabled arch */ + default: + return false; } } - UNICORN_EXPORT uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) { @@ -156,142 +161,138 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) QTAILQ_INIT(&uc->address_spaces); - switch(arch) { - default: - break; + switch (arch) { + default: + break; #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: - if ((mode & ~UC_MODE_M68K_MASK) || - !(mode & UC_MODE_BIG_ENDIAN)) { - free(uc); - return UC_ERR_MODE; - } - uc->init_arch = m68k_uc_init; - break; + case UC_ARCH_M68K: + if ((mode & ~UC_MODE_M68K_MASK) || !(mode & UC_MODE_BIG_ENDIAN)) { + free(uc); + return UC_ERR_MODE; + } + uc->init_arch = m68k_uc_init; + break; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: - if ((mode & ~UC_MODE_X86_MASK) || - (mode & UC_MODE_BIG_ENDIAN) || - !(mode & (UC_MODE_16|UC_MODE_32|UC_MODE_64))) { - free(uc); - return UC_ERR_MODE; - } - uc->init_arch = x86_uc_init; - break; + case UC_ARCH_X86: + if ((mode & ~UC_MODE_X86_MASK) || (mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_16 | UC_MODE_32 | UC_MODE_64))) { + free(uc); + return UC_ERR_MODE; + } + uc->init_arch = x86_uc_init; + break; #endif #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: - if ((mode & ~UC_MODE_ARM_MASK)) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_BIG_ENDIAN) { - uc->init_arch = armeb_uc_init; - } else { - uc->init_arch = arm_uc_init; - } + case UC_ARCH_ARM: + if ((mode & ~UC_MODE_ARM_MASK)) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_BIG_ENDIAN) { + uc->init_arch = armeb_uc_init; + } else { + uc->init_arch = arm_uc_init; + } - if (mode & UC_MODE_THUMB) { - uc->thumb = 1; - } - break; + if (mode & UC_MODE_THUMB) { + uc->thumb = 1; + } + break; #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: - if (mode & ~UC_MODE_ARM_MASK) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_BIG_ENDIAN) { - uc->init_arch = arm64eb_uc_init; - } else { - uc->init_arch = arm64_uc_init; - } - break; + case UC_ARCH_ARM64: + if (mode & ~UC_MODE_ARM_MASK) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_BIG_ENDIAN) { + uc->init_arch = arm64eb_uc_init; + } else { + uc->init_arch = arm64_uc_init; + } + break; #endif -#if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) - case UC_ARCH_MIPS: - if ((mode & ~UC_MODE_MIPS_MASK) || - !(mode & (UC_MODE_MIPS32|UC_MODE_MIPS64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_BIG_ENDIAN) { +#if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || \ + defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) + case UC_ARCH_MIPS: + if ((mode & ~UC_MODE_MIPS_MASK) || + !(mode & (UC_MODE_MIPS32 | UC_MODE_MIPS64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_BIG_ENDIAN) { #ifdef UNICORN_HAS_MIPS - if (mode & UC_MODE_MIPS32) { - uc->init_arch = mips_uc_init; - } + if (mode & UC_MODE_MIPS32) { + uc->init_arch = mips_uc_init; + } #endif #ifdef UNICORN_HAS_MIPS64 - if (mode & UC_MODE_MIPS64) { - uc->init_arch = mips64_uc_init; - } + if (mode & UC_MODE_MIPS64) { + uc->init_arch = mips64_uc_init; + } #endif - } else { // little endian + } else { // little endian #ifdef UNICORN_HAS_MIPSEL - if (mode & UC_MODE_MIPS32) { - uc->init_arch = mipsel_uc_init; - } + if (mode & UC_MODE_MIPS32) { + uc->init_arch = mipsel_uc_init; + } #endif #ifdef UNICORN_HAS_MIPS64EL - if (mode & UC_MODE_MIPS64) { - uc->init_arch = mips64el_uc_init; - } -#endif + if (mode & UC_MODE_MIPS64) { + uc->init_arch = mips64el_uc_init; } - break; +#endif + } + break; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: - if ((mode & ~UC_MODE_SPARC_MASK) || - !(mode & UC_MODE_BIG_ENDIAN) || - !(mode & (UC_MODE_SPARC32|UC_MODE_SPARC64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_SPARC64) { - uc->init_arch = sparc64_uc_init; - } else { - uc->init_arch = sparc_uc_init; - } - break; + case UC_ARCH_SPARC: + if ((mode & ~UC_MODE_SPARC_MASK) || !(mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_SPARC32 | UC_MODE_SPARC64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_SPARC64) { + uc->init_arch = sparc64_uc_init; + } else { + uc->init_arch = sparc_uc_init; + } + break; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: - if ((mode & ~UC_MODE_PPC_MASK) || - !(mode & UC_MODE_BIG_ENDIAN) || - !(mode & (UC_MODE_PPC32|UC_MODE_PPC64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_PPC64) { - uc->init_arch = ppc64_uc_init; - } else { - uc->init_arch = ppc_uc_init; - } - break; + case UC_ARCH_PPC: + if ((mode & ~UC_MODE_PPC_MASK) || !(mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_PPC32 | UC_MODE_PPC64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_PPC64) { + uc->init_arch = ppc64_uc_init; + } else { + uc->init_arch = ppc_uc_init; + } + break; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: - if ((mode & ~UC_MODE_RISCV_MASK) || - !(mode & (UC_MODE_RISCV32|UC_MODE_RISCV64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_RISCV32) { - uc->init_arch = riscv32_uc_init; - } else if (mode & UC_MODE_RISCV64) { - uc->init_arch =riscv64_uc_init; - } else { - free(uc); - return UC_ERR_MODE; - } - break; + case UC_ARCH_RISCV: + if ((mode & ~UC_MODE_RISCV_MASK) || + !(mode & (UC_MODE_RISCV32 | UC_MODE_RISCV64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_RISCV32) { + uc->init_arch = riscv32_uc_init; + } else if (mode & UC_MODE_RISCV64) { + uc->init_arch = riscv64_uc_init; + } else { + free(uc); + return UC_ERR_MODE; + } + break; #endif - } if (uc->init_arch == NULL) { @@ -317,7 +318,6 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) } } - UNICORN_EXPORT uc_err uc_close(uc_engine *uc) { @@ -341,7 +341,7 @@ uc_err uc_close(uc_engine *uc) /* flatviews */ g_hash_table_destroy(uc->flat_views); - + // During flatviews destruction, we may still access memory regions. // So we free them afterwards. /* memory */ @@ -390,7 +390,7 @@ uc_err uc_close(uc_engine *uc) cur = uc->saved_contexts.head; while (cur != NULL) { struct list_item *next = cur->next; - struct uc_context *context = (struct uc_context*)cur->data; + struct uc_context *context = (struct uc_context *)cur->data; context->uc = NULL; cur = next; } @@ -403,7 +403,6 @@ uc_err uc_close(uc_engine *uc) return UC_ERR_OK; } - UNICORN_EXPORT uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count) { @@ -417,7 +416,6 @@ uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count) return ret; } - UNICORN_EXPORT uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count) { @@ -431,7 +429,6 @@ uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count) return ret; } - UNICORN_EXPORT uc_err uc_reg_read(uc_engine *uc, int regid, void *value) { @@ -450,13 +447,13 @@ static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size) { size_t count = 0, len; - while(count < size) { + while (count < size) { MemoryRegion *mr = memory_mapping(uc, address); if (mr) { len = (size_t)MIN(size - count, mr->end - address); count += len; address += len; - } else {// this address is not mapped in yet + } else { // this address is not mapped in yet break; } } @@ -464,7 +461,6 @@ static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size) return (count == size); } - UNICORN_EXPORT uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) { @@ -484,11 +480,12 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) } // memory area can overlap adjacent memory blocks - while(count < size) { + while (count < size) { MemoryRegion *mr = memory_mapping(uc, address); if (mr) { len = (size_t)MIN(size - count, mr->end - address); - if (uc->read_mem(&uc->address_space_memory, address, bytes, len) == false) { + if (uc->read_mem(&uc->address_space_memory, address, bytes, len) == + false) { break; } count += len; @@ -507,7 +504,8 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) } 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) { size_t count = 0, len; const uint8_t *bytes = _bytes; @@ -525,21 +523,23 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t } // memory area can overlap adjacent memory blocks - while(count < size) { + while (count < size) { MemoryRegion *mr = memory_mapping(uc, address); if (mr) { uint32_t operms = mr->perms; - if (!(operms & UC_PROT_WRITE)) {// write protected - // but this is not the program accessing memory, so temporarily mark writable + if (!(operms & UC_PROT_WRITE)) { // write protected + // but this is not the program accessing memory, so temporarily + // mark writable uc->readonly_mem(mr, false); } len = (size_t)MIN(size - count, mr->end - address); - if (uc->write_mem(&uc->address_space_memory, address, bytes, len) == false) { + if (uc->write_mem(&uc->address_space_memory, address, bytes, len) == + false) { break; } - if (!(operms & UC_PROT_WRITE)) {// write protected + if (!(operms & UC_PROT_WRITE)) { // write protected // now write protect it again uc->readonly_mem(mr, true); } @@ -547,7 +547,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t count += len; address += len; bytes += len; - } else {// this address is not mapped in yet + } else { // this address is not mapped in yet break; } } @@ -559,7 +559,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t } } -#define TIMEOUT_STEP 2 // microseconds +#define TIMEOUT_STEP 2 // microseconds static void *_timeout_fn(void *arg) { struct uc_struct *uc = arg; @@ -571,7 +571,7 @@ static void *_timeout_fn(void *arg) if (uc->emulation_done) { break; } - } while((uint64_t)(get_clock() - current_time) < uc->timeout); + } while ((uint64_t)(get_clock() - current_time) < uc->timeout); // timeout before emulation is done? if (!uc->emulation_done) { @@ -586,11 +586,12 @@ static void *_timeout_fn(void *arg) static void enable_emu_timer(uc_engine *uc, uint64_t timeout) { uc->timeout = timeout; - qemu_thread_create(uc, &uc->timer, "timeout", _timeout_fn, - uc, QEMU_THREAD_JOINABLE); + qemu_thread_create(uc, &uc->timer, "timeout", _timeout_fn, uc, + QEMU_THREAD_JOINABLE); } -static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, + void *user_data) { // count this instruction. ah ah ah. uc->emu_counter++; @@ -604,11 +605,12 @@ static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, static void clear_deleted_hooks(uc_engine *uc) { - struct list_item * cur; - struct hook * hook; + struct list_item *cur; + struct hook *hook; int i; - - for (cur = uc->hooks_to_del.head; cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { + + for (cur = uc->hooks_to_del.head; + cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { assert(hook->to_delete); for (i = 0; i < UC_HOOK_MAX; i++) { if (list_remove(&uc->hook[i], (void *)hook)) { @@ -626,7 +628,8 @@ static void clear_deleted_hooks(uc_engine *uc) } 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) { // reset the counter uc->emu_counter = 0; @@ -636,69 +639,69 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time uc->timed_out = false; uc->first_tb = true; - switch(uc->arch) { - default: - break; + switch (uc->arch) { + default: + break; #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: - uc_reg_write(uc, UC_M68K_REG_PC, &begin); - break; + case UC_ARCH_M68K: + uc_reg_write(uc, UC_M68K_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: - switch(uc->mode) { - default: - break; - case UC_MODE_16: { - uint64_t ip; - uint16_t cs; - - uc_reg_read(uc, UC_X86_REG_CS, &cs); - // compensate for later adding up IP & CS - ip = begin - cs*16; - uc_reg_write(uc, UC_X86_REG_IP, &ip); - break; - } - case UC_MODE_32: - uc_reg_write(uc, UC_X86_REG_EIP, &begin); - break; - case UC_MODE_64: - uc_reg_write(uc, UC_X86_REG_RIP, &begin); - break; - } + case UC_ARCH_X86: + switch (uc->mode) { + default: break; + case UC_MODE_16: { + uint64_t ip; + uint16_t cs; + + uc_reg_read(uc, UC_X86_REG_CS, &cs); + // compensate for later adding up IP & CS + ip = begin - cs * 16; + uc_reg_write(uc, UC_X86_REG_IP, &ip); + break; + } + case UC_MODE_32: + uc_reg_write(uc, UC_X86_REG_EIP, &begin); + break; + case UC_MODE_64: + uc_reg_write(uc, UC_X86_REG_RIP, &begin); + break; + } + break; #endif #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: - uc_reg_write(uc, UC_ARM_REG_R15, &begin); - break; + case UC_ARCH_ARM: + uc_reg_write(uc, UC_ARM_REG_R15, &begin); + break; #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: - uc_reg_write(uc, UC_ARM64_REG_PC, &begin); - break; + case UC_ARCH_ARM64: + uc_reg_write(uc, UC_ARM64_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_MIPS - case UC_ARCH_MIPS: - // TODO: MIPS32/MIPS64/BIGENDIAN etc - uc_reg_write(uc, UC_MIPS_REG_PC, &begin); - break; + case UC_ARCH_MIPS: + // TODO: MIPS32/MIPS64/BIGENDIAN etc + uc_reg_write(uc, UC_MIPS_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: - // TODO: Sparc/Sparc64 - uc_reg_write(uc, UC_SPARC_REG_PC, &begin); - break; + case UC_ARCH_SPARC: + // TODO: Sparc/Sparc64 + uc_reg_write(uc, UC_SPARC_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: - uc_reg_write(uc, UC_PPC_REG_PC, &begin); - break; + case UC_ARCH_PPC: + uc_reg_write(uc, UC_PPC_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: - uc_reg_write(uc, UC_RISCV_REG_PC, &begin); - break; + case UC_ARCH_RISCV: + uc_reg_write(uc, UC_RISCV_REG_PC, &begin); + break; #endif } @@ -717,7 +720,8 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time // so instead of appending, we must insert the hook at the begin // of the hook list uc->hook_insert = 1; - err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, NULL, 1, 0); + err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, + NULL, 1, 0); // restore to append mode for uc_hook_add() uc->hook_insert = 0; if (err != UC_ERR_OK) { @@ -728,7 +732,7 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time uc->addr_end = until; if (timeout) { - enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds + enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds } uc->vm_start(uc); @@ -747,7 +751,6 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time return uc->invalid_error; } - UNICORN_EXPORT uc_err uc_emu_stop(uc_engine *uc) { @@ -765,14 +768,16 @@ uc_err uc_emu_stop(uc_engine *uc) return UC_ERR_OK; } -// return target index where a memory region at the address exists, or could be inserted +// return target index where a memory region at the address exists, or could be +// inserted // -// address either is inside the mapping at the returned index, or is in free space before -// the next mapping. +// address either is inside the mapping at the returned index, or is in free +// space before the next mapping. // -// if there is overlap, between regions, ending address will be higher than the starting -// address of the mapping at returned index -static int bsearch_mapped_blocks(const uc_engine *uc, uint64_t address) { +// if there is overlap, between regions, ending address will be higher than the +// starting address of the mapping at returned index +static int bsearch_mapped_blocks(const uc_engine *uc, uint64_t address) +{ int left, right, mid; MemoryRegion *mapping; @@ -817,7 +822,8 @@ static bool memory_overlap(struct uc_struct *uc, uint64_t begin, size_t size) } // common setup/error checking shared between uc_mem_map and uc_mem_map_ptr -static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, MemoryRegion *block) +static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, + uint32_t perms, MemoryRegion *block) { MemoryRegion **regions; int pos; @@ -826,9 +832,10 @@ static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t per return UC_ERR_NOMEM; } - if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { //time to grow - regions = (MemoryRegion**)g_realloc(uc->mapped_blocks, - sizeof(MemoryRegion*) * (uc->mapped_block_count + MEM_BLOCK_INCR)); + if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { // time to grow + regions = (MemoryRegion **)g_realloc( + uc->mapped_blocks, + sizeof(MemoryRegion *) * (uc->mapped_block_count + MEM_BLOCK_INCR)); if (regions == NULL) { return UC_ERR_NOMEM; } @@ -838,7 +845,8 @@ static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t per pos = bsearch_mapped_blocks(uc, block->addr); // shift the array right to give space for the new pointer - memmove(&uc->mapped_blocks[pos + 1], &uc->mapped_blocks[pos], sizeof(MemoryRegion*) * (uc->mapped_block_count - pos)); + memmove(&uc->mapped_blocks[pos + 1], &uc->mapped_blocks[pos], + sizeof(MemoryRegion *) * (uc->mapped_block_count - pos)); uc->mapped_blocks[pos] = block; uc->mapped_block_count++; @@ -846,7 +854,8 @@ static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t per return UC_ERR_OK; } -static uc_err mem_map_check(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) +static uc_err mem_map_check(uc_engine *uc, uint64_t address, size_t size, + uint32_t perms) { if (size == 0) { // invalid memory mapping @@ -895,11 +904,13 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) return res; } - return mem_map(uc, address, size, perms, uc->memory_map(uc, address, size, perms)); + return mem_map(uc, address, size, perms, + uc->memory_map(uc, address, size, perms)); } 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) { uc_err res; @@ -916,7 +927,8 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t per return res; } - return mem_map(uc, address, size, UC_PROT_ALL, uc->memory_map_ptr(uc, address, size, perms, ptr)); + return mem_map(uc, address, size, UC_PROT_ALL, + uc->memory_map_ptr(uc, address, size, perms, ptr)); } UNICORN_EXPORT @@ -937,7 +949,8 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size, // The callbacks do not need to be checked for NULL here, as their presence // (or lack thereof) will determine the permissions used. return mem_map(uc, address, size, UC_PROT_NONE, - uc->memory_map_io(uc, address, size, read_cb, write_cb, user_data_read, user_data_write)); + uc->memory_map_io(uc, address, size, read_cb, write_cb, + user_data_read, user_data_write)); } // Create a backup copy of the indicated MemoryRegion. @@ -946,7 +959,8 @@ static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr) { uint8_t *block = (uint8_t *)g_malloc0((size_t)int128_get64(mr->size)); if (block != NULL) { - uc_err err = uc_mem_read(uc, mr->addr, block, (size_t)int128_get64(mr->size)); + uc_err err = + uc_mem_read(uc, mr->addr, block, (size_t)int128_get64(mr->size)); if (err != UC_ERR_OK) { free(block); block = NULL; @@ -971,8 +985,8 @@ static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr) */ // TODO: investigate whether qemu region manipulation functions already offered // this capability -static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t address, - size_t size, bool do_delete) +static bool split_region(struct uc_struct *uc, MemoryRegion *mr, + uint64_t address, size_t size, bool do_delete) { uint8_t *backup; uint32_t perms; @@ -999,8 +1013,10 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres return false; } - QLIST_FOREACH(block, &uc->ram_list.blocks, next) { - if (block->offset <= mr->addr && block->used_length >= (mr->end - mr->addr)) { + QLIST_FOREACH(block, &uc->ram_list.blocks, next) + { + if (block->offset <= mr->addr && + block->used_length >= (mr->end - mr->addr)) { break; } } @@ -1022,13 +1038,15 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres } } - // save the essential information required for the split before mr gets deleted + // save the essential information required for the split before mr gets + // deleted perms = mr->perms; begin = mr->addr; end = mr->end; // unmap this region first, then do split it later - if (uc_mem_unmap(uc, mr->addr, (size_t)int128_get64(mr->size)) != UC_ERR_OK) { + if (uc_mem_unmap(uc, mr->addr, (size_t)int128_get64(mr->size)) != + UC_ERR_OK) { goto error; } @@ -1052,10 +1070,10 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres r_size = (size_t)(end - chunk_end); m_size = (size_t)(chunk_end - address); - // If there are error in any of the below operations, things are too far gone - // at that point to recover. Could try to remap orignal region, but these smaller - // allocation just failed so no guarantee that we can recover the original - // allocation at this point + // If there are error in any of the below operations, things are too far + // gone at that point to recover. Could try to remap orignal region, but + // these smaller allocation just failed so no guarantee that we can recover + // the original allocation at this point if (l_size > 0) { if (!prealloc) { if (uc_mem_map(uc, begin, l_size, perms) != UC_ERR_OK) { @@ -1076,11 +1094,13 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres if (uc_mem_map(uc, address, m_size, perms) != UC_ERR_OK) { goto error; } - if (uc_mem_write(uc, address, backup + l_size, m_size) != UC_ERR_OK) { + if (uc_mem_write(uc, address, backup + l_size, m_size) != + UC_ERR_OK) { goto error; } } else { - if (uc_mem_map_ptr(uc, address, m_size, perms, backup + l_size) != UC_ERR_OK) { + if (uc_mem_map_ptr(uc, address, m_size, perms, backup + l_size) != + UC_ERR_OK) { goto error; } } @@ -1091,11 +1111,13 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres if (uc_mem_map(uc, chunk_end, r_size, perms) != UC_ERR_OK) { goto error; } - if (uc_mem_write(uc, chunk_end, backup + l_size + m_size, r_size) != UC_ERR_OK) { + if (uc_mem_write(uc, chunk_end, backup + l_size + m_size, r_size) != + UC_ERR_OK) { goto error; } } else { - if (uc_mem_map_ptr(uc, chunk_end, r_size, perms, backup + l_size + m_size) != UC_ERR_OK) { + if (uc_mem_map_ptr(uc, chunk_end, r_size, perms, + backup + l_size + m_size) != UC_ERR_OK) { goto error; } } @@ -1114,7 +1136,8 @@ error: } UNICORN_EXPORT -uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint32_t perms) +uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, + uint32_t perms) { MemoryRegion *mr; uint64_t addr = address; @@ -1154,7 +1177,7 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 // We may need to split regions if this area spans adjacent regions addr = address; count = 0; - while(count < size) { + while (count < size) { mr = memory_mapping(uc, addr); len = (size_t)MIN(size - count, mr->end - addr); if (!split_region(uc, mr, addr, len, false)) { @@ -1163,7 +1186,8 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 mr = memory_mapping(uc, addr); // will this remove EXEC permission? - if (((mr->perms & UC_PROT_EXEC) != 0) && ((perms & UC_PROT_EXEC) == 0)) { + if (((mr->perms & UC_PROT_EXEC) != 0) && + ((perms & UC_PROT_EXEC) == 0)) { remove_exec = true; } mr->perms = perms; @@ -1173,7 +1197,8 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 addr += len; } - // if EXEC permission is removed, then quit TB and continue at the same place + // if EXEC permission is removed, then quit TB and continue at the same + // place if (remove_exec) { uc->quit_request = true; uc_emu_stop(uc); @@ -1217,7 +1242,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) // We may need to split regions if this area spans adjacent regions addr = address; count = 0; - while(count < size) { + while (count < size) { mr = memory_mapping(uc, addr); len = (size_t)MIN(size - count, mr->end - addr); if (!split_region(uc, mr, addr, len, true)) { @@ -1228,7 +1253,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) // so unmap here mr = memory_mapping(uc, addr); if (mr != NULL) { - uc->memory_unmap(uc, mr); + uc->memory_unmap(uc, mr); } count += len; addr += len; @@ -1238,7 +1263,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) } // find the memory region of this address -MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) +MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address) { unsigned int i; @@ -1253,13 +1278,15 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) // try with the cache index first i = uc->mapped_block_cache_index; - if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && address < uc->mapped_blocks[i]->end) { + if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && + address < uc->mapped_blocks[i]->end) { return uc->mapped_blocks[i]; } i = bsearch_mapped_blocks(uc, address); - if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && address <= uc->mapped_blocks[i]->end - 1) + if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && + address <= uc->mapped_blocks[i]->end - 1) return uc->mapped_blocks[i]; // not found @@ -1268,7 +1295,7 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) 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, ...) { int ret = UC_ERR_OK; int i = 0; @@ -1296,7 +1323,7 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, va_end(valist); if (uc->insn_hook_validate) { - if (! uc->insn_hook_validate(hook->insn)) { + if (!uc->insn_hook_validate(hook->insn)) { free(hook); return UC_ERR_HOOK; } @@ -1352,7 +1379,6 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, return ret; } - UNICORN_EXPORT uc_err uc_hook_del(uc_engine *uc, uc_hook hh) { @@ -1365,7 +1391,7 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh) // an optimization would be to align the hook pointer // and store the type mask in the hook pointer. for (i = 0; i < UC_HOOK_MAX; i++) { - if (list_exists(&uc->hook[i], (void *) hook)) { + if (list_exists(&uc->hook[i], (void *)hook)) { hook->to_delete = true; list_append(&uc->hooks_to_del, hook); } @@ -1375,13 +1401,18 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh) } // TCG helper -void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, int64_t address); -void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, int64_t address) +void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, + int64_t address); +void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, + int64_t address) { struct uc_struct *uc = handle; struct list_item *cur; struct hook *hook; - int hook_flags = index & UC_HOOK_FLAG_MASK; // The index here may contain additional flags. See the comments of uc_hook_idx for details. + int hook_flags = + index & + UC_HOOK_FLAG_MASK; // The index here may contain additional flags. See + // the comments of uc_hook_idx for details. index = index & UC_HOOK_IDX_MASK; @@ -1395,30 +1426,35 @@ void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, int64_t return; } - for (cur = uc->hook[index].head; cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { + for (cur = uc->hook[index].head; + cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { if (hook->to_delete) { continue; } - // on invalid block/instruction, call instruction counter (if enable), then quit + // on invalid block/instruction, call instruction counter (if enable), + // then quit if (size == 0) { if (index == UC_HOOK_CODE_IDX && uc->count_hook) { // this is the instruction counter (first hook in the list) - ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data); + ((uc_cb_hookcode_t)hook->callback)(uc, address, size, + hook->user_data); } return; } if (HOOK_BOUND_CHECK(hook, (uint64_t)address)) { - ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data); + ((uc_cb_hookcode_t)hook->callback)(uc, address, size, + hook->user_data); } // the last callback may already asked to stop emulation // Unicorn: - // In an ARM IT block, we behave like the emulation continues normally. No check_exit_request - // is generated and the hooks are triggered normally. In other words, the whole IT block is - // treated as a single instruction. + // In an ARM IT block, we behave like the emulation continues + // normally. No check_exit_request is generated and the hooks are + // triggered normally. In other words, the whole IT block is treated + // as a single instruction. if (uc->stop_request && !(hook_flags & UC_HOOK_FLAG_NO_STOP)) { break; } @@ -1455,29 +1491,29 @@ uc_err uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count) UNICORN_EXPORT uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result) { - switch(type) { - default: - return UC_ERR_ARG; + switch (type) { + default: + return UC_ERR_ARG; - case UC_QUERY_PAGE_SIZE: - *result = uc->target_page_size; - break; + case UC_QUERY_PAGE_SIZE: + *result = uc->target_page_size; + break; - case UC_QUERY_ARCH: - *result = uc->arch; - break; + case UC_QUERY_ARCH: + *result = uc->arch; + break; - case UC_QUERY_MODE: + case UC_QUERY_MODE: #ifdef UNICORN_HAS_ARM - if (uc->arch == UC_ARCH_ARM) { - return uc->query(uc, type, result); - } + if (uc->arch == UC_ARCH_ARM) { + return uc->query(uc, type, result); + } #endif - return UC_ERR_ARG; + return UC_ERR_ARG; - case UC_QUERY_TIMEOUT: - *result = uc->timed_out; - break; + case UC_QUERY_TIMEOUT: + *result = uc->timed_out; + break; } return UC_ERR_OK; @@ -1517,20 +1553,20 @@ UNICORN_EXPORT size_t uc_context_size(uc_engine *uc) { // return the total size of struct uc_context - return sizeof(uc_context) + uc->cpu_context_size + sizeof(*uc->cpu->jmp_env); + return sizeof(uc_context) + uc->cpu_context_size + + sizeof(*uc->cpu->jmp_env); } UNICORN_EXPORT uc_err uc_context_save(uc_engine *uc, uc_context *context) { memcpy(context->data, uc->cpu->env_ptr, context->context_size); - memcpy(context->data + context->context_size, uc->cpu->jmp_env, context->jmp_env_size); + memcpy(context->data + context->context_size, uc->cpu->jmp_env, + context->jmp_env_size); return UC_ERR_OK; } - - UNICORN_EXPORT uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value) { @@ -1544,120 +1580,123 @@ uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value) } // Keep in mind that we don't a uc_engine when r/w the registers of a context. -static void find_context_reg_rw_function(uc_arch arch, uc_mode mode, context_reg_rw_t *rw) +static void find_context_reg_rw_function(uc_arch arch, uc_mode mode, + context_reg_rw_t *rw) { // We believe that the arch/mode pair is correct. - switch(arch) { - default: - rw->context_reg_read = NULL; - rw->context_reg_write = NULL; - break; + switch (arch) { + default: + rw->context_reg_read = NULL; + rw->context_reg_write = NULL; + break; #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: - rw->context_reg_read = m68k_context_reg_read; - rw->context_reg_write = m68k_context_reg_write; - break; + case UC_ARCH_M68K: + rw->context_reg_read = m68k_context_reg_read; + rw->context_reg_write = m68k_context_reg_write; + break; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: - rw->context_reg_read = x86_context_reg_read; - rw->context_reg_write = x86_context_reg_write; - break; + case UC_ARCH_X86: + rw->context_reg_read = x86_context_reg_read; + rw->context_reg_write = x86_context_reg_write; + break; #endif #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: - if (mode & UC_MODE_BIG_ENDIAN) { - rw->context_reg_read = armeb_context_reg_read; - rw->context_reg_write = armeb_context_reg_write; - } else { - rw->context_reg_read = arm_context_reg_read; - rw->context_reg_write = arm_context_reg_write; - } + case UC_ARCH_ARM: + if (mode & UC_MODE_BIG_ENDIAN) { + rw->context_reg_read = armeb_context_reg_read; + rw->context_reg_write = armeb_context_reg_write; + } else { + rw->context_reg_read = arm_context_reg_read; + rw->context_reg_write = arm_context_reg_write; + } #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: - if (mode & UC_MODE_BIG_ENDIAN) { - rw->context_reg_read = arm64eb_context_reg_read; - rw->context_reg_write = arm64eb_context_reg_write; - } else { - rw->context_reg_read = arm64_context_reg_read; - rw->context_reg_write = arm64_context_reg_write; - } - break; + case UC_ARCH_ARM64: + if (mode & UC_MODE_BIG_ENDIAN) { + rw->context_reg_read = arm64eb_context_reg_read; + rw->context_reg_write = arm64eb_context_reg_write; + } else { + rw->context_reg_read = arm64_context_reg_read; + rw->context_reg_write = arm64_context_reg_write; + } + break; #endif -#if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) - case UC_ARCH_MIPS: - if (mode & UC_MODE_BIG_ENDIAN) { +#if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || \ + defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) + case UC_ARCH_MIPS: + if (mode & UC_MODE_BIG_ENDIAN) { #ifdef UNICORN_HAS_MIPS - if (mode & UC_MODE_MIPS32) { - rw->context_reg_read = mips_context_reg_read; - rw->context_reg_write = mips_context_reg_write; - } + if (mode & UC_MODE_MIPS32) { + rw->context_reg_read = mips_context_reg_read; + rw->context_reg_write = mips_context_reg_write; + } #endif #ifdef UNICORN_HAS_MIPS64 - if (mode & UC_MODE_MIPS64) { - rw->context_reg_read = mips64_context_reg_read; - rw->context_reg_write = mips64_context_reg_write; - } + if (mode & UC_MODE_MIPS64) { + rw->context_reg_read = mips64_context_reg_read; + rw->context_reg_write = mips64_context_reg_write; + } #endif - } else { // little endian + } else { // little endian #ifdef UNICORN_HAS_MIPSEL - if (mode & UC_MODE_MIPS32) { - rw->context_reg_read = mipsel_context_reg_read; - rw->context_reg_write = mipsel_context_reg_write; - } + if (mode & UC_MODE_MIPS32) { + rw->context_reg_read = mipsel_context_reg_read; + rw->context_reg_write = mipsel_context_reg_write; + } #endif #ifdef UNICORN_HAS_MIPS64EL - if (mode & UC_MODE_MIPS64) { - rw->context_reg_read = mips64el_context_reg_read; - rw->context_reg_write = mips64el_context_reg_write; - } -#endif + if (mode & UC_MODE_MIPS64) { + rw->context_reg_read = mips64el_context_reg_read; + rw->context_reg_write = mips64el_context_reg_write; } - break; +#endif + } + break; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: - if (mode & UC_MODE_SPARC64) { - rw->context_reg_read = sparc64_context_reg_read; - rw->context_reg_write = sparc64_context_reg_write; - } else { - rw->context_reg_read = sparc_context_reg_read; - rw->context_reg_write = sparc_context_reg_write; - } - break; + case UC_ARCH_SPARC: + if (mode & UC_MODE_SPARC64) { + rw->context_reg_read = sparc64_context_reg_read; + rw->context_reg_write = sparc64_context_reg_write; + } else { + rw->context_reg_read = sparc_context_reg_read; + rw->context_reg_write = sparc_context_reg_write; + } + break; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: - if (mode & UC_MODE_PPC64) { - rw->context_reg_read = ppc64_context_reg_read; - rw->context_reg_write = ppc64_context_reg_write; - } else { - rw->context_reg_read = ppc_context_reg_read; - rw->context_reg_write = ppc_context_reg_write; - } - break; + case UC_ARCH_PPC: + if (mode & UC_MODE_PPC64) { + rw->context_reg_read = ppc64_context_reg_read; + rw->context_reg_write = ppc64_context_reg_write; + } else { + rw->context_reg_read = ppc_context_reg_read; + rw->context_reg_write = ppc_context_reg_write; + } + break; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: - if (mode & UC_MODE_RISCV32) { - rw->context_reg_read = riscv32_context_reg_read; - rw->context_reg_write = riscv32_context_reg_write; - } else if (mode & UC_MODE_RISCV64) { - rw->context_reg_read = riscv64_context_reg_read; - rw->context_reg_write = riscv64_context_reg_write; - } - break; + case UC_ARCH_RISCV: + if (mode & UC_MODE_RISCV32) { + rw->context_reg_read = riscv32_context_reg_read; + rw->context_reg_write = riscv32_context_reg_write; + } else if (mode & UC_MODE_RISCV64) { + rw->context_reg_read = riscv64_context_reg_read; + rw->context_reg_write = riscv64_context_reg_write; + } + break; #endif } - + return; } UNICORN_EXPORT -uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals, int count) +uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals, + int count) { int ret = UC_ERR_OK; context_reg_rw_t rw; @@ -1673,7 +1712,8 @@ uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals, } UNICORN_EXPORT -uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals, int count) +uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals, + int count) { int ret = UC_ERR_OK; context_reg_rw_t rw; @@ -1693,7 +1733,8 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context) { memcpy(uc->cpu->env_ptr, context->data, context->context_size); if (list_exists(&uc->saved_contexts, context)) { - memcpy(uc->cpu->jmp_env, context->data + context->context_size, context->jmp_env_size); + memcpy(uc->cpu->jmp_env, context->data + context->context_size, + context->jmp_env_size); } return UC_ERR_OK; @@ -1702,7 +1743,7 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context) UNICORN_EXPORT uc_err uc_context_free(uc_context *context) { - uc_engine* uc = context->uc; + uc_engine *uc = context->uc; // if uc is NULL, it means that uc_engine has been free-ed. if (uc) { list_remove(&uc->saved_contexts, context);