Fix wrong sync after UC_ERR_[READ, WRITE, FETCH]_[UNMAPPED, PROT] (#1368)

* Fix wrong sync after UC_ERR_[READ, WRITE, FETCH]_[UNMAPPED, PROT]

Note that:
1. We only guarantee the pc (and other internal states) is correct
if and only of `uc_emu_start` returns without any error (or errors
have been handled in callbacks.).
2. If memory read/write error isn't handled by hooks, the state is
undefined and the pc is probably wrong if no hook is installed.

This fixes #1323.

* Rename variables

* Add note in unicorn.h

* Refine test_i386_invalid_mem_read_in_tb
This commit is contained in:
lazymio
2021-05-12 00:10:45 +08:00
committed by GitHub
parent 58c50c4be7
commit 225d387325
3 changed files with 96 additions and 12 deletions

View File

@ -327,17 +327,31 @@ static tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
* or timer mode is in effect, since these already fix the PC.
*/
if (!HOOK_EXISTS(env->uc, UC_HOOK_CODE) && !env->uc->timeout) {
if (cc->synchronize_from_tb) {
// avoid sync twice when helper_uc_tracecode() already did this.
if (env->uc->emu_counter <= env->uc->emu_count &&
!env->uc->stop_request && !env->uc->quit_request)
cc->synchronize_from_tb(cpu, tb);
} else {
assert(cc->set_pc);
// avoid sync twice when helper_uc_tracecode() already did this.
if (env->uc->emu_counter <= env->uc->emu_count &&
!env->uc->stop_request && !env->uc->quit_request)
cc->set_pc(cpu, tb->pc);
// We should sync pc for R/W error.
switch (env->invalid_error) {
case UC_ERR_WRITE_PROT:
case UC_ERR_READ_PROT:
case UC_ERR_FETCH_PROT:
case UC_ERR_WRITE_UNMAPPED:
case UC_ERR_READ_UNMAPPED:
case UC_ERR_FETCH_UNMAPPED:
case UC_ERR_WRITE_UNALIGNED:
case UC_ERR_READ_UNALIGNED:
case UC_ERR_FETCH_UNALIGNED:
break;
default:
if (cc->synchronize_from_tb) {
// avoid sync twice when helper_uc_tracecode() already did this.
if (env->uc->emu_counter <= env->uc->emu_count &&
!env->uc->stop_request && !env->uc->quit_request)
cc->synchronize_from_tb(cpu, tb);
} else {
assert(cc->set_pc);
// avoid sync twice when helper_uc_tracecode() already did this.
if (env->uc->emu_counter <= env->uc->emu_count &&
!env->uc->stop_request && !env->uc->quit_request)
cc->set_pc(cpu, tb->pc);
}
}
}
}