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
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 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 init_tcg; // already initialized local TCGv variables?
bool stop_request; // request to immediately stop emulation - for uc_emu_stop() 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() 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; continue;
if (!HOOK_BOUND_CHECK(hook, addr)) if (!HOOK_BOUND_CHECK(hook, addr))
continue; 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; break;
} }
#else #else
@ -216,7 +216,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue; continue;
if (!HOOK_BOUND_CHECK(hook, addr)) if (!HOOK_BOUND_CHECK(hook, addr))
continue; 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; break;
} }
#endif #endif
@ -241,7 +241,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue; continue;
if (!HOOK_BOUND_CHECK(hook, addr)) if (!HOOK_BOUND_CHECK(hook, addr))
continue; 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; break;
} }
@ -263,6 +263,7 @@ 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 // See UC_HOOK_MEM_READ_AFTER & UC_MEM_READ_AFTER if you only care
// about successful read // about successful read
if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { if (READ_ACCESS_TYPE == MMU_DATA_LOAD) {
if (!uc->size_recur_mem) { // disabling read callback if in recursive call
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) {
if (hook->to_delete) if (hook->to_delete)
continue; continue;
@ -271,6 +272,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data); ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data);
} }
} }
}
// Unicorn: callback on non-readable memory // Unicorn: callback on non-readable memory
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
@ -280,7 +282,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue; continue;
if (!HOOK_BOUND_CHECK(hook, addr)) if (!HOOK_BOUND_CHECK(hook, addr))
continue; 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; break;
} }
@ -373,8 +375,11 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
addr2 = addr1 + DATA_SIZE; addr2 = addr1 + DATA_SIZE;
/* Note the adjustment at the beginning of the function. /* Note the adjustment at the beginning of the function.
Undo that for the recursion. */ 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); 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); res2 = helper_le_ld_name(env, addr2, mmu_idx, retaddr + GETPC_ADJ);
uc->size_recur_mem = 0;
shift = (addr & (DATA_SIZE - 1)) * 8; shift = (addr & (DATA_SIZE - 1)) * 8;
/* Little-endian combine. */ /* Little-endian combine. */
@ -408,6 +413,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
_out: _out:
// Unicorn: callback on successful read // Unicorn: callback on successful read
if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { if (READ_ACCESS_TYPE == MMU_DATA_LOAD) {
if (!uc->size_recur_mem) { // disabling read callback if in recursive call
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) { HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) {
if (hook->to_delete) if (hook->to_delete)
continue; continue;
@ -416,6 +422,7 @@ _out:
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, DATA_SIZE, res, hook->user_data); ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, DATA_SIZE, res, hook->user_data);
} }
} }
}
return res; return res;
} }
@ -449,7 +456,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue; continue;
if (!HOOK_BOUND_CHECK(hook, addr)) if (!HOOK_BOUND_CHECK(hook, addr))
continue; 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; break;
} }
#else #else
@ -459,7 +466,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue; continue;
if (!HOOK_BOUND_CHECK(hook, addr)) if (!HOOK_BOUND_CHECK(hook, addr))
continue; 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; break;
} }
#endif #endif
@ -484,7 +491,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue; continue;
if (!HOOK_BOUND_CHECK(hook, addr)) if (!HOOK_BOUND_CHECK(hook, addr))
continue; 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; break;
} }
@ -506,6 +513,7 @@ 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 // See UC_HOOK_MEM_READ_AFTER & UC_MEM_READ_AFTER if you only care
// about successful read // about successful read
if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { if (READ_ACCESS_TYPE == MMU_DATA_LOAD) {
if (!uc->size_recur_mem) { // disabling read callback if in recursive call
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) {
if (hook->to_delete) if (hook->to_delete)
continue; continue;
@ -514,6 +522,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data); ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data);
} }
} }
}
// Unicorn: callback on non-readable memory // Unicorn: callback on non-readable memory
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
@ -523,7 +532,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
continue; continue;
if (!HOOK_BOUND_CHECK(hook, addr)) if (!HOOK_BOUND_CHECK(hook, addr))
continue; 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; break;
} }
@ -615,8 +624,11 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
addr2 = addr1 + DATA_SIZE; addr2 = addr1 + DATA_SIZE;
/* Note the adjustment at the beginning of the function. /* Note the adjustment at the beginning of the function.
Undo that for the recursion. */ 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); 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); res2 = helper_be_ld_name(env, addr2, mmu_idx, retaddr + GETPC_ADJ);
uc->size_recur_mem = 0;
shift = (addr & (DATA_SIZE - 1)) * 8; shift = (addr & (DATA_SIZE - 1)) * 8;
/* Big-endian combine. */ /* Big-endian combine. */
@ -646,6 +658,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
_out: _out:
// Unicorn: callback on successful read // Unicorn: callback on successful read
if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { if (READ_ACCESS_TYPE == MMU_DATA_LOAD) {
if (!uc->size_recur_mem) { // disabling read callback if in recursive call
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) { HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) {
if (hook->to_delete) if (hook->to_delete)
continue; continue;
@ -654,6 +667,7 @@ _out:
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, DATA_SIZE, res, hook->user_data); ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, DATA_SIZE, res, hook->user_data);
} }
} }
}
return res; return res;
} }
@ -719,6 +733,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
struct uc_struct *uc = env->uc; struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr); MemoryRegion *mr = memory_mapping(uc, addr);
if (!uc->size_recur_mem) { // disabling write callback if in recursive call
// Unicorn: callback on memory write // Unicorn: callback on memory write
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) { HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) {
if (hook->to_delete) if (hook->to_delete)
@ -727,6 +742,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
continue; continue;
((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data); ((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data);
} }
}
// Unicorn: callback on invalid memory // Unicorn: callback on invalid memory
if (mr == NULL) { if (mr == NULL) {
@ -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--) { for (i = DATA_SIZE - 1; i >= 0; i--) {
/* Little-endian extract. */ /* Little-endian extract. */
uint8_t val8 = (uint8_t)(val >> (i * 8)); 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. /* Note the adjustment at the beginning of the function.
Undo that for the recursion. */ Undo that for the recursion. */
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8, 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) if (env->invalid_error != UC_ERR_OK)
break; break;
} }
uc->size_recur_mem = 0;
return; return;
} }
@ -884,6 +903,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
struct uc_struct *uc = env->uc; struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr); MemoryRegion *mr = memory_mapping(uc, addr);
if (!uc->size_recur_mem) { // disabling write callback if in recursive call
// Unicorn: callback on memory write // Unicorn: callback on memory write
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) { HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) {
if (hook->to_delete) if (hook->to_delete)
@ -892,6 +912,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
continue; continue;
((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data); ((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data);
} }
}
// Unicorn: callback on invalid memory // Unicorn: callback on invalid memory
if (mr == NULL) { if (mr == NULL) {
@ -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--) { for (i = DATA_SIZE - 1; i >= 0; i--) {
/* Big-endian extract. */ /* Big-endian extract. */
uint8_t val8 = (uint8_t)(val >> (((DATA_SIZE - 1) * 8) - (i * 8))); 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. /* Note the adjustment at the beginning of the function.
Undo that for the recursion. */ Undo that for the recursion. */
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8, 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) if (env->invalid_error != UC_ERR_OK)
break; break;
} }
uc->size_recur_mem = 0;
return; 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->invalid_error = UC_ERR_OK;
uc->block_full = false; uc->block_full = false;
uc->emulation_done = false; uc->emulation_done = false;
uc->size_recur_mem = 0;
uc->timed_out = false; uc->timed_out = false;
switch(uc->arch) { switch(uc->arch) {