diff --git a/qemu/target/i386/misc_helper.c b/qemu/target/i386/misc_helper.c index 9a6754ce..ccc12c81 100644 --- a/qemu/target/i386/misc_helper.c +++ b/qemu/target/i386/misc_helper.c @@ -217,6 +217,7 @@ void helper_rdtsc(CPUX86State *env) uc_engine *uc = env->uc; struct hook *hook; int skip_rdtsc = 0; + bool synced = false; if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { raise_exception_ra(env, EXCP0D_GPF, GETPC()); @@ -234,6 +235,11 @@ void helper_rdtsc(CPUX86State *env) // Multiple rdtsc callbacks returning different values is undefined. // true -> skip the rdtsc instruction if (hook->insn == UC_X86_INS_RDTSC) { + 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_rdtsc, ((uc_cb_insn_cpuid_t)hook->callback)(env->uc, hook->user_data)); } @@ -255,6 +261,7 @@ void helper_rdtscp(CPUX86State *env) uc_engine *uc = env->uc; struct hook *hook; int skip_rdtscp = 0; + bool synced = false; if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { raise_exception_ra(env, EXCP0D_GPF, GETPC()); @@ -272,6 +279,11 @@ void helper_rdtscp(CPUX86State *env) // Multiple rdtscp callbacks returning different values is undefined. // true -> skip the rdtscp instruction if (hook->insn == UC_X86_INS_RDTSCP) { + 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_rdtscp, ((uc_cb_insn_cpuid_t)hook->callback)(env->uc, hook->user_data)); } diff --git a/qemu/target/i386/seg_helper.c b/qemu/target/i386/seg_helper.c index 82726652..97447fee 100644 --- a/qemu/target/i386/seg_helper.c +++ b/qemu/target/i386/seg_helper.c @@ -974,6 +974,7 @@ void helper_syscall(CPUX86State *env, int next_eip_addend) // Unicorn: call registered syscall hooks struct hook *hook; uc_engine *uc = env->uc; + bool synced = false; HOOK_FOREACH_VAR_DECLARE; HOOK_FOREACH(env->uc, hook, UC_HOOK_INSN) { @@ -982,6 +983,11 @@ void helper_syscall(CPUX86State *env, int next_eip_addend) if (!HOOK_BOUND_CHECK(hook, env->eip)) continue; if (hook->insn == UC_X86_INS_SYSCALL) { + 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(((uc_cb_insn_syscall_t)hook->callback)(env->uc, hook->user_data)); } @@ -2352,6 +2358,7 @@ void helper_sysenter(CPUX86State *env, int next_eip_addend) // Unicorn: call registered SYSENTER hooks struct hook *hook; uc_engine *uc = env->uc; + bool synced = false; HOOK_FOREACH_VAR_DECLARE; HOOK_FOREACH(env->uc, hook, UC_HOOK_INSN) { @@ -2360,6 +2367,11 @@ void helper_sysenter(CPUX86State *env, int next_eip_addend) if (!HOOK_BOUND_CHECK(hook, env->eip)) continue; if (hook->insn == UC_X86_INS_SYSENTER) { + 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(((uc_cb_insn_syscall_t)hook->callback)(env->uc, hook->user_data)); }