Ensure that PC is not fixed up when code tracing or timing. (#1179)

Under some circumstances, the PC is not fixed up properly when
returning from the execution of a block in cpu_tb_exec. This appears
to be caused by the resetting of the PC from the tb.

This change removes the additional fixup in the cases where there
is code tracing or timing active. Either of these cases would result
in the wrong PC being reported.

Closes unicorn-engine#1105.

Backports commit b59632fb645d456338472e3d757c065c0ed74ad5 from unicorn
This commit is contained in:
Charles Ferguson 2020-01-14 09:49:41 -05:00 committed by Lioncash
parent 8259d76c6c
commit 784d580f01

View file

@ -54,33 +54,34 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
* of the start of the TB. * of the start of the TB.
*/ */
CPUClass *cc = CPU_GET_CLASS(env->uc, cpu); CPUClass *cc = CPU_GET_CLASS(env->uc, cpu);
// Unicorn: commented out
//qemu_log_mask_and_addr(CPU_LOG_EXEC, last_tb->pc, /*
// "Stopped execution of TB chain before %p [" * Both set_pc() & synchronize_fromtb() can be ignored when code tracing hook is installed,
// TARGET_FMT_lx "] %s\n", * or timer mode is in effect, since these already fix the PC.
// last_tb->tc.ptr, last_tb->pc, */
// lookup_symbol(last_tb->pc)); if (!HOOK_EXISTS(env->uc, UC_HOOK_CODE) && !env->uc->timeout) {
if (cc->synchronize_from_tb) { if (cc->synchronize_from_tb) {
// avoid sync twice when helper_uc_tracecode() already did this. // avoid sync twice when helper_uc_tracecode() already did this.
if (env->uc->emu_counter <= env->uc->emu_count && if (env->uc->emu_counter <= env->uc->emu_count &&
!env->uc->stop_request && !env->uc->quit_request) { !env->uc->stop_request && !env->uc->quit_request)
cc->synchronize_from_tb(cpu, last_tb); cc->synchronize_from_tb(cpu, last_tb);
} } else {
} else { assert(cc->set_pc);
assert(cc->set_pc); // avoid sync twice when helper_uc_tracecode() already did this.
// avoid sync twice when helper_uc_tracecode() already did this. if (env->uc->emu_counter <= env->uc->emu_count &&
if (env->uc->emu_counter <= env->uc->emu_count && !env->uc->stop_request && !env->uc->quit_request)
!env->uc->stop_request && !env->uc->quit_request) { cc->set_pc(cpu, last_tb->pc);
cc->set_pc(cpu, last_tb->pc);
} }
} }
} }
if (tb_exit == TB_EXIT_REQUESTED) { if (tb_exit == TB_EXIT_REQUESTED) {
/* We were asked to stop executing TBs (probably a pending /* We were asked to stop executing TBs (probably a pending
* interrupt. We've now stopped, so clear the flag. * interrupt. We've now stopped, so clear the flag.
*/ */
atomic_set(&cpu->tcg_exit_req, 0); atomic_set(&cpu->tcg_exit_req, 0);
} }
return ret; return ret;
} }