diff --git a/.gitignore b/.gitignore index 50b09750..c82b9fb1 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,4 @@ config.log regress/map_crash regress/sigill regress/sigill2 +regress/block_test diff --git a/include/uc_priv.h b/include/uc_priv.h index 1494cc65..2703627c 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -163,6 +163,8 @@ struct uc_struct { uint64_t addr_end; // address where emulation stops (@end param of uc_emu_start()) int thumb; // thumb mode for ARM + // full TCG cache leads to middle-block break in the last translation? + bool block_full; }; #include "qemu_macro.h" diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 161e7613..a3293920 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -121,7 +121,7 @@ typedef enum uc_err { // Callback function for tracing code (UC_HOOK_CODE & UC_HOOK_BLOCK) // @address: address where the code is being executed -// @size: size of machine instruction being executed +// @size: size of machine instruction(s) being executed, or 0 when size is unknown // @user_data: user data passed to tracing APIs. typedef void (*uc_cb_hookcode_t)(uch handle, uint64_t address, uint32_t size, void *user_data); diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index 15b941c4..7ce37ef8 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -8256,6 +8256,7 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, target_ulong cs_base; int num_insns; int max_insns; + bool block_full = false; /* generate intermediate code */ pc_start = tb->pc; @@ -8349,7 +8350,9 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, max_insns = CF_COUNT_MASK; // Unicorn: trace this block on request - if (env->uc->hook_block) { + // Only hook this block if it is not broken from previous translation due to + // full translation cache + if (env->uc->hook_block && !env->uc->block_full) { struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_BLOCK, pc_start); if (trace) { env->uc->block_addr = pc_start; @@ -8407,6 +8410,7 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, num_insns >= max_insns) { gen_jmp_im(dc, pc_ptr - dc->cs_base); gen_eob(dc); + block_full = true; break; } } @@ -8427,6 +8431,8 @@ done_generating: tb->size = pc_ptr - pc_start; // tb->icount = num_insns; } + + env->uc->block_full = block_full; } void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) diff --git a/qemu/translate-all.c b/qemu/translate-all.c index 9723f23f..aaebee42 100644 --- a/qemu/translate-all.c +++ b/qemu/translate-all.c @@ -179,8 +179,10 @@ static int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_s gen_intermediate_code(env, tb); // Unicorn: when tracing block, patch 1st operand for block size - if (env->uc->hook_block) { - if (env->uc->block_addr == tb->pc) + if (env->uc->hook_block && env->uc->block_addr == tb->pc) { + if (env->uc->block_full) // block size is unknown + *(s->gen_opparam_buf + 1) = 0; + else *(s->gen_opparam_buf + 1) = tb->size; } diff --git a/regress/block_test.c b/regress/block_test.c index ce5180c9..9d74d199 100755 --- a/regress/block_test.c +++ b/regress/block_test.c @@ -6,7 +6,7 @@ #include -static count = 1; +static int count = 1; // Callback function for tracing code (UC_HOOK_CODE & UC_HOOK_BLOCK) // @address: address where the code is being executed @@ -79,4 +79,6 @@ int main() { fprintf(stderr, "ok %d - uc_emu_start\n", count++); fprintf(stderr, "ok %d - Done", count++); + + return 0; } diff --git a/uc.c b/uc.c index 2011c693..65179095 100644 --- a/uc.c +++ b/uc.c @@ -414,6 +414,7 @@ uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout uc->emu_counter = 0; uc->stop_request = false; uc->invalid_error = UC_ERR_OK; + uc->block_full = false; switch(uc->arch) { default: