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:
@ -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()
|
||||||
|
@ -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
1
uc.c
@ -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) {
|
||||||
|
Reference in New Issue
Block a user