From 83ad137ac235cee4b4700663d9dd914133d67069 Mon Sep 17 00:00:00 2001 From: mio Date: Sat, 12 Apr 2025 23:22:04 +0800 Subject: [PATCH] Sync HOOK_INSN hooks --- qemu/include/exec/ioport.h | 12 +++++----- qemu/softmmu/ioport.c | 43 +++++++++++++++++++++++++++++----- qemu/target/i386/misc_helper.c | 19 +++++++++------ 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/qemu/include/exec/ioport.h b/qemu/include/exec/ioport.h index 93d39b43..cdd6b2df 100644 --- a/qemu/include/exec/ioport.h +++ b/qemu/include/exec/ioport.h @@ -40,12 +40,12 @@ typedef struct MemoryRegionPortio { #define PORTIO_END_OF_LIST() { } -void cpu_outb(struct uc_struct *uc, uint32_t addr, uint8_t val); -void cpu_outw(struct uc_struct *uc, uint32_t addr, uint16_t val); -void cpu_outl(struct uc_struct *uc, uint32_t addr, uint32_t val); -uint8_t cpu_inb(struct uc_struct *uc, uint32_t addr); -uint16_t cpu_inw(struct uc_struct *uc, uint32_t addr); -uint32_t cpu_inl(struct uc_struct *uc, uint32_t addr); +void cpu_outb(struct uc_struct *uc, uint32_t addr, uint8_t val, uintptr_t retaddr); +void cpu_outw(struct uc_struct *uc, uint32_t addr, uint16_t val, uintptr_t retaddr); +void cpu_outl(struct uc_struct *uc, uint32_t addr, uint32_t val, uintptr_t retaddr); +uint8_t cpu_inb(struct uc_struct *uc, uint32_t addr, uintptr_t retaddr); +uint16_t cpu_inw(struct uc_struct *uc, uint32_t addr, uintptr_t retaddr); +uint32_t cpu_inl(struct uc_struct *uc, uint32_t addr, uintptr_t retaddr); typedef struct PortioList { const struct MemoryRegionPortio *ports; diff --git a/qemu/softmmu/ioport.c b/qemu/softmmu/ioport.c index d8721b53..fdf8d0f4 100644 --- a/qemu/softmmu/ioport.c +++ b/qemu/softmmu/ioport.c @@ -28,10 +28,11 @@ #include "qemu/osdep.h" #include "cpu.h" #include "exec/memory.h" +#include "exec/exec-all.h" #include "uc_priv.h" #include "tcg/tcg-apple-jit.h" -void cpu_outb(struct uc_struct *uc, uint32_t addr, uint8_t val) +void cpu_outb(struct uc_struct *uc, uint32_t addr, uint8_t val, uintptr_t retaddr) { // address_space_write(&uc->address_space_io, addr, MEMTXATTRS_UNSPECIFIED, // &val, 1); @@ -39,17 +40,22 @@ void cpu_outb(struct uc_struct *uc, uint32_t addr, uint8_t val) //LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); // Unicorn: call registered OUT callbacks struct hook *hook; + bool synced = false; HOOK_FOREACH_VAR_DECLARE; HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { if (hook->to_delete) continue; if (hook->insn == UC_X86_INS_OUT) { + if (!synced && !uc->skip_sync_pc_on_exit && retaddr) { + cpu_restore_state(uc->cpu, retaddr, false); + synced = true; + } JIT_CALLBACK_GUARD(((uc_cb_insn_out_t)hook->callback)(uc, addr, 1, val, hook->user_data)); } } } -void cpu_outw(struct uc_struct *uc, uint32_t addr, uint16_t val) +void cpu_outw(struct uc_struct *uc, uint32_t addr, uint16_t val, uintptr_t retaddr) { // uint8_t buf[2]; @@ -60,17 +66,22 @@ void cpu_outw(struct uc_struct *uc, uint32_t addr, uint16_t val) //LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); // Unicorn: call registered OUT callbacks struct hook *hook; + bool synced = false; HOOK_FOREACH_VAR_DECLARE; HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { if (hook->to_delete) continue; if (hook->insn == UC_X86_INS_OUT) { + if (!synced && !uc->skip_sync_pc_on_exit && retaddr) { + cpu_restore_state(uc->cpu, retaddr, false); + synced = true; + } JIT_CALLBACK_GUARD(((uc_cb_insn_out_t)hook->callback)(uc, addr, 2, val, hook->user_data)); } } } -void cpu_outl(struct uc_struct *uc, uint32_t addr, uint32_t val) +void cpu_outl(struct uc_struct *uc, uint32_t addr, uint32_t val, uintptr_t retaddr) { // uint8_t buf[4]; @@ -81,17 +92,22 @@ void cpu_outl(struct uc_struct *uc, uint32_t addr, uint32_t val) //LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); // Unicorn: call registered OUT callbacks struct hook *hook; + bool synced = false; HOOK_FOREACH_VAR_DECLARE; HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { if (hook->to_delete) continue; if (hook->insn == UC_X86_INS_OUT) { + if (!synced && !uc->skip_sync_pc_on_exit && retaddr) { + cpu_restore_state(uc->cpu, retaddr, false); + synced = true; + } JIT_CALLBACK_GUARD(((uc_cb_insn_out_t)hook->callback)(uc, addr, 4, val, hook->user_data)); } } } -uint8_t cpu_inb(struct uc_struct *uc, uint32_t addr) +uint8_t cpu_inb(struct uc_struct *uc, uint32_t addr, uintptr_t retaddr) { // uint8_t val; @@ -101,11 +117,16 @@ uint8_t cpu_inb(struct uc_struct *uc, uint32_t addr) //LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); // Unicorn: call registered IN callbacks struct hook *hook; + bool synced = false; HOOK_FOREACH_VAR_DECLARE; HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { if (hook->to_delete) continue; if (hook->insn == UC_X86_INS_IN) { + if (!synced && !uc->skip_sync_pc_on_exit && retaddr) { + cpu_restore_state(uc->cpu, retaddr, false); + synced = true; + } uint8_t ret; JIT_CALLBACK_GUARD_VAR(ret, ((uc_cb_insn_in_t)hook->callback)(uc, addr, 1, hook->user_data)); return ret; @@ -115,7 +136,7 @@ uint8_t cpu_inb(struct uc_struct *uc, uint32_t addr) return 0; } -uint16_t cpu_inw(struct uc_struct *uc, uint32_t addr) +uint16_t cpu_inw(struct uc_struct *uc, uint32_t addr, uintptr_t retaddr) { // uint8_t buf[2]; // uint16_t val; @@ -126,11 +147,16 @@ uint16_t cpu_inw(struct uc_struct *uc, uint32_t addr) //LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); // Unicorn: call registered IN callbacks struct hook *hook; + bool synced = false; HOOK_FOREACH_VAR_DECLARE; HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { if (hook->to_delete) continue; if (hook->insn == UC_X86_INS_IN) { + if (!synced && !uc->skip_sync_pc_on_exit && retaddr) { + cpu_restore_state(uc->cpu, retaddr, false); + synced = true; + } uint16_t ret; JIT_CALLBACK_GUARD_VAR(ret, ((uc_cb_insn_in_t)hook->callback)(uc, addr, 2, hook->user_data)); return ret; @@ -140,7 +166,7 @@ uint16_t cpu_inw(struct uc_struct *uc, uint32_t addr) return 0; } -uint32_t cpu_inl(struct uc_struct *uc, uint32_t addr) +uint32_t cpu_inl(struct uc_struct *uc, uint32_t addr, uintptr_t retaddr) { // uint8_t buf[4]; // uint32_t val; @@ -153,11 +179,16 @@ uint32_t cpu_inl(struct uc_struct *uc, uint32_t addr) //LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); // Unicorn: call registered IN callbacks struct hook *hook; + bool synced = false; HOOK_FOREACH_VAR_DECLARE; HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { if (hook->to_delete) continue; if (hook->insn == UC_X86_INS_IN) { + if (!synced && !uc->skip_sync_pc_on_exit && retaddr) { + cpu_restore_state(uc->cpu, retaddr, false); + synced = true; + } uint32_t ret; JIT_CALLBACK_GUARD_VAR(ret, ((uc_cb_insn_in_t)hook->callback)(uc, addr, 4, hook->user_data)); return ret; diff --git a/qemu/target/i386/misc_helper.c b/qemu/target/i386/misc_helper.c index a8aec2bf..9a6754ce 100644 --- a/qemu/target/i386/misc_helper.c +++ b/qemu/target/i386/misc_helper.c @@ -35,7 +35,7 @@ void helper_outb(CPUX86State *env, uint32_t port, uint32_t data) // address_space_stb(env->uc, &env->uc->address_space_io, port, data & 0xff, // #endif // cpu_get_mem_attrs(env), NULL); - return cpu_outb(env->uc, port, data); + return cpu_outb(env->uc, port, data, GETPC()); } target_ulong helper_inb(CPUX86State *env, uint32_t port) @@ -46,7 +46,7 @@ target_ulong helper_inb(CPUX86State *env, uint32_t port) // return address_space_ldub(env->uc, &env->uc->address_space_io, port, // #endif // cpu_get_mem_attrs(env), NULL); - return cpu_inb(env->uc, port); + return cpu_inb(env->uc, port, GETPC()); } void helper_outw(CPUX86State *env, uint32_t port, uint32_t data) @@ -57,7 +57,7 @@ void helper_outw(CPUX86State *env, uint32_t port, uint32_t data) // address_space_stw(env->uc, &env->uc->address_space_io, port, data & 0xffff, // #endif // cpu_get_mem_attrs(env), NULL); - return cpu_outw(env->uc, port, data); + return cpu_outw(env->uc, port, data, GETPC()); } target_ulong helper_inw(CPUX86State *env, uint32_t port) @@ -68,7 +68,7 @@ target_ulong helper_inw(CPUX86State *env, uint32_t port) // return address_space_lduw(env->uc, &env->uc->address_space_io, port, // #endif // cpu_get_mem_attrs(env), NULL); - return cpu_inw(env->uc, port); + return cpu_inw(env->uc, port, GETPC()); } void helper_outl(CPUX86State *env, uint32_t port, uint32_t data) @@ -79,7 +79,7 @@ void helper_outl(CPUX86State *env, uint32_t port, uint32_t data) // address_space_stl(env->uc, &env->uc->address_space_io, port, data, // #endif // cpu_get_mem_attrs(env), NULL); - return cpu_outl(env->uc, port, data); + return cpu_outl(env->uc, port, data, GETPC()); } target_ulong helper_inl(CPUX86State *env, uint32_t port) @@ -90,7 +90,7 @@ target_ulong helper_inl(CPUX86State *env, uint32_t port) // return address_space_ldl(env->uc, &env->uc->address_space_io, port, // #endif // cpu_get_mem_attrs(env), NULL); - return cpu_inl(env->uc, port); + return cpu_inl(env->uc, port, GETPC()); } void helper_into(CPUX86State *env, int next_eip_addend) @@ -109,7 +109,7 @@ void helper_cpuid(CPUX86State *env) uc_engine *uc = env->uc; struct hook *hook; int skip_cpuid = 0; - + bool synced = false; cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC()); // Unicorn: call registered CPUID hooks @@ -123,6 +123,11 @@ void helper_cpuid(CPUX86State *env) // Multiple cpuid callbacks returning different values is undefined. // true -> skip the cpuid instruction if (hook->insn == UC_X86_INS_CPUID) { + uintptr_t pc = GETPC(); + if (!synced && !uc->skip_sync_pc_on_exit && pc) { + cpu_restore_state(uc->cpu, pc, false); + synced = true; + } JIT_CALLBACK_GUARD_VAR(skip_cpuid, ((uc_cb_insn_cpuid_t)hook->callback)(env->uc, hook->user_data)); }