From 026f4c447e944cd855fd0d44fea52ac31bc3a372 Mon Sep 17 00:00:00 2001 From: Sai Cao <1665673333@qq.com> Date: Fri, 12 Apr 2024 11:14:48 +0800 Subject: [PATCH 1/5] Fix: UC_HOOK_MEM_READ only triggered once on Arm64 Host machine. add simple tests https://github.com/unicorn-engine/unicorn/issues/1908 --- qemu/tcg/aarch64/tcg-target.inc.c | 28 ++++++++++++++---- tests/unit/test_arm64.c | 48 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/qemu/tcg/aarch64/tcg-target.inc.c b/qemu/tcg/aarch64/tcg-target.inc.c index 85185611b1..4a9e2886d1 100644 --- a/qemu/tcg/aarch64/tcg-target.inc.c +++ b/qemu/tcg/aarch64/tcg-target.inc.c @@ -1582,11 +1582,16 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) TCGMemOpIdx oi = lb->oi; MemOp opc = get_memop(oi); MemOp size = opc & MO_SIZE; + bool success=false; + if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ)|HOOK_EXISTS(s->uc, UC_HOOK_MEM_WRITE)){ + success=reloc_pc26(lb->label_ptr[0], s->code_ptr); - if (!reloc_pc19(lb->label_ptr[0], s->code_ptr)) { + }else{ + success=reloc_pc19(lb->label_ptr[0], s->code_ptr); + } + if(!success){ return false; } - tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0); tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg); tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, oi); @@ -1608,10 +1613,15 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) MemOp opc = get_memop(oi); MemOp size = opc & MO_SIZE; - if (!reloc_pc19(lb->label_ptr[0], s->code_ptr)) { + bool success=false; + if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ)|HOOK_EXISTS(s->uc, UC_HOOK_MEM_WRITE)){ + success=reloc_pc26(lb->label_ptr[0], s->code_ptr); + }else{ + success=reloc_pc19(lb->label_ptr[0], s->code_ptr); + } + if(!success){ return false; } - tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0); tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg); tcg_out_mov(s, size == MO_64, TCG_REG_X2, lb->datalo_reg); @@ -1656,6 +1666,11 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, MemOp opc, #ifdef TARGET_ARM struct uc_struct *uc = s->uc; #endif + if(HOOK_EXISTS(s->uc,UC_HOOK_MEM_READ)|HOOK_EXISTS(s->uc,UC_HOOK_MEM_WRITE)){ + *label_ptr = s->code_ptr; + tcg_out_insn_3206(s,I3206_B,0); + return; + } unsigned a_bits = get_alignment_bits(opc); unsigned s_bits = opc & MO_SIZE; unsigned a_mask = (1u << a_bits) - 1; @@ -1707,7 +1722,8 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, MemOp opc, /* If not equal, we jump to the slow path. */ *label_ptr = s->code_ptr; - tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0); + // tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0); + tcg_out_insn_3202(s, I3202_B_C, TCG_COND_NE, 0); } #endif /* CONFIG_SOFTMMU */ @@ -2924,4 +2940,4 @@ static const DebugFrame debug_frame = { void tcg_register_jit(TCGContext *s, void *buf, size_t buf_size) { tcg_register_jit_int(s, buf, buf_size, &debug_frame, sizeof(debug_frame)); -} +} \ No newline at end of file diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index e82869fd95..946685fcfe 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -371,6 +371,53 @@ static void test_arm64_block_invalid_mem_read_write_sync(void) OK(uc_close(uc)); } +static bool test_arm64_mem_read_write_cb(uc_engine *uc, int type, + uint64_t address, int size, + int64_t value, void *user_data) +{ + uint64_t *count = (uint64_t *)user_data; + switch (type) { + case UC_MEM_READ: + count[0]++; + break; + case UC_MEM_WRITE: + count[1]++; + break; + } + + return 0; +} +static void test_arm64_mem_hook_read_write(void) +{ + uc_engine *uc; + // ldp x1, x2, [sp] + // stp x1, x2,[sp] + // ldp x1, x2, [sp] + // stp x1, x2,[sp] + const char code[] = {0xe1, 0x0b, 0x40, 0xa9, 0xe1, 0x0b, 0x00, 0xa9, + 0xe1, 0x0b, 0x40, 0xa9, 0xe1, 0x0b, 0x00, 0xa9}; + uint64_t r_sp; + r_sp = 0x16db6a040; + uc_hook hk; + uint64_t counter[2] = {0, 0}; + + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code), + UC_CPU_ARM64_A72); + + uc_reg_write(uc, UC_ARM64_REG_SP, &r_sp); + uc_mem_map(uc, 0x16db68000, 1024 * 16, UC_PROT_ALL); + + OK(uc_hook_add(uc, &hk, UC_HOOK_MEM_READ, test_arm64_mem_read_write_cb, + counter, 1, 0)); + OK(uc_hook_add(uc, &hk, UC_HOOK_MEM_WRITE, test_arm64_mem_read_write_cb, + counter, 1, 0)); + + uc_assert_err(UC_ERR_OK, uc_emu_start(uc, code_start, + code_start + sizeof(code), 0, 0)); + + TEST_CHECK(counter[0] == 4 && counter[1] == 4); + OK(uc_close(uc)); +} TEST_LIST = {{"test_arm64_until", test_arm64_until}, {"test_arm64_code_patching", test_arm64_code_patching}, @@ -385,4 +432,5 @@ TEST_LIST = {{"test_arm64_until", test_arm64_until}, {"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}, + {"test_arm64_mem_read_hook", test_arm64_mem_hook_read_write}, {NULL, NULL}}; From 40672861c44f8c3c936fd5a5ffda1565feb81a62 Mon Sep 17 00:00:00 2001 From: Sai Cao <1665673333@qq.com> Date: Fri, 12 Apr 2024 18:12:25 +0800 Subject: [PATCH 2/5] Remove hook mem tests --- qemu/tcg/aarch64/tcg-target.inc.c | 4 ++-- tests/unit/test_arm64.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qemu/tcg/aarch64/tcg-target.inc.c b/qemu/tcg/aarch64/tcg-target.inc.c index 8cf16eef75..5dfec0b1fc 100644 --- a/qemu/tcg/aarch64/tcg-target.inc.c +++ b/qemu/tcg/aarch64/tcg-target.inc.c @@ -1587,7 +1587,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) MemOp opc = get_memop(oi); MemOp size = opc & MO_SIZE; bool success=false; - if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ)|HOOK_EXISTS(s->uc, UC_HOOK_MEM_WRITE)){ + if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ)||HOOK_EXISTS(s->uc, UC_HOOK_MEM_WRITE)){ success=reloc_pc26(lb->label_ptr[0], s->code_ptr); }else{ @@ -1618,7 +1618,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) MemOp size = opc & MO_SIZE; bool success=false; - if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ)|HOOK_EXISTS(s->uc, UC_HOOK_MEM_WRITE)){ + if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ)||HOOK_EXISTS(s->uc, UC_HOOK_MEM_WRITE)){ success=reloc_pc26(lb->label_ptr[0], s->code_ptr); }else{ success=reloc_pc19(lb->label_ptr[0], s->code_ptr); diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index ab2bad8c8f..21281a0e96 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -591,5 +591,5 @@ TEST_LIST = {{"test_arm64_until", test_arm64_until}, test_arm64_block_invalid_mem_read_write_sync}, {"test_arm64_mmu", test_arm64_mmu}, {"test_arm64_pc_wrap", test_arm64_pc_wrap}, - {"test_arm64_mem_read_hook", test_arm64_mem_hook_read_write}, + // {"test_arm64_mem_read_hook", test_arm64_mem_hook_read_write}, {NULL, NULL}}; From 1d3bfc4f94b52fbb892842792f401d16a58efaa6 Mon Sep 17 00:00:00 2001 From: Sai Cao <1665673333@qq.com> Date: Thu, 6 Jun 2024 10:06:22 +0800 Subject: [PATCH 3/5] make unaligned read only have one callback --- format.sh | 0 qemu/accel/tcg/cputlb.c | 20 +++++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) mode change 100644 => 100755 format.sh diff --git a/format.sh b/format.sh old mode 100644 new mode 100755 diff --git a/qemu/accel/tcg/cputlb.c b/qemu/accel/tcg/cputlb.c index 41ae6b07ca..966fb8480c 100644 --- a/qemu/accel/tcg/cputlb.c +++ b/qemu/accel/tcg/cputlb.c @@ -1550,16 +1550,18 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, // now it is read on mapped memory if (!code_read) { // this is date reading - HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { - if (hook->to_delete) - continue; - if (!HOOK_BOUND_CHECK(hook, paddr)) - continue; - JIT_CALLBACK_GUARD(((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, paddr, size, 0, hook->user_data)); + if (!uc->size_recur_mem) { + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { + if (hook->to_delete) + continue; + if (!HOOK_BOUND_CHECK(hook, paddr)) + continue; + JIT_CALLBACK_GUARD(((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, paddr, size, 0, hook->user_data)); - // the last callback may already asked to stop emulation - if (uc->stop_request) - break; + // the last callback may already asked to stop emulation + if (uc->stop_request) + break; + } } // callback on non-readable memory From 2d87f9c7002abaee4965e66bc5a2c7ce229c0829 Mon Sep 17 00:00:00 2001 From: Sai Cao <1665673333@qq.com> Date: Sat, 16 Nov 2024 11:42:16 +0800 Subject: [PATCH 4/5] Fix bug that CF_NOCACHE TB excuted without regeneration. --- qemu/accel/tcg/cpu-exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu/accel/tcg/cpu-exec.c b/qemu/accel/tcg/cpu-exec.c index f938cfaa70..fc47eecbfc 100644 --- a/qemu/accel/tcg/cpu-exec.c +++ b/qemu/accel/tcg/cpu-exec.c @@ -257,7 +257,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu, struct hook *hook; tb = tb_lookup__cpu_state(cpu, &pc, &cs_base, &flags, cf_mask); - if (tb == NULL) { + if (tb == NULL||tb->cflags&CF_NOCACHE) { mmap_lock(); tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask); mmap_unlock(); From d01904d3f33bd58c54271a7e28c402dbaddda847 Mon Sep 17 00:00:00 2001 From: Sai Cao <1665673333@qq.com> Date: Thu, 19 Dec 2024 11:29:20 +0800 Subject: [PATCH 5/5] Fix bug that tcg_region_alloc tbs were not flush this cause uc_ctl_remove_cache remove a invalid tbs. --- qemu/tcg/tcg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qemu/tcg/tcg.c b/qemu/tcg/tcg.c index dcacec7cc4..2b643b495f 100644 --- a/qemu/tcg/tcg.c +++ b/qemu/tcg/tcg.c @@ -808,6 +808,7 @@ TranslationBlock *tcg_tb_alloc(TCGContext *s) if (tcg_region_alloc(s)) { return NULL; } + tb_flush(s->uc->cpu); goto retry; } s->code_gen_ptr = next;