diff --git a/include/uc_priv.h b/include/uc_priv.h index 1a894815..ef8be62c 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -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() diff --git a/qemu/softmmu_template.h b/qemu/softmmu_template.h index f39509bd..3e8fa9f6 100644 --- a/qemu/softmmu_template.h +++ b/qemu/softmmu_template.h @@ -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; } diff --git a/uc.c b/uc.c index e9e0bd4d..038c7803 100644 --- a/uc.c +++ b/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->block_full = false; uc->emulation_done = false; + uc->size_recur_mem = 0; uc->timed_out = false; switch(uc->arch) {