fix recursive UC_HOOK_MEM callbacks for cross pages access (#1113)

Co-authored-by: bruno <bruno>
Co-authored-by: Nguyen Anh Quynh <aquynh@gmail.com>
This commit is contained in:
BrunoPujos 2020-05-25 10:22:28 +02:00 committed by GitHub
parent ac68fd441d
commit 6cad700b69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 46 deletions

View File

@ -223,6 +223,8 @@ struct uc_struct {
uint64_t block_addr; // save the last block address we hooked
int size_recur_mem; // size for mem access when in a recursive call
bool init_tcg; // already initialized local TCGv variables?
bool stop_request; // request to immediately stop emulation - for uc_emu_stop()
bool quit_request; // request to quit the current TB, but continue to emulate - for uc_mem_protect()

View File

@ -206,7 +206,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data)))
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE - uc->size_recur_mem, 0, hook->user_data)))
break;
}
#else
@ -216,7 +216,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data)))
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE - uc->size_recur_mem, 0, hook->user_data)))
break;
}
#endif
@ -241,7 +241,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0, hook->user_data)))
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE - uc->size_recur_mem, 0, hook->user_data)))
break;
}
@ -263,12 +263,14 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
// See UC_HOOK_MEM_READ_AFTER & UC_MEM_READ_AFTER if you only care
// about successful read
if (READ_ACCESS_TYPE == MMU_DATA_LOAD) {
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data);
if (!uc->size_recur_mem) { // disabling read callback if in recursive call
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data);
}
}
}
@ -280,7 +282,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0, hook->user_data)))
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, DATA_SIZE - uc->size_recur_mem, 0, hook->user_data)))
break;
}
@ -373,8 +375,11 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
addr2 = addr1 + DATA_SIZE;
/* Note the adjustment at the beginning of the function.
Undo that for the recursion. */
uc->size_recur_mem = DATA_SIZE - (addr - addr1); // size already treated by callback
res1 = helper_le_ld_name(env, addr1, mmu_idx, retaddr + GETPC_ADJ);
uc->size_recur_mem = (addr2 - addr);
res2 = helper_le_ld_name(env, addr2, mmu_idx, retaddr + GETPC_ADJ);
uc->size_recur_mem = 0;
shift = (addr & (DATA_SIZE - 1)) * 8;
/* Little-endian combine. */
@ -408,12 +413,14 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
_out:
// Unicorn: callback on successful read
if (READ_ACCESS_TYPE == MMU_DATA_LOAD) {
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, DATA_SIZE, res, hook->user_data);
if (!uc->size_recur_mem) { // disabling read callback if in recursive call
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, DATA_SIZE, res, hook->user_data);
}
}
}
@ -449,7 +456,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data)))
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE - uc->size_recur_mem, 0, hook->user_data)))
break;
}
#else
@ -459,7 +466,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data)))
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE - uc->size_recur_mem, 0, hook->user_data)))
break;
}
#endif
@ -484,7 +491,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0, hook->user_data)))
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE - uc->size_recur_mem, 0, hook->user_data)))
break;
}
@ -506,12 +513,14 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
// See UC_HOOK_MEM_READ_AFTER & UC_MEM_READ_AFTER if you only care
// about successful read
if (READ_ACCESS_TYPE == MMU_DATA_LOAD) {
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data);
if (!uc->size_recur_mem) { // disabling read callback if in recursive call
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data);
}
}
}
@ -523,7 +532,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0, hook->user_data)))
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, DATA_SIZE - uc->size_recur_mem, 0, hook->user_data)))
break;
}
@ -615,8 +624,11 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
addr2 = addr1 + DATA_SIZE;
/* Note the adjustment at the beginning of the function.
Undo that for the recursion. */
uc->size_recur_mem = DATA_SIZE - (addr - addr1); // size already treated by callback
res1 = helper_be_ld_name(env, addr1, mmu_idx, retaddr + GETPC_ADJ);
uc->size_recur_mem = (addr2 - addr);
res2 = helper_be_ld_name(env, addr2, mmu_idx, retaddr + GETPC_ADJ);
uc->size_recur_mem = 0;
shift = (addr & (DATA_SIZE - 1)) * 8;
/* Big-endian combine. */
@ -646,12 +658,14 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
_out:
// Unicorn: callback on successful read
if (READ_ACCESS_TYPE == MMU_DATA_LOAD) {
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, DATA_SIZE, res, hook->user_data);
if (!uc->size_recur_mem) { // disabling read callback if in recursive call
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, DATA_SIZE, res, hook->user_data);
}
}
}
@ -719,13 +733,15 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr);
// Unicorn: callback on memory write
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data);
if (!uc->size_recur_mem) { // disabling write callback if in recursive call
// Unicorn: callback on memory write
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data);
}
}
// Unicorn: callback on invalid memory
@ -840,6 +856,8 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
for (i = DATA_SIZE - 1; i >= 0; i--) {
/* Little-endian extract. */
uint8_t val8 = (uint8_t)(val >> (i * 8));
// size already treated, this is used only for diabling the write cb
uc->size_recur_mem = DATA_SIZE - i ;
/* Note the adjustment at the beginning of the function.
Undo that for the recursion. */
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
@ -847,6 +865,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
if (env->invalid_error != UC_ERR_OK)
break;
}
uc->size_recur_mem = 0;
return;
}
@ -884,13 +903,15 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr);
// Unicorn: callback on memory write
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data);
if (!uc->size_recur_mem) { // disabling write callback if in recursive call
// Unicorn: callback on memory write
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) {
if (hook->to_delete)
continue;
if (!HOOK_BOUND_CHECK(hook, addr))
continue;
((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data);
}
}
// Unicorn: callback on invalid memory
@ -1005,6 +1026,8 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
for (i = DATA_SIZE - 1; i >= 0; i--) {
/* Big-endian extract. */
uint8_t val8 = (uint8_t)(val >> (((DATA_SIZE - 1) * 8) - (i * 8)));
// size already treated, this is used only for diabling the write cb
uc->size_recur_mem = DATA_SIZE - i ;
/* Note the adjustment at the beginning of the function.
Undo that for the recursion. */
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
@ -1012,6 +1035,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
if (env->invalid_error != UC_ERR_OK)
break;
}
uc->size_recur_mem = 0;
return;
}

1
uc.c
View File

@ -559,6 +559,7 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time
uc->invalid_error = UC_ERR_OK;
uc->block_full = false;
uc->emulation_done = false;
uc->size_recur_mem = 0;
uc->timed_out = false;
switch(uc->arch) {