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:
parent
ac68fd441d
commit
6cad700b69
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue