From 22ea31cdf752c3307c5008cb2987536e8f0d6930 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Wed, 20 Jul 2022 13:48:13 +0200 Subject: [PATCH 01/77] Fail when VEX.L is set in SSE instructions (AVX is not supported) Closes #1656 --- qemu/target/i386/translate.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index eef26242..b4dc56f2 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -3378,6 +3378,10 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, if (is_xmm) reg |= rex_r; mod = (modrm >> 6) & 3; + /* VEX.L (256 bit) encodings are not supported */ + if (s->vex_l != 0) { + goto illegal_op; // perhaps it should be unknown_op? + } if (sse_fn_epp == SSE_SPECIAL) { b |= (b1 << 8); switch(b) { From e485f398467252106abb1da6b04a8afbe37c7f04 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Wed, 20 Jul 2022 13:59:27 +0200 Subject: [PATCH 02/77] Add a test to make sure VEX.L stops emulation with an error --- tests/regress/x86_vex.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/regress/x86_vex.c b/tests/regress/x86_vex.c index a05f2cf6..1808de42 100644 --- a/tests/regress/x86_vex.c +++ b/tests/regress/x86_vex.c @@ -47,12 +47,37 @@ static void test_vmovdqu(void) OK(uc_close(uc)); } +/* https://github.com/unicorn-engine/unicorn/issues/1656 */ +static void test_vex_l(void) +{ + uc_engine *uc; + uc_err err; + + /* vmovdqu ymm1, [rcx] */ + char code[] = { '\xC5', '\xFE', '\x6F', '\x09' }; + + /* initialize memory and run emulation */ + OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); + OK(uc_mem_map(uc, 0, 2 * 1024 * 1024, UC_PROT_ALL)); + + OK(uc_mem_write(uc, 0, code, sizeof(code) / sizeof(code[0]))); + + err = uc_emu_start(uc, 0, sizeof(code) / sizeof(code[0]), 0, 0); + if(err != UC_ERR_INSN_INVALID) { + fprintf(stderr, "%s", uc_strerror(err)); + assert(false); + } + + OK(uc_close(uc)); +} + /* TODO: Add more vex prefixed instructions Suggestions: vxorpd, vxorps, vandpd, ... */ int main(int argc, char **argv, char **envp) { test_vmovdqu(); + test_vex_l(); return 0; } From 2b25867e4b6c821eaa194ce1e22ed06d12d916a7 Mon Sep 17 00:00:00 2001 From: Zach Szczesniak Date: Wed, 20 Jul 2022 18:31:13 -0400 Subject: [PATCH 03/77] Fixed endianness when writing PPC32 CR register. --- qemu/target/ppc/unicorn.c | 2 +- tests/unit/test_ppc.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/qemu/target/ppc/unicorn.c b/qemu/target/ppc/unicorn.c index ffdde3fe..de91d88c 100644 --- a/qemu/target/ppc/unicorn.c +++ b/qemu/target/ppc/unicorn.c @@ -292,7 +292,7 @@ static void reg_write(CPUPPCState *env, unsigned int regid, const void *value) break; case UC_PPC_REG_CR: val = *(uint32_t *)value; - for (i = 0; i < 8; i++) { + for (i = 7; i >= 0; i--) { env->crf[i] = val & 0b1111; val >>= 4; } diff --git a/tests/unit/test_ppc.c b/tests/unit/test_ppc.c index b7b34a08..4322a8fd 100644 --- a/tests/unit/test_ppc.c +++ b/tests/unit/test_ppc.c @@ -89,7 +89,24 @@ static void test_ppc32_sc(void) OK(uc_close(uc)); } +static void test_ppc32_cr(void) +{ + uc_engine *uc; + uint32_t r_cr = 0x12345678; + + uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, NULL, 0); + + OK(uc_reg_write(uc, UC_PPC_REG_CR, &r_cr)); + r_cr = 0; + OK(uc_reg_read(uc, UC_PPC_REG_CR, &r_cr)); + + TEST_CHECK(r_cr == 0x12345678); + + OK(uc_close(uc)); +} + TEST_LIST = {{"test_ppc32_add", test_ppc32_add}, {"test_ppc32_fadd", test_ppc32_fadd}, {"test_ppc32_sc", test_ppc32_sc}, + {"test_ppc32_cr", test_ppc32_cr}, {NULL, NULL}}; \ No newline at end of file From 5b5905695d4d9759c0d7f6665673ddeb7ea8beef Mon Sep 17 00:00:00 2001 From: Mio Date: Sat, 23 Jul 2022 19:21:31 +0800 Subject: [PATCH 04/77] Fix wrong location of UC_ARM64_REG_CP_REG in python bindings --- bindings/python/unicorn/unicorn.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index c7823568..1687ab63 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -357,15 +357,14 @@ def reg_write(reg_write_func, arch, reg_id, value): reg = uc_arm64_neon128() reg.low_qword = value & 0xffffffffffffffff reg.high_qword = value >> 64 - - if arch == uc.UC_ARCH_ARM: - if reg_id == arm64_const.UC_ARM64_REG_CP_REG: + elif reg_id == arm64_const.UC_ARM64_REG_CP_REG: reg = uc_arm64_cp_reg() if not isinstance(value, tuple) or len(value) != 6: raise UcError(uc.UC_ERR_ARG) reg.crn, reg.crm, reg.op0, reg.op1, reg.op2, reg.val = value - elif reg_id == arm_const.UC_ARM_REG_CP_REG: + if arch == uc.UC_ARCH_ARM: + if reg_id == arm_const.UC_ARM_REG_CP_REG: reg = uc_arm_cp_reg() if not isinstance(value, tuple) or len(value) != 8: raise UcError(uc.UC_ERR_ARG) From c7ff9d66cf5c49a7726c7c87a8a0871c79faf063 Mon Sep 17 00:00:00 2001 From: Mio Date: Sat, 23 Jul 2022 19:26:35 +0800 Subject: [PATCH 05/77] Move vex.l test to test_x86 --- tests/unit/test_x86.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 04d4c76f..9c1f4da3 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1106,6 +1106,25 @@ static void test_x86_correct_address_in_long_jump_hook(void) OK(uc_close(uc)); } +static void test_x86_invalid_vex_l(void) +{ + uc_engine *uc; + uc_err err; + + /* vmovdqu ymm1, [rcx] */ + char code[] = { '\xC5', '\xFE', '\x6F', '\x09' }; + + /* initialize memory and run emulation */ + OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); + OK(uc_mem_map(uc, 0, 2 * 1024 * 1024, UC_PROT_ALL)); + + OK(uc_mem_write(uc, 0, code, sizeof(code) / sizeof(code[0]))); + + uc_assert_err(UC_ERR_INSN_INVALID, uc_emu_start(uc, 0, sizeof(code) / sizeof(code[0]), 0, 0)); + + OK(uc_close(uc)); +} + TEST_LIST = { {"test_x86_in", test_x86_in}, {"test_x86_out", test_x86_out}, @@ -1143,4 +1162,5 @@ TEST_LIST = { test_x86_correct_address_in_small_jump_hook}, {"test_x86_correct_address_in_long_jump_hook", test_x86_correct_address_in_long_jump_hook}, + {"test_x86_invalid_vex_l", test_x86_invalid_vex_l}, {NULL, NULL}}; From d6d57834b0d4a3454ddd5a70e645813c58fb3e6e Mon Sep 17 00:00:00 2001 From: Mio Date: Sat, 23 Jul 2022 19:27:37 +0800 Subject: [PATCH 06/77] Format code --- include/unicorn/unicorn.h | 4 ++-- tests/unit/test_x86.c | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 38178de7..c8315b83 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -118,8 +118,8 @@ typedef enum uc_mode { UC_MODE_ARM = 0, // ARM mode UC_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2) // Depreciated, use UC_ARM_CPU_* with uc_ctl instead. - UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series. - UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM + UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series. + UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM UC_MODE_ARMBE8 = 1 << 10, // Big-endian data and Little-endian code. // Legacy support for UC1 only. diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 9c1f4da3..76b9b159 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1112,7 +1112,7 @@ static void test_x86_invalid_vex_l(void) uc_err err; /* vmovdqu ymm1, [rcx] */ - char code[] = { '\xC5', '\xFE', '\x6F', '\x09' }; + char code[] = {'\xC5', '\xFE', '\x6F', '\x09'}; /* initialize memory and run emulation */ OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); @@ -1120,7 +1120,8 @@ static void test_x86_invalid_vex_l(void) OK(uc_mem_write(uc, 0, code, sizeof(code) / sizeof(code[0]))); - uc_assert_err(UC_ERR_INSN_INVALID, uc_emu_start(uc, 0, sizeof(code) / sizeof(code[0]), 0, 0)); + uc_assert_err(UC_ERR_INSN_INVALID, + uc_emu_start(uc, 0, sizeof(code) / sizeof(code[0]), 0, 0)); OK(uc_close(uc)); } @@ -1162,5 +1163,5 @@ TEST_LIST = { test_x86_correct_address_in_small_jump_hook}, {"test_x86_correct_address_in_long_jump_hook", test_x86_correct_address_in_long_jump_hook}, - {"test_x86_invalid_vex_l", test_x86_invalid_vex_l}, + {"test_x86_invalid_vex_l", test_x86_invalid_vex_l}, {NULL, NULL}}; From 06a1858ffd4e76298f5fb04d7da3a149f3637d2b Mon Sep 17 00:00:00 2001 From: mio Date: Sat, 23 Jul 2022 20:09:38 +0800 Subject: [PATCH 07/77] Disable ming32 test --- .github/workflows/build-uc2.yml | 54 ++++++++++++++++----------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/build-uc2.yml b/.github/workflows/build-uc2.yml index 7e6b7839..9f302239 100644 --- a/.github/workflows/build-uc2.yml +++ b/.github/workflows/build-uc2.yml @@ -68,20 +68,20 @@ jobs: archiver: '7z a', generators: 'Ninja' } - - { - os: windows-2019, - arch: x64, - python-arch: x64, - python-ver: '3.8', - name: 'windows-x64 MINGW32 static', - shared: "no", - mingw: MINGW32, - mingw-arch: i686, - artifact: 'windows_mingw32.7z', - build_type: 'Debug', - archiver: '7z a', - generators: 'Ninja' - } + # - { # This fails randomly which can't be reproduced. + # os: windows-2019, + # arch: x64, + # python-arch: x64, + # python-ver: '3.8', + # name: 'windows-x64 MINGW32 static', + # shared: "no", + # mingw: MINGW32, + # mingw-arch: i686, + # artifact: 'windows_mingw32.7z', + # build_type: 'Debug', + # archiver: '7z a', + # generators: 'Ninja' + # } - { os: windows-2019, arch: x64, @@ -95,19 +95,19 @@ jobs: archiver: '7z a', generators: 'Visual Studio 16 2019' } - - { - os: windows-2019, - arch: x86, - python-arch: x86, - python-ver: '3.8', - name: 'windows-x86 MSVC 32bit shared', - msvc-arch: x86, - artifact: 'windows_msvc32_shared.7z', - shared: 'yes', - build_type: 'Debug', - archiver: '7z a', - generators: 'Visual Studio 16 2019' - } + # - { # This fails randomly which can't be reproduced. + # os: windows-2019, + # arch: x86, + # python-arch: x86, + # python-ver: '3.8', + # name: 'windows-x86 MSVC 32bit shared', + # msvc-arch: x86, + # artifact: 'windows_msvc32_shared.7z', + # shared: 'yes', + # build_type: 'Debug', + # archiver: '7z a', + # generators: 'Visual Studio 16 2019' + # } - { os: windows-2019, arch: x64, From 6d283cf464b82a86f7930e39c91c92ad3cefb58f Mon Sep 17 00:00:00 2001 From: mio Date: Sat, 23 Jul 2022 20:39:01 +0800 Subject: [PATCH 08/77] Fix ppc symbols clash --- qemu/ppc.h | 8 ++++++++ qemu/ppc64.h | 8 ++++++++ symbols.sh | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/qemu/ppc.h b/qemu/ppc.h index 7022629e..eff4b69d 100644 --- a/qemu/ppc.h +++ b/qemu/ppc.h @@ -1708,4 +1708,12 @@ #define ppc_dcr_init ppc_dcr_init_ppc #define ppc_cpu_pir ppc_cpu_pir_ppc #define ppc_irq_reset ppc_irq_reset_ppc +#define store_booke_tsr store_booke_tsr_ppc +#define get_pteg_offset32 get_pteg_offset32_ppc +#define ppc_booke_timers_init ppc_booke_timers_init_ppc +#define ppc_hash32_handle_mmu_fault ppc_hash32_handle_mmu_fault_ppc +#define gen_helper_store_booke_tsr gen_helper_store_booke_tsr_ppc +#define gen_helper_store_booke_tcr gen_helper_store_booke_tcr_ppc +#define store_booke_tcr store_booke_tcr_ppc +#define ppc_hash32_get_phys_page_debug ppc_hash32_get_phys_page_debug_ppc #endif diff --git a/qemu/ppc64.h b/qemu/ppc64.h index 992caf87..c08ee2d6 100644 --- a/qemu/ppc64.h +++ b/qemu/ppc64.h @@ -1708,4 +1708,12 @@ #define ppc_dcr_init ppc_dcr_init_ppc64 #define ppc_cpu_pir ppc_cpu_pir_ppc64 #define ppc_irq_reset ppc_irq_reset_ppc64 +#define store_booke_tsr store_booke_tsr_ppc64 +#define get_pteg_offset32 get_pteg_offset32_ppc64 +#define ppc_booke_timers_init ppc_booke_timers_init_ppc64 +#define ppc_hash32_handle_mmu_fault ppc_hash32_handle_mmu_fault_ppc64 +#define gen_helper_store_booke_tsr gen_helper_store_booke_tsr_ppc64 +#define gen_helper_store_booke_tcr gen_helper_store_booke_tcr_ppc64 +#define store_booke_tcr store_booke_tcr_ppc64 +#define ppc_hash32_get_phys_page_debug ppc_hash32_get_phys_page_debug_ppc64 #endif diff --git a/symbols.sh b/symbols.sh index 2968b959..0d426c00 100755 --- a/symbols.sh +++ b/symbols.sh @@ -6264,6 +6264,14 @@ ppc_dcr_register \ ppc_dcr_init \ ppc_cpu_pir \ ppc_irq_reset \ +store_booke_tsr \ +get_pteg_offset32 \ +ppc_booke_timers_init \ +ppc_hash32_handle_mmu_fault \ +gen_helper_store_booke_tsr \ +gen_helper_store_booke_tcr \ +store_booke_tcr \ +ppc_hash32_get_phys_page_debug \ " ppc64_SYMBOLS=${ppc_SYMBOLS} From 3d028882ed0006c4ccc53150b28cd4e3e0bd20fd Mon Sep 17 00:00:00 2001 From: mio Date: Sat, 23 Jul 2022 20:49:00 +0800 Subject: [PATCH 09/77] Fix wrong cput model check in uc_ctl --- uc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uc.c b/uc.c index 6bff4e77..82471965 100644 --- a/uc.c +++ b/uc.c @@ -2240,7 +2240,7 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) } else { int model = va_arg(args, int); - if (model <= 0 || uc->init_done) { + if (model < 0 || uc->init_done) { err = UC_ERR_ARG; break; } From ca6a8b4cacce62bbcf709eb60a30eafe22859b9a Mon Sep 17 00:00:00 2001 From: Yu3h0 <82574337+Yu3H0@users.noreply.github.com> Date: Mon, 25 Jul 2022 14:54:21 +0800 Subject: [PATCH 10/77] fix issue 1663:tricore pc don't move --- qemu/target/tricore/helper.h | 1 + qemu/target/tricore/op_helper.c | 9 +++++++++ qemu/target/tricore/translate.c | 20 ++++++++++++++------ qemu/tricore.h | 1 + symbols.sh | 1 + 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/qemu/target/tricore/helper.h b/qemu/target/tricore/helper.h index e1ee5fa0..e0712597 100644 --- a/qemu/target/tricore/helper.h +++ b/qemu/target/tricore/helper.h @@ -22,6 +22,7 @@ DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_6(uc_traceopcode, void, ptr, i64, i64, i32, ptr, i64) +DEF_HELPER_1(uc_tricore_exit,void, env) /* Arithmetic */ DEF_HELPER_3(add_ssov, i32, env, i32, i32) diff --git a/qemu/target/tricore/op_helper.c b/qemu/target/tricore/op_helper.c index 57ad816f..6bb7b3a0 100644 --- a/qemu/target/tricore/op_helper.c +++ b/qemu/target/tricore/op_helper.c @@ -2793,3 +2793,12 @@ uint32_t helper_psw_read(CPUTriCoreState *env) { return psw_read(env); } + +void helper_uc_tricore_exit(CPUTriCoreState *env) +{ + CPUState *cs = env_cpu(env); + + cs->exception_index = EXCP_HLT; + cs->halted = 1; + cpu_loop_exit(cs); +} \ No newline at end of file diff --git a/qemu/target/tricore/translate.c b/qemu/target/tricore/translate.c index 112f2eb0..016306fb 100644 --- a/qemu/target/tricore/translate.c +++ b/qemu/target/tricore/translate.c @@ -33,6 +33,11 @@ #include "exec/translator.h" #include "exec/gen-icount.h" +/* + * Unicorn: Special disas state for exiting in the middle of tb. + */ +#define DISAS_UC_EXIT DISAS_TARGET_6 + static const char *regnames_a[] = { "a0" , "a1" , "a2" , "a3" , "a4" , "a5" , "a6" , "a7" , "a8" , "a9" , "sp" , "a11" , @@ -9227,11 +9232,7 @@ static void tricore_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) // Unicorn: end address tells us to stop emulation if (uc_addr_is_exit(uc, ctx->base.pc_next)) { - gen_helper_rfe(tcg_ctx, tcg_ctx->cpu_env); - tcg_gen_exit_tb(tcg_ctx, NULL, 0); - cpu->exception_index = EXCP_HLT; - cpu->halted = 1; - ctx->base.is_jmp = DISAS_NORETURN; + ctx->base.is_jmp = DISAS_UC_EXIT; } else { insn_lo = cpu_lduw_code(env, ctx->base.pc_next); is_16bit = tricore_insn_is_16bit(insn_lo); @@ -9239,6 +9240,9 @@ static void tricore_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) insn_size = is_16bit ? 2 : 4; // Unicorn: trace this instruction on request if (HOOK_EXISTS_BOUNDED(ctx->uc, UC_HOOK_CODE, ctx->base.pc_next)) { + // Sync PC in advance + gen_save_pc(ctx, ctx->base.pc_next); + gen_uc_tracecode(tcg_ctx, insn_size, UC_HOOK_CODE_IDX, ctx->uc, ctx->base.pc_next); // the callback might want to stop emulation immediately @@ -9282,6 +9286,10 @@ static void tricore_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) case DISAS_TOO_MANY: gen_goto_tb(ctx, 0, ctx->base.pc_next); break; + case DISAS_UC_EXIT: + gen_save_pc(ctx, ctx->base.pc_next); + gen_helper_uc_tricore_exit(ctx->uc->tcg_ctx, ctx->uc->tcg_ctx->cpu_env); + break; case DISAS_NORETURN: break; default: @@ -9371,4 +9379,4 @@ void tricore_tcg_init(struct uc_struct *uc) tcg_ctx->cpu_PSW_SAV = tcg_global_mem_new(uc->tcg_ctx, tcg_ctx->cpu_env, offsetof(CPUTriCoreState, PSW_USB_SAV), "PSW_SAV"); -} \ No newline at end of file +} diff --git a/qemu/tricore.h b/qemu/tricore.h index 6603175f..3f41fc76 100644 --- a/qemu/tricore.h +++ b/qemu/tricore.h @@ -1286,4 +1286,5 @@ #define helper_pack helper_pack_tricore #define gen_intermediate_code gen_intermediate_code_tricore #define restore_state_to_opc restore_state_to_opc_tricore +#define helper_uc_tricore_exit helper_uc_tricore_exit_tricore #endif diff --git a/symbols.sh b/symbols.sh index 2968b959..f7c2272c 100755 --- a/symbols.sh +++ b/symbols.sh @@ -6284,6 +6284,7 @@ helper_fmsub \ helper_pack \ gen_intermediate_code \ restore_state_to_opc \ +helper_uc_tricore_exit \ " ARCHS="x86_64 arm aarch64 riscv32 riscv64 mips mipsel mips64 mips64el sparc sparc64 m68k ppc ppc64 s390x tricore" From 8303328aa830c2a1436266eec7e13058e93d3ec3 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 14 Aug 2022 12:42:34 +0200 Subject: [PATCH 11/77] Obtain memory mapping after hooks are called --- qemu/accel/tcg/cputlb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qemu/accel/tcg/cputlb.c b/qemu/accel/tcg/cputlb.c index 62233bc0..7a77dc51 100644 --- a/qemu/accel/tcg/cputlb.c +++ b/qemu/accel/tcg/cputlb.c @@ -1977,7 +1977,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, size_t size = memop_size(op); struct hook *hook; bool handled; - MemoryRegion *mr = memory_mapping(uc, addr); + MemoryRegion *mr; if (!uc->size_recur_mem) { // disabling write callback if in recursive call // Unicorn: callback on memory write @@ -1994,6 +1994,9 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, } } + // Load the latest memory mapping. + mr = memory_mapping(uc, addr); + // Unicorn: callback on invalid memory if (mr == NULL) { handled = false; From 01e8d969c8caff5096b1c0c933b46f83e1fed9e0 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 14 Aug 2022 12:56:52 +0200 Subject: [PATCH 12/77] Update to r25 Ref: https://github.com/actions/runner-images/issues/5930 --- .github/workflows/build-uc2.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-uc2.yml b/.github/workflows/build-uc2.yml index 9f302239..09d25d8d 100644 --- a/.github/workflows/build-uc2.yml +++ b/.github/workflows/build-uc2.yml @@ -328,9 +328,9 @@ jobs: brew install p7zip cmake ninja mkdir build mkdir instdir - cmake . -DCMAKE_TOOLCHAIN_FILE="$ANDROID_HOME/ndk/21.4.7075529/build/cmake/android.toolchain.cmake" \ + cmake . -DCMAKE_TOOLCHAIN_FILE="$ANDROID_HOME/ndk/25.0.8775105/build/cmake/android.toolchain.cmake" \ -DANDROID_PLATFORM=android-28 \ - -DANDROID_NDK="$ANDROID_HOME/ndk/21.4.7075529" \ + -DANDROID_NDK="$ANDROID_HOME/ndk/25.0.8775105" \ -DANDROID_ABI=${{ matrix.config.arch }} \ -DOLP_SDK_ENABLE_TESTING=NO \ -DOLP_SDK_BUILD_EXAMPLES=ON \ From 2c00546c6e146f16b92a53583142815e1b3a493d Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 14 Aug 2022 13:35:54 +0200 Subject: [PATCH 13/77] Merge rhelmot's fix --- qemu/accel/tcg/cpu-exec.c | 3 ++ qemu/accel/tcg/cputlb.c | 16 ++++-- qemu/accel/tcg/translate-all.c | 5 +- tests/unit/test_x86.c | 94 ++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 7 deletions(-) diff --git a/qemu/accel/tcg/cpu-exec.c b/qemu/accel/tcg/cpu-exec.c index 471ddc94..688cc98c 100644 --- a/qemu/accel/tcg/cpu-exec.c +++ b/qemu/accel/tcg/cpu-exec.c @@ -595,6 +595,9 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu) } tb = tb_find(cpu, last_tb, tb_exit, cflags); + if (unlikely(cpu->exit_request)) { + continue; + } cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit); /* Try to align the host and virtual clocks if the guest is in advance */ diff --git a/qemu/accel/tcg/cputlb.c b/qemu/accel/tcg/cputlb.c index 7a77dc51..9305b06c 100644 --- a/qemu/accel/tcg/cputlb.c +++ b/qemu/accel/tcg/cputlb.c @@ -1451,7 +1451,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, continue; if (!HOOK_BOUND_CHECK(hook, addr)) continue; - if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, size - uc->size_recur_mem, 0, hook->user_data))) + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, size, 0, hook->user_data))) break; // the last callback may already asked to stop emulation @@ -1466,7 +1466,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, continue; if (!HOOK_BOUND_CHECK(hook, addr)) continue; - if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, size - uc->size_recur_mem, 0, hook->user_data))) + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, size, 0, hook->user_data))) break; // the last callback may already asked to stop emulation @@ -1518,7 +1518,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, continue; if (!HOOK_BOUND_CHECK(hook, addr)) continue; - if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, size - uc->size_recur_mem, 0, hook->user_data))) + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, size, 0, hook->user_data))) break; // the last callback may already asked to stop emulation @@ -1546,7 +1546,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, continue; if (!HOOK_BOUND_CHECK(hook, addr)) continue; - if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, size - uc->size_recur_mem, 0, hook->user_data))) + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, size, 0, hook->user_data))) break; // the last callback may already asked to stop emulation @@ -1635,11 +1635,15 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, target_ulong addr1, addr2; uint64_t r1, r2; unsigned shift; + int old_size; do_unaligned_access: addr1 = addr & ~((target_ulong)size - 1); addr2 = addr1 + size; + old_size = uc->size_recur_mem; + uc->size_recur_mem = size; r1 = full_load(env, addr1, oi, retaddr); r2 = full_load(env, addr2, oi, retaddr); + uc->size_recur_mem = old_size; shift = (addr & (size - 1)) * 8; if (memop_big_endian(op)) { @@ -2139,6 +2143,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, CPUTLBEntry *entry2; target_ulong page2, tlb_addr2; size_t size2; + int old_size; do_unaligned_access: /* @@ -2181,6 +2186,8 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, * This loop must go in the forward direction to avoid issues * with self-modifying code in Windows 64-bit. */ + old_size = uc->size_recur_mem; + uc->size_recur_mem = size; for (i = 0; i < size; ++i) { uint8_t val8; if (memop_big_endian(op)) { @@ -2192,6 +2199,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, } helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr); } + uc->size_recur_mem = old_size; return; } diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c index 232a9178..91dd5ce7 100644 --- a/qemu/accel/tcg/translate-all.c +++ b/qemu/accel/tcg/translate-all.c @@ -1584,9 +1584,8 @@ TranslationBlock *tb_gen_code(CPUState *cpu, phys_pc = get_page_addr_code(env, pc); if (phys_pc == -1) { - /* Generate a temporary TB with 1 insn in it */ - cflags &= ~CF_COUNT_MASK; - cflags |= CF_NOCACHE | 1; + /* Generate a temporary TB; do not cache */ + cflags |= CF_NOCACHE; } cflags &= ~CF_CLUSTER_MASK; diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 76b9b159..c91b733d 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1106,6 +1106,7 @@ static void test_x86_correct_address_in_long_jump_hook(void) OK(uc_close(uc)); } + static void test_x86_invalid_vex_l(void) { uc_engine *uc; @@ -1122,7 +1123,98 @@ static void test_x86_invalid_vex_l(void) uc_assert_err(UC_ERR_INSN_INVALID, uc_emu_start(uc, 0, sizeof(code) / sizeof(code[0]), 0, 0)); + OK(uc_close(uc)); +} +struct writelog_t { + uint32_t addr, size; +}; + +static void test_x86_unaligned_access_callback(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, int64_t value, void *user_data) +{ + TEST_CHECK(size != 0); + struct writelog_t *write_log = (struct writelog_t *)user_data; + + for (int i = 0; i < 10; i++) { + if (write_log[i].size == 0) { + write_log[i].addr = (uint32_t) address; + write_log[i].size = (uint32_t) size; + return; + } + } + TEST_ASSERT(false); +} + +static void test_x86_unaligned_access(void) +{ + uc_engine *uc; + uc_hook hook; + // mov dword ptr [0x200001], eax; mov eax, dword ptr [0x200001] + char code[] = "\xa3\x01\x00\x20\x00\xa1\x01\x00\x20\x00"; + uint32_t r_eax = 0x41424344; + struct writelog_t write_log[10]; + struct writelog_t read_log[10]; + memset(write_log, 0, sizeof(write_log)); + memset(read_log, 0, sizeof(read_log)); + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); + OK(uc_mem_map(uc, 0x200000, 0x1000, UC_PROT_ALL)); + OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_WRITE, test_x86_unaligned_access_callback, + write_log, 1, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_READ, test_x86_unaligned_access_callback, + read_log, 1, 0)); + + OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_eax)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + TEST_CHECK(write_log[0].addr == 0x200001); + TEST_CHECK(write_log[0].size == 4); + TEST_CHECK(write_log[1].size == 0); + + TEST_CHECK(read_log[0].addr == 0x200001); + TEST_CHECK(read_log[0].size == 4); + TEST_CHECK(read_log[1].size == 0); + + char b; + OK(uc_mem_read(uc, 0x200001, &b, 1)); + TEST_CHECK(b == 0x44); + OK(uc_mem_read(uc, 0x200002, &b, 1)); + TEST_CHECK(b == 0x43); + OK(uc_mem_read(uc, 0x200003, &b, 1)); + TEST_CHECK(b == 0x42); + OK(uc_mem_read(uc, 0x200004, &b, 1)); + TEST_CHECK(b == 0x41); + + OK(uc_close(uc)); +} + +static void test_x86_lazy_mapping_mem_callback(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, int64_t value, void *user_data) +{ + OK(uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL)); + OK(uc_mem_write(uc, 0x1000, "\x90\x90", 2)); // nop; nop +} + +static void test_x86_lazy_mapping_block_callback(uc_engine *uc, + uint64_t address, uint32_t size, void *user_data) +{ + int *block_count = (int*)user_data; + (*block_count)++; +} + +static void test_x86_lazy_mapping(void) +{ + uc_engine *uc; + uc_hook mem_hook, block_hook; + int block_count = 0; + + OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); + OK(uc_hook_add(uc, &mem_hook, UC_HOOK_MEM_FETCH_UNMAPPED, test_x86_lazy_mapping_mem_callback, NULL, 1, 0)); + OK(uc_hook_add(uc, &block_hook, UC_HOOK_BLOCK, test_x86_lazy_mapping_block_callback, &block_count, 1, 0)); + + OK(uc_emu_start(uc, 0x1000, 0x1002, 0, 0)); + TEST_CHECK(block_count == 1); OK(uc_close(uc)); } @@ -1164,4 +1256,6 @@ TEST_LIST = { {"test_x86_correct_address_in_long_jump_hook", test_x86_correct_address_in_long_jump_hook}, {"test_x86_invalid_vex_l", test_x86_invalid_vex_l}, + {"test_x86_unaligned_access", test_x86_unaligned_access}, + {"test_x86_lazy_mapping", test_x86_lazy_mapping}, {NULL, NULL}}; From 419d710c4ac9b0461df2b153c98ddc1f1ebfa38f Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 14 Aug 2022 13:37:25 +0200 Subject: [PATCH 14/77] Return true when we handled the memory events --- tests/unit/test_x86.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index c91b733d..75fe1a8f 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1189,11 +1189,14 @@ static void test_x86_unaligned_access(void) OK(uc_close(uc)); } -static void test_x86_lazy_mapping_mem_callback(uc_engine *uc, uc_mem_type type, +static bool test_x86_lazy_mapping_mem_callback(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data) { OK(uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL)); OK(uc_mem_write(uc, 0x1000, "\x90\x90", 2)); // nop; nop + + // Handled! + return true; } static void test_x86_lazy_mapping_block_callback(uc_engine *uc, From bdb141aeef1639ba78fe9ffc3392dbae69d35623 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 14 Aug 2022 15:42:37 +0200 Subject: [PATCH 15/77] Disable unaligned access test on ppc and aarch64 The memoy read operations on these architectures are inlined e.g. ldur on aarch64 --- CMakeLists.txt | 3 +++ tests/unit/test_x86.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9574be94..62504489 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1412,6 +1412,9 @@ if(UNICORN_BUILD_TESTS) file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb shell \"chmod +x /data/local/tmp/build/${TEST_FILE}\"\n") file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb shell \'LD_LIBRARY_PATH=/data/local/tmp/build:$LD_LIBRARY_PATH /data/local/tmp/build/${TEST_FILE}\' || exit -1\n") endif() + if (UNICORN_TARGET_ARCH STREQUAL "aarch64" OR UNICORN_TARGET_ARCH STREQUAL "ppc") + target_compile_definitions(${TEST_FILE} PRIVATE TARGET_READ_INLINED) + endif() endforeach() endif() diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 75fe1a8f..ba37e638 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1126,6 +1126,7 @@ static void test_x86_invalid_vex_l(void) OK(uc_close(uc)); } +#ifndef TARGET_READ_INLINED struct writelog_t { uint32_t addr, size; }; @@ -1188,6 +1189,7 @@ static void test_x86_unaligned_access(void) OK(uc_close(uc)); } +#endif static bool test_x86_lazy_mapping_mem_callback(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data) @@ -1259,6 +1261,8 @@ TEST_LIST = { {"test_x86_correct_address_in_long_jump_hook", test_x86_correct_address_in_long_jump_hook}, {"test_x86_invalid_vex_l", test_x86_invalid_vex_l}, +#ifndef TARGET_READ_INLINED {"test_x86_unaligned_access", test_x86_unaligned_access}, +#endif {"test_x86_lazy_mapping", test_x86_lazy_mapping}, {NULL, NULL}}; From 2e8986174b9c223793aae1eabbb68d8555c06990 Mon Sep 17 00:00:00 2001 From: relapids Date: Mon, 15 Aug 2022 05:38:29 -0700 Subject: [PATCH 16/77] Fix leak in test_mem_protect_map_ptr. --- tests/unit/test_mem.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index fae4b21f..a1db14e1 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -142,6 +142,9 @@ static void test_mem_protect_map_ptr(void) TEST_CHECK(val == mem); OK(uc_close(uc)); + + free(data2); + free(data1); } static void test_map_at_the_end(void) From 7430e249ea4f6988b972209e8fa52c0f6a8c6910 Mon Sep 17 00:00:00 2001 From: relapids Date: Mon, 15 Aug 2022 05:55:25 -0700 Subject: [PATCH 17/77] Fix for incorrect argument types passed to uc_ctl_request_cache/uc_ctl_remove_cache in test_uc_ctl_tb_cache. --- samples/sample_ctl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c index bf55c02a..f154f24e 100644 --- a/samples/sample_ctl.c +++ b/samples/sample_ctl.c @@ -243,7 +243,7 @@ static void test_uc_ctl_tb_cache() // Now we request cache for all TBs. for (int i = 0; i < TB_COUNT; i++) { - err = uc_ctl_request_cache(uc, ADDRESS + i * TCG_MAX_INSNS, &tb); + err = uc_ctl_request_cache(uc, (uint64_t)(ADDRESS + i * TCG_MAX_INSNS), &tb); printf(">>> TB is cached at 0x%" PRIx64 " which has %" PRIu16 " instructions with %" PRIu16 " bytes.\n", tb.pc, tb.icount, tb.size); @@ -258,8 +258,8 @@ static void test_uc_ctl_tb_cache() // Now we clear cache for all TBs. for (int i = 0; i < TB_COUNT; i++) { - err = uc_ctl_remove_cache(uc, ADDRESS + i * TCG_MAX_INSNS, - ADDRESS + i * TCG_MAX_INSNS + 1); + err = uc_ctl_remove_cache(uc, (uint64_t)(ADDRESS + i * TCG_MAX_INSNS), + (uint64_t)(ADDRESS + i * TCG_MAX_INSNS + 1)); if (err) { printf("Failed on uc_ctl() with error returned: %u\n", err); return; From 1c63021592a5b5bc964cfd0ef58a88c3237e2aa7 Mon Sep 17 00:00:00 2001 From: mio Date: Mon, 15 Aug 2022 20:33:00 +0200 Subject: [PATCH 18/77] Disable mingw32 tests correctly --- .github/workflows/build-uc2.yml | 54 ++++++++++++++++----------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/build-uc2.yml b/.github/workflows/build-uc2.yml index 09d25d8d..5f34b64f 100644 --- a/.github/workflows/build-uc2.yml +++ b/.github/workflows/build-uc2.yml @@ -54,20 +54,20 @@ jobs: archiver: '7z a', generators: 'Ninja' } - - { - os: windows-2019, - arch: x64, - python-arch: x64, - python-ver: '3.8', - name: 'windows-x64 MINGW32 shared', - shared: "yes", - mingw: MINGW32, - mingw-arch: i686, - artifact: 'windows_mingw32.7z', - build_type: 'Debug', - archiver: '7z a', - generators: 'Ninja' - } + # - { # This fails randomly which can't be reproduced. + # os: windows-2019, + # arch: x64, + # python-arch: x64, + # python-ver: '3.8', + # name: 'windows-x64 MINGW32 shared', + # shared: "yes", + # mingw: MINGW32, + # mingw-arch: i686, + # artifact: 'windows_mingw32.7z', + # build_type: 'Debug', + # archiver: '7z a', + # generators: 'Ninja' + # } # - { # This fails randomly which can't be reproduced. # os: windows-2019, # arch: x64, @@ -95,19 +95,19 @@ jobs: archiver: '7z a', generators: 'Visual Studio 16 2019' } - # - { # This fails randomly which can't be reproduced. - # os: windows-2019, - # arch: x86, - # python-arch: x86, - # python-ver: '3.8', - # name: 'windows-x86 MSVC 32bit shared', - # msvc-arch: x86, - # artifact: 'windows_msvc32_shared.7z', - # shared: 'yes', - # build_type: 'Debug', - # archiver: '7z a', - # generators: 'Visual Studio 16 2019' - # } + - { + os: windows-2019, + arch: x86, + python-arch: x86, + python-ver: '3.8', + name: 'windows-x86 MSVC 32bit shared', + msvc-arch: x86, + artifact: 'windows_msvc32_shared.7z', + shared: 'yes', + build_type: 'Debug', + archiver: '7z a', + generators: 'Visual Studio 16 2019' + } - { os: windows-2019, arch: x64, From 2ac7b5579704091a2b64265d9f5d1db327722213 Mon Sep 17 00:00:00 2001 From: relapids Date: Mon, 15 Aug 2022 05:26:48 -0700 Subject: [PATCH 19/77] Allow building with clang-cl on Windows. --- qemu/include/qemu/atomic.h | 64 +++++++++++++++++------------------ qemu/include/qemu/int128.h | 2 ++ qemu/target/ppc/excp_helper.c | 4 +++ 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/qemu/include/qemu/atomic.h b/qemu/include/qemu/atomic.h index 3eb72dbe..4e26bedf 100644 --- a/qemu/include/qemu/atomic.h +++ b/qemu/include/qemu/atomic.h @@ -31,38 +31,38 @@ * implicit promotion. int and larger types, as well as pointers, can be * converted to a non-qualified type just by applying a binary operator. */ -#define typeof_strip_qual(expr) \ - typeof( \ - __builtin_choose_expr( \ - __builtin_types_compatible_p(typeof(expr), bool) || \ - __builtin_types_compatible_p(typeof(expr), const bool) || \ - __builtin_types_compatible_p(typeof(expr), volatile bool) || \ - __builtin_types_compatible_p(typeof(expr), const volatile bool), \ - (bool)1, \ - __builtin_choose_expr( \ - __builtin_types_compatible_p(typeof(expr), signed char) || \ - __builtin_types_compatible_p(typeof(expr), const signed char) || \ - __builtin_types_compatible_p(typeof(expr), volatile signed char) || \ - __builtin_types_compatible_p(typeof(expr), const volatile signed char), \ - (signed char)1, \ - __builtin_choose_expr( \ - __builtin_types_compatible_p(typeof(expr), unsigned char) || \ - __builtin_types_compatible_p(typeof(expr), const unsigned char) || \ - __builtin_types_compatible_p(typeof(expr), volatile unsigned char) || \ - __builtin_types_compatible_p(typeof(expr), const volatile unsigned char), \ - (unsigned char)1, \ - __builtin_choose_expr( \ - __builtin_types_compatible_p(typeof(expr), signed short) || \ - __builtin_types_compatible_p(typeof(expr), const signed short) || \ - __builtin_types_compatible_p(typeof(expr), volatile signed short) || \ - __builtin_types_compatible_p(typeof(expr), const volatile signed short), \ - (signed short)1, \ - __builtin_choose_expr( \ - __builtin_types_compatible_p(typeof(expr), unsigned short) || \ - __builtin_types_compatible_p(typeof(expr), const unsigned short) || \ - __builtin_types_compatible_p(typeof(expr), volatile unsigned short) || \ - __builtin_types_compatible_p(typeof(expr), const volatile unsigned short), \ - (unsigned short)1, \ +#define typeof_strip_qual(expr) \ + __typeof__( \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof__(expr), bool) || \ + __builtin_types_compatible_p(__typeof__(expr), const bool) || \ + __builtin_types_compatible_p(__typeof__(expr), volatile bool) || \ + __builtin_types_compatible_p(__typeof__(expr), const volatile bool), \ + (bool)1, \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), const signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), volatile signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), const volatile signed char), \ + (signed char)1, \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char) || \ + __builtin_types_compatible_p(__typeof__(expr), const unsigned char) || \ + __builtin_types_compatible_p(__typeof__(expr), volatile unsigned char) || \ + __builtin_types_compatible_p(__typeof__(expr), const volatile unsigned char), \ + (unsigned char)1, \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), const signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), volatile signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), const volatile signed short), \ + (signed short)1, \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), const unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), volatile unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), const volatile unsigned short), \ + (unsigned short)1, \ (expr)+0)))))) #ifdef __ATOMIC_RELAXED diff --git a/qemu/include/qemu/int128.h b/qemu/include/qemu/int128.h index d32511a6..d1d1ad44 100644 --- a/qemu/include/qemu/int128.h +++ b/qemu/include/qemu/int128.h @@ -146,7 +146,9 @@ static inline Int128 bswap128(Int128 a) #else /* !CONFIG_INT128 */ typedef struct Int128 Int128; +#if !(defined(_MSC_VER) && defined(__clang__)) typedef Int128 __int128_t; +#endif struct Int128 { uint64_t lo; diff --git a/qemu/target/ppc/excp_helper.c b/qemu/target/ppc/excp_helper.c index beaef6cd..f1114b5b 100644 --- a/qemu/target/ppc/excp_helper.c +++ b/qemu/target/ppc/excp_helper.c @@ -1061,7 +1061,11 @@ void helper_store_msr(CPUPPCState *env, target_ulong val) } #if defined(TARGET_PPC64) +#if defined(_MSC_VER) && defined(__clang__) +void helper_pminsn(CPUPPCState *env, uint32_t insn) +#else void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) +#endif { CPUState *cs; From 5a54b3d7af7fd2477bce9ac61485d0ea260795cb Mon Sep 17 00:00:00 2001 From: relapids Date: Mon, 15 Aug 2022 06:45:25 -0700 Subject: [PATCH 20/77] Fix a segfault inside tb_remove_from_jmp_list by forcing clang-cl to use the same atomic routines as MSVC. --- qemu/include/qemu/atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu/include/qemu/atomic.h b/qemu/include/qemu/atomic.h index 4e26bedf..84922100 100644 --- a/qemu/include/qemu/atomic.h +++ b/qemu/include/qemu/atomic.h @@ -65,7 +65,7 @@ (unsigned short)1, \ (expr)+0)))))) -#ifdef __ATOMIC_RELAXED +#if defined(__ATOMIC_RELAXED) && !(defined(_MSC_VER) && defined(__clang__)) /* For C11 atomic ops */ /* Sanity check that the size of an atomic operation isn't "overly large". From a3ccbf2e594a34fc10c83f246cc21b19f35c8817 Mon Sep 17 00:00:00 2001 From: relapids Date: Mon, 15 Aug 2022 15:56:25 -0700 Subject: [PATCH 21/77] Fix memory leak in PPC target. --- qemu/target/ppc/unicorn.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/qemu/target/ppc/unicorn.c b/qemu/target/ppc/unicorn.c index de91d88c..8ce3e02b 100644 --- a/qemu/target/ppc/unicorn.c +++ b/qemu/target/ppc/unicorn.c @@ -109,6 +109,7 @@ static void ppc_release(void *ctx) int i; TCGContext *tcg_ctx = (TCGContext *)ctx; PowerPCCPU *cpu = (PowerPCCPU *)tcg_ctx->uc->cpu; + CPUPPCState *env = &cpu->env; CPUTLBDesc *d = cpu->neg.tlb.d; CPUTLBDescFast *f = cpu->neg.tlb.f; CPUTLBDesc *desc; @@ -132,6 +133,20 @@ static void ppc_release(void *ctx) // g_free(tcg_ctx->tb_ctx.tbs); + if (env->nb_tlb != 0) { + switch(env->tlb_type) { + case TLB_6XX: + g_free(env->tlb.tlb6); + break; + case TLB_EMB: + g_free(env->tlb.tlbe); + break; + case TLB_MAS: + g_free(env->tlb.tlbm); + break; + } + } + ppc_cpu_instance_finalize(tcg_ctx->uc->cpu); ppc_cpu_unrealize(tcg_ctx->uc->cpu); } From e15173dd264a9c3cb2d87e7ca11c48786699865d Mon Sep 17 00:00:00 2001 From: relapids Date: Mon, 15 Aug 2022 21:26:29 -0700 Subject: [PATCH 22/77] Fix memory leaks in TriCore target. --- qemu/target/tricore/unicorn.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/qemu/target/tricore/unicorn.c b/qemu/target/tricore/unicorn.c index 2ccb2c0d..88e937bb 100644 --- a/qemu/target/tricore/unicorn.c +++ b/qemu/target/tricore/unicorn.c @@ -263,6 +263,25 @@ static int tricore_cpus_init(struct uc_struct *uc, const char *cpu_model) return 0; } +static void tricore_release(void *ctx) +{ + int i; + TCGContext *tcg_ctx = (TCGContext *)ctx; + TriCoreCPU *cpu = (TriCoreCPU *)tcg_ctx->uc->cpu; + CPUTLBDesc *d = cpu->neg.tlb.d; + CPUTLBDescFast *f = cpu->neg.tlb.f; + CPUTLBDesc *desc; + CPUTLBDescFast *fast; + + release_common(ctx); + for (i = 0; i < NB_MMU_MODES; i++) { + desc = &(d[i]); + fast = &(f[i]); + g_free(desc->iotlb); + g_free(fast->table); + } +} + void tricore_uc_init(struct uc_struct *uc) { uc->reg_read = tricore_reg_read; @@ -271,6 +290,7 @@ void tricore_uc_init(struct uc_struct *uc) uc->set_pc = tricore_set_pc; uc->get_pc = tricore_get_pc; uc->cpus_init = tricore_cpus_init; + uc->release = tricore_release; uc->cpu_context_size = offsetof(CPUTriCoreState, end_reset_fields); uc_common_init(uc); -} \ No newline at end of file +} From 154a21d6a3e80df49f7bc4a58cae97388f2fa6bd Mon Sep 17 00:00:00 2001 From: relapids Date: Thu, 18 Aug 2022 18:29:24 -0700 Subject: [PATCH 23/77] Disable ARM-specific tests when ARM is unavailable. --- CMakeLists.txt | 3 +++ tests/unit/test_ctl.c | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 62504489..f63beabb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1403,6 +1403,9 @@ if(UNICORN_BUILD_TESTS) add_executable(${TEST_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/unit/${TEST_FILE}.c ) + target_compile_options(${TEST_FILE} PRIVATE + ${UNICORN_COMPILE_OPTIONS} + ) target_link_libraries(${TEST_FILE} PRIVATE ${SAMPLES_LIB} ) diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 3b56611d..b96d7cf5 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -175,6 +175,8 @@ static void test_uc_ctl_tb_cache(void) OK(uc_close(uc)); } +// Test requires UC_ARCH_ARM. +#ifdef UNICORN_HAS_ARM static void test_uc_ctl_change_page_size(void) { uc_engine *uc; @@ -191,7 +193,10 @@ static void test_uc_ctl_change_page_size(void) OK(uc_close(uc)); OK(uc_close(uc2)); } +#endif +// Test requires UC_ARCH_ARM. +#ifdef UNICORN_HAS_ARM // Copy from test_arm.c but with new API. static void test_uc_ctl_arm_cpu(void) { @@ -226,6 +231,7 @@ static void test_uc_ctl_arm_cpu(void) OK(uc_close(uc)); } +#endif static void test_uc_hook_cached_cb(uc_engine *uc, uint64_t addr, size_t size, void *user_data) @@ -289,7 +295,9 @@ TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, {"test_uc_ctl_time_out", test_uc_ctl_time_out}, {"test_uc_ctl_exits", test_uc_ctl_exits}, {"test_uc_ctl_tb_cache", test_uc_ctl_tb_cache}, +#ifdef UNICORN_HAS_ARM {"test_uc_ctl_change_page_size", test_uc_ctl_change_page_size}, {"test_uc_ctl_arm_cpu", test_uc_ctl_arm_cpu}, +#endif {"test_uc_hook_cached_uaf", test_uc_hook_cached_uaf}, - {NULL, NULL}}; \ No newline at end of file + {NULL, NULL}}; From a0eb240a2954eb0b32a152a2c1cc0af50ce637a9 Mon Sep 17 00:00:00 2001 From: relapids Date: Thu, 18 Aug 2022 21:59:32 -0700 Subject: [PATCH 24/77] Fix MSVC runtime library handling in CMakeLists. --- CMakeLists.txt | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 62504489..0218f5c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,16 +3,18 @@ cmake_minimum_required(VERSION 3.1) -if(MSVC) - if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.15") - # set all policies to max supported by actual running cmake version - # mainly want the following: - # CMP0091: prevent msvcrt flags being added to default CMAKE__FLAGS_ - # CMP0092: prevent warning flags being added to default CMAKE__FLAGS - cmake_policy(VERSION ${CMAKE_VERSION}) - else() - message(FATAL_ERROR "please update cmake") - endif() +# Only required for MSVC, but we can't know the compiler at this point because we haven't +# called enable_language() or project(), and if we did that it would lock in the old +# policy. Setting these policies is harmless for non-MSVC though, so just enable them +# always. +if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.15") + # Set explicitly the policies we want rather than raising the base to the current + # version. This prevents unintended behavior changes as CMake evolves and provides a + # consistent experience across different CMake versions. + # CMP0091: prevent msvcrt flags being added to default CMAKE__FLAGS_ + cmake_policy(SET CMP0091 NEW) + # CMP0092: prevent warning flags being added to default CMAKE__FLAGS for MSVC + cmake_policy(SET CMP0092 NEW) endif() # Workaround to fix wrong compiler on macos. @@ -31,6 +33,13 @@ endif() project(unicorn C) +# We depend on the availability of the CMAKE_MSVC_RUNTIME_LIBRARY, which is only +# available in CMake 3.15 and above (see also the comments above in regards to policy +# CMP0091). +if(MSVC AND CMAKE_VERSION VERSION_LESS "3.15") + message(FATAL_ERROR "Please update CMake to 3.15 or greater.") +endif() + # mainline qemu mostly just uses compiler default set(CMAKE_C_STANDARD 11) From c4a0813f4aa708f5235ec420c21c335ae2eaa1ae Mon Sep 17 00:00:00 2001 From: Mio Date: Wed, 31 Aug 2022 23:26:01 +0800 Subject: [PATCH 25/77] Add a test for infinite loop when sync-ing pc for UC_HOOL_BLOCK #1661 --- tests/unit/test_arm64.c | 43 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 8afdd0ec..bd64a4c9 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -1,10 +1,14 @@ +#include "acutest.h" +#include "unicorn/unicorn.h" #include "unicorn_test.h" +#include +#include 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, uc_cpu_arm cpu) + const char *code, uint64_t size, uc_cpu_arm64 cpu) { OK(uc_open(arch, mode, uc)); OK(uc_ctl_set_cpu_model(*uc, cpu)); @@ -291,6 +295,42 @@ static void test_arm64_correct_address_in_long_jump_hook(void) OK(uc_close(uc)); } +static void test_arm64_block_sync_pc_cb(uc_engine* uc, uint64_t addr, uint32_t size, void* data) +{ + uint64_t val = code_start; + bool first = *(bool*)data; + if (first) { + OK(uc_reg_write(uc, UC_ARM64_REG_PC, (void*)&val)); + *(bool*)data = false; + } +} + +static void test_arm64_block_sync_pc(void) +{ + uc_engine* uc; + // add x0, x0, #1234;bl t;t:mov x1, #5678; + const char code[] = "\x00\x48\x13\x91\x01\x00\x00\x94\xc1\xc5\x82\xd2"; + uc_hook hk; + uint64_t x0; + bool data = true; + + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1, + UC_CPU_ARM64_A72); + OK(uc_hook_add(uc, &hk, UC_HOOK_BLOCK, test_arm64_block_sync_pc_cb, (void*)&data, code_start + 8, code_start + 12)); + + x0 = 0; + OK(uc_reg_write(uc, UC_ARM64_REG_X0, (void*)&x0)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_ARM64_REG_X0, (void*)&x0)); + + TEST_CHECK(x0 == (1234 * 2)); + + OK(uc_hook_del(uc, hk)); + OK(uc_close(uc)); +} + + TEST_LIST = {{"test_arm64_until", test_arm64_until}, {"test_arm64_code_patching", test_arm64_code_patching}, {"test_arm64_code_patching_count", test_arm64_code_patching_count}, @@ -301,4 +341,5 @@ TEST_LIST = {{"test_arm64_until", test_arm64_until}, test_arm64_correct_address_in_small_jump_hook}, {"test_arm64_correct_address_in_long_jump_hook", test_arm64_correct_address_in_long_jump_hook}, + {"test_arm64_block_sync_pc", test_arm64_block_sync_pc}, {NULL, NULL}}; From 092014a6cc85ee94b42646eed2db4a98012e1e31 Mon Sep 17 00:00:00 2001 From: Mio Date: Wed, 31 Aug 2022 23:26:40 +0800 Subject: [PATCH 26/77] Don't sync pc if user requests a restart --- qemu/accel/tcg/cpu-exec.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/qemu/accel/tcg/cpu-exec.c b/qemu/accel/tcg/cpu-exec.c index 688cc98c..05266c6f 100644 --- a/qemu/accel/tcg/cpu-exec.c +++ b/qemu/accel/tcg/cpu-exec.c @@ -86,11 +86,14 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb) case UC_ERR_FETCH_UNALIGNED: break; default: - if (cc->synchronize_from_tb) { - cc->synchronize_from_tb(cpu, last_tb); - } else { - assert(cc->set_pc); - cc->set_pc(cpu, last_tb->pc); + // If we receive a quit request, users has sync-ed PC themselves. + if (!cpu->uc->quit_request) { + if (cc->synchronize_from_tb) { + cc->synchronize_from_tb(cpu, last_tb); + } else { + assert(cc->set_pc); + cc->set_pc(cpu, last_tb->pc); + } } } } From a0e119c6f0e494801a094e28b3bddf32bab7024d Mon Sep 17 00:00:00 2001 From: Mio Date: Wed, 31 Aug 2022 23:27:24 +0800 Subject: [PATCH 27/77] Format code --- qemu/target/ppc/unicorn.c | 2 +- samples/sample_ctl.c | 3 ++- tests/unit/test_arm64.c | 23 ++++++++++++----------- tests/unit/test_x86.c | 30 +++++++++++++++++------------- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/qemu/target/ppc/unicorn.c b/qemu/target/ppc/unicorn.c index 8ce3e02b..b157ce5a 100644 --- a/qemu/target/ppc/unicorn.c +++ b/qemu/target/ppc/unicorn.c @@ -134,7 +134,7 @@ static void ppc_release(void *ctx) // g_free(tcg_ctx->tb_ctx.tbs); if (env->nb_tlb != 0) { - switch(env->tlb_type) { + switch (env->tlb_type) { case TLB_6XX: g_free(env->tlb.tlb6); break; diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c index f154f24e..0b1b5898 100644 --- a/samples/sample_ctl.c +++ b/samples/sample_ctl.c @@ -243,7 +243,8 @@ static void test_uc_ctl_tb_cache() // Now we request cache for all TBs. for (int i = 0; i < TB_COUNT; i++) { - err = uc_ctl_request_cache(uc, (uint64_t)(ADDRESS + i * TCG_MAX_INSNS), &tb); + err = uc_ctl_request_cache(uc, (uint64_t)(ADDRESS + i * TCG_MAX_INSNS), + &tb); printf(">>> TB is cached at 0x%" PRIx64 " which has %" PRIu16 " instructions with %" PRIu16 " bytes.\n", tb.pc, tb.icount, tb.size); diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index bd64a4c9..0de80937 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -295,19 +295,20 @@ static void test_arm64_correct_address_in_long_jump_hook(void) OK(uc_close(uc)); } -static void test_arm64_block_sync_pc_cb(uc_engine* uc, uint64_t addr, uint32_t size, void* data) +static void test_arm64_block_sync_pc_cb(uc_engine *uc, uint64_t addr, + uint32_t size, void *data) { uint64_t val = code_start; - bool first = *(bool*)data; + bool first = *(bool *)data; if (first) { - OK(uc_reg_write(uc, UC_ARM64_REG_PC, (void*)&val)); - *(bool*)data = false; + OK(uc_reg_write(uc, UC_ARM64_REG_PC, (void *)&val)); + *(bool *)data = false; } } static void test_arm64_block_sync_pc(void) { - uc_engine* uc; + uc_engine *uc; // add x0, x0, #1234;bl t;t:mov x1, #5678; const char code[] = "\x00\x48\x13\x91\x01\x00\x00\x94\xc1\xc5\x82\xd2"; uc_hook hk; @@ -316,13 +317,14 @@ static void test_arm64_block_sync_pc(void) uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1, UC_CPU_ARM64_A72); - OK(uc_hook_add(uc, &hk, UC_HOOK_BLOCK, test_arm64_block_sync_pc_cb, (void*)&data, code_start + 8, code_start + 12)); - + OK(uc_hook_add(uc, &hk, UC_HOOK_BLOCK, test_arm64_block_sync_pc_cb, + (void *)&data, code_start + 8, code_start + 12)); + x0 = 0; - OK(uc_reg_write(uc, UC_ARM64_REG_X0, (void*)&x0)); + OK(uc_reg_write(uc, UC_ARM64_REG_X0, (void *)&x0)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); - OK(uc_reg_read(uc, UC_ARM64_REG_X0, (void*)&x0)); + OK(uc_reg_read(uc, UC_ARM64_REG_X0, (void *)&x0)); TEST_CHECK(x0 == (1234 * 2)); @@ -330,7 +332,6 @@ static void test_arm64_block_sync_pc(void) OK(uc_close(uc)); } - TEST_LIST = {{"test_arm64_until", test_arm64_until}, {"test_arm64_code_patching", test_arm64_code_patching}, {"test_arm64_code_patching_count", test_arm64_code_patching_count}, @@ -341,5 +342,5 @@ TEST_LIST = {{"test_arm64_until", test_arm64_until}, test_arm64_correct_address_in_small_jump_hook}, {"test_arm64_correct_address_in_long_jump_hook", test_arm64_correct_address_in_long_jump_hook}, - {"test_arm64_block_sync_pc", test_arm64_block_sync_pc}, + {"test_arm64_block_sync_pc", test_arm64_block_sync_pc}, {NULL, NULL}}; diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index ba37e638..a9291f92 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1106,7 +1106,6 @@ static void test_x86_correct_address_in_long_jump_hook(void) OK(uc_close(uc)); } - static void test_x86_invalid_vex_l(void) { uc_engine *uc; @@ -1132,15 +1131,16 @@ struct writelog_t { }; static void test_x86_unaligned_access_callback(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) { TEST_CHECK(size != 0); struct writelog_t *write_log = (struct writelog_t *)user_data; for (int i = 0; i < 10; i++) { if (write_log[i].size == 0) { - write_log[i].addr = (uint32_t) address; - write_log[i].size = (uint32_t) size; + write_log[i].addr = (uint32_t)address; + write_log[i].size = (uint32_t)size; return; } } @@ -1161,10 +1161,10 @@ static void test_x86_unaligned_access(void) uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); OK(uc_mem_map(uc, 0x200000, 0x1000, UC_PROT_ALL)); - OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_WRITE, test_x86_unaligned_access_callback, - write_log, 1, 0)); - OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_READ, test_x86_unaligned_access_callback, - read_log, 1, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_WRITE, + test_x86_unaligned_access_callback, write_log, 1, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_READ, + test_x86_unaligned_access_callback, read_log, 1, 0)); OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_eax)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -1192,7 +1192,8 @@ static void test_x86_unaligned_access(void) #endif static bool test_x86_lazy_mapping_mem_callback(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) { OK(uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL)); OK(uc_mem_write(uc, 0x1000, "\x90\x90", 2)); // nop; nop @@ -1202,9 +1203,10 @@ static bool test_x86_lazy_mapping_mem_callback(uc_engine *uc, uc_mem_type type, } static void test_x86_lazy_mapping_block_callback(uc_engine *uc, - uint64_t address, uint32_t size, void *user_data) + uint64_t address, + uint32_t size, void *user_data) { - int *block_count = (int*)user_data; + int *block_count = (int *)user_data; (*block_count)++; } @@ -1215,8 +1217,10 @@ static void test_x86_lazy_mapping(void) int block_count = 0; OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); - OK(uc_hook_add(uc, &mem_hook, UC_HOOK_MEM_FETCH_UNMAPPED, test_x86_lazy_mapping_mem_callback, NULL, 1, 0)); - OK(uc_hook_add(uc, &block_hook, UC_HOOK_BLOCK, test_x86_lazy_mapping_block_callback, &block_count, 1, 0)); + OK(uc_hook_add(uc, &mem_hook, UC_HOOK_MEM_FETCH_UNMAPPED, + test_x86_lazy_mapping_mem_callback, NULL, 1, 0)); + OK(uc_hook_add(uc, &block_hook, UC_HOOK_BLOCK, + test_x86_lazy_mapping_block_callback, &block_count, 1, 0)); OK(uc_emu_start(uc, 0x1000, 0x1002, 0, 0)); TEST_CHECK(block_count == 1); From fb802575d7a8c37b5a3be00164f9c65c3f9241d1 Mon Sep 17 00:00:00 2001 From: Lily Wang <494550702@qq.com> Date: Fri, 9 Sep 2022 01:22:17 -0700 Subject: [PATCH 28/77] Add vcpkg installation instructions --- docs/COMPILE.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/COMPILE.md b/docs/COMPILE.md index c2e475d5..ad16bcdf 100644 --- a/docs/COMPILE.md +++ b/docs/COMPILE.md @@ -128,3 +128,17 @@ mkdir build; cd build cmake .. -DCMAKE_C_COMPILER=gcc-arm-linux-gnueabihf make ``` + +## Building from vcpkg + +The Unicorn port in vcpkg is kept up to date by Microsoft team members and community contributors. The url of vcpkg is: https://github.com/Microsoft/vcpkg . You can download and install unicorn using the vcpkg dependency manager: + +```bash +git clone https://github.com/Microsoft/vcpkg.git +cd vcpkg +./bootstrap-vcpkg.sh # ./bootstrap-vcpkg.bat for Windows +./vcpkg integrate install +./vcpkg install unicorn +``` + +If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. From 325d02e64197374129ac210efa9a0f50eeb588c8 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 25 Sep 2022 17:17:45 +0200 Subject: [PATCH 29/77] Use ANDROID_NDK --- .github/workflows/build-uc2.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-uc2.yml b/.github/workflows/build-uc2.yml index 5f34b64f..7ee95894 100644 --- a/.github/workflows/build-uc2.yml +++ b/.github/workflows/build-uc2.yml @@ -328,9 +328,9 @@ jobs: brew install p7zip cmake ninja mkdir build mkdir instdir - cmake . -DCMAKE_TOOLCHAIN_FILE="$ANDROID_HOME/ndk/25.0.8775105/build/cmake/android.toolchain.cmake" \ + cmake . -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ -DANDROID_PLATFORM=android-28 \ - -DANDROID_NDK="$ANDROID_HOME/ndk/25.0.8775105" \ + -DANDROID_NDK="$ANDROID_NDK" \ -DANDROID_ABI=${{ matrix.config.arch }} \ -DOLP_SDK_ENABLE_TESTING=NO \ -DOLP_SDK_BUILD_EXAMPLES=ON \ From 32a3a6865a636d520a90138f48f0023fe51d6d3a Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 25 Sep 2022 17:41:09 +0200 Subject: [PATCH 30/77] Don't resize user alloc-ed memory --- qemu/exec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/qemu/exec.c b/qemu/exec.c index 719895a3..2a664788 100644 --- a/qemu/exec.c +++ b/qemu/exec.c @@ -1087,8 +1087,12 @@ RAMBlock *qemu_ram_alloc_from_ptr(struct uc_struct *uc, ram_addr_t size, void *h RAMBlock *new_block; ram_addr_t max_size = size; - size = HOST_PAGE_ALIGN(uc, size); - max_size = HOST_PAGE_ALIGN(uc, max_size); + // Don't resize pre-alloced memory as they are given by users. + if (!host) { + size = HOST_PAGE_ALIGN(uc, size); + max_size = HOST_PAGE_ALIGN(uc, max_size); + } + new_block = g_malloc0(sizeof(*new_block)); if (new_block == NULL) return NULL; From e76b2db434382f59661471faae02b022a3ee5a30 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 25 Sep 2022 18:09:41 +0200 Subject: [PATCH 31/77] Support build in a sdist --- bindings/python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/setup.py b/bindings/python/setup.py index 51dfb9fe..8920a2eb 100755 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -26,7 +26,7 @@ ROOT_DIR = os.path.dirname(os.path.realpath(__file__)) LIBS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'lib') HEADERS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'include') SRC_DIR = os.path.join(ROOT_DIR, 'src') -UC_DIR = os.path.join(ROOT_DIR, '../..') +UC_DIR = SRC_DIR if os.path.exists(SRC_DIR) else os.path.join(ROOT_DIR, '../..') BUILD_DIR = os.path.join(UC_DIR, 'build_python') VERSION = "2.0.0" From e1e7b252686205006c4d10f66d66857c4f045784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20R=C3=B6hling?= Date: Sat, 24 Sep 2022 13:58:23 +0200 Subject: [PATCH 32/77] Adjust big memory test for host pagesize On machines with a page size larger than 4K, the requested memory size in `test_map_big_memory` gets rounded up and overflows to zero. This PR adds some code to query the page size and adjust the requested memory size accordingly. --- tests/unit/test_mem.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index a1db14e1..8910fdcf 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -184,8 +184,15 @@ static void test_map_big_memory(void) OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); +#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) + uint64_t requested_size = 0xfffffffffffff000; // assume 4K page size +#else + long ps = sysconf(_SC_PAGESIZE); + uint64_t requested_size = (uint64_t)(-ps); +#endif + uc_assert_err(UC_ERR_NOMEM, - uc_mem_map(uc, 0x0, 0xfffffffffffff000, UC_PROT_ALL)); + uc_mem_map(uc, 0x0, requested_size, UC_PROT_ALL)); OK(uc_close(uc)); } From a98cd25747ed933136ecc2f4b48874aa0350a8f3 Mon Sep 17 00:00:00 2001 From: Sh4w Date: Mon, 26 Sep 2022 00:18:31 +0800 Subject: [PATCH 33/77] Fix type hint of reg_write in Python bindings --- bindings/python/unicorn/unicorn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index 1687ab63..2e6a938f 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -560,7 +560,7 @@ class Uc(object): return reg_read(functools.partial(_uc.uc_reg_read, self._uch), self._arch, reg_id, opt) # write to a register, tuple for arm cp regs. - def reg_write(self, reg_id: Union[int, ARMCPRegValue, ARM64CPRegValue, X86MMRReg, X86FPReg], value: int): + def reg_write(self, reg_id: int, value: Union[int, ARMCPRegValue, ARM64CPRegValue, X86MMRReg, X86FPReg]): return reg_write(functools.partial(_uc.uc_reg_write, self._uch), self._arch, reg_id, value) # read from MSR - X86 only From 97b2e44c777059eff850bf9a9c24994b647f7c04 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 25 Sep 2022 18:43:09 +0200 Subject: [PATCH 34/77] Also copy cmake files --- bindings/python/setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bindings/python/setup.py b/bindings/python/setup.py index 8920a2eb..20bc2440 100755 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -69,6 +69,7 @@ def copy_sources(): src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.[ch]"))) src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.mk"))) + src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.cmake"))) src.extend(glob.glob(os.path.join(ROOT_DIR, "../../LICENSE*"))) src.extend(glob.glob(os.path.join(ROOT_DIR, "../../README.md"))) From 7fb6264d02ef410b240d697dc74e03e3f85385f6 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 25 Sep 2022 18:46:04 +0200 Subject: [PATCH 35/77] Also copy glib_compat and samples --- bindings/python/setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bindings/python/setup.py b/bindings/python/setup.py index 20bc2440..f8948d62 100755 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -60,6 +60,9 @@ def copy_sources(): shutil.copytree(os.path.join(ROOT_DIR, '../../include'), os.path.join(SRC_DIR, 'include/')) # make -> configure -> clean -> clean tests fails unless tests is present shutil.copytree(os.path.join(ROOT_DIR, '../../tests'), os.path.join(SRC_DIR, 'tests/')) + shutil.copytree(os.path.join(ROOT_DIR, '../../samples'), os.path.join(SRC_DIR, 'samples/')) + shutil.copytree(os.path.join(ROOT_DIR, '../../glib_compat'), os.path.join(SRC_DIR, 'glib_compat/')) + try: # remove site-specific configuration file # might not exist From 1065c2dff43f026e7f9ea924115ebac8b0cebe45 Mon Sep 17 00:00:00 2001 From: relapids Date: Tue, 16 Aug 2022 00:06:02 -0700 Subject: [PATCH 36/77] Fix test_uc_hook_cached_uaf for MacOS M1 (aarch64). --- tests/unit/test_ctl.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index b96d7cf5..5eef28d0 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -251,15 +251,22 @@ static void test_uc_hook_cached_uaf(void) uc_hook h; uint64_t count = 0; #ifndef _WIN32 - void *callback = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, + // Apple Silicon does not allow RWX pages. + void *callback = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + TEST_CHECK(callback != (void*)-1); #else void *callback = VirtualAlloc(NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + TEST_CHECK(callback != NULL); #endif memcpy(callback, (void *)test_uc_hook_cached_cb, 4096); +#ifndef _WIN32 + TEST_CHECK(mprotect(callback, 4096, PROT_READ | PROT_EXEC) == 0); +#endif + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); OK(uc_hook_add(uc, &h, UC_HOOK_CODE, (void *)callback, (void *)&count, 1, @@ -273,8 +280,16 @@ static void test_uc_hook_cached_uaf(void) // This will clear deleted hooks and SHOULD clear cache. OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); +#ifndef _WIN32 + TEST_CHECK(mprotect(callback, 4096, PROT_READ | PROT_WRITE) == 0); +#endif + memset(callback, 0, 4096); +#ifndef _WIN32 + TEST_CHECK(mprotect(callback, 4096, PROT_READ | PROT_EXEC) == 0); +#endif + // Now hooks are deleted and thus this will trigger a UAF OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); From b0b3a57bcdd775ba8629be124deae8f7e6036464 Mon Sep 17 00:00:00 2001 From: mio Date: Tue, 27 Sep 2022 23:13:06 +0200 Subject: [PATCH 37/77] Update FAQ --- docs/FAQ.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 4bb568ce..20bb58e2 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -30,6 +30,13 @@ On x86, all available instructions are: `in` `out` `syscall` `sysenter` `cpuid`. If you are still using Unicorn1, please upgrade to Unicorn2 for better support. +## Memory hooks get called multiple times for a single instruction + +There are several possibilities, e.g.: + +- The instruction might access memory multiple times like `rep stos` in x86. +- The address to access is bad-aligned and thus the MMU emulation will split the access into several aligned memory access. In worst cases on some arch, it leads to byte by byte access. + ## I can't recover from unmapped read/write even I return `true` in the hook, why? This is a minor change in memory hooks behavior between Unicorn1 and Unicorn2. To gracefully recover from memory read/write error, you have to map the invalid memory before you return true. @@ -38,9 +45,11 @@ It is due to the fact that, if users return `true` without memory mapping set up See the [sample](https://github.com/unicorn-engine/unicorn/blob/c05fbb7e63aed0b60fc2888e08beceb17bce8ac4/samples/sample_x86.c#L1379-L1393) for details. -## My MIPS emulation gets weird read/write error and CPU exceptions. +## My emulation gets weird read/write error and CPU exceptions. -Note you might have an address that falls in MIPS `kseg` segments. In that case, MMU is bypassed and you have to make sure the corresponding physical memory is mapped. See [#217](https://github.com/unicorn-engine/unicorn/issues/217), [#1371](https://github.com/unicorn-engine/unicorn/issues/1371), [#1550](https://github.com/unicorn-engine/unicorn/issues/1371). +For MIPS, you might have an address that falls in MIPS `kseg` segments. In that case, MMU is bypassed and you have to make sure the corresponding physical memory is mapped. See [#217](https://github.com/unicorn-engine/unicorn/issues/217), [#1371](https://github.com/unicorn-engine/unicorn/issues/1371), [#1550](https://github.com/unicorn-engine/unicorn/issues/1371). + +For ARM, you might have an address that falls in some non-executable segments. For example, for m-class ARM cpu, some memory area is not executable according to [the ARM document](https://developer.arm.com/documentation/ddi0403/d/System-Level-Architecture/System-Address-Map/The-system-address-map?lang=en). ## KeyboardInterrupt is not raised during `uc.emu_start` From 19d8876e2350bf325181c52f7acf752e89452d15 Mon Sep 17 00:00:00 2001 From: mio Date: Sat, 1 Oct 2022 00:13:36 +0200 Subject: [PATCH 38/77] Deep copy for arm cpu state --- include/uc_priv.h | 14 ++++ qemu/target/arm/unicorn_arm.c | 142 ++++++++++++++++++++++++++++++++++ tests/unit/test_arm.c | 25 ++++++ uc.c | 30 ++++--- 4 files changed, 202 insertions(+), 9 deletions(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index 7af9c615..030fadce 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -168,6 +168,16 @@ typedef void (*uc_add_inline_hook_t)(struct uc_struct *uc, struct hook *hk, // Delete a hook from helper_table typedef void (*uc_del_inline_hook_t)(struct uc_struct *uc, struct hook *hk); +// Return the size of a CPU context +typedef size_t (*uc_context_size_t)(struct uc_struct *uc); + +// Generate a CPU context +typedef uc_err (*uc_context_save_t)(struct uc_struct *uc, uc_context *context); + +// Restore a CPU context +typedef uc_err (*uc_context_restore_t)(struct uc_struct *uc, + uc_context *context); + // hook list offsets // // The lowest 6 bits are used for hook type index while the others @@ -285,6 +295,10 @@ struct uc_struct { uc_add_inline_hook_t add_inline_hook; uc_del_inline_hook_t del_inline_hook; + uc_context_size_t context_size; + uc_context_save_t context_save; + uc_context_restore_t context_restore; + /* only 1 cpu in unicorn, do not need current_cpu to handle current running cpu. */ CPUState *cpu; diff --git a/qemu/target/arm/unicorn_arm.c b/qemu/target/arm/unicorn_arm.c index c8531426..bb39b348 100644 --- a/qemu/target/arm/unicorn_arm.c +++ b/qemu/target/arm/unicorn_arm.c @@ -621,6 +621,145 @@ static int arm_cpus_init(struct uc_struct *uc, const char *cpu_model) return 0; } +static size_t uc_arm_context_size(struct uc_struct *uc) +{ + size_t ret = offsetof(CPUARMState, cpu_watchpoint); + ARMCPU *cpu = (ARMCPU *)uc->cpu; + CPUARMState *env = (CPUARMState *)&cpu->env; + uint32_t nr; + +#define ARM_ENV_CHECK(field) \ + if (field) { \ + ret += sizeof(uint32_t) * (nr + 1); \ + } else { \ + ret += sizeof(uint32_t); \ + } + + // /* PMSAv7 MPU */ + // struct { + // uint32_t *drbar; + // uint32_t *drsr; + // uint32_t *dracr; + // uint32_t rnr[M_REG_NUM_BANKS]; + // } pmsav7; + // /* PMSAv8 MPU */ + // struct { + // /* The PMSAv8 implementation also shares some PMSAv7 config + // * and state: + // * pmsav7.rnr (region number register) + // * pmsav7_dregion (number of configured regions) + // */ + // uint32_t *rbar[M_REG_NUM_BANKS]; + // uint32_t *rlar[M_REG_NUM_BANKS]; + // uint32_t mair0[M_REG_NUM_BANKS]; + // uint32_t mair1[M_REG_NUM_BANKS]; + // } pmsav8; + nr = cpu->pmsav7_dregion; + ARM_ENV_CHECK(env->pmsav7.drbar) + ARM_ENV_CHECK(env->pmsav7.drsr) + ARM_ENV_CHECK(env->pmsav7.dracr) + ARM_ENV_CHECK(env->pmsav8.rbar[M_REG_NS]) + ARM_ENV_CHECK(env->pmsav8.rbar[M_REG_S]) + ARM_ENV_CHECK(env->pmsav8.rlar[M_REG_NS]) + ARM_ENV_CHECK(env->pmsav8.rlar[M_REG_S]) + + // /* v8M SAU */ + // struct { + // uint32_t *rbar; + // uint32_t *rlar; + // uint32_t rnr; + // uint32_t ctrl; + // } sau; + nr = cpu->sau_sregion; + ARM_ENV_CHECK(env->sau.rbar) + ARM_ENV_CHECK(env->sau.rlar) +#undef ARM_ENV_CHECK + // These fields are never used: + // void *nvic; + // const struct arm_boot_info *boot_info; + // void *gicv3state; + return ret; +} + +static uc_err uc_arm_context_save(struct uc_struct *uc, uc_context *context) +{ + char *p = NULL; + ARMCPU *cpu = (ARMCPU *)uc->cpu; + CPUARMState *env = (CPUARMState *)&cpu->env; + uint32_t nr = 0; + +#define ARM_ENV_SAVE(field) \ + if (!field) { \ + *(uint32_t *)p = 0; \ + p += sizeof(uint32_t); \ + } else { \ + *(uint32_t *)p = nr; \ + p += sizeof(uint32_t); \ + memcpy(p, (void *)field, sizeof(uint32_t) * nr); \ + p += sizeof(uint32_t) * nr; \ + } + p = context->data; + memcpy(p, uc->cpu->env_ptr, uc->cpu_context_size); + p += uc->cpu_context_size; + + nr = cpu->pmsav7_dregion; + ARM_ENV_SAVE(env->pmsav7.drbar) + ARM_ENV_SAVE(env->pmsav7.drsr) + ARM_ENV_SAVE(env->pmsav7.dracr) + ARM_ENV_SAVE(env->pmsav8.rbar[M_REG_NS]) + ARM_ENV_SAVE(env->pmsav8.rbar[M_REG_S]) + ARM_ENV_SAVE(env->pmsav8.rlar[M_REG_NS]) + ARM_ENV_SAVE(env->pmsav8.rlar[M_REG_S]) + + nr = cpu->sau_sregion; + ARM_ENV_SAVE(env->sau.rbar) + ARM_ENV_SAVE(env->sau.rlar) + +#undef ARM_ENV_SAVE + return UC_ERR_OK; +} + +static uc_err uc_arm_context_restore(struct uc_struct *uc, uc_context *context) +{ + char *p = NULL; + ARMCPU *cpu = (ARMCPU *)uc->cpu; + CPUARMState *env = (CPUARMState *)&cpu->env; + uint32_t nr, ctx_nr; + +#define ARM_ENV_RESTORE(field) \ + ctx_nr = *(uint32_t *)p; \ + if (ctx_nr != 0) { \ + p += sizeof(uint32_t); \ + if (field && ctx_nr == nr) { \ + memcpy(field, p, sizeof(uint32_t) * ctx_nr); \ + } \ + p += sizeof(uint32_t) * ctx_nr; \ + } else { \ + p += sizeof(uint32_t); \ + } + + p = context->data; + memcpy(uc->cpu->env_ptr, p, uc->cpu_context_size); + p += uc->cpu_context_size; + + nr = cpu->pmsav7_dregion; + ARM_ENV_RESTORE(env->pmsav7.drbar) + ARM_ENV_RESTORE(env->pmsav7.drsr) + ARM_ENV_RESTORE(env->pmsav7.dracr) + ARM_ENV_RESTORE(env->pmsav8.rbar[M_REG_NS]) + ARM_ENV_RESTORE(env->pmsav8.rbar[M_REG_S]) + ARM_ENV_RESTORE(env->pmsav8.rlar[M_REG_NS]) + ARM_ENV_RESTORE(env->pmsav8.rlar[M_REG_S]) + + nr = cpu->sau_sregion; + ARM_ENV_RESTORE(env->sau.rbar) + ARM_ENV_RESTORE(env->sau.rlar) + +#undef ARM_ENV_RESTORE + + return UC_ERR_OK; +} + void arm_uc_init(struct uc_struct *uc) { uc->reg_read = arm_reg_read; @@ -634,5 +773,8 @@ void arm_uc_init(struct uc_struct *uc) uc->cpus_init = arm_cpus_init; uc->opcode_hook_invalidate = arm_opcode_hook_invalidate; uc->cpu_context_size = offsetof(CPUARMState, cpu_watchpoint); + uc->context_size = uc_arm_context_size; + uc->context_save = uc_arm_context_save; + uc->context_restore = uc_arm_context_restore; uc_common_init(uc); } diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index 1efd5682..66898e62 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -751,6 +751,30 @@ static void test_armeb_ldrb(void) OK(uc_close(uc)); } +static void test_arm_context_save(void) +{ + uc_engine *uc; + uc_engine *uc2; + char code[] = "\x83\xb0"; // sub sp, #0xc + uc_context *ctx; + + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB, code, sizeof(code) - 1, + UC_CPU_ARM_CORTEX_R5); + + OK(uc_context_alloc(uc, &ctx)); + OK(uc_context_save(uc, ctx)); + OK(uc_context_restore(uc, ctx)); + + uc_common_setup(&uc2, UC_ARCH_ARM, UC_MODE_THUMB, code, sizeof(code) - 1, + UC_CPU_ARM_CORTEX_A7); // Note the different CPU model + + OK(uc_context_restore(uc2, ctx)); + + OK(uc_context_free(ctx)); + OK(uc_close(uc)); + OK(uc_close(uc2)); +} + TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_thumb_sub", test_arm_thumb_sub}, {"test_armeb_sub", test_armeb_sub}, @@ -773,4 +797,5 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_be_cpsr_sctlr", test_arm_be_cpsr_sctlr}, {"test_arm_switch_endian", test_arm_switch_endian}, {"test_armeb_ldrb", test_armeb_ldrb}, + {"test_arm_context_save", test_arm_context_save}, {NULL, NULL}}; \ No newline at end of file diff --git a/uc.c b/uc.c index 82471965..f69cf3a7 100644 --- a/uc.c +++ b/uc.c @@ -2,6 +2,7 @@ /* By Nguyen Anh Quynh , 2015 */ /* Modified for Unicorn Engine by Chen Huitao, 2020 */ +#include "unicorn/unicorn.h" #if defined(UNICORN_HAS_OSXKERNEL) #include #else @@ -1861,7 +1862,7 @@ uc_err uc_context_alloc(uc_engine *uc, uc_context **context) *_context = g_malloc(size); if (*_context) { - (*_context)->context_size = uc->cpu_context_size; + (*_context)->context_size = size - sizeof(uc_context); (*_context)->arch = uc->arch; (*_context)->mode = uc->mode; return UC_ERR_OK; @@ -1881,8 +1882,13 @@ UNICORN_EXPORT size_t uc_context_size(uc_engine *uc) { UC_INIT(uc); - // return the total size of struct uc_context - return sizeof(uc_context) + uc->cpu_context_size; + + if (!uc->context_size) { + // return the total size of struct uc_context + return sizeof(uc_context) + uc->cpu_context_size; + } else { + return sizeof(uc_context) + uc->context_size(uc); + } } UNICORN_EXPORT @@ -1890,9 +1896,12 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context) { UC_INIT(uc); - memcpy(context->data, uc->cpu->env_ptr, context->context_size); - - return UC_ERR_OK; + if (!uc->context_save) { + memcpy(context->data, uc->cpu->env_ptr, context->context_size); + return UC_ERR_OK; + } else { + return uc->context_save(uc, context); + } } UNICORN_EXPORT @@ -2064,9 +2073,12 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context) { UC_INIT(uc); - memcpy(uc->cpu->env_ptr, context->data, context->context_size); - - return UC_ERR_OK; + if (!uc->context_restore) { + memcpy(uc->cpu->env_ptr, context->data, context->context_size); + return UC_ERR_OK; + } else { + return uc->context_restore(uc, context); + } } UNICORN_EXPORT From c144f061451e5d12d6583202e73f5063233ed7a5 Mon Sep 17 00:00:00 2001 From: mio Date: Sat, 1 Oct 2022 00:13:59 +0200 Subject: [PATCH 39/77] Format code --- tests/unit/test_ctl.c | 2 +- tests/unit/test_mem.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 5eef28d0..6277da67 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -254,7 +254,7 @@ static void test_uc_hook_cached_uaf(void) // Apple Silicon does not allow RWX pages. void *callback = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - TEST_CHECK(callback != (void*)-1); + TEST_CHECK(callback != (void *)-1); #else void *callback = VirtualAlloc(NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index 8910fdcf..997330c4 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -185,7 +185,7 @@ static void test_map_big_memory(void) OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) - uint64_t requested_size = 0xfffffffffffff000; // assume 4K page size + uint64_t requested_size = 0xfffffffffffff000; // assume 4K page size #else long ps = sysconf(_SC_PAGESIZE); uint64_t requested_size = (uint64_t)(-ps); From 6ca077d139b9801e990651a5d2abd253c9156d77 Mon Sep 17 00:00:00 2001 From: mio Date: Sat, 1 Oct 2022 01:01:22 +0200 Subject: [PATCH 40/77] Build aarch64 wheel --- .github/workflows/PyPI-publishing.yml | 10 +++++++++- bindings/python/build_wheel_aarch64.sh | 10 ++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 bindings/python/build_wheel_aarch64.sh diff --git a/.github/workflows/PyPI-publishing.yml b/.github/workflows/PyPI-publishing.yml index 143db4e7..5f64540a 100644 --- a/.github/workflows/PyPI-publishing.yml +++ b/.github/workflows/PyPI-publishing.yml @@ -46,6 +46,12 @@ jobs: python-ver: '3.8', name: 'manylinux2014_i686' } + - { + os: ubuntu-latest, + arch: x64, + python-ver: '3.8', + name: 'manylinux2014_aarch64' + } - { os: ubuntu-latest, arch: x64, @@ -101,7 +107,9 @@ jobs: cd bindings/python && python setup.py build -p win32 sdist bdist_wheel -p win32 rm dist/*.tar.gz elif [ ${{ matrix.config.name }} == 'manylinux2014_i686' ]; then - docker run --rm -v `pwd`/:/work dockcross/manylinux2014-x86 > ./dockcross + docker run --rm -v `pwd`/:/work quay.io/pypa/manylinux2014_aarch64 bash /work/bindings/python/build_wheel_aarch64.sh + elif [ ${{ matrix.config.name }} == 'manylinux2014_aarch64' ]; then + docker run --rm -v `pwd`/:/work dockcross/manylinux2014-aarch64 > ./dockcross chmod +x ./dockcross ./dockcross bindings/python/build_wheel.sh elif [ ${{ matrix.config.name }} == 'manylinux2014_x86_64' ]; then diff --git a/bindings/python/build_wheel_aarch64.sh b/bindings/python/build_wheel_aarch64.sh new file mode 100644 index 00000000..0e681242 --- /dev/null +++ b/bindings/python/build_wheel_aarch64.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +yum install python3 -y +python3 -m pip install -U setuptools wheel auditwheel +cd /work/bindings/python +python3 setup.py bdist_wheel + +cd dist +auditwheel repair *.whl +mv -f wheelhouse/*.whl . From a0ff997c849cd300e450f5bcd0ab833a0bb50247 Mon Sep 17 00:00:00 2001 From: mio Date: Sat, 1 Oct 2022 01:02:04 +0200 Subject: [PATCH 41/77] Fix ubuntu arch --- .github/workflows/PyPI-publishing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/PyPI-publishing.yml b/.github/workflows/PyPI-publishing.yml index 5f64540a..581ce213 100644 --- a/.github/workflows/PyPI-publishing.yml +++ b/.github/workflows/PyPI-publishing.yml @@ -48,7 +48,7 @@ jobs: } - { os: ubuntu-latest, - arch: x64, + arch: aarch64, python-ver: '3.8', name: 'manylinux2014_aarch64' } From 23852aa77eebda6d7d7ea5ac3f7fa69df7558702 Mon Sep 17 00:00:00 2001 From: mio Date: Sat, 1 Oct 2022 01:04:49 +0200 Subject: [PATCH 42/77] Fix wrong build command --- .github/workflows/PyPI-publishing.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/PyPI-publishing.yml b/.github/workflows/PyPI-publishing.yml index 581ce213..4ae6d858 100644 --- a/.github/workflows/PyPI-publishing.yml +++ b/.github/workflows/PyPI-publishing.yml @@ -107,11 +107,11 @@ jobs: cd bindings/python && python setup.py build -p win32 sdist bdist_wheel -p win32 rm dist/*.tar.gz elif [ ${{ matrix.config.name }} == 'manylinux2014_i686' ]; then - docker run --rm -v `pwd`/:/work quay.io/pypa/manylinux2014_aarch64 bash /work/bindings/python/build_wheel_aarch64.sh - elif [ ${{ matrix.config.name }} == 'manylinux2014_aarch64' ]; then - docker run --rm -v `pwd`/:/work dockcross/manylinux2014-aarch64 > ./dockcross + docker run --rm -v `pwd`/:/work dockcross/manylinux2014-x86 > ./dockcross chmod +x ./dockcross ./dockcross bindings/python/build_wheel.sh + elif [ ${{ matrix.config.name }} == 'manylinux2014_aarch64' ]; then + docker run --rm -v `pwd`/:/work quay.io/pypa/manylinux2014_aarch64 bash /work/bindings/python/build_wheel_aarch64.sh elif [ ${{ matrix.config.name }} == 'manylinux2014_x86_64' ]; then docker run --rm -v `pwd`/:/work dockcross/manylinux2014-x64 > ./dockcross chmod +x ./dockcross From 50a0b59d0d43cc0447b533cb2be9ea1d0893cfa6 Mon Sep 17 00:00:00 2001 From: mio Date: Sat, 1 Oct 2022 01:31:13 +0200 Subject: [PATCH 43/77] Use dockcross for aarch64 wheel --- .github/workflows/PyPI-publishing.yml | 4 +++- bindings/python/build_wheel.sh | 13 +++++++++---- bindings/python/build_wheel_aarch64.sh | 10 ---------- 3 files changed, 12 insertions(+), 15 deletions(-) delete mode 100644 bindings/python/build_wheel_aarch64.sh diff --git a/.github/workflows/PyPI-publishing.yml b/.github/workflows/PyPI-publishing.yml index 4ae6d858..5f254bc2 100644 --- a/.github/workflows/PyPI-publishing.yml +++ b/.github/workflows/PyPI-publishing.yml @@ -111,7 +111,9 @@ jobs: chmod +x ./dockcross ./dockcross bindings/python/build_wheel.sh elif [ ${{ matrix.config.name }} == 'manylinux2014_aarch64' ]; then - docker run --rm -v `pwd`/:/work quay.io/pypa/manylinux2014_aarch64 bash /work/bindings/python/build_wheel_aarch64.sh + docker run --rm -v `pwd`/:/work dockcross/manylinux2014-aarch64 > ./dockcross + chmod +x ./dockcross + ./dockcross bindings/python/build_wheel.sh --plat-name manylinux2014_aarch64 elif [ ${{ matrix.config.name }} == 'manylinux2014_x86_64' ]; then docker run --rm -v `pwd`/:/work dockcross/manylinux2014-x64 > ./dockcross chmod +x ./dockcross diff --git a/bindings/python/build_wheel.sh b/bindings/python/build_wheel.sh index e3c9d444..05a28bf1 100755 --- a/bindings/python/build_wheel.sh +++ b/bindings/python/build_wheel.sh @@ -5,10 +5,15 @@ cd bindings/python # Compile wheels if [ -f /opt/python/cp36-cp36m/bin/python ];then - /opt/python/cp36-cp36m/bin/python setup.py bdist_wheel + /opt/python/cp36-cp36m/bin/python setup.py bdist_wheel $@ else - python3 setup.py bdist_wheel + python3 setup.py bdist_wheel $@ fi cd dist -auditwheel repair *.whl -mv -f wheelhouse/*.whl . + +# We can't repair an aarch64 wheel on x64 hosts +# https://github.com/pypa/auditwheel/issues/244 +if [[ ! "$*" =~ "aarch64" ]];then + auditwheel repair *.whl + mv -f wheelhouse/*.whl . +fi \ No newline at end of file diff --git a/bindings/python/build_wheel_aarch64.sh b/bindings/python/build_wheel_aarch64.sh deleted file mode 100644 index 0e681242..00000000 --- a/bindings/python/build_wheel_aarch64.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -yum install python3 -y -python3 -m pip install -U setuptools wheel auditwheel -cd /work/bindings/python -python3 setup.py bdist_wheel - -cd dist -auditwheel repair *.whl -mv -f wheelhouse/*.whl . From 302fb1b6b3d5ffad110106fb557b8a9ae1b9bd35 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 9 Oct 2022 14:18:55 +0200 Subject: [PATCH 44/77] Add help wanted tag --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index eb995b0a..04c46b3e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -14,5 +14,5 @@ jobs: days-before-stale: 60 days-before-close: 15 exempt-all-milestones: true - exempt-issue-labels: 'pinned' + exempt-issue-labels: 'pinned,help wanted' exempt-pr-labels: 'pinned' From 66adfff20d6ca1c10b56b4c0a3ba678f86be770d Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Wed, 12 Oct 2022 14:39:10 +0800 Subject: [PATCH 45/77] samples: fix a typo --- samples/sample_x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/sample_x86.c b/samples/sample_x86.c index 384e74b1..d8500cc4 100644 --- a/samples/sample_x86.c +++ b/samples/sample_x86.c @@ -1404,7 +1404,7 @@ static void test_i386_hook_mem_invalid() uc_err err; printf("===================================\n"); - printf("Emulate i386 code that tiggers invalid memory read/write.\n"); + printf("Emulate i386 code that triggers invalid memory read/write.\n"); err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); if (err) { From b99ec09c9037308c969677fe1f5ba86f79ef6646 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Wed, 12 Oct 2022 14:43:01 +0800 Subject: [PATCH 46/77] tests: remove unused var --- tests/unit/test_x86.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index a9291f92..b4c94dcf 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1109,7 +1109,6 @@ static void test_x86_correct_address_in_long_jump_hook(void) static void test_x86_invalid_vex_l(void) { uc_engine *uc; - uc_err err; /* vmovdqu ymm1, [rcx] */ char code[] = {'\xC5', '\xFE', '\x6F', '\x09'}; From 12fd4fc086d78350e58a4f893aa8607f85d27580 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Fri, 14 Oct 2022 15:15:48 +0200 Subject: [PATCH 47/77] aarch64: Add FPCR and FPSR registers Co-authored-by: merry --- include/unicorn/arm64.h | 4 ++++ qemu/target/arm/unicorn_aarch64.c | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/unicorn/arm64.h b/include/unicorn/arm64.h index 933be479..aab2ab9c 100644 --- a/include/unicorn/arm64.h +++ b/include/unicorn/arm64.h @@ -313,6 +313,10 @@ typedef enum uc_arm64_reg { UC_ARM64_REG_PSTATE, + //> floating point control and status registers + UC_ARM64_REG_FPCR, + UC_ARM64_REG_FPSR, + //> exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead UC_ARM64_REG_ELR_EL0, UC_ARM64_REG_ELR_EL1, diff --git a/qemu/target/arm/unicorn_aarch64.c b/qemu/target/arm/unicorn_aarch64.c index f24c9506..4b533047 100644 --- a/qemu/target/arm/unicorn_aarch64.c +++ b/qemu/target/arm/unicorn_aarch64.c @@ -210,6 +210,12 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value) case UC_ARM64_REG_PSTATE: *(uint32_t *)value = pstate_read(env); break; + case UC_ARM64_REG_FPCR: + *(uint32_t *)value = vfp_get_fpcr(env); + break; + case UC_ARM64_REG_FPSR: + *(uint32_t *)value = vfp_get_fpsr(env); + break; case UC_ARM64_REG_TTBR0_EL1: *(uint64_t *)value = env->cp15.ttbr0_el[1]; break; @@ -303,6 +309,12 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value) case UC_ARM64_REG_PSTATE: pstate_write(env, *(uint32_t *)value); break; + case UC_ARM64_REG_FPCR: + vfp_set_fpcr(env, *(uint32_t *)value); + break; + case UC_ARM64_REG_FPSR: + vfp_set_fpsr(env, *(uint32_t *)value); + break; case UC_ARM64_REG_TTBR0_EL1: env->cp15.ttbr0_el[1] = *(uint64_t *)value; break; From c787fa8e646957139d8086a098ebf1e36dffcc8d Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Fri, 14 Oct 2022 15:16:38 +0200 Subject: [PATCH 48/77] bindings: Update Arm64 consts --- bindings/dotnet/UnicornManaged/Const/Arm64.fs | 56 ++++++++++--------- bindings/go/unicorn/arm64_const.go | 56 ++++++++++--------- bindings/java/unicorn/Arm64Const.java | 56 ++++++++++--------- bindings/pascal/unicorn/Arm64Const.pas | 56 ++++++++++--------- bindings/python/unicorn/arm64_const.py | 56 ++++++++++--------- .../lib/unicorn_engine/arm64_const.rb | 56 ++++++++++--------- 6 files changed, 180 insertions(+), 156 deletions(-) diff --git a/bindings/dotnet/UnicornManaged/Const/Arm64.fs b/bindings/dotnet/UnicornManaged/Const/Arm64.fs index f323fcf9..7357a252 100644 --- a/bindings/dotnet/UnicornManaged/Const/Arm64.fs +++ b/bindings/dotnet/UnicornManaged/Const/Arm64.fs @@ -288,37 +288,41 @@ module Arm64 = let UC_ARM64_REG_TPIDR_EL1 = 264 let UC_ARM64_REG_PSTATE = 265 + // floating point control and status registers + let UC_ARM64_REG_FPCR = 266 + let UC_ARM64_REG_FPSR = 267 + // exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead - let UC_ARM64_REG_ELR_EL0 = 266 - let UC_ARM64_REG_ELR_EL1 = 267 - let UC_ARM64_REG_ELR_EL2 = 268 - let UC_ARM64_REG_ELR_EL3 = 269 + let UC_ARM64_REG_ELR_EL0 = 268 + let UC_ARM64_REG_ELR_EL1 = 269 + let UC_ARM64_REG_ELR_EL2 = 270 + let UC_ARM64_REG_ELR_EL3 = 271 // stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead - let UC_ARM64_REG_SP_EL0 = 270 - let UC_ARM64_REG_SP_EL1 = 271 - let UC_ARM64_REG_SP_EL2 = 272 - let UC_ARM64_REG_SP_EL3 = 273 + let UC_ARM64_REG_SP_EL0 = 272 + let UC_ARM64_REG_SP_EL1 = 273 + let UC_ARM64_REG_SP_EL2 = 274 + let UC_ARM64_REG_SP_EL3 = 275 // other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead - let UC_ARM64_REG_TTBR0_EL1 = 274 - let UC_ARM64_REG_TTBR1_EL1 = 275 - let UC_ARM64_REG_ESR_EL0 = 276 - let UC_ARM64_REG_ESR_EL1 = 277 - let UC_ARM64_REG_ESR_EL2 = 278 - let UC_ARM64_REG_ESR_EL3 = 279 - let UC_ARM64_REG_FAR_EL0 = 280 - let UC_ARM64_REG_FAR_EL1 = 281 - let UC_ARM64_REG_FAR_EL2 = 282 - let UC_ARM64_REG_FAR_EL3 = 283 - let UC_ARM64_REG_PAR_EL1 = 284 - let UC_ARM64_REG_MAIR_EL1 = 285 - let UC_ARM64_REG_VBAR_EL0 = 286 - let UC_ARM64_REG_VBAR_EL1 = 287 - let UC_ARM64_REG_VBAR_EL2 = 288 - let UC_ARM64_REG_VBAR_EL3 = 289 - let UC_ARM64_REG_CP_REG = 290 - let UC_ARM64_REG_ENDING = 291 + let UC_ARM64_REG_TTBR0_EL1 = 276 + let UC_ARM64_REG_TTBR1_EL1 = 277 + let UC_ARM64_REG_ESR_EL0 = 278 + let UC_ARM64_REG_ESR_EL1 = 279 + let UC_ARM64_REG_ESR_EL2 = 280 + let UC_ARM64_REG_ESR_EL3 = 281 + let UC_ARM64_REG_FAR_EL0 = 282 + let UC_ARM64_REG_FAR_EL1 = 283 + let UC_ARM64_REG_FAR_EL2 = 284 + let UC_ARM64_REG_FAR_EL3 = 285 + let UC_ARM64_REG_PAR_EL1 = 286 + let UC_ARM64_REG_MAIR_EL1 = 287 + let UC_ARM64_REG_VBAR_EL0 = 288 + let UC_ARM64_REG_VBAR_EL1 = 289 + let UC_ARM64_REG_VBAR_EL2 = 290 + let UC_ARM64_REG_VBAR_EL3 = 291 + let UC_ARM64_REG_CP_REG = 292 + let UC_ARM64_REG_ENDING = 293 // alias registers let UC_ARM64_REG_IP0 = 215 diff --git a/bindings/go/unicorn/arm64_const.go b/bindings/go/unicorn/arm64_const.go index 2f324154..7d89bace 100644 --- a/bindings/go/unicorn/arm64_const.go +++ b/bindings/go/unicorn/arm64_const.go @@ -283,37 +283,41 @@ const ( ARM64_REG_TPIDR_EL1 = 264 ARM64_REG_PSTATE = 265 +// floating point control and status registers + ARM64_REG_FPCR = 266 + ARM64_REG_FPSR = 267 + // exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead - ARM64_REG_ELR_EL0 = 266 - ARM64_REG_ELR_EL1 = 267 - ARM64_REG_ELR_EL2 = 268 - ARM64_REG_ELR_EL3 = 269 + ARM64_REG_ELR_EL0 = 268 + ARM64_REG_ELR_EL1 = 269 + ARM64_REG_ELR_EL2 = 270 + ARM64_REG_ELR_EL3 = 271 // stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead - ARM64_REG_SP_EL0 = 270 - ARM64_REG_SP_EL1 = 271 - ARM64_REG_SP_EL2 = 272 - ARM64_REG_SP_EL3 = 273 + ARM64_REG_SP_EL0 = 272 + ARM64_REG_SP_EL1 = 273 + ARM64_REG_SP_EL2 = 274 + ARM64_REG_SP_EL3 = 275 // other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead - ARM64_REG_TTBR0_EL1 = 274 - ARM64_REG_TTBR1_EL1 = 275 - ARM64_REG_ESR_EL0 = 276 - ARM64_REG_ESR_EL1 = 277 - ARM64_REG_ESR_EL2 = 278 - ARM64_REG_ESR_EL3 = 279 - ARM64_REG_FAR_EL0 = 280 - ARM64_REG_FAR_EL1 = 281 - ARM64_REG_FAR_EL2 = 282 - ARM64_REG_FAR_EL3 = 283 - ARM64_REG_PAR_EL1 = 284 - ARM64_REG_MAIR_EL1 = 285 - ARM64_REG_VBAR_EL0 = 286 - ARM64_REG_VBAR_EL1 = 287 - ARM64_REG_VBAR_EL2 = 288 - ARM64_REG_VBAR_EL3 = 289 - ARM64_REG_CP_REG = 290 - ARM64_REG_ENDING = 291 + ARM64_REG_TTBR0_EL1 = 276 + ARM64_REG_TTBR1_EL1 = 277 + ARM64_REG_ESR_EL0 = 278 + ARM64_REG_ESR_EL1 = 279 + ARM64_REG_ESR_EL2 = 280 + ARM64_REG_ESR_EL3 = 281 + ARM64_REG_FAR_EL0 = 282 + ARM64_REG_FAR_EL1 = 283 + ARM64_REG_FAR_EL2 = 284 + ARM64_REG_FAR_EL3 = 285 + ARM64_REG_PAR_EL1 = 286 + ARM64_REG_MAIR_EL1 = 287 + ARM64_REG_VBAR_EL0 = 288 + ARM64_REG_VBAR_EL1 = 289 + ARM64_REG_VBAR_EL2 = 290 + ARM64_REG_VBAR_EL3 = 291 + ARM64_REG_CP_REG = 292 + ARM64_REG_ENDING = 293 // alias registers ARM64_REG_IP0 = 215 diff --git a/bindings/java/unicorn/Arm64Const.java b/bindings/java/unicorn/Arm64Const.java index 77b9e49a..699320af 100644 --- a/bindings/java/unicorn/Arm64Const.java +++ b/bindings/java/unicorn/Arm64Const.java @@ -285,37 +285,41 @@ public interface Arm64Const { public static final int UC_ARM64_REG_TPIDR_EL1 = 264; public static final int UC_ARM64_REG_PSTATE = 265; +// floating point control and status registers + public static final int UC_ARM64_REG_FPCR = 266; + public static final int UC_ARM64_REG_FPSR = 267; + // exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead - public static final int UC_ARM64_REG_ELR_EL0 = 266; - public static final int UC_ARM64_REG_ELR_EL1 = 267; - public static final int UC_ARM64_REG_ELR_EL2 = 268; - public static final int UC_ARM64_REG_ELR_EL3 = 269; + public static final int UC_ARM64_REG_ELR_EL0 = 268; + public static final int UC_ARM64_REG_ELR_EL1 = 269; + public static final int UC_ARM64_REG_ELR_EL2 = 270; + public static final int UC_ARM64_REG_ELR_EL3 = 271; // stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead - public static final int UC_ARM64_REG_SP_EL0 = 270; - public static final int UC_ARM64_REG_SP_EL1 = 271; - public static final int UC_ARM64_REG_SP_EL2 = 272; - public static final int UC_ARM64_REG_SP_EL3 = 273; + public static final int UC_ARM64_REG_SP_EL0 = 272; + public static final int UC_ARM64_REG_SP_EL1 = 273; + public static final int UC_ARM64_REG_SP_EL2 = 274; + public static final int UC_ARM64_REG_SP_EL3 = 275; // other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead - public static final int UC_ARM64_REG_TTBR0_EL1 = 274; - public static final int UC_ARM64_REG_TTBR1_EL1 = 275; - public static final int UC_ARM64_REG_ESR_EL0 = 276; - public static final int UC_ARM64_REG_ESR_EL1 = 277; - public static final int UC_ARM64_REG_ESR_EL2 = 278; - public static final int UC_ARM64_REG_ESR_EL3 = 279; - public static final int UC_ARM64_REG_FAR_EL0 = 280; - public static final int UC_ARM64_REG_FAR_EL1 = 281; - public static final int UC_ARM64_REG_FAR_EL2 = 282; - public static final int UC_ARM64_REG_FAR_EL3 = 283; - public static final int UC_ARM64_REG_PAR_EL1 = 284; - public static final int UC_ARM64_REG_MAIR_EL1 = 285; - public static final int UC_ARM64_REG_VBAR_EL0 = 286; - public static final int UC_ARM64_REG_VBAR_EL1 = 287; - public static final int UC_ARM64_REG_VBAR_EL2 = 288; - public static final int UC_ARM64_REG_VBAR_EL3 = 289; - public static final int UC_ARM64_REG_CP_REG = 290; - public static final int UC_ARM64_REG_ENDING = 291; + public static final int UC_ARM64_REG_TTBR0_EL1 = 276; + public static final int UC_ARM64_REG_TTBR1_EL1 = 277; + public static final int UC_ARM64_REG_ESR_EL0 = 278; + public static final int UC_ARM64_REG_ESR_EL1 = 279; + public static final int UC_ARM64_REG_ESR_EL2 = 280; + public static final int UC_ARM64_REG_ESR_EL3 = 281; + public static final int UC_ARM64_REG_FAR_EL0 = 282; + public static final int UC_ARM64_REG_FAR_EL1 = 283; + public static final int UC_ARM64_REG_FAR_EL2 = 284; + public static final int UC_ARM64_REG_FAR_EL3 = 285; + public static final int UC_ARM64_REG_PAR_EL1 = 286; + public static final int UC_ARM64_REG_MAIR_EL1 = 287; + public static final int UC_ARM64_REG_VBAR_EL0 = 288; + public static final int UC_ARM64_REG_VBAR_EL1 = 289; + public static final int UC_ARM64_REG_VBAR_EL2 = 290; + public static final int UC_ARM64_REG_VBAR_EL3 = 291; + public static final int UC_ARM64_REG_CP_REG = 292; + public static final int UC_ARM64_REG_ENDING = 293; // alias registers public static final int UC_ARM64_REG_IP0 = 215; diff --git a/bindings/pascal/unicorn/Arm64Const.pas b/bindings/pascal/unicorn/Arm64Const.pas index 9e3939d3..05347e71 100644 --- a/bindings/pascal/unicorn/Arm64Const.pas +++ b/bindings/pascal/unicorn/Arm64Const.pas @@ -286,37 +286,41 @@ const UC_ARM64_REG_TPIDR_EL1 = 264; UC_ARM64_REG_PSTATE = 265; +// floating point control and status registers + UC_ARM64_REG_FPCR = 266; + UC_ARM64_REG_FPSR = 267; + // exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_ELR_EL0 = 266; - UC_ARM64_REG_ELR_EL1 = 267; - UC_ARM64_REG_ELR_EL2 = 268; - UC_ARM64_REG_ELR_EL3 = 269; + UC_ARM64_REG_ELR_EL0 = 268; + UC_ARM64_REG_ELR_EL1 = 269; + UC_ARM64_REG_ELR_EL2 = 270; + UC_ARM64_REG_ELR_EL3 = 271; // stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_SP_EL0 = 270; - UC_ARM64_REG_SP_EL1 = 271; - UC_ARM64_REG_SP_EL2 = 272; - UC_ARM64_REG_SP_EL3 = 273; + UC_ARM64_REG_SP_EL0 = 272; + UC_ARM64_REG_SP_EL1 = 273; + UC_ARM64_REG_SP_EL2 = 274; + UC_ARM64_REG_SP_EL3 = 275; // other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_TTBR0_EL1 = 274; - UC_ARM64_REG_TTBR1_EL1 = 275; - UC_ARM64_REG_ESR_EL0 = 276; - UC_ARM64_REG_ESR_EL1 = 277; - UC_ARM64_REG_ESR_EL2 = 278; - UC_ARM64_REG_ESR_EL3 = 279; - UC_ARM64_REG_FAR_EL0 = 280; - UC_ARM64_REG_FAR_EL1 = 281; - UC_ARM64_REG_FAR_EL2 = 282; - UC_ARM64_REG_FAR_EL3 = 283; - UC_ARM64_REG_PAR_EL1 = 284; - UC_ARM64_REG_MAIR_EL1 = 285; - UC_ARM64_REG_VBAR_EL0 = 286; - UC_ARM64_REG_VBAR_EL1 = 287; - UC_ARM64_REG_VBAR_EL2 = 288; - UC_ARM64_REG_VBAR_EL3 = 289; - UC_ARM64_REG_CP_REG = 290; - UC_ARM64_REG_ENDING = 291; + UC_ARM64_REG_TTBR0_EL1 = 276; + UC_ARM64_REG_TTBR1_EL1 = 277; + UC_ARM64_REG_ESR_EL0 = 278; + UC_ARM64_REG_ESR_EL1 = 279; + UC_ARM64_REG_ESR_EL2 = 280; + UC_ARM64_REG_ESR_EL3 = 281; + UC_ARM64_REG_FAR_EL0 = 282; + UC_ARM64_REG_FAR_EL1 = 283; + UC_ARM64_REG_FAR_EL2 = 284; + UC_ARM64_REG_FAR_EL3 = 285; + UC_ARM64_REG_PAR_EL1 = 286; + UC_ARM64_REG_MAIR_EL1 = 287; + UC_ARM64_REG_VBAR_EL0 = 288; + UC_ARM64_REG_VBAR_EL1 = 289; + UC_ARM64_REG_VBAR_EL2 = 290; + UC_ARM64_REG_VBAR_EL3 = 291; + UC_ARM64_REG_CP_REG = 292; + UC_ARM64_REG_ENDING = 293; // alias registers UC_ARM64_REG_IP0 = 215; diff --git a/bindings/python/unicorn/arm64_const.py b/bindings/python/unicorn/arm64_const.py index 8d7c5a70..485daf43 100644 --- a/bindings/python/unicorn/arm64_const.py +++ b/bindings/python/unicorn/arm64_const.py @@ -281,37 +281,41 @@ UC_ARM64_REG_TPIDRRO_EL0 = 263 UC_ARM64_REG_TPIDR_EL1 = 264 UC_ARM64_REG_PSTATE = 265 +# floating point control and status registers +UC_ARM64_REG_FPCR = 266 +UC_ARM64_REG_FPSR = 267 + # exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead -UC_ARM64_REG_ELR_EL0 = 266 -UC_ARM64_REG_ELR_EL1 = 267 -UC_ARM64_REG_ELR_EL2 = 268 -UC_ARM64_REG_ELR_EL3 = 269 +UC_ARM64_REG_ELR_EL0 = 268 +UC_ARM64_REG_ELR_EL1 = 269 +UC_ARM64_REG_ELR_EL2 = 270 +UC_ARM64_REG_ELR_EL3 = 271 # stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead -UC_ARM64_REG_SP_EL0 = 270 -UC_ARM64_REG_SP_EL1 = 271 -UC_ARM64_REG_SP_EL2 = 272 -UC_ARM64_REG_SP_EL3 = 273 +UC_ARM64_REG_SP_EL0 = 272 +UC_ARM64_REG_SP_EL1 = 273 +UC_ARM64_REG_SP_EL2 = 274 +UC_ARM64_REG_SP_EL3 = 275 # other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead -UC_ARM64_REG_TTBR0_EL1 = 274 -UC_ARM64_REG_TTBR1_EL1 = 275 -UC_ARM64_REG_ESR_EL0 = 276 -UC_ARM64_REG_ESR_EL1 = 277 -UC_ARM64_REG_ESR_EL2 = 278 -UC_ARM64_REG_ESR_EL3 = 279 -UC_ARM64_REG_FAR_EL0 = 280 -UC_ARM64_REG_FAR_EL1 = 281 -UC_ARM64_REG_FAR_EL2 = 282 -UC_ARM64_REG_FAR_EL3 = 283 -UC_ARM64_REG_PAR_EL1 = 284 -UC_ARM64_REG_MAIR_EL1 = 285 -UC_ARM64_REG_VBAR_EL0 = 286 -UC_ARM64_REG_VBAR_EL1 = 287 -UC_ARM64_REG_VBAR_EL2 = 288 -UC_ARM64_REG_VBAR_EL3 = 289 -UC_ARM64_REG_CP_REG = 290 -UC_ARM64_REG_ENDING = 291 +UC_ARM64_REG_TTBR0_EL1 = 276 +UC_ARM64_REG_TTBR1_EL1 = 277 +UC_ARM64_REG_ESR_EL0 = 278 +UC_ARM64_REG_ESR_EL1 = 279 +UC_ARM64_REG_ESR_EL2 = 280 +UC_ARM64_REG_ESR_EL3 = 281 +UC_ARM64_REG_FAR_EL0 = 282 +UC_ARM64_REG_FAR_EL1 = 283 +UC_ARM64_REG_FAR_EL2 = 284 +UC_ARM64_REG_FAR_EL3 = 285 +UC_ARM64_REG_PAR_EL1 = 286 +UC_ARM64_REG_MAIR_EL1 = 287 +UC_ARM64_REG_VBAR_EL0 = 288 +UC_ARM64_REG_VBAR_EL1 = 289 +UC_ARM64_REG_VBAR_EL2 = 290 +UC_ARM64_REG_VBAR_EL3 = 291 +UC_ARM64_REG_CP_REG = 292 +UC_ARM64_REG_ENDING = 293 # alias registers UC_ARM64_REG_IP0 = 215 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb index 6ec37708..3e379a43 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb @@ -283,37 +283,41 @@ module UnicornEngine UC_ARM64_REG_TPIDR_EL1 = 264 UC_ARM64_REG_PSTATE = 265 +# floating point control and status registers + UC_ARM64_REG_FPCR = 266 + UC_ARM64_REG_FPSR = 267 + # exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_ELR_EL0 = 266 - UC_ARM64_REG_ELR_EL1 = 267 - UC_ARM64_REG_ELR_EL2 = 268 - UC_ARM64_REG_ELR_EL3 = 269 + UC_ARM64_REG_ELR_EL0 = 268 + UC_ARM64_REG_ELR_EL1 = 269 + UC_ARM64_REG_ELR_EL2 = 270 + UC_ARM64_REG_ELR_EL3 = 271 # stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_SP_EL0 = 270 - UC_ARM64_REG_SP_EL1 = 271 - UC_ARM64_REG_SP_EL2 = 272 - UC_ARM64_REG_SP_EL3 = 273 + UC_ARM64_REG_SP_EL0 = 272 + UC_ARM64_REG_SP_EL1 = 273 + UC_ARM64_REG_SP_EL2 = 274 + UC_ARM64_REG_SP_EL3 = 275 # other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_TTBR0_EL1 = 274 - UC_ARM64_REG_TTBR1_EL1 = 275 - UC_ARM64_REG_ESR_EL0 = 276 - UC_ARM64_REG_ESR_EL1 = 277 - UC_ARM64_REG_ESR_EL2 = 278 - UC_ARM64_REG_ESR_EL3 = 279 - UC_ARM64_REG_FAR_EL0 = 280 - UC_ARM64_REG_FAR_EL1 = 281 - UC_ARM64_REG_FAR_EL2 = 282 - UC_ARM64_REG_FAR_EL3 = 283 - UC_ARM64_REG_PAR_EL1 = 284 - UC_ARM64_REG_MAIR_EL1 = 285 - UC_ARM64_REG_VBAR_EL0 = 286 - UC_ARM64_REG_VBAR_EL1 = 287 - UC_ARM64_REG_VBAR_EL2 = 288 - UC_ARM64_REG_VBAR_EL3 = 289 - UC_ARM64_REG_CP_REG = 290 - UC_ARM64_REG_ENDING = 291 + UC_ARM64_REG_TTBR0_EL1 = 276 + UC_ARM64_REG_TTBR1_EL1 = 277 + UC_ARM64_REG_ESR_EL0 = 278 + UC_ARM64_REG_ESR_EL1 = 279 + UC_ARM64_REG_ESR_EL2 = 280 + UC_ARM64_REG_ESR_EL3 = 281 + UC_ARM64_REG_FAR_EL0 = 282 + UC_ARM64_REG_FAR_EL1 = 283 + UC_ARM64_REG_FAR_EL2 = 284 + UC_ARM64_REG_FAR_EL3 = 285 + UC_ARM64_REG_PAR_EL1 = 286 + UC_ARM64_REG_MAIR_EL1 = 287 + UC_ARM64_REG_VBAR_EL0 = 288 + UC_ARM64_REG_VBAR_EL1 = 289 + UC_ARM64_REG_VBAR_EL2 = 290 + UC_ARM64_REG_VBAR_EL3 = 291 + UC_ARM64_REG_CP_REG = 292 + UC_ARM64_REG_ENDING = 293 # alias registers UC_ARM64_REG_IP0 = 215 From ff1f0a5c1a8efd2edec6a36fb420a8041e1e35fb Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Fri, 14 Oct 2022 16:57:46 +0200 Subject: [PATCH 49/77] dotnet: Refactor .NET bindings for .NET5.0 --- .../dotnet/UnicornManaged/AssemblyInfo.fs | 41 ---- .../UnicornManaged/Binding/BindingFactory.fs | 4 +- bindings/dotnet/UnicornManaged/Unicorn.fs | 103 ++++----- .../UnicornManaged/UnicornManaged.fsproj | 94 +++----- bindings/dotnet/UnicornSamples/App.config | 6 - bindings/dotnet/UnicornSamples/Program.cs | 4 +- .../UnicornSamples/Properties/AssemblyInfo.cs | 36 --- .../dotnet/UnicornSamples/ShellcodeSample.cs | 87 ++++--- .../UnicornSamples/UnicornSamples.csproj | 93 ++------ bindings/dotnet/UnicornSamples/Utils.cs | 28 +-- bindings/dotnet/UnicornSamples/X86Sample32.cs | 218 ++++++++---------- .../dotnet/UnicornSamples/packages.config | 4 - 12 files changed, 251 insertions(+), 467 deletions(-) delete mode 100644 bindings/dotnet/UnicornManaged/AssemblyInfo.fs delete mode 100644 bindings/dotnet/UnicornSamples/App.config delete mode 100644 bindings/dotnet/UnicornSamples/Properties/AssemblyInfo.cs delete mode 100644 bindings/dotnet/UnicornSamples/packages.config diff --git a/bindings/dotnet/UnicornManaged/AssemblyInfo.fs b/bindings/dotnet/UnicornManaged/AssemblyInfo.fs deleted file mode 100644 index 16d8c919..00000000 --- a/bindings/dotnet/UnicornManaged/AssemblyInfo.fs +++ /dev/null @@ -1,41 +0,0 @@ -namespace UnicornManaged.AssemblyInfo - -open System.Reflection -open System.Runtime.CompilerServices -open System.Runtime.InteropServices - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[] -[] -[] -[] -[] -[] -[] -[] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [] -[] -[] - -do - () \ No newline at end of file diff --git a/bindings/dotnet/UnicornManaged/Binding/BindingFactory.fs b/bindings/dotnet/UnicornManaged/Binding/BindingFactory.fs index f55f72ec..6ea0b183 100644 --- a/bindings/dotnet/UnicornManaged/Binding/BindingFactory.fs +++ b/bindings/dotnet/UnicornManaged/Binding/BindingFactory.fs @@ -1,13 +1,11 @@ namespace UnicornManaged.Binding -open System module BindingFactory = let mutable _instance = NativeBinding.instance let setDefaultBinding(binding: IBinding) = _instance <- binding - + let getDefault() = _instance - diff --git a/bindings/dotnet/UnicornManaged/Unicorn.fs b/bindings/dotnet/UnicornManaged/Unicorn.fs index 0a05d30d..31decbcd 100644 --- a/bindings/dotnet/UnicornManaged/Unicorn.fs +++ b/bindings/dotnet/UnicornManaged/Unicorn.fs @@ -1,7 +1,6 @@ namespace UnicornManaged - + open System -open System.Threading open System.Collections.Generic open System.Runtime.InteropServices open System.Linq @@ -20,7 +19,7 @@ and OutHook = delegate of Unicorn * Int32 * Int32 * Int32 * Object -> unit and SyscallHook = delegate of Unicorn * Object -> unit // the managed unicorn engine -and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = +and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = // hook callback list let _codeHooks = new List<(CodeHook * Object)>() @@ -43,24 +42,24 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = (UC_HOOK_MEM_WRITE_PROT, UC_MEM_WRITE_PROT) (UC_HOOK_MEM_FETCH_PROT, UC_MEM_FETCH_PROT) ] |> dict - + let mutable _eng = [|UIntPtr.Zero|] - + let checkResult(errCode: Int32, errMsg: String) = if errCode <> Common.UC_ERR_OK then raise(ApplicationException(String.Format("{0}. Error: {1}", errMsg, errCode))) - + let hookDel(callbacks: List<'a * Object>) (callback: 'a)= // TODO: invoke the native function in order to not call the trampoline anymore callbacks |> Seq.tryFind(fun item -> match item with | (c, _) -> c = callback) |> (fun k -> if k.IsSome then callbacks.Remove(k.Value) |> ignore) - + let allocate(size: Int32) = let mem = Marshal.AllocHGlobal(size) _disposablePointers.Add(mem) mem.ToPointer() - do + do // initialize event list _eventMemMap |> Seq.map(fun kv -> kv.Key) @@ -72,7 +71,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = checkResult(err, "Unable to open the Unicorn Engine") new(arch, mode) = new Unicorn(arch, mode, BindingFactory.getDefault()) - + member private this.CheckResult(errorCode: Int32) = // return the exception instead of raising it in order to have a more meaningful stack trace if errorCode <> Common.UC_ERR_OK then @@ -82,43 +81,43 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = member this.MemMap(address: Int64, size: Int64, perm: Int32) = let size = new UIntPtr(uint64 size) - match binding.MemMap(_eng.[0], uint64 address, size, uint32 perm) |> this.CheckResult with + match binding.MemMap(_eng.[0], uint64 address, size, uint32 perm) |> this.CheckResult with | Some e -> raise e | None -> () member this.MemMapPtr(address: Int64, size: Int64, perm: Int32, ptr: IntPtr) = let size = new UIntPtr(uint64 size) let ptr = new UIntPtr(ptr.ToPointer()) - match binding.MemMapPtr(_eng.[0], uint64 address, size, uint32 perm, ptr) |> this.CheckResult with - | Some e -> raise e | None -> () - + match binding.MemMapPtr(_eng.[0], uint64 address, size, uint32 perm, ptr) |> this.CheckResult with + | Some e -> raise e | None -> () + member this.MemUnmap(address: Int64, size: Int64) = let size = new UIntPtr(uint64 size) - match binding.MemUnmap(_eng.[0], uint64 address, size) |> this.CheckResult with - | Some e -> raise e | None -> () + match binding.MemUnmap(_eng.[0], uint64 address, size) |> this.CheckResult with + | Some e -> raise e | None -> () member this.MemProtect(address: Int64, size: Int64, ?perm: Int32) = let size = new UIntPtr(uint64 size) let perm = defaultArg perm Common.UC_PROT_ALL - match binding.MemProtect(_eng.[0], uint64 address, size, uint32 perm) |> this.CheckResult with - | Some e -> raise e | None -> () - + match binding.MemProtect(_eng.[0], uint64 address, size, uint32 perm) |> this.CheckResult with + | Some e -> raise e | None -> () + member this.MemWrite(address: Int64, value: Byte array) = - match binding.MemWrite(_eng.[0], uint64 address, value, new UIntPtr(uint32 value.Length)) |> this.CheckResult with + match binding.MemWrite(_eng.[0], uint64 address, value, new UIntPtr(uint32 value.Length)) |> this.CheckResult with | Some e -> raise e | None -> () member this.MemRead(address: Int64, memValue: Byte array) = - match binding.MemRead(_eng.[0], uint64 address, memValue, new UIntPtr(uint32 memValue.Length)) |> this.CheckResult with + match binding.MemRead(_eng.[0], uint64 address, memValue, new UIntPtr(uint32 memValue.Length)) |> this.CheckResult with | Some e -> raise e | None -> () member this.RegWrite(regId: Int32, value: Byte array) = - match binding.RegWrite(_eng.[0], regId, value) |> this.CheckResult with + match binding.RegWrite(_eng.[0], regId, value) |> this.CheckResult with | Some e -> raise e | None -> () member this.RegWrite(regId: Int32, value: Int64) = this.RegWrite(regId, int64ToBytes value) member this.RegRead(regId: Int32, regValue: Byte array) = - match binding.RegRead(_eng.[0], regId, regValue) |> this.CheckResult with + match binding.RegRead(_eng.[0], regId, regValue) |> this.CheckResult with | Some e -> raise e | None -> () member this.RegRead(regId: Int32) = @@ -127,15 +126,15 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = bytesToInt64 buffer member this.EmuStart(beginAddr: Int64, untilAddr: Int64, timeout: Int64, count: Int64) = - match binding.EmuStart(_eng.[0], uint64 beginAddr, uint64 untilAddr, uint64 timeout, uint64 count) |> this.CheckResult with + match binding.EmuStart(_eng.[0], uint64 beginAddr, uint64 untilAddr, uint64 timeout, uint64 count) |> this.CheckResult with | Some e -> raise e | None -> () member this.EmuStop() = - match binding.EmuStop(_eng.[0]) |> this.CheckResult with + match binding.EmuStop(_eng.[0]) |> this.CheckResult with | Some e -> raise e | None -> () - + member this.Close() = - match binding.Close(_eng.[0]) |> this.CheckResult with + match binding.Close(_eng.[0]) |> this.CheckResult with | Some e -> raise e | None -> () member this.ArchSupported(arch: Int32) = @@ -148,15 +147,15 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = let errorStringPointer = binding.Strerror(errorNo) Marshal.PtrToStringAnsi(errorStringPointer) - member this.AddCodeHook(callback: CodeHook, userData: Object, beginAddr: Int64, endAddr: Int64) = + member this.AddCodeHook(callback: CodeHook, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) = _codeHooks |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData)) - + if _codeHooks |> Seq.isEmpty then - let funcPointer = Marshal.GetFunctionPointerForDelegate(new CodeHookInternal(trampoline)) + let funcPointer = Marshal.GetFunctionPointerForDelegate(new CodeHookInternal(trampoline)) let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with + match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with | Some e -> raise e | None -> () _codeHooks.Add(callback, userData) @@ -167,7 +166,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = member this.HookDel(callback: CodeHook) = hookDel _codeHooks callback - member this.AddBlockHook(callback: BlockHook, userData: Object, beginAddr: Int64, endAddr: Int64) = + member this.AddBlockHook(callback: BlockHook, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) = _blockHooks |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData)) @@ -175,7 +174,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = if _blockHooks |> Seq.isEmpty then let funcPointer = Marshal.GetFunctionPointerForDelegate(new BlockHookInternal(trampoline)) let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with + match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with | Some e -> raise e | None -> () _blockHooks.Add(callback, userData) @@ -183,15 +182,15 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = member this.HookDel(callback: BlockHook) = hookDel _blockHooks callback - member this.AddInterruptHook(callback: InterruptHook, userData: Object, hookBegin: UInt64, hookEnd : UInt64) = + member this.AddInterruptHook(callback: InterruptHook, userData: Object, hookBegin: UInt64, hookEnd : UInt64) = let trampoline(u: IntPtr) (intNumber: Int32) (user: IntPtr) = _interruptHooks |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, intNumber, userData)) - + if _interruptHooks |> Seq.isEmpty then let funcPointer = Marshal.GetFunctionPointerForDelegate(new InterruptHookInternal(trampoline)) let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, hookBegin, hookEnd) |> this.CheckResult with + match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, hookBegin, hookEnd) |> this.CheckResult with | Some e -> raise e | None -> () _interruptHooks.Add(callback, userData) @@ -202,7 +201,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = member this.HookDel(callback: InterruptHook) = hookDel _interruptHooks callback - member this.AddMemReadHook(callback: MemReadHook, userData: Object, beginAddr: Int64, endAddr: Int64) = + member this.AddMemReadHook(callback: MemReadHook, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) = _memReadHooks |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData)) @@ -210,7 +209,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = if _memReadHooks |> Seq.isEmpty then let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemReadHookInternal(trampoline)) let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with + match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with | Some e -> raise e | None -> () _memReadHooks.Add(callback, userData) @@ -218,15 +217,15 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = member this.HookDel(callback: MemReadHook) = hookDel _memReadHooks callback - member this.AddMemWriteHook(callback: MemWriteHook, userData: Object, beginAddr: Int64, endAddr: Int64) = + member this.AddMemWriteHook(callback: MemWriteHook, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) = _memWriteHooks |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, value, userData)) - + if _memWriteHooks |> Seq.isEmpty then let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemWriteHookInternal(trampoline)) let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with + match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with | Some e -> raise e | None -> () _memWriteHooks.Add(callback, userData) @@ -235,7 +234,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = hookDel _memWriteHooks callback member this.AddEventMemHook(callback: EventMemHook, eventType: Int32, userData: Object) = - let trampoline(u: IntPtr) (eventType: Int32) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) = + let trampoline(u: IntPtr) (eventType: Int32) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) = _memEventHooks.Keys |> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0) |> Seq.map(fun eventflag -> _memEventHooks.[eventflag]) @@ -249,12 +248,12 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = |> Seq.filter(fun eventFlag -> _memEventHooks.[eventFlag] |> Seq.isEmpty) |> Seq.iter(fun eventFlag -> let funcPointer = Marshal.GetFunctionPointerForDelegate(new EventMemHookInternal(trampoline)) - let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, eventFlag, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0) |> this.CheckResult with + let hh = new UIntPtr(allocate(IntPtr.Size)) + match binding.HookAddNoarg(_eng.[0], hh, eventFlag, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0) |> this.CheckResult with | Some e -> raise e | None -> () ) - // register the callbacks + // register the callbacks _memEventHooks.Keys |> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0) |> Seq.iter(fun eventFlag -> _memEventHooks.[eventFlag].Add((callback, userData))) @@ -271,11 +270,11 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = _inHooks |> Seq.map(fun (callback, userData) -> callback.Invoke(this, port, size, userData)) |> Seq.last - + if _inHooks |> Seq.isEmpty then let funcPointer = Marshal.GetFunctionPointerForDelegate(new InHookInternal(trampoline)) let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_IN) |> this.CheckResult with + match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_IN) |> this.CheckResult with | Some e -> raise e | None -> () _inHooks.Add(callback, userData) @@ -287,11 +286,11 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = let trampoline(u: IntPtr) (port: Int32) (size: Int32) (value: Int32) (user: IntPtr) = _outHooks |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, port, size, value, userData)) - + if _outHooks |> Seq.isEmpty then let funcPointer = Marshal.GetFunctionPointerForDelegate(new OutHookInternal(trampoline)) let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_OUT) |> this.CheckResult with + match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_OUT) |> this.CheckResult with | Some e -> raise e | None -> () _outHooks.Add(callback, userData) @@ -303,18 +302,18 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = let trampoline(u: IntPtr) (user: IntPtr) = _syscallHooks |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, userData)) - + if _syscallHooks |> Seq.isEmpty then let funcPointer = Marshal.GetFunctionPointerForDelegate(new SyscallHookInternal(trampoline)) let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_SYSCALL) |> this.CheckResult with + match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_SYSCALL) |> this.CheckResult with | Some e -> raise e | None -> () _syscallHooks.Add(callback, userData) member this.AddSyscallHook(callback: SyscallHook) = this.AddSyscallHook(callback, null) - + member this.Version() = let (major, minor) = (new UIntPtr(), new UIntPtr()) let combined = binding.Version(major, minor) @@ -340,4 +339,4 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = interface IDisposable with member this.Dispose() = - this.Dispose() \ No newline at end of file + this.Dispose() diff --git a/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj b/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj index e10cd735..864e4e96 100644 --- a/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj +++ b/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj @@ -1,56 +1,45 @@ - - - + - Debug - AnyCPU - 2.0 - 0c21f1c1-2725-4a46-9022-1905f85822a5 - Library + net5.0 UnicornManaged UnicornManaged - v4.5 - 4.3.1.0 + Copyright © Antonio Parata 2016 + https://github.com/unicorn-engine/unicorn + 2.0.0 + 0c21f1c1-2725-4a46-9022-1905f85822a5 true - UnicornManaged - + true + + + 3 + + - true - full - false - false - bin\Debug\ - DEBUG;TRACE - 3 - bin\Debug\UnicornManaged.XML - - - pdbonly - true - true - bin\Release\ - TRACE - 3 - bin\Release\UnicornManaged.XML - + true + full + false + false + DEBUG;TRACE + + + pdbonly + true + true + TRACE + + - - - True - - - - - - - + + + + @@ -61,27 +50,4 @@ - - 11 - - - - - $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets - - - - - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets - - - - - - \ No newline at end of file + diff --git a/bindings/dotnet/UnicornSamples/App.config b/bindings/dotnet/UnicornSamples/App.config deleted file mode 100644 index d1428ad7..00000000 --- a/bindings/dotnet/UnicornSamples/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/bindings/dotnet/UnicornSamples/Program.cs b/bindings/dotnet/UnicornSamples/Program.cs index 41cfb19c..f961708a 100644 --- a/bindings/dotnet/UnicornSamples/Program.cs +++ b/bindings/dotnet/UnicornSamples/Program.cs @@ -2,9 +2,9 @@ namespace UnicornSamples { - class Program + internal static class Program { - static void Main(string[] args) + private static void Main(string[] args) { // X86 tests 32bit X86Sample32.X86Code32(); diff --git a/bindings/dotnet/UnicornSamples/Properties/AssemblyInfo.cs b/bindings/dotnet/UnicornSamples/Properties/AssemblyInfo.cs deleted file mode 100644 index aacf2f82..00000000 --- a/bindings/dotnet/UnicornSamples/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("UnicornSamples")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("UnicornSamples")] -[assembly: AssemblyCopyright("Copyright © Antonio Parata 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("b80b5987-1e24-4309-8bf9-c4f91270f21c")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/bindings/dotnet/UnicornSamples/ShellcodeSample.cs b/bindings/dotnet/UnicornSamples/ShellcodeSample.cs index be654d6f..7982e5e4 100644 --- a/bindings/dotnet/UnicornSamples/ShellcodeSample.cs +++ b/bindings/dotnet/UnicornSamples/ShellcodeSample.cs @@ -1,24 +1,20 @@ using Gee.External.Capstone; using Gee.External.Capstone.X86; using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; -using System.Reflection; using System.Text; -using System.Threading.Tasks; using UnicornManaged; using UnicornManaged.Const; namespace UnicornSamples { - internal class ShellcodeSample + internal static class ShellcodeSample { - private const Int64 ADDRESS = 0x1000000; + private const long ADDRESS = 0x1000000; public static void X86Code32Self() { - Byte[] X86_CODE32_SELF = + byte[] X86_CODE32_SELF = { 0xeb, 0x1c, 0x5a, 0x89, 0xd6, 0x8b, 0x02, 0x66, 0x3d, 0xca, 0x7d, 0x75, 0x06, 0x66, 0x05, 0x03, 0x03, 0x89, 0x02, 0xfe, 0xc2, 0x3d, 0x41, 0x41, 0x41, 0x41, 0x75, 0xe9, 0xff, 0xe6, 0xe8, 0xdf, 0xff, 0xff, @@ -31,7 +27,7 @@ namespace UnicornSamples public static void X86Code32() { - Byte[] X86_CODE32 = + byte[] X86_CODE32 = { 0xeb, 0x19, 0x31, 0xc0, 0x31, 0xdb, 0x31, 0xd2, 0x31, 0xc9, 0xb0, 0x04, 0xb3, 0x01, 0x59, 0xb2, 0x05, 0xcd, 0x80, 0x31, 0xc0, 0xb0, 0x01, 0x31, 0xdb, 0xcd, 0x80, 0xe8, 0xe2, 0xff, 0xff, 0xff, 0x68, 0x65, @@ -41,39 +37,39 @@ namespace UnicornSamples Run(X86_CODE32); } - private static void Run(Byte[] code) + private static void Run(byte[] code) { Console.WriteLine(); var stackTrace = new StackTrace(); var stackFrame = stackTrace.GetFrames()[1]; var methodName = stackFrame.GetMethod().Name; - Console.WriteLine("*** Start: " + methodName); + Console.WriteLine($"*** Start: {methodName}"); RunTest(code, ADDRESS); - Console.WriteLine("*** End: " + methodName); + Console.WriteLine($"*** End: {methodName}"); Console.WriteLine(); } - private static void RunTest(Byte[] code, Int64 address) + private static void RunTest(byte[] code, long address) { try { using (var u = new Unicorn(Common.UC_ARCH_X86, Common.UC_MODE_32)) - using(var disassembler = CapstoneDisassembler.CreateX86Disassembler(DisassembleMode.Bit32)) + using(var disassembler = CapstoneDisassembler.CreateX86Disassembler(X86DisassembleMode.Bit32)) { - Console.WriteLine("Unicorn version: {0}", u.Version()); - + Console.WriteLine($"Unicorn version: {u.Version()}"); + // map 2MB of memory for this emulation u.MemMap(address, 2 * 1024 * 1024, Common.UC_PROT_ALL); // write machine code to be emulated to memory u.MemWrite(address, code); - + // initialize machine registers u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000)); - var regv = new Byte[4]; + var regv = new byte[4]; u.RegRead(X86.UC_X86_REG_ESP, regv); // tracing all instructions by having @begin > @end @@ -84,7 +80,7 @@ namespace UnicornSamples // handle SYSCALL u.AddSyscallHook(SyscallHookCallback); - + Console.WriteLine(">>> Start tracing code"); // emulate machine code in infinite time @@ -98,44 +94,44 @@ namespace UnicornSamples Console.Error.WriteLine("Emulation FAILED! " + ex.Message); } } - - private static void CodeHookCallback( - CapstoneDisassembler disassembler, - Unicorn u, - Int64 addr, - Int32 size, - Object userData) - { - Console.Write("[+] 0x{0}: ", addr.ToString("X")); - var eipBuffer = new Byte[4]; + private static void CodeHookCallback( + CapstoneX86Disassembler disassembler, + Unicorn u, + long addr, + int size, + object userData) + { + Console.Write($"[+] 0x{addr:X}: "); + + var eipBuffer = new byte[4]; u.RegRead(X86.UC_X86_REG_EIP, eipBuffer); var effectiveSize = Math.Min(16, size); - var tmp = new Byte[effectiveSize]; + var tmp = new byte[effectiveSize]; u.MemRead(addr, tmp); var sb = new StringBuilder(); foreach (var t in tmp) { - sb.AppendFormat("{0} ", (0xFF & t).ToString("X")); + sb.AppendFormat($"{(0xFF & t):X} "); } - Console.Write("{0,-20}", sb); + Console.Write($"{sb,-20}"); Console.WriteLine(Utils.Disassemble(disassembler, tmp)); } - private static void SyscallHookCallback(Unicorn u, Object userData) + private static void SyscallHookCallback(Unicorn u, object userData) { - var eaxBuffer = new Byte[4]; + var eaxBuffer = new byte[4]; u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer); var eax = Utils.ToInt(eaxBuffer); - Console.WriteLine("[!] Syscall EAX = 0x{0}", eax.ToString("X")); + Console.WriteLine($"[!] Syscall EAX = 0x{eax:X}"); u.EmuStop(); } - private static void InterruptHookCallback(Unicorn u, Int32 intNumber, Object userData) + private static void InterruptHookCallback(Unicorn u, int intNumber, object userData) { // only handle Linux syscall if (intNumber != 0x80) @@ -143,8 +139,8 @@ namespace UnicornSamples return; } - var eaxBuffer = new Byte[4]; - var eipBuffer = new Byte[4]; + var eaxBuffer = new byte[4]; + var eipBuffer = new byte[4]; u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer); u.RegRead(X86.UC_X86_REG_EIP, eipBuffer); @@ -155,19 +151,19 @@ namespace UnicornSamples switch (eax) { default: - Console.WriteLine("[!] Interrupt 0x{0} num {1}, EAX=0x{2}", eip.ToString("X"), intNumber.ToString("X"), eax.ToString("X")); + Console.WriteLine($"[!] Interrupt 0x{eip:X} num {intNumber:X}, EAX=0x{eax:X}"); break; case 1: // sys_exit - Console.WriteLine("[!] Interrupt 0x{0} num {1}, SYS_EXIT", eip.ToString("X"), intNumber.ToString("X")); + Console.WriteLine($"[!] Interrupt 0x{eip:X} num {intNumber:X}, SYS_EXIT"); u.EmuStop(); break; case 4: // sys_write // ECX = buffer address - var ecxBuffer = new Byte[4]; + var ecxBuffer = new byte[4]; // EDX = buffer size - var edxBuffer = new Byte[4]; + var edxBuffer = new byte[4]; u.RegRead(X86.UC_X86_REG_ECX, ecxBuffer); u.RegRead(X86.UC_X86_REG_EDX, edxBuffer); @@ -177,16 +173,11 @@ namespace UnicornSamples // read the buffer in var size = Math.Min(256, edx); - var buffer = new Byte[size]; + var buffer = new byte[size]; u.MemRead(ecx, buffer); var content = Encoding.Default.GetString(buffer); - Console.WriteLine( - "[!] Interrupt 0x{0}: num {1}, SYS_WRITE. buffer = 0x{2}, size = , content = '{3}'", - eip.ToString("X"), - ecx.ToString("X"), - edx.ToString("X"), - content); + Console.WriteLine($"[!] Interrupt 0x{eip:X}: num {ecx:X}, SYS_WRITE. buffer = 0x{edx:X}, size = {size:X}, content = '{content}'"); break; } diff --git a/bindings/dotnet/UnicornSamples/UnicornSamples.csproj b/bindings/dotnet/UnicornSamples/UnicornSamples.csproj index 3a087b03..d7464c04 100644 --- a/bindings/dotnet/UnicornSamples/UnicornSamples.csproj +++ b/bindings/dotnet/UnicornSamples/UnicornSamples.csproj @@ -1,43 +1,28 @@ - - - + - Debug - AnyCPU - {B80B5987-1E24-4309-8BF9-C4F91270F21C} + net5.0 Exe - Properties UnicornSamples UnicornSamples - v4.5 - 512 + Copyright © Antonio Parata 2016 + https://github.com/unicorn-engine/unicorn + 2.0.0 + {B80B5987-1E24-4309-8BF9-C4F91270F21C} + true - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true + + + prompt + 4 + + - x86 true full false bin\Debug\ DEBUG;TRACE - prompt - 4 false false @@ -47,62 +32,16 @@ true bin\Release\ TRACE - prompt - 4 - - - ..\packages\Gee.External.Capstone.1.2.2\lib\net45\Gee.External.Capstone.dll - True - - - - - - - - - - - - - - - - - - - - - - - - False - Microsoft .NET Framework 4.5 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - + {0c21f1c1-2725-4a46-9022-1905f85822a5} UnicornManaged + - - + - - \ No newline at end of file diff --git a/bindings/dotnet/UnicornSamples/Utils.cs b/bindings/dotnet/UnicornSamples/Utils.cs index 1f4d287a..aff34d50 100644 --- a/bindings/dotnet/UnicornSamples/Utils.cs +++ b/bindings/dotnet/UnicornSamples/Utils.cs @@ -1,45 +1,41 @@ -using Gee.External.Capstone; -using Gee.External.Capstone.X86; +using Gee.External.Capstone.X86; using System; -using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace UnicornSamples { internal static class Utils { - public static Int64 ToInt(Byte[] val) + public static long ToInt(byte[] val) { - UInt64 res = 0; + ulong res = 0; for (var i = 0; i < val.Length; i++) { var v = val[i] & 0xFF; - res += (UInt64)(v << (i * 8)); + res += (ulong)(v << (i * 8)); } - return (Int64)res; + return (long)res; } - public static Byte[] Int64ToBytes(Int64 intVal) + public static byte[] Int64ToBytes(long intVal) { - var res = new Byte[8]; - var uval = (UInt64)intVal; + var res = new byte[8]; + var uval = (ulong)intVal; for (var i = 0; i < res.Length; i++) { - res[i] = (Byte)(uval & 0xff); + res[i] = (byte)(uval & 0xff); uval = uval >> 8; } return res; } - public static String Disassemble(CapstoneDisassembler disassembler, Byte[] code) + public static string Disassemble(CapstoneX86Disassembler disassembler, byte[] code) { var sb = new StringBuilder(); - var instructions = disassembler.DisassembleAll(code); + var instructions = disassembler.Disassemble(code); foreach (var instruction in instructions) { - sb.AppendFormat("{0} {1}{2}", instruction.Mnemonic, instruction.Operand, Environment.NewLine); + sb.AppendFormat($"{instruction.Mnemonic} {instruction.Operand}{Environment.NewLine}"); } return sb.ToString().Trim(); } diff --git a/bindings/dotnet/UnicornSamples/X86Sample32.cs b/bindings/dotnet/UnicornSamples/X86Sample32.cs index 6bcd8309..24333839 100644 --- a/bindings/dotnet/UnicornSamples/X86Sample32.cs +++ b/bindings/dotnet/UnicornSamples/X86Sample32.cs @@ -1,34 +1,30 @@ using Gee.External.Capstone; using Gee.External.Capstone.X86; using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; -using System.Reflection; using System.Text; -using System.Threading.Tasks; using UnicornManaged; using UnicornManaged.Const; namespace UnicornSamples { - internal class X86Sample32 + internal static class X86Sample32 { - private const Int64 ADDRESS = 0x1000000; + private const long ADDRESS = 0x1000000; public static void X86Code32() { - Byte[] X86_CODE32 = + byte[] X86_CODE32 = { // INC ecx; DEC edx 0x41, 0x4a }; Run(X86_CODE32); } - + public static void X86Code32InvalidMemRead() { - Byte[] X86_CODE32_MEM_READ = + byte[] X86_CODE32_MEM_READ = { // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx 0x8B, 0x0D, 0xAA, 0xAA, 0xAA, 0xAA, 0x41, 0x4a @@ -38,7 +34,7 @@ namespace UnicornSamples public static void X86Code32InvalidMemWriteWithRuntimeFix() { - Byte[] X86_CODE32_MEM_WRITE = + byte[] X86_CODE32_MEM_WRITE = { // mov [0xaaaaaaaa], ecx; INC ecx; DEC edx 0x89, 0x0D, 0xAA, 0xAA, 0xAA, 0xAA, 0x41, 0x4a @@ -48,7 +44,7 @@ namespace UnicornSamples public static void X86Code32InOut() { - Byte[] X86_CODE32_INOUT = + byte[] X86_CODE32_INOUT = { // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx 0x41, 0xE4, 0x3F, 0x4a, 0xE6, 0x46, 0x43 @@ -57,14 +53,14 @@ namespace UnicornSamples } - private static void Run(Byte[] code, Boolean raiseException = false) + private static void Run(byte[] code, bool raiseException = false) { Console.WriteLine(); var stackTrace = new StackTrace(); var stackFrame = stackTrace.GetFrames()[1]; - var methodName = stackFrame.GetMethod().Name; + var methodName = stackFrame.GetMethod()?.Name; - Console.WriteLine("*** Start: " + methodName); + Console.WriteLine($"*** Start: {methodName}"); Exception e = null; try { @@ -84,93 +80,88 @@ namespace UnicornSamples Console.WriteLine(); } - private static void RunTest(Byte[] code, Int64 address, Int32 mode) + private static void RunTest(byte[] code, long address, int mode) { - using (var u = new Unicorn(Common.UC_ARCH_X86, mode)) - using (var disassembler = CapstoneDisassembler.CreateX86Disassembler(DisassembleMode.Bit32)) - { - Console.WriteLine("Unicorn version: {0}", u.Version()); + using var u = new Unicorn(Common.UC_ARCH_X86, mode); + using var disassembler = CapstoneDisassembler.CreateX86Disassembler(X86DisassembleMode.Bit32); + Console.WriteLine($"Unicorn version: {u.Version()}"); - // map 2MB of memory for this emulation - u.MemMap(address, 2 * 1024 * 1024, Common.UC_PROT_ALL); + // map 2MB of memory for this emulation + u.MemMap(address, 2 * 1024 * 1024, Common.UC_PROT_ALL); - // initialize machine registers - u.RegWrite(X86.UC_X86_REG_EAX, 0x1234); - u.RegWrite(X86.UC_X86_REG_ECX, 0x1234); - u.RegWrite(X86.UC_X86_REG_EDX, 0x7890); + // initialize machine registers + u.RegWrite(X86.UC_X86_REG_EAX, 0x1234); + u.RegWrite(X86.UC_X86_REG_ECX, 0x1234); + u.RegWrite(X86.UC_X86_REG_EDX, 0x7890); - // write machine code to be emulated to memory - u.MemWrite(address, code); + // write machine code to be emulated to memory + u.MemWrite(address, code); - // initialize machine registers - u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000)); + // initialize machine registers + u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000)); - // handle IN & OUT instruction - u.AddInHook(InHookCallback); - u.AddOutHook(OutHookCallback); + // handle IN & OUT instruction + u.AddInHook(InHookCallback); + u.AddOutHook(OutHookCallback); - // tracing all instructions by having @begin > @end - u.AddCodeHook((uc, addr, size, userData) => CodeHookCallback(disassembler, uc, addr, size, userData), 1, 0); + // tracing all instructions by having @begin > @end + u.AddCodeHook((uc, addr, size, userData) => CodeHookCallback(disassembler, uc, addr, size, userData), 1, 0); - // handle interrupt ourself - u.AddInterruptHook(InterruptHookCallback); + // handle interrupt ourself + u.AddInterruptHook(InterruptHookCallback); - // handle SYSCALL - u.AddSyscallHook(SyscallHookCallback); + // handle SYSCALL + u.AddSyscallHook(SyscallHookCallback); - // intercept invalid memory events - u.AddEventMemHook(MemMapHookCallback, Common.UC_HOOK_MEM_READ_UNMAPPED | Common.UC_HOOK_MEM_WRITE_UNMAPPED); + // intercept invalid memory events + u.AddEventMemHook(MemMapHookCallback, Common.UC_HOOK_MEM_READ_UNMAPPED | Common.UC_HOOK_MEM_WRITE_UNMAPPED); - Console.WriteLine(">>> Start tracing code"); + Console.WriteLine(">>> Start tracing code"); - // emulate machine code in infinite time - u.EmuStart(address, address + code.Length, 0u, 0u); + // emulate machine code in infinite time + u.EmuStart(address, address + code.Length, 0u, 0u); - // print registers - var ecx = u.RegRead(X86.UC_X86_REG_ECX); - var edx = u.RegRead(X86.UC_X86_REG_EDX); - var eax = u.RegRead(X86.UC_X86_REG_EAX); - Console.WriteLine("[!] EAX = {0}", eax.ToString("X")); - Console.WriteLine("[!] ECX = {0}", ecx.ToString("X")); - Console.WriteLine("[!] EDX = {0}", edx.ToString("X")); + // print registers + var ecx = u.RegRead(X86.UC_X86_REG_ECX); + var edx = u.RegRead(X86.UC_X86_REG_EDX); + var eax = u.RegRead(X86.UC_X86_REG_EAX); + Console.WriteLine($"[!] EAX = {eax:X}"); + Console.WriteLine($"[!] ECX = {ecx:X}"); + Console.WriteLine($"[!] EDX = {edx:X}"); - Console.WriteLine(">>> Emulation Done!"); - } + Console.WriteLine(">>> Emulation Done!"); } - private static Int32 InHookCallback(Unicorn u, Int32 port, Int32 size, Object userData) + private static int InHookCallback(Unicorn u, int port, int size, object userData) { - var eip = u.RegRead(X86.UC_X86_REG_EIP); - Console.WriteLine("[!] Reading from port 0x{0}, size: {1}, address: 0x{2}", port.ToString("X"), size.ToString("X"), eip.ToString("X")); - var res = 0; - switch (size) + var eip = u.RegRead(X86.UC_X86_REG_EIP); + Console.WriteLine($"[!] Reading from port 0x{port:X}, size: {size:X}, address: 0x{eip:X}"); + var res = size switch { - case 1: + 1 => // read 1 byte to AL - res = 0xf1; - break; - case 2: + 0xf1, + 2 => // read 2 byte to AX - res = 0xf2; - break; - case 4: + 0xf2, + 4 => // read 4 byte to EAX - res = 0xf4; - break; - } + 0xf4, + _ => 0 + }; - Console.WriteLine("[!] Return value: {0}", res.ToString("X")); + Console.WriteLine($"[!] Return value: {res:X}"); return res; } - private static void OutHookCallback(Unicorn u, Int32 port, Int32 size, Int32 value, Object userData) + private static void OutHookCallback(Unicorn u, int port, int size, int value, object userData) { var eip = u.RegRead(X86.UC_X86_REG_EIP); - Console.WriteLine("[!] Writing to port 0x{0}, size: {1}, value: 0x{2}, address: 0x{3}", port.ToString("X"), size.ToString("X"), value.ToString("X"), eip.ToString("X")); + Console.WriteLine($"[!] Writing to port 0x{port:X}, size: {size:X}, value: 0x{value:X}, address: 0x{eip:X}"); // confirm that value is indeed the value of AL/ AX / EAX var v = 0L; - var regName = String.Empty; + var regName = string.Empty; switch (size) { case 1: @@ -190,85 +181,81 @@ namespace UnicornSamples break; } - Console.WriteLine("[!] Register {0}: {1}", regName, v.ToString("X")); + Console.WriteLine("[!] Register {0}: {1:X}", regName, v); } - private static Boolean MemMapHookCallback(Unicorn u, Int32 eventType, Int64 address, Int32 size, Int64 value, Object userData) + private static bool MemMapHookCallback(Unicorn u, int eventType, long address, int size, long value, object userData) { - if (eventType == Common.UC_MEM_WRITE_UNMAPPED) - { - Console.WriteLine("[!] Missing memory is being WRITE at 0x{0}, data size = {1}, data value = 0x{2}. Map memory.", address.ToString("X"), size.ToString("X"), value.ToString("X")); - u.MemMap(0xaaaa0000, 2 * 1024 * 1024, Common.UC_PROT_ALL); - return true; - } - else - { - return false; - } + if (eventType != Common.UC_MEM_WRITE_UNMAPPED) return false; + + Console.WriteLine($"[!] Missing memory is being WRITE at 0x{address:X}, data size = {size:X}, data value = 0x{value:X}. Map memory."); + u.MemMap(0xaaaa0000, 2 * 1024 * 1024, Common.UC_PROT_ALL); + + return true; } private static void CodeHookCallback1( - CapstoneDisassembler disassembler, + CapstoneX86Disassembler disassembler, Unicorn u, - Int64 addr, - Int32 size, - Object userData) + long addr, + int size, + object userData) { - Console.Write("[+] 0x{0}: ", addr.ToString("X")); + Console.Write($"[+] 0x{addr:X}: "); - var eipBuffer = new Byte[4]; + var eipBuffer = new byte[4]; u.RegRead(X86.UC_X86_REG_EIP, eipBuffer); var effectiveSize = Math.Min(16, size); - var tmp = new Byte[effectiveSize]; + var tmp = new byte[effectiveSize]; u.MemRead(addr, tmp); var sb = new StringBuilder(); foreach (var t in tmp) { - sb.AppendFormat("{0} ", (0xFF & t).ToString("X")); + sb.AppendFormat($"{(0xFF & t):X} "); } - Console.Write("{0,-20}", sb); + Console.Write($"{sb,-20}"); Console.WriteLine(Utils.Disassemble(disassembler, tmp)); } private static void CodeHookCallback( - CapstoneDisassembler disassembler, + CapstoneX86Disassembler disassembler, Unicorn u, - Int64 addr, - Int32 size, - Object userData) + long addr, + int size, + object userData) { - Console.Write("[+] 0x{0}: ", addr.ToString("X")); + Console.Write($"[+] 0x{addr:X}: "); - var eipBuffer = new Byte[4]; + var eipBuffer = new byte[4]; u.RegRead(X86.UC_X86_REG_EIP, eipBuffer); var effectiveSize = Math.Min(16, size); - var tmp = new Byte[effectiveSize]; + var tmp = new byte[effectiveSize]; u.MemRead(addr, tmp); var sb = new StringBuilder(); foreach (var t in tmp) { - sb.AppendFormat("{0} ", (0xFF & t).ToString("X")); + sb.AppendFormat($"{(0xFF & t):X} "); } - Console.Write("{0,-20}", sb); + Console.Write($"{sb,-20}"); Console.WriteLine(Utils.Disassemble(disassembler, tmp)); } - private static void SyscallHookCallback(Unicorn u, Object userData) + private static void SyscallHookCallback(Unicorn u, object userData) { - var eaxBuffer = new Byte[4]; + var eaxBuffer = new byte[4]; u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer); var eax = Utils.ToInt(eaxBuffer); - Console.WriteLine("[!] Syscall EAX = 0x{0}", eax.ToString("X")); + Console.WriteLine($"[!] Syscall EAX = 0x{eax:X}"); u.EmuStop(); } - private static void InterruptHookCallback(Unicorn u, Int32 intNumber, Object userData) + private static void InterruptHookCallback(Unicorn u, int intNumber, object userData) { // only handle Linux syscall if (intNumber != 0x80) @@ -276,8 +263,8 @@ namespace UnicornSamples return; } - var eaxBuffer = new Byte[4]; - var eipBuffer = new Byte[4]; + var eaxBuffer = new byte[4]; + var eipBuffer = new byte[4]; u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer); u.RegRead(X86.UC_X86_REG_EIP, eipBuffer); @@ -288,19 +275,19 @@ namespace UnicornSamples switch (eax) { default: - Console.WriteLine("[!] Interrupt 0x{0} num {1}, EAX=0x{2}", eip.ToString("X"), intNumber.ToString("X"), eax.ToString("X")); + Console.WriteLine($"[!] Interrupt 0x{eip:X} num {intNumber:X}, EAX=0x{eax:X}"); break; case 1: // sys_exit - Console.WriteLine("[!] Interrupt 0x{0} num {1}, SYS_EXIT", eip.ToString("X"), intNumber.ToString("X")); + Console.WriteLine($"[!] Interrupt 0x{eip:X} num {intNumber:X}, SYS_EXIT"); u.EmuStop(); break; case 4: // sys_write // ECX = buffer address - var ecxBuffer = new Byte[4]; + var ecxBuffer = new byte[4]; // EDX = buffer size - var edxBuffer = new Byte[4]; + var edxBuffer = new byte[4]; u.RegRead(X86.UC_X86_REG_ECX, ecxBuffer); u.RegRead(X86.UC_X86_REG_EDX, edxBuffer); @@ -310,16 +297,11 @@ namespace UnicornSamples // read the buffer in var size = Math.Min(256, edx); - var buffer = new Byte[size]; + var buffer = new byte[size]; u.MemRead(ecx, buffer); var content = Encoding.Default.GetString(buffer); - Console.WriteLine( - "[!] Interrupt 0x{0}: num {1}, SYS_WRITE. buffer = 0x{2}, size = , content = '{3}'", - eip.ToString("X"), - ecx.ToString("X"), - edx.ToString("X"), - content); + Console.WriteLine($"[!] Interrupt 0x{eip:X}: num {ecx:X}, SYS_WRITE. buffer = 0x{edx:X}, size = {size:X}, content = '{content}'"); break; } diff --git a/bindings/dotnet/UnicornSamples/packages.config b/bindings/dotnet/UnicornSamples/packages.config deleted file mode 100644 index d4215eec..00000000 --- a/bindings/dotnet/UnicornSamples/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file From b1af49f72b5197e35fb5d35d6fbcfc0c4e0175a7 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Fri, 14 Oct 2022 17:16:57 +0200 Subject: [PATCH 50/77] dotnet: Adapt README.md to recent changes --- bindings/dotnet/README.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/bindings/dotnet/README.md b/bindings/dotnet/README.md index 77171645..e299649a 100644 --- a/bindings/dotnet/README.md +++ b/bindings/dotnet/README.md @@ -7,15 +7,19 @@ from source. 1. Compile the code - [Windows] - To compile the code open the UnicornSln.sln with Microsoft Visual - Studio 12 or with a newer version and just press Ctrl+Shift+B to build - the solution. - - You need to have installed at least version 4.5 of the .NET framework. - - [Linux] - TODO + You need to have at least version 5.0 of .NET installed. + + 1. Windows + + To compile the code open the UnicornSln.sln with Microsoft Visual + Studio 12 or with a newer version and just press Ctrl+Shift+B to build + the solution. + + 2. Linux + + To compile the code open a terminal in this directory + and enter the following command to build the solution: + `dotnet build` 2. Usage From 442dd437e10dbbcc522379da9adbbbf9dca9b2f2 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Fri, 14 Oct 2022 17:27:47 +0200 Subject: [PATCH 51/77] aarch64: Move FPCR and FPSR registers to not break compatibility Co-authored-by: merry --- include/unicorn/arm64.h | 8 ++++---- qemu/target/arm/unicorn_aarch64.c | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/unicorn/arm64.h b/include/unicorn/arm64.h index aab2ab9c..fd8192fb 100644 --- a/include/unicorn/arm64.h +++ b/include/unicorn/arm64.h @@ -313,10 +313,6 @@ typedef enum uc_arm64_reg { UC_ARM64_REG_PSTATE, - //> floating point control and status registers - UC_ARM64_REG_FPCR, - UC_ARM64_REG_FPSR, - //> exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead UC_ARM64_REG_ELR_EL0, UC_ARM64_REG_ELR_EL1, @@ -354,6 +350,10 @@ typedef enum uc_arm64_reg { UC_ARM64_REG_CP_REG, + //> floating point control and status registers + UC_ARM64_REG_FPCR, + UC_ARM64_REG_FPSR, + UC_ARM64_REG_ENDING, // <-- mark the end of the list of registers //> alias registers diff --git a/qemu/target/arm/unicorn_aarch64.c b/qemu/target/arm/unicorn_aarch64.c index 4b533047..fec0db68 100644 --- a/qemu/target/arm/unicorn_aarch64.c +++ b/qemu/target/arm/unicorn_aarch64.c @@ -210,12 +210,6 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value) case UC_ARM64_REG_PSTATE: *(uint32_t *)value = pstate_read(env); break; - case UC_ARM64_REG_FPCR: - *(uint32_t *)value = vfp_get_fpcr(env); - break; - case UC_ARM64_REG_FPSR: - *(uint32_t *)value = vfp_get_fpsr(env); - break; case UC_ARM64_REG_TTBR0_EL1: *(uint64_t *)value = env->cp15.ttbr0_el[1]; break; @@ -231,6 +225,12 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value) case UC_ARM64_REG_CP_REG: ret = read_cp_reg(env, (uc_arm64_cp_reg *)value); break; + case UC_ARM64_REG_FPCR: + *(uint32_t *)value = vfp_get_fpcr(env); + break; + case UC_ARM64_REG_FPSR: + *(uint32_t *)value = vfp_get_fpsr(env); + break; } } @@ -309,12 +309,6 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value) case UC_ARM64_REG_PSTATE: pstate_write(env, *(uint32_t *)value); break; - case UC_ARM64_REG_FPCR: - vfp_set_fpcr(env, *(uint32_t *)value); - break; - case UC_ARM64_REG_FPSR: - vfp_set_fpsr(env, *(uint32_t *)value); - break; case UC_ARM64_REG_TTBR0_EL1: env->cp15.ttbr0_el[1] = *(uint64_t *)value; break; @@ -330,6 +324,12 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value) case UC_ARM64_REG_CP_REG: ret = write_cp_reg(env, (uc_arm64_cp_reg *)value); break; + case UC_ARM64_REG_FPCR: + vfp_set_fpcr(env, *(uint32_t *)value); + break; + case UC_ARM64_REG_FPSR: + vfp_set_fpsr(env, *(uint32_t *)value); + break; } } From 7b8b75b9f84ed2a7191130ebe965b8f6cd1872a0 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Fri, 14 Oct 2022 17:33:07 +0200 Subject: [PATCH 52/77] bindings: Adjust consts --- bindings/dotnet/UnicornManaged/Const/Arm64.fs | 58 +++++++++---------- bindings/go/unicorn/arm64_const.go | 58 +++++++++---------- bindings/java/unicorn/Arm64Const.java | 58 +++++++++---------- bindings/pascal/unicorn/Arm64Const.pas | 58 +++++++++---------- bindings/python/unicorn/arm64_const.py | 58 +++++++++---------- .../lib/unicorn_engine/arm64_const.rb | 58 +++++++++---------- 6 files changed, 174 insertions(+), 174 deletions(-) diff --git a/bindings/dotnet/UnicornManaged/Const/Arm64.fs b/bindings/dotnet/UnicornManaged/Const/Arm64.fs index 7357a252..4c509d03 100644 --- a/bindings/dotnet/UnicornManaged/Const/Arm64.fs +++ b/bindings/dotnet/UnicornManaged/Const/Arm64.fs @@ -288,40 +288,40 @@ module Arm64 = let UC_ARM64_REG_TPIDR_EL1 = 264 let UC_ARM64_REG_PSTATE = 265 - // floating point control and status registers - let UC_ARM64_REG_FPCR = 266 - let UC_ARM64_REG_FPSR = 267 - // exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead - let UC_ARM64_REG_ELR_EL0 = 268 - let UC_ARM64_REG_ELR_EL1 = 269 - let UC_ARM64_REG_ELR_EL2 = 270 - let UC_ARM64_REG_ELR_EL3 = 271 + let UC_ARM64_REG_ELR_EL0 = 266 + let UC_ARM64_REG_ELR_EL1 = 267 + let UC_ARM64_REG_ELR_EL2 = 268 + let UC_ARM64_REG_ELR_EL3 = 269 // stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead - let UC_ARM64_REG_SP_EL0 = 272 - let UC_ARM64_REG_SP_EL1 = 273 - let UC_ARM64_REG_SP_EL2 = 274 - let UC_ARM64_REG_SP_EL3 = 275 + let UC_ARM64_REG_SP_EL0 = 270 + let UC_ARM64_REG_SP_EL1 = 271 + let UC_ARM64_REG_SP_EL2 = 272 + let UC_ARM64_REG_SP_EL3 = 273 // other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead - let UC_ARM64_REG_TTBR0_EL1 = 276 - let UC_ARM64_REG_TTBR1_EL1 = 277 - let UC_ARM64_REG_ESR_EL0 = 278 - let UC_ARM64_REG_ESR_EL1 = 279 - let UC_ARM64_REG_ESR_EL2 = 280 - let UC_ARM64_REG_ESR_EL3 = 281 - let UC_ARM64_REG_FAR_EL0 = 282 - let UC_ARM64_REG_FAR_EL1 = 283 - let UC_ARM64_REG_FAR_EL2 = 284 - let UC_ARM64_REG_FAR_EL3 = 285 - let UC_ARM64_REG_PAR_EL1 = 286 - let UC_ARM64_REG_MAIR_EL1 = 287 - let UC_ARM64_REG_VBAR_EL0 = 288 - let UC_ARM64_REG_VBAR_EL1 = 289 - let UC_ARM64_REG_VBAR_EL2 = 290 - let UC_ARM64_REG_VBAR_EL3 = 291 - let UC_ARM64_REG_CP_REG = 292 + let UC_ARM64_REG_TTBR0_EL1 = 274 + let UC_ARM64_REG_TTBR1_EL1 = 275 + let UC_ARM64_REG_ESR_EL0 = 276 + let UC_ARM64_REG_ESR_EL1 = 277 + let UC_ARM64_REG_ESR_EL2 = 278 + let UC_ARM64_REG_ESR_EL3 = 279 + let UC_ARM64_REG_FAR_EL0 = 280 + let UC_ARM64_REG_FAR_EL1 = 281 + let UC_ARM64_REG_FAR_EL2 = 282 + let UC_ARM64_REG_FAR_EL3 = 283 + let UC_ARM64_REG_PAR_EL1 = 284 + let UC_ARM64_REG_MAIR_EL1 = 285 + let UC_ARM64_REG_VBAR_EL0 = 286 + let UC_ARM64_REG_VBAR_EL1 = 287 + let UC_ARM64_REG_VBAR_EL2 = 288 + let UC_ARM64_REG_VBAR_EL3 = 289 + let UC_ARM64_REG_CP_REG = 290 + + // floating point control and status registers + let UC_ARM64_REG_FPCR = 291 + let UC_ARM64_REG_FPSR = 292 let UC_ARM64_REG_ENDING = 293 // alias registers diff --git a/bindings/go/unicorn/arm64_const.go b/bindings/go/unicorn/arm64_const.go index 7d89bace..e3548c78 100644 --- a/bindings/go/unicorn/arm64_const.go +++ b/bindings/go/unicorn/arm64_const.go @@ -283,40 +283,40 @@ const ( ARM64_REG_TPIDR_EL1 = 264 ARM64_REG_PSTATE = 265 -// floating point control and status registers - ARM64_REG_FPCR = 266 - ARM64_REG_FPSR = 267 - // exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead - ARM64_REG_ELR_EL0 = 268 - ARM64_REG_ELR_EL1 = 269 - ARM64_REG_ELR_EL2 = 270 - ARM64_REG_ELR_EL3 = 271 + ARM64_REG_ELR_EL0 = 266 + ARM64_REG_ELR_EL1 = 267 + ARM64_REG_ELR_EL2 = 268 + ARM64_REG_ELR_EL3 = 269 // stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead - ARM64_REG_SP_EL0 = 272 - ARM64_REG_SP_EL1 = 273 - ARM64_REG_SP_EL2 = 274 - ARM64_REG_SP_EL3 = 275 + ARM64_REG_SP_EL0 = 270 + ARM64_REG_SP_EL1 = 271 + ARM64_REG_SP_EL2 = 272 + ARM64_REG_SP_EL3 = 273 // other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead - ARM64_REG_TTBR0_EL1 = 276 - ARM64_REG_TTBR1_EL1 = 277 - ARM64_REG_ESR_EL0 = 278 - ARM64_REG_ESR_EL1 = 279 - ARM64_REG_ESR_EL2 = 280 - ARM64_REG_ESR_EL3 = 281 - ARM64_REG_FAR_EL0 = 282 - ARM64_REG_FAR_EL1 = 283 - ARM64_REG_FAR_EL2 = 284 - ARM64_REG_FAR_EL3 = 285 - ARM64_REG_PAR_EL1 = 286 - ARM64_REG_MAIR_EL1 = 287 - ARM64_REG_VBAR_EL0 = 288 - ARM64_REG_VBAR_EL1 = 289 - ARM64_REG_VBAR_EL2 = 290 - ARM64_REG_VBAR_EL3 = 291 - ARM64_REG_CP_REG = 292 + ARM64_REG_TTBR0_EL1 = 274 + ARM64_REG_TTBR1_EL1 = 275 + ARM64_REG_ESR_EL0 = 276 + ARM64_REG_ESR_EL1 = 277 + ARM64_REG_ESR_EL2 = 278 + ARM64_REG_ESR_EL3 = 279 + ARM64_REG_FAR_EL0 = 280 + ARM64_REG_FAR_EL1 = 281 + ARM64_REG_FAR_EL2 = 282 + ARM64_REG_FAR_EL3 = 283 + ARM64_REG_PAR_EL1 = 284 + ARM64_REG_MAIR_EL1 = 285 + ARM64_REG_VBAR_EL0 = 286 + ARM64_REG_VBAR_EL1 = 287 + ARM64_REG_VBAR_EL2 = 288 + ARM64_REG_VBAR_EL3 = 289 + ARM64_REG_CP_REG = 290 + +// floating point control and status registers + ARM64_REG_FPCR = 291 + ARM64_REG_FPSR = 292 ARM64_REG_ENDING = 293 // alias registers diff --git a/bindings/java/unicorn/Arm64Const.java b/bindings/java/unicorn/Arm64Const.java index 699320af..bb196037 100644 --- a/bindings/java/unicorn/Arm64Const.java +++ b/bindings/java/unicorn/Arm64Const.java @@ -285,40 +285,40 @@ public interface Arm64Const { public static final int UC_ARM64_REG_TPIDR_EL1 = 264; public static final int UC_ARM64_REG_PSTATE = 265; -// floating point control and status registers - public static final int UC_ARM64_REG_FPCR = 266; - public static final int UC_ARM64_REG_FPSR = 267; - // exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead - public static final int UC_ARM64_REG_ELR_EL0 = 268; - public static final int UC_ARM64_REG_ELR_EL1 = 269; - public static final int UC_ARM64_REG_ELR_EL2 = 270; - public static final int UC_ARM64_REG_ELR_EL3 = 271; + public static final int UC_ARM64_REG_ELR_EL0 = 266; + public static final int UC_ARM64_REG_ELR_EL1 = 267; + public static final int UC_ARM64_REG_ELR_EL2 = 268; + public static final int UC_ARM64_REG_ELR_EL3 = 269; // stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead - public static final int UC_ARM64_REG_SP_EL0 = 272; - public static final int UC_ARM64_REG_SP_EL1 = 273; - public static final int UC_ARM64_REG_SP_EL2 = 274; - public static final int UC_ARM64_REG_SP_EL3 = 275; + public static final int UC_ARM64_REG_SP_EL0 = 270; + public static final int UC_ARM64_REG_SP_EL1 = 271; + public static final int UC_ARM64_REG_SP_EL2 = 272; + public static final int UC_ARM64_REG_SP_EL3 = 273; // other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead - public static final int UC_ARM64_REG_TTBR0_EL1 = 276; - public static final int UC_ARM64_REG_TTBR1_EL1 = 277; - public static final int UC_ARM64_REG_ESR_EL0 = 278; - public static final int UC_ARM64_REG_ESR_EL1 = 279; - public static final int UC_ARM64_REG_ESR_EL2 = 280; - public static final int UC_ARM64_REG_ESR_EL3 = 281; - public static final int UC_ARM64_REG_FAR_EL0 = 282; - public static final int UC_ARM64_REG_FAR_EL1 = 283; - public static final int UC_ARM64_REG_FAR_EL2 = 284; - public static final int UC_ARM64_REG_FAR_EL3 = 285; - public static final int UC_ARM64_REG_PAR_EL1 = 286; - public static final int UC_ARM64_REG_MAIR_EL1 = 287; - public static final int UC_ARM64_REG_VBAR_EL0 = 288; - public static final int UC_ARM64_REG_VBAR_EL1 = 289; - public static final int UC_ARM64_REG_VBAR_EL2 = 290; - public static final int UC_ARM64_REG_VBAR_EL3 = 291; - public static final int UC_ARM64_REG_CP_REG = 292; + public static final int UC_ARM64_REG_TTBR0_EL1 = 274; + public static final int UC_ARM64_REG_TTBR1_EL1 = 275; + public static final int UC_ARM64_REG_ESR_EL0 = 276; + public static final int UC_ARM64_REG_ESR_EL1 = 277; + public static final int UC_ARM64_REG_ESR_EL2 = 278; + public static final int UC_ARM64_REG_ESR_EL3 = 279; + public static final int UC_ARM64_REG_FAR_EL0 = 280; + public static final int UC_ARM64_REG_FAR_EL1 = 281; + public static final int UC_ARM64_REG_FAR_EL2 = 282; + public static final int UC_ARM64_REG_FAR_EL3 = 283; + public static final int UC_ARM64_REG_PAR_EL1 = 284; + public static final int UC_ARM64_REG_MAIR_EL1 = 285; + public static final int UC_ARM64_REG_VBAR_EL0 = 286; + public static final int UC_ARM64_REG_VBAR_EL1 = 287; + public static final int UC_ARM64_REG_VBAR_EL2 = 288; + public static final int UC_ARM64_REG_VBAR_EL3 = 289; + public static final int UC_ARM64_REG_CP_REG = 290; + +// floating point control and status registers + public static final int UC_ARM64_REG_FPCR = 291; + public static final int UC_ARM64_REG_FPSR = 292; public static final int UC_ARM64_REG_ENDING = 293; // alias registers diff --git a/bindings/pascal/unicorn/Arm64Const.pas b/bindings/pascal/unicorn/Arm64Const.pas index 05347e71..800846b3 100644 --- a/bindings/pascal/unicorn/Arm64Const.pas +++ b/bindings/pascal/unicorn/Arm64Const.pas @@ -286,40 +286,40 @@ const UC_ARM64_REG_TPIDR_EL1 = 264; UC_ARM64_REG_PSTATE = 265; -// floating point control and status registers - UC_ARM64_REG_FPCR = 266; - UC_ARM64_REG_FPSR = 267; - // exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_ELR_EL0 = 268; - UC_ARM64_REG_ELR_EL1 = 269; - UC_ARM64_REG_ELR_EL2 = 270; - UC_ARM64_REG_ELR_EL3 = 271; + UC_ARM64_REG_ELR_EL0 = 266; + UC_ARM64_REG_ELR_EL1 = 267; + UC_ARM64_REG_ELR_EL2 = 268; + UC_ARM64_REG_ELR_EL3 = 269; // stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_SP_EL0 = 272; - UC_ARM64_REG_SP_EL1 = 273; - UC_ARM64_REG_SP_EL2 = 274; - UC_ARM64_REG_SP_EL3 = 275; + UC_ARM64_REG_SP_EL0 = 270; + UC_ARM64_REG_SP_EL1 = 271; + UC_ARM64_REG_SP_EL2 = 272; + UC_ARM64_REG_SP_EL3 = 273; // other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_TTBR0_EL1 = 276; - UC_ARM64_REG_TTBR1_EL1 = 277; - UC_ARM64_REG_ESR_EL0 = 278; - UC_ARM64_REG_ESR_EL1 = 279; - UC_ARM64_REG_ESR_EL2 = 280; - UC_ARM64_REG_ESR_EL3 = 281; - UC_ARM64_REG_FAR_EL0 = 282; - UC_ARM64_REG_FAR_EL1 = 283; - UC_ARM64_REG_FAR_EL2 = 284; - UC_ARM64_REG_FAR_EL3 = 285; - UC_ARM64_REG_PAR_EL1 = 286; - UC_ARM64_REG_MAIR_EL1 = 287; - UC_ARM64_REG_VBAR_EL0 = 288; - UC_ARM64_REG_VBAR_EL1 = 289; - UC_ARM64_REG_VBAR_EL2 = 290; - UC_ARM64_REG_VBAR_EL3 = 291; - UC_ARM64_REG_CP_REG = 292; + UC_ARM64_REG_TTBR0_EL1 = 274; + UC_ARM64_REG_TTBR1_EL1 = 275; + UC_ARM64_REG_ESR_EL0 = 276; + UC_ARM64_REG_ESR_EL1 = 277; + UC_ARM64_REG_ESR_EL2 = 278; + UC_ARM64_REG_ESR_EL3 = 279; + UC_ARM64_REG_FAR_EL0 = 280; + UC_ARM64_REG_FAR_EL1 = 281; + UC_ARM64_REG_FAR_EL2 = 282; + UC_ARM64_REG_FAR_EL3 = 283; + UC_ARM64_REG_PAR_EL1 = 284; + UC_ARM64_REG_MAIR_EL1 = 285; + UC_ARM64_REG_VBAR_EL0 = 286; + UC_ARM64_REG_VBAR_EL1 = 287; + UC_ARM64_REG_VBAR_EL2 = 288; + UC_ARM64_REG_VBAR_EL3 = 289; + UC_ARM64_REG_CP_REG = 290; + +// floating point control and status registers + UC_ARM64_REG_FPCR = 291; + UC_ARM64_REG_FPSR = 292; UC_ARM64_REG_ENDING = 293; // alias registers diff --git a/bindings/python/unicorn/arm64_const.py b/bindings/python/unicorn/arm64_const.py index 485daf43..53135ab8 100644 --- a/bindings/python/unicorn/arm64_const.py +++ b/bindings/python/unicorn/arm64_const.py @@ -281,40 +281,40 @@ UC_ARM64_REG_TPIDRRO_EL0 = 263 UC_ARM64_REG_TPIDR_EL1 = 264 UC_ARM64_REG_PSTATE = 265 -# floating point control and status registers -UC_ARM64_REG_FPCR = 266 -UC_ARM64_REG_FPSR = 267 - # exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead -UC_ARM64_REG_ELR_EL0 = 268 -UC_ARM64_REG_ELR_EL1 = 269 -UC_ARM64_REG_ELR_EL2 = 270 -UC_ARM64_REG_ELR_EL3 = 271 +UC_ARM64_REG_ELR_EL0 = 266 +UC_ARM64_REG_ELR_EL1 = 267 +UC_ARM64_REG_ELR_EL2 = 268 +UC_ARM64_REG_ELR_EL3 = 269 # stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead -UC_ARM64_REG_SP_EL0 = 272 -UC_ARM64_REG_SP_EL1 = 273 -UC_ARM64_REG_SP_EL2 = 274 -UC_ARM64_REG_SP_EL3 = 275 +UC_ARM64_REG_SP_EL0 = 270 +UC_ARM64_REG_SP_EL1 = 271 +UC_ARM64_REG_SP_EL2 = 272 +UC_ARM64_REG_SP_EL3 = 273 # other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead -UC_ARM64_REG_TTBR0_EL1 = 276 -UC_ARM64_REG_TTBR1_EL1 = 277 -UC_ARM64_REG_ESR_EL0 = 278 -UC_ARM64_REG_ESR_EL1 = 279 -UC_ARM64_REG_ESR_EL2 = 280 -UC_ARM64_REG_ESR_EL3 = 281 -UC_ARM64_REG_FAR_EL0 = 282 -UC_ARM64_REG_FAR_EL1 = 283 -UC_ARM64_REG_FAR_EL2 = 284 -UC_ARM64_REG_FAR_EL3 = 285 -UC_ARM64_REG_PAR_EL1 = 286 -UC_ARM64_REG_MAIR_EL1 = 287 -UC_ARM64_REG_VBAR_EL0 = 288 -UC_ARM64_REG_VBAR_EL1 = 289 -UC_ARM64_REG_VBAR_EL2 = 290 -UC_ARM64_REG_VBAR_EL3 = 291 -UC_ARM64_REG_CP_REG = 292 +UC_ARM64_REG_TTBR0_EL1 = 274 +UC_ARM64_REG_TTBR1_EL1 = 275 +UC_ARM64_REG_ESR_EL0 = 276 +UC_ARM64_REG_ESR_EL1 = 277 +UC_ARM64_REG_ESR_EL2 = 278 +UC_ARM64_REG_ESR_EL3 = 279 +UC_ARM64_REG_FAR_EL0 = 280 +UC_ARM64_REG_FAR_EL1 = 281 +UC_ARM64_REG_FAR_EL2 = 282 +UC_ARM64_REG_FAR_EL3 = 283 +UC_ARM64_REG_PAR_EL1 = 284 +UC_ARM64_REG_MAIR_EL1 = 285 +UC_ARM64_REG_VBAR_EL0 = 286 +UC_ARM64_REG_VBAR_EL1 = 287 +UC_ARM64_REG_VBAR_EL2 = 288 +UC_ARM64_REG_VBAR_EL3 = 289 +UC_ARM64_REG_CP_REG = 290 + +# floating point control and status registers +UC_ARM64_REG_FPCR = 291 +UC_ARM64_REG_FPSR = 292 UC_ARM64_REG_ENDING = 293 # alias registers diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb index 3e379a43..aef319be 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb @@ -283,40 +283,40 @@ module UnicornEngine UC_ARM64_REG_TPIDR_EL1 = 264 UC_ARM64_REG_PSTATE = 265 -# floating point control and status registers - UC_ARM64_REG_FPCR = 266 - UC_ARM64_REG_FPSR = 267 - # exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_ELR_EL0 = 268 - UC_ARM64_REG_ELR_EL1 = 269 - UC_ARM64_REG_ELR_EL2 = 270 - UC_ARM64_REG_ELR_EL3 = 271 + UC_ARM64_REG_ELR_EL0 = 266 + UC_ARM64_REG_ELR_EL1 = 267 + UC_ARM64_REG_ELR_EL2 = 268 + UC_ARM64_REG_ELR_EL3 = 269 # stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_SP_EL0 = 272 - UC_ARM64_REG_SP_EL1 = 273 - UC_ARM64_REG_SP_EL2 = 274 - UC_ARM64_REG_SP_EL3 = 275 + UC_ARM64_REG_SP_EL0 = 270 + UC_ARM64_REG_SP_EL1 = 271 + UC_ARM64_REG_SP_EL2 = 272 + UC_ARM64_REG_SP_EL3 = 273 # other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead - UC_ARM64_REG_TTBR0_EL1 = 276 - UC_ARM64_REG_TTBR1_EL1 = 277 - UC_ARM64_REG_ESR_EL0 = 278 - UC_ARM64_REG_ESR_EL1 = 279 - UC_ARM64_REG_ESR_EL2 = 280 - UC_ARM64_REG_ESR_EL3 = 281 - UC_ARM64_REG_FAR_EL0 = 282 - UC_ARM64_REG_FAR_EL1 = 283 - UC_ARM64_REG_FAR_EL2 = 284 - UC_ARM64_REG_FAR_EL3 = 285 - UC_ARM64_REG_PAR_EL1 = 286 - UC_ARM64_REG_MAIR_EL1 = 287 - UC_ARM64_REG_VBAR_EL0 = 288 - UC_ARM64_REG_VBAR_EL1 = 289 - UC_ARM64_REG_VBAR_EL2 = 290 - UC_ARM64_REG_VBAR_EL3 = 291 - UC_ARM64_REG_CP_REG = 292 + UC_ARM64_REG_TTBR0_EL1 = 274 + UC_ARM64_REG_TTBR1_EL1 = 275 + UC_ARM64_REG_ESR_EL0 = 276 + UC_ARM64_REG_ESR_EL1 = 277 + UC_ARM64_REG_ESR_EL2 = 278 + UC_ARM64_REG_ESR_EL3 = 279 + UC_ARM64_REG_FAR_EL0 = 280 + UC_ARM64_REG_FAR_EL1 = 281 + UC_ARM64_REG_FAR_EL2 = 282 + UC_ARM64_REG_FAR_EL3 = 283 + UC_ARM64_REG_PAR_EL1 = 284 + UC_ARM64_REG_MAIR_EL1 = 285 + UC_ARM64_REG_VBAR_EL0 = 286 + UC_ARM64_REG_VBAR_EL1 = 287 + UC_ARM64_REG_VBAR_EL2 = 288 + UC_ARM64_REG_VBAR_EL3 = 289 + UC_ARM64_REG_CP_REG = 290 + +# floating point control and status registers + UC_ARM64_REG_FPCR = 291 + UC_ARM64_REG_FPSR = 292 UC_ARM64_REG_ENDING = 293 # alias registers From 35010035d709039bcd4be2493d0a62f846a27231 Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 20 Oct 2022 20:10:27 +0200 Subject: [PATCH 53/77] Fix macro typo Thanks @roehling --- qemu/target/ppc/translate/vsx-impl.inc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu/target/ppc/translate/vsx-impl.inc.c b/qemu/target/ppc/translate/vsx-impl.inc.c index 41c6b3ca..679da149 100644 --- a/qemu/target/ppc/translate/vsx-impl.inc.c +++ b/qemu/target/ppc/translate/vsx-impl.inc.c @@ -1603,7 +1603,7 @@ static void gen_xxspltw(DisasContext *ctx) tofs = vsr_full_offset(rt); bofs = vsr_full_offset(rb); bofs += uim << MO_32; -#ifndef HOST_WORDS_BIG_ENDIAN +#ifndef HOST_WORDS_BIGENDIAN bofs ^= 8 | 4; #endif From 0522f728b6561ed65e5e86483b769464dbc5d0c0 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Thu, 20 Oct 2022 20:35:18 +0200 Subject: [PATCH 54/77] dotnet: Remove faulty property groups --- .../UnicornManaged/UnicornManaged.fsproj | 14 -------------- .../UnicornSamples/UnicornSamples.csproj | 18 ------------------ 2 files changed, 32 deletions(-) diff --git a/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj b/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj index 864e4e96..2b076296 100644 --- a/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj +++ b/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj @@ -15,20 +15,6 @@ 3 - - true - full - false - false - DEBUG;TRACE - - - pdbonly - true - true - TRACE - - diff --git a/bindings/dotnet/UnicornSamples/UnicornSamples.csproj b/bindings/dotnet/UnicornSamples/UnicornSamples.csproj index d7464c04..37239526 100644 --- a/bindings/dotnet/UnicornSamples/UnicornSamples.csproj +++ b/bindings/dotnet/UnicornSamples/UnicornSamples.csproj @@ -8,7 +8,6 @@ https://github.com/unicorn-engine/unicorn 2.0.0 {B80B5987-1E24-4309-8BF9-C4F91270F21C} - true @@ -16,23 +15,6 @@ prompt 4 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - false - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - From a5d4d30a3152c7f6b7044553b530ee185e77d355 Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 20 Oct 2022 21:19:18 +0200 Subject: [PATCH 55/77] Sync PC for mem ldst on aarch64 --- qemu/target/arm/translate-a64.c | 6 +++++ tests/unit/test_arm64.c | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 2b5bdd43..21bf5e8c 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -3845,6 +3845,12 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) /* Loads and stores */ static void disas_ldst(DisasContext *s, uint32_t insn) { + if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ) || HOOK_EXISTS(s->uc, UC_HOOK_MEM_WRITE)) { + // sync PC if there are memory hooks. + // TODO: Better granularity by checking ldst type and corresponding hook type + gen_a64_set_pc_im(s->uc->tcg_ctx, s->pc_curr); + } + switch (extract32(insn, 24, 6)) { case 0x08: /* Load/store exclusive */ disas_ldst_excl(s, insn); diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 0de80937..789be967 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -332,6 +332,46 @@ static void test_arm64_block_sync_pc(void) OK(uc_close(uc)); } +static bool +test_arm64_block_invalid_mem_read_write_sync_cb(uc_engine *uc, int type, + uint64_t address, int size, + int64_t value, void *user_data) +{ + return 0; +} + +static void test_arm64_block_invalid_mem_read_write_sync(void) +{ + uc_engine *uc; + // mov x0, #1 + // mov x1, #2 + // ldr x0, [x1] + const char code[] = "\x20\x00\x80\xd2\x41\x00\x80\xd2\x20\x00\x40\xf9"; + uint64_t r_pc, r_x0, r_x1; + uc_hook hk; + + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1, + UC_CPU_ARM64_A72); + + OK(uc_hook_add(uc, &hk, UC_HOOK_MEM_READ, + test_arm64_block_invalid_mem_read_write_sync_cb, NULL, 1, + 0)); + + uc_assert_err( + UC_ERR_READ_UNMAPPED, + uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc)); + OK(uc_reg_read(uc, UC_ARM64_REG_X0, &r_x0)); + OK(uc_reg_read(uc, UC_ARM64_REG_X1, &r_x1)); + + TEST_CHECK(r_pc == code_start + 8); + // TEST_CHECK(r_x0 == 1); // Unfortunately this can't be guarantee-ed + TEST_CHECK(r_x1 == 2); + + OK(uc_close(uc)); +} + TEST_LIST = {{"test_arm64_until", test_arm64_until}, {"test_arm64_code_patching", test_arm64_code_patching}, {"test_arm64_code_patching_count", test_arm64_code_patching_count}, @@ -343,4 +383,6 @@ TEST_LIST = {{"test_arm64_until", test_arm64_until}, {"test_arm64_correct_address_in_long_jump_hook", test_arm64_correct_address_in_long_jump_hook}, {"test_arm64_block_sync_pc", test_arm64_block_sync_pc}, + {"test_arm64_block_invalid_mem_read_write_sync", + test_arm64_block_invalid_mem_read_write_sync}, {NULL, NULL}}; From 13b8e2625f7be3b550e7e92e8f048cac1f7022c1 Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 20 Oct 2022 21:25:21 +0200 Subject: [PATCH 56/77] Check PC range for mem hooks --- qemu/target/arm/translate-a64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 21bf5e8c..28abf774 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -3845,7 +3845,7 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) /* Loads and stores */ static void disas_ldst(DisasContext *s, uint32_t insn) { - if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ) || HOOK_EXISTS(s->uc, UC_HOOK_MEM_WRITE)) { + if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_MEM_READ, s->pc_curr) || HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_MEM_WRITE, s->pc_curr)) { // sync PC if there are memory hooks. // TODO: Better granularity by checking ldst type and corresponding hook type gen_a64_set_pc_im(s->uc->tcg_ctx, s->pc_curr); From 040146e059137a42b43475b31b67a15f3bc4ffcb Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Thu, 20 Oct 2022 21:31:46 +0200 Subject: [PATCH 57/77] dotnet: Target .NET 6.0 --- bindings/dotnet/UnicornManaged/UnicornManaged.fsproj | 2 +- bindings/dotnet/UnicornSamples/UnicornSamples.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj b/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj index 2b076296..1a66562a 100644 --- a/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj +++ b/bindings/dotnet/UnicornManaged/UnicornManaged.fsproj @@ -1,6 +1,6 @@  - net5.0 + net6.0 UnicornManaged UnicornManaged Copyright © Antonio Parata 2016 diff --git a/bindings/dotnet/UnicornSamples/UnicornSamples.csproj b/bindings/dotnet/UnicornSamples/UnicornSamples.csproj index 37239526..bd603441 100644 --- a/bindings/dotnet/UnicornSamples/UnicornSamples.csproj +++ b/bindings/dotnet/UnicornSamples/UnicornSamples.csproj @@ -1,6 +1,6 @@  - net5.0 + net6.0 Exe UnicornSamples UnicornSamples @@ -26,4 +26,4 @@ - \ No newline at end of file + From e5756b79f8782ee1c67cbb7c0f6d4c23135fa447 Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 20 Oct 2022 21:47:09 +0200 Subject: [PATCH 58/77] Update FAQ --- docs/FAQ.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 20bb58e2..5a833139 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -9,7 +9,30 @@ Optimize your program with less instrumentation, e.g. by using `UC_HOOK_BLOCK` i ## Why do I get a wrong PC after emulation stops? -PC is only guaranteed to be correct if you install `UC_HOOK_CODE`. This is due to the fact that updating PC is a big performance overhead during emulation. +Updating PC is a very large overhead (10x slower in the worst case, see FAQ above) for emulation so the PC sync guarantee is explained below: + +- A `UC_HOOK_CODE` is installed. In this case, the PC is sync-ed _everywhere_ within the effective range of the hook. However, on some architectures, the PC might by sync-ed all the time if the hook is installed. +- A `UC_HOOK_MEM_READ` or `UC_HOOK_MEM_WRITE` is installed. In this case, the PC is sync-ed exactly before any read/write events within the effective range of the hook. +- Emulation (`uc_emu_start`) terminates without any exception. In this case, the PC will point to the next instruction. +- No hook mentioned above is installed and emulation terminates with exceptions. In this case, the PC is sync-ed at the basic block boundary, in other words, the first instruction of the basic block where the exception happens. + +Below is an example: + +``` +mov x0, #1 <--- the PC will be here +mov x1, #2 +ldr x0, [x1] <--- exception here +``` + +If `ldr x0, [x1]` fails with memory exceptions, the PC will be left at the beginning of the basic block, in this case `mov x0, #1`. + +However, if a `UC_HOOK_MEM_READ` hook is installed, the PC will be sync-ed: + +``` +mov x0, #1 +mov x1, #2 +ldr x0, [x1] <--- exception here and PC sync-ed here +``` ## I get an “Unhandled CPU Exception”, why? From 3ea7857be3bba21a1c41dc3f5629f36cc9747946 Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 20 Oct 2022 21:57:28 +0200 Subject: [PATCH 59/77] Exit early when invalid read happens In this way, the target register won't be overwritten --- qemu/accel/tcg/cputlb.c | 11 +++++++++++ tests/unit/test_arm64.c | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/qemu/accel/tcg/cputlb.c b/qemu/accel/tcg/cputlb.c index 9305b06c..04c892a2 100644 --- a/qemu/accel/tcg/cputlb.c +++ b/qemu/accel/tcg/cputlb.c @@ -1484,6 +1484,11 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, if (mr == NULL) { uc->invalid_error = UC_ERR_MAP; cpu_exit(uc->cpu); + // XXX(@lazymio): We have to exit early so that the target register won't be overwritten + // because qemu might generate tcg code like: + // qemu_ld_i64 x0,x1,leq,8 sync: 0 dead: 0 1 + // where we don't have a change to recover x0 value + cpu_loop_exit(uc->cpu); return 0; } } else { @@ -1491,6 +1496,8 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uc->invalid_error = error_code; // printf("***** Invalid fetch (unmapped memory) at " TARGET_FMT_lx "\n", addr); cpu_exit(uc->cpu); + // See comments above + cpu_loop_exit(uc->cpu); return 0; } } @@ -1533,6 +1540,8 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uc->invalid_error = UC_ERR_READ_PROT; // printf("***** Invalid memory read (non-readable) at " TARGET_FMT_lx "\n", addr); cpu_exit(uc->cpu); + // See comments above + cpu_loop_exit(uc->cpu); return 0; } } @@ -1561,6 +1570,8 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uc->invalid_error = UC_ERR_FETCH_PROT; // printf("***** Invalid fetch (non-executable) at " TARGET_FMT_lx "\n", addr); cpu_exit(uc->cpu); + // See comments above + cpu_loop_exit(uc->cpu); return 0; } } diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 789be967..52bd95ca 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -366,7 +366,7 @@ static void test_arm64_block_invalid_mem_read_write_sync(void) OK(uc_reg_read(uc, UC_ARM64_REG_X1, &r_x1)); TEST_CHECK(r_pc == code_start + 8); - // TEST_CHECK(r_x0 == 1); // Unfortunately this can't be guarantee-ed + TEST_CHECK(r_x0 == 1); TEST_CHECK(r_x1 == 2); OK(uc_close(uc)); From 6162708bb294e16030a0ae019f71425a246283da Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 21 Oct 2022 11:29:57 +0200 Subject: [PATCH 60/77] Hack more to support BE32 --- qemu/target/arm/cpu.c | 2 +- qemu/target/arm/cpu.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/qemu/target/arm/cpu.c b/qemu/target/arm/cpu.c index dce2f45b..45540fe6 100644 --- a/qemu/target/arm/cpu.c +++ b/qemu/target/arm/cpu.c @@ -2188,7 +2188,7 @@ ARMCPU *cpu_arm_init(struct uc_struct *uc) env->uncached_cpsr |= CPSR_E; } - if (uc->mode & UC_MODE_BIG_ENDIAN && !arm_feature(env, ARM_FEATURE_V7) && !arm_feature(env, ARM_FEATURE_V8)) { + if (uc->mode & UC_MODE_BIG_ENDIAN) { // Big endian code access. env->cp15.sctlr_ns |= SCTLR_B; } diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index bbc66eb5..f857850c 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -3098,7 +3098,8 @@ static inline bool arm_sctlr_b(CPUARMState *env) * let linux-user ignore the fact that it conflicts with SCTLR_B. * This lets people run BE32 binaries with "-cpu any". */ - !arm_feature(env, ARM_FEATURE_V7) && + // Unicorn: Our hack to support BE32 mode + // !arm_feature(env, ARM_FEATURE_V7) && (env->cp15.sctlr_el[1] & SCTLR_B) != 0; } From da3999b6f0a3d520b729531ab2542bd36760a10f Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 21 Oct 2022 11:37:07 +0200 Subject: [PATCH 61/77] Add tests for thumb2 --- tests/unit/test_arm.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index 66898e62..139fa7c3 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -775,6 +775,46 @@ static void test_arm_context_save(void) OK(uc_close(uc2)); } +static void test_arm_thumb2(void) +{ + uc_engine *uc; + // MOVS R0, #0x24 + // AND.W R0, R0, #4 + char code[] = "\x24\x20\x00\xF0\x04\x00"; + uint32_t r_r0; + + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_LITTLE_ENDIAN, + code, sizeof(code) - 1, UC_CPU_ARM_CORTEX_R5); + + 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)); + + TEST_CHECK(r_r0 == 0x4); + + OK(uc_close(uc)); +} + +static void test_armeb_be32_thumb2(void) +{ + uc_engine *uc; + // MOVS R0, #0x24 + // AND.W R0, R0, #4 + char code[] = "\x20\x24\xF0\x00\x00\x04"; + uint32_t r_r0; + + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_BIG_ENDIAN, code, + sizeof(code) - 1, UC_CPU_ARM_CORTEX_R5); + + 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)); + + TEST_CHECK(r_r0 == 0x4); + + 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}, @@ -798,4 +838,6 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_switch_endian", test_arm_switch_endian}, {"test_armeb_ldrb", test_armeb_ldrb}, {"test_arm_context_save", test_arm_context_save}, + {"test_arm_thumb2", test_arm_thumb2}, + {"test_armeb_be32_thumb2", test_armeb_be32_thumb2}, {NULL, NULL}}; \ No newline at end of file From fb8fb1ca7ab16103ed4c6996cf97ad32b7bf5d63 Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 27 Oct 2022 22:51:56 +0200 Subject: [PATCH 62/77] Add headers for endianess --- tests/unit/bswap.h | 47 ++++++++++++++++++++++++ tests/unit/endian.h | 75 +++++++++++++++++++++++++++++++++++++++ tests/unit/unicorn_test.h | 14 ++++++++ 3 files changed, 136 insertions(+) create mode 100644 tests/unit/bswap.h create mode 100644 tests/unit/endian.h diff --git a/tests/unit/bswap.h b/tests/unit/bswap.h new file mode 100644 index 00000000..832badab --- /dev/null +++ b/tests/unit/bswap.h @@ -0,0 +1,47 @@ +// Copy from google/cityhash:src/city.cc (MIT) + +#ifdef _MSC_VER + +#include +#define bswap_32(x) _byteswap_ulong(x) +#define bswap_64(x) _byteswap_uint64(x) + +#elif defined(__APPLE__) + +// Mac OS X / Darwin features +#include +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) + +#elif defined(__sun) || defined(sun) + +#include +#define bswap_32(x) BSWAP_32(x) +#define bswap_64(x) BSWAP_64(x) + +#elif defined(__FreeBSD__) + +#include +#define bswap_32(x) bswap32(x) +#define bswap_64(x) bswap64(x) + +#elif defined(__OpenBSD__) + +#include +#define bswap_32(x) swap32(x) +#define bswap_64(x) swap64(x) + +#elif defined(__NetBSD__) + +#include +#include +#if defined(__BSWAP_RENAME) && !defined(__bswap_32) +#define bswap_32(x) bswap32(x) +#define bswap_64(x) bswap64(x) +#endif + +#else + +#include + +#endif \ No newline at end of file diff --git a/tests/unit/endian.h b/tests/unit/endian.h new file mode 100644 index 00000000..5bc86308 --- /dev/null +++ b/tests/unit/endian.h @@ -0,0 +1,75 @@ +// Copy fron boost 1.43.0 + +// Copyright 2005 Caleb Epstein +// Copyright 2006 John Maddock +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/* + * Copyright notice reproduced from , from + * which this code was originally taken. + * + * Modified by Caleb Epstein to use with GNU libc and to + * defined the BOOST_ENDIAN macro. + */ + +#ifndef BOOST_DETAIL_ENDIAN_HPP +#define BOOST_DETAIL_ENDIAN_HPP + +// GNU libc offers the helpful header which defines +// __BYTE_ORDER + +#if defined (__GLIBC__) +# include +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define BOOST_LITTLE_ENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define BOOST_BIG_ENDIAN +# elif (__BYTE_ORDER == __PDP_ENDIAN) +# define BOOST_PDP_ENDIAN +# else +# error Unknown machine endianness detected. +# endif +# define BOOST_BYTE_ORDER __BYTE_ORDER +#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define BOOST_BIG_ENDIAN +# define BOOST_BYTE_ORDER 4321 +#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define BOOST_LITTLE_ENDIAN +# define BOOST_BYTE_ORDER 1234 +#elif defined(__sparc) || defined(__sparc__) \ + || defined(_POWER) || defined(__powerpc__) \ + || defined(__ppc__) || defined(__hpux) || defined(__hppa) \ + || defined(_MIPSEB) || defined(_POWER) \ + || defined(__s390__) +# define BOOST_BIG_ENDIAN +# define BOOST_BYTE_ORDER 4321 +#elif defined(__i386__) || defined(__alpha__) \ + || defined(__ia64) || defined(__ia64__) \ + || defined(_M_IX86) || defined(_M_IA64) \ + || defined(_M_ALPHA) || defined(__amd64) \ + || defined(__amd64__) || defined(_M_AMD64) \ + || defined(__x86_64) || defined(__x86_64__) \ + || defined(_M_X64) || defined(__bfin__) + +# define BOOST_LITTLE_ENDIAN +# define BOOST_BYTE_ORDER 1234 +#else +# error The file boost/detail/endian.hpp needs to be set up for your CPU type. +#endif + + +#endif diff --git a/tests/unit/unicorn_test.h b/tests/unit/unicorn_test.h index a2e12042..3d32843f 100644 --- a/tests/unit/unicorn_test.h +++ b/tests/unit/unicorn_test.h @@ -5,6 +5,8 @@ #include #include #include "acutest.h" +#include "endian.h" +#include "bswap.h" /** * Assert that err matches expect @@ -22,4 +24,16 @@ */ #define OK(stat) uc_assert_err(UC_ERR_OK, stat) +#ifdef BOOST_LITTLE_ENDIAN +#define LEINT32(x) (x) +#define LEINT64(x) (x) +#define BEINT32(x) (bswap_32(x)) +#define BEINT64(x) (bswap_64(x)) +#else +#define LEINT32(x) (bswap_32(x)) +#define LEINT64(x) (bswap_64(x)) +#define BEINT32(x) (x) +#define BEINT64(x) (x) +#endif + #endif /* UNICORN_TEST_H */ From e01556557e4a273beed19865d11ecbc9bb4dd4e3 Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 27 Oct 2022 22:52:25 +0200 Subject: [PATCH 63/77] Fix endianess in test_ctl --- tests/unit/test_ctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 6277da67..aa57474b 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -62,8 +62,8 @@ static inline int64_t get_clock_realtime(void) #endif -const uint64_t code_start = 0x1000; -const uint64_t code_len = 0x4000; +const uint64_t code_start = LEINT64(0x1000); +const uint64_t code_len = LEINT64(0x4000); static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, const char *code, uint64_t size) From bb7b5bb64ae3eca6e36393f5f01a093319aa6a34 Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 27 Oct 2022 23:32:15 +0200 Subject: [PATCH 64/77] Use macro bswap --- tests/unit/bswap.h | 47 --------------------------------------- tests/unit/unicorn_test.h | 19 +++++++++++++++- 2 files changed, 18 insertions(+), 48 deletions(-) delete mode 100644 tests/unit/bswap.h diff --git a/tests/unit/bswap.h b/tests/unit/bswap.h deleted file mode 100644 index 832badab..00000000 --- a/tests/unit/bswap.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copy from google/cityhash:src/city.cc (MIT) - -#ifdef _MSC_VER - -#include -#define bswap_32(x) _byteswap_ulong(x) -#define bswap_64(x) _byteswap_uint64(x) - -#elif defined(__APPLE__) - -// Mac OS X / Darwin features -#include -#define bswap_32(x) OSSwapInt32(x) -#define bswap_64(x) OSSwapInt64(x) - -#elif defined(__sun) || defined(sun) - -#include -#define bswap_32(x) BSWAP_32(x) -#define bswap_64(x) BSWAP_64(x) - -#elif defined(__FreeBSD__) - -#include -#define bswap_32(x) bswap32(x) -#define bswap_64(x) bswap64(x) - -#elif defined(__OpenBSD__) - -#include -#define bswap_32(x) swap32(x) -#define bswap_64(x) swap64(x) - -#elif defined(__NetBSD__) - -#include -#include -#if defined(__BSWAP_RENAME) && !defined(__bswap_32) -#define bswap_32(x) bswap32(x) -#define bswap_64(x) bswap64(x) -#endif - -#else - -#include - -#endif \ No newline at end of file diff --git a/tests/unit/unicorn_test.h b/tests/unit/unicorn_test.h index 3d32843f..dbc17a27 100644 --- a/tests/unit/unicorn_test.h +++ b/tests/unit/unicorn_test.h @@ -6,7 +6,24 @@ #include #include "acutest.h" #include "endian.h" -#include "bswap.h" + +// Copied from glibc-2.29 + +/* Swap bytes in 32 bit value. */ +#define bswap_32(x) \ + ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) | \ + (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) + +/* Swap bytes in 64 bit value. */ +#define bswap_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) /** * Assert that err matches expect From d80cd54b0f72c4b73d490d558f35152309f9fda1 Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 27 Oct 2022 23:39:43 +0200 Subject: [PATCH 65/77] Revert test_ctl endian changes --- tests/unit/test_ctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index aa57474b..6277da67 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -62,8 +62,8 @@ static inline int64_t get_clock_realtime(void) #endif -const uint64_t code_start = LEINT64(0x1000); -const uint64_t code_len = LEINT64(0x4000); +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) From 47275c18f4c699201d8e8ca12558168847517f89 Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 28 Oct 2022 15:02:59 +0200 Subject: [PATCH 66/77] Fix a test bug --- tests/unit/test_ctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 6277da67..05f4c54e 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -110,14 +110,14 @@ static void test_uc_ctl_exits(void) r_eax = 0; r_ebx = 0; OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_eax)); - OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_ebx)); + OK(uc_reg_write(uc, UC_X86_REG_EBX, &r_ebx)); // Run two times. OK(uc_emu_start(uc, code_start, 0, 0, 0)); OK(uc_emu_start(uc, code_start, 0, 0, 0)); OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_eax)); - OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_ebx)); + OK(uc_reg_read(uc, UC_X86_REG_EBX, &r_ebx)); TEST_CHECK(r_eax == 1); TEST_CHECK(r_ebx == 1); From 98980c904c8f85c3d8d2c4b4b2d033dc63a3bd6b Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 28 Oct 2022 15:59:14 +0200 Subject: [PATCH 67/77] Pass the correct size integers --- uc.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/uc.c b/uc.c index f69cf3a7..965d772a 100644 --- a/uc.c +++ b/uc.c @@ -754,12 +754,13 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, } uc->nested_level++; + uint32_t begin_pc32 = READ_DWORD(begin); switch (uc->arch) { default: break; #ifdef UNICORN_HAS_M68K case UC_ARCH_M68K: - uc_reg_write(uc, UC_M68K_REG_PC, &begin); + uc_reg_write(uc, UC_M68K_REG_PC, &begin_pc32); break; #endif #ifdef UNICORN_HAS_X86 @@ -778,7 +779,7 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, break; } case UC_MODE_32: - uc_reg_write(uc, UC_X86_REG_EIP, &begin); + uc_reg_write(uc, UC_X86_REG_EIP, &begin_pc32); break; case UC_MODE_64: uc_reg_write(uc, UC_X86_REG_RIP, &begin); @@ -788,7 +789,7 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, #endif #ifdef UNICORN_HAS_ARM case UC_ARCH_ARM: - uc_reg_write(uc, UC_ARM_REG_R15, &begin); + uc_reg_write(uc, UC_ARM_REG_R15, &begin_pc32); break; #endif #ifdef UNICORN_HAS_ARM64 @@ -799,7 +800,7 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, #ifdef UNICORN_HAS_MIPS case UC_ARCH_MIPS: // TODO: MIPS32/MIPS64/BIGENDIAN etc - uc_reg_write(uc, UC_MIPS_REG_PC, &begin); + uc_reg_write(uc, UC_MIPS_REG_PC, &begin_pc32); break; #endif #ifdef UNICORN_HAS_SPARC @@ -815,7 +816,11 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, #endif #ifdef UNICORN_HAS_RISCV case UC_ARCH_RISCV: - uc_reg_write(uc, UC_RISCV_REG_PC, &begin); + if (uc->mode & UC_MODE_RISCV64) { + uc_reg_write(uc, UC_RISCV_REG_PC, &begin); + } else { + uc_reg_write(uc, UC_RISCV_REG_PC, &begin_pc32); + } break; #endif #ifdef UNICORN_HAS_S390X @@ -825,7 +830,7 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, #endif #ifdef UNICORN_HAS_TRICORE case UC_ARCH_TRICORE: - uc_reg_write(uc, UC_TRICORE_REG_PC, &begin); + uc_reg_write(uc, UC_TRICORE_REG_PC, &begin_pc32); break; #endif } From 4b961a8ef63861d4bd1ec7c8ac8e6268f8ab5078 Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 28 Oct 2022 16:20:20 +0200 Subject: [PATCH 68/77] Apply fix for big endian hosts per #1710 --- tests/unit/test_arm.c | 6 +++--- tests/unit/test_arm64.c | 2 +- tests/unit/test_mem.c | 4 ++-- tests/unit/test_mips.c | 2 +- tests/unit/test_x86.c | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index 139fa7c3..9206fa24 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -164,9 +164,9 @@ static void test_arm_thumb_ite(void) OK(uc_reg_write(uc, UC_ARM_REG_R3, &r_r3)); OK(uc_mem_map(uc, r_sp, 0x1000, UC_PROT_ALL)); - r_r2 = 0x68; + r_r2 = LEINT32(0x68); OK(uc_mem_write(uc, r_sp, &r_r2, 4)); - r_r2 = 0x4d; + r_r2 = LEINT32(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, @@ -396,7 +396,7 @@ static void test_arm_v8(void) { char code[] = "\xd0\xe8\xff\x17"; // LDAEXD.W R1, [R0] uc_engine *uc; - uint32_t r_r1 = 0xdeadbeef; + uint32_t r_r1 = LEINT32(0xdeadbeef); uint32_t r_r0; uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB, code, sizeof(code) - 1, diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 52bd95ca..e82869fd 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -137,7 +137,7 @@ static void test_arm64_v8_pac(void) OK(uc_mem_read(uc, 0x40000, (void *)&mem, 8)); - TEST_CHECK(mem == r_x8); + TEST_CHECK(LEINT64(mem) == r_x8); OK(uc_close(uc)); } diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index 997330c4..4e2f176a 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -55,7 +55,7 @@ static void test_mem_protect(void) OK(uc_emu_start(qc, 0x1000, 0x1000 + sizeof(code) - 1, 0, 1)); OK(uc_mem_read(qc, 0x2000 + 4, &mem, 4)); - TEST_CHECK(mem == 0xdeadbeef); + TEST_CHECK(LEINT32(mem) == 0xdeadbeef); OK(uc_close(qc)); } @@ -92,7 +92,7 @@ static void test_splitting_mmio_unmap(void) // mov ebx, [0x4004] <-- mmio read char code[] = "\x8b\x0d\x04\x30\x00\x00\x8b\x1d\x04\x40\x00\x00"; int r_ecx, r_ebx; - int bytes = 0xdeadbeef; + int bytes = LEINT32(0xdeadbeef); OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); diff --git a/tests/unit/test_mips.c b/tests/unit/test_mips.c index 28cd4e8c..8a00b856 100644 --- a/tests/unit/test_mips.c +++ b/tests/unit/test_mips.c @@ -112,7 +112,7 @@ static void test_mips_lwx_exception_issue_1314(void) reg = 0; OK(uc_reg_write(uc, UC_MIPS_REG_1, ®)); OK(uc_reg_write(uc, UC_MIPS_REG_T9, ®)); - reg = 0xdeadbeef; + reg = LEINT32(0xdeadbeef); OK(uc_mem_write(uc, 0x10000, ®, 4)); reg = 0x10000; OK(uc_reg_write(uc, UC_MIPS_REG_S3, ®)); diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index b4c94dcf..7918d4c5 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -422,7 +422,7 @@ static void test_x86_x87_fnstenv(void) OK(uc_mem_read(uc, base, fnstenv, sizeof(fnstenv))); // But update FCS:FIP for fld. - TEST_CHECK(fnstenv[3] == last_eip); + TEST_CHECK(LEINT32(fnstenv[3]) == last_eip); OK(uc_close(uc)); } @@ -530,7 +530,7 @@ static void test_x86_smc_xor(void) OK(uc_mem_read(uc, code_start + 3, (void *)&result, 4)); - TEST_CHECK(result == (0x3ea98b13 ^ 0xbc4177e6)); + TEST_CHECK(LEINT32(result) == (0x3ea98b13 ^ 0xbc4177e6)); OK(uc_close(uc)); } @@ -562,7 +562,7 @@ static void test_x86_mmio_uc_mem_rw_write_callback(uc_engine *uc, static void test_x86_mmio_uc_mem_rw(void) { uc_engine *uc; - int data = 0xdeadbeef; + int data = LEINT32(0xdeadbeef); OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); @@ -572,7 +572,7 @@ static void test_x86_mmio_uc_mem_rw(void) OK(uc_mem_write(uc, 0x20004, (void *)&data, 4)); OK(uc_mem_read(uc, 0x20008, (void *)&data, 4)); - TEST_CHECK(data == 0x19260817); + TEST_CHECK(LEINT32(data) == 0x19260817); OK(uc_close(uc)); } From 3c18ddcc410f8d6af950807b7ccb94c90e117ac7 Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 28 Oct 2022 16:23:50 +0200 Subject: [PATCH 69/77] Fix PC write for PPC32/64 --- uc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/uc.c b/uc.c index 965d772a..b8469aa6 100644 --- a/uc.c +++ b/uc.c @@ -811,7 +811,11 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, #endif #ifdef UNICORN_HAS_PPC case UC_ARCH_PPC: - uc_reg_write(uc, UC_PPC_REG_PC, &begin); + if (uc->mode & UC_MODE_PPC64) { + uc_reg_write(uc, UC_PPC_REG_PC, &begin); + } else { + uc_reg_write(uc, UC_PPC_REG_PC, &begin_pc32); + } break; #endif #ifdef UNICORN_HAS_RISCV From 9c5358c7598ad2429bdadb89cbfb927914d12045 Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 28 Oct 2022 17:37:02 +0200 Subject: [PATCH 70/77] Respect QEMU ZMM_Q to work on big endian hosts --- qemu/target/i386/unicorn.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index 2141424f..f10b70e2 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -289,9 +289,9 @@ static void reg_read(CPUX86State *env, unsigned int regid, void *value, 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]; + ZMMReg *reg = (ZMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + dst[0] = reg->ZMM_Q(0); + dst[1] = reg->ZMM_Q(1); return; } case UC_X86_REG_ST0: @@ -323,10 +323,10 @@ static void reg_read(CPUX86State *env, unsigned int regid, void *value, 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]; + ZMMReg *lo_reg = (ZMMReg *)&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[0] = lo_reg->ZMM_Q(0); + dst[1] = lo_reg->ZMM_Q(1); dst[2] = hi_reg->_d[0]; dst[3] = hi_reg->_d[1]; return; @@ -828,9 +828,9 @@ static void reg_read(CPUX86State *env, unsigned int regid, void *value, 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]; + ZMMReg *reg = (ZMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + dst[0] = reg->ZMM_Q(0); + dst[1] = reg->ZMM_Q(1); break; } case UC_X86_REG_FS_BASE: @@ -896,9 +896,9 @@ static int reg_write(CPUX86State *env, unsigned int regid, const void *value, 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]; + ZMMReg *reg = (ZMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + reg->ZMM_Q(0) = src[0]; + reg->ZMM_Q(1) = src[1]; return 0; } case UC_X86_REG_ST0: @@ -930,10 +930,12 @@ static int reg_write(CPUX86State *env, unsigned int regid, const void *value, 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]; + ZMMReg *lo_reg = (ZMMReg *)&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]; + lo_reg->ZMM_Q(0) = src[0]; + lo_reg->ZMM_Q(1) = src[1]; + // YMM is not supported by QEMU at all + // As of qemu 5.0.1, ymmh_regs is nowhere used. hi_reg->_d[0] = src[2]; hi_reg->_d[1] = src[3]; return 0; @@ -1471,9 +1473,9 @@ static int reg_write(CPUX86State *env, unsigned int regid, const void *value, 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]; + ZMMReg *reg = (ZMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + reg->ZMM_Q(0) = src[0]; + reg->ZMM_Q(1) = src[1]; break; } case UC_X86_REG_FS_BASE: From 563104fa91ffdafabe517ec1c15c585d495028ab Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 28 Oct 2022 17:44:17 +0200 Subject: [PATCH 71/77] IP register is 2 bytes --- uc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uc.c b/uc.c index b8469aa6..667f40ca 100644 --- a/uc.c +++ b/uc.c @@ -769,7 +769,7 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, default: break; case UC_MODE_16: { - uint64_t ip; + uint16_t ip; uint16_t cs; uc_reg_read(uc, UC_X86_REG_CS, &cs); From 428ed8fd212e313981ce3e904e17c226873feee1 Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 28 Oct 2022 17:47:55 +0200 Subject: [PATCH 72/77] Fix test_x86_unaligned_access for big endian hosts --- tests/unit/test_x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 7918d4c5..f403dfb2 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1152,7 +1152,7 @@ static void test_x86_unaligned_access(void) uc_hook hook; // mov dword ptr [0x200001], eax; mov eax, dword ptr [0x200001] char code[] = "\xa3\x01\x00\x20\x00\xa1\x01\x00\x20\x00"; - uint32_t r_eax = 0x41424344; + uint32_t r_eax = LEINT32(0x41424344); struct writelog_t write_log[10]; struct writelog_t read_log[10]; memset(write_log, 0, sizeof(write_log)); From a40bf26263f95e37a157d3db7bc035f2b6ad4fa8 Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 28 Oct 2022 17:53:20 +0200 Subject: [PATCH 73/77] Disable test_x86_unaligned_access on be hosts --- tests/unit/test_x86.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index f403dfb2..8e9d7cd3 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1124,7 +1124,10 @@ static void test_x86_invalid_vex_l(void) OK(uc_close(uc)); } -#ifndef TARGET_READ_INLINED +// AARCH64 inline the read while s390x won't split the access. Though not tested on other hosts +// but we restrict a bit more. +#if !defined(TARGET_READ_INLINED) && defined(BOOST_LITTLE_ENDIAN) + struct writelog_t { uint32_t addr, size; }; From fc193ffe241a870f5938999d3e54d9aa7572a1b1 Mon Sep 17 00:00:00 2001 From: mio Date: Fri, 28 Oct 2022 17:55:39 +0200 Subject: [PATCH 74/77] Fix missing macros --- tests/unit/test_x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 8e9d7cd3..ddc84710 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1267,7 +1267,7 @@ TEST_LIST = { {"test_x86_correct_address_in_long_jump_hook", test_x86_correct_address_in_long_jump_hook}, {"test_x86_invalid_vex_l", test_x86_invalid_vex_l}, -#ifndef TARGET_READ_INLINED +#if !defined(TARGET_READ_INLINED) && defined(BOOST_LITTLE_ENDIAN) {"test_x86_unaligned_access", test_x86_unaligned_access}, #endif {"test_x86_lazy_mapping", test_x86_lazy_mapping}, From 951f155f0a52228ebcc65ba4cc43ada3d47fae6c Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 29 Oct 2022 01:32:05 +0800 Subject: [PATCH 75/77] Update SECURITY.md --- SECURITY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SECURITY.md b/SECURITY.md index 5398de8c..8334f63b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,2 +1,3 @@ aquynh -at- gmail.com + mio -at- lazym.io From 8ac20e20122ce0f32f4541fde33867499ee28d42 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Mon, 31 Oct 2022 12:37:18 +0800 Subject: [PATCH 76/77] python: add some more comments for samples --- bindings/python/sample_ctl.py | 3 ++- bindings/python/sample_s390x.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) mode change 100644 => 100755 bindings/python/sample_ctl.py diff --git a/bindings/python/sample_ctl.py b/bindings/python/sample_ctl.py old mode 100644 new mode 100755 index 8e33ad29..202a2094 --- a/bindings/python/sample_ctl.py +++ b/bindings/python/sample_ctl.py @@ -1,4 +1,5 @@ -# Unicorn Emulator Engine +#!/usr/bin/env python +# Sample code for Unicorn. # By Lazymio(@wtdcode), 2021 from unicorn import * diff --git a/bindings/python/sample_s390x.py b/bindings/python/sample_s390x.py index c2a3ec58..6b96d827 100644 --- a/bindings/python/sample_s390x.py +++ b/bindings/python/sample_s390x.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# Sample code for S390x of Unicorn. from unicorn import * from unicorn.s390x_const import * From e6da8168035ff50b1123bc30d7e58d1f34d2d13b Mon Sep 17 00:00:00 2001 From: mio Date: Mon, 31 Oct 2022 16:08:51 +0100 Subject: [PATCH 77/77] Update changelog --- ChangeLog | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/ChangeLog b/ChangeLog index 85c2600c..224883de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,43 @@ This file details the changelog of Unicorn Engine. +------------------------------- +[Version 2.0.1]: Nov 1st, 2022 + +Unicorn2 makes the first step to [Debian packages](https://tracker.debian.org/pkg/unicorn-engine) and [vcpkg](https://github.com/microsoft/vcpkg/pull/26101)! Thanks @roehling and @LilyWangL ! + +Features: + +- Support building & running on BE hosts. #1710 +- Fix and support `clang-cl` on Windows. #1687 +- Fix python `sdist` and add aarch64 Linux wheels. Note `pip` can build Unicorn2 on M1 now! +- C# binding is refined and upgraded to .Net 6. #1723 + +Fix/Improvements: + +- Various bindings improvements. #1723 +- Improvements for tests. #1684 #1683 #1691 #1711 +- Fail explicitly when VEX.L is set. #1658 +- Fix endianness when writing PPC32 CR register. #1659 +- Fix a bug in `uc_ctl_set_cpu_model` check. +- Fix Tricore PC not updating. #1668 +- Fix the mapping not updated if users modify the mappings in the hooks. +- Handle pathological cases consistently. #1651 +- Fix memory leaks in PPC target. #1680 +- Fix memory leaks in Tricore target. #1681 +- Fix MSVC handling in cmake. #1693 +- Fix PC sync-ing problems for `UC_HOOK_BLOCK` hooks. +- Fix PC sync-ed twice when users request a soft restart. +- Prevent overflow with pre-allocated RAM blocks. #1712 +- Add FPCR and FPSR registers #1722 +- Fix ARM CPU state not deep copied. +- Fix PC not sync-ed for memory operation on aarch64. +- Exit invalid store operations early to avoid the target registers being overwritten. +- Improve the support for ARM BE32. + +Thanks: + +@roehling @LilyWangL @mrexodia @zachriggle @Yu3H0 @rhelmot @relapids @sh4w1 @TSRBerry + ------------------------------- [Version 2.0.0]: July 7th, 2022