rework code/block tracing

This commit is contained in:
Ryan Hileman 2016-01-22 18:28:17 -08:00
parent 33180b5afa
commit 2ac1281f82
15 changed files with 66 additions and 121 deletions

2
list.c
View file

@ -18,6 +18,8 @@ void list_clear(struct list *list)
free(cur);
cur = next;
}
list->head = NULL;
list->tail = NULL;
}
// returns generated linked list node, or NULL on failure

View file

@ -1,4 +1,4 @@
DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr)
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_FLAGS_1(clz_arm, TCG_CALL_NO_RWG_SE, i32, i32)

View file

@ -10970,7 +10970,6 @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
{
uint32_t insn;
struct hook *hook;
TCGContext *tcg_ctx = env->uc->tcg_ctx;
// Unicorn: end address tells us to stop emulation
@ -10985,10 +10984,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
s->pc += 4;
// Unicorn: trace this instruction on request
HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
if (! HOOK_BOUND_CHECK(hook, s->pc - 4))
continue;
gen_uc_tracecode(tcg_ctx, 4, hook->callback, env->uc, s->pc - 4, hook->user_data);
if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, s->pc - 4)) {
gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, env->uc, s->pc - 4);
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
}
@ -11044,7 +11041,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
int max_insns;
TCGContext *tcg_ctx = env->uc->tcg_ctx;
bool block_full = false;
struct hook *hook;
pc_start = tb->pc;
@ -11116,14 +11112,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
// Unicorn: trace this block on request
// Only hook this block if it is not broken from previous translation due to
// full translation cache
if (! env->uc->block_full) {
HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
if (! HOOK_BOUND_CHECK(hook, pc_start))
continue;
if (! env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
// save block address to see if we need to patch block size later
env->uc->block_addr = pc_start;
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
}
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
}
gen_tb_start(tcg_ctx);

View file

@ -7680,7 +7680,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
TCGv_i32 tmp3;
TCGv_i32 addr;
TCGv_i64 tmp64;
struct hook *hook;
/* M variants do not implement ARM mode. */
if (arm_dc_feature(s, ARM_FEATURE_M)) {
@ -7688,10 +7687,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
}
// Unicorn: trace this instruction on request
HOOK_FOREACH(s->uc, hook, UC_HOOK_CODE) {
if (! HOOK_BOUND_CHECK(hook, s->pc - 4))
continue;
gen_uc_tracecode(tcg_ctx, 4, hook->callback, s->uc, s->pc - 4, hook->user_data);
if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_CODE, s->pc - 4)) {
gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, s->uc, s->pc - 4);
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
}
@ -10391,7 +10388,6 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
TCGv_i32 tmp;
TCGv_i32 tmp2;
TCGv_i32 addr;
struct hook *hook;
// Unicorn: end address tells us to stop emulation
if (s->pc == s->uc->addr_end) {
@ -10410,11 +10406,9 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
}
// Unicorn: trace this instruction on request
HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
if (! HOOK_BOUND_CHECK(hook, s->pc))
continue;
gen_uc_tracecode(tcg_ctx, 2, hook->callback, env->uc, s->pc, hook->user_data);
// check to see if we need to exit immediately
if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_CODE, s->pc)) {
gen_uc_tracecode(tcg_ctx, 2, UC_HOOK_CODE_IDX, s->uc, s->pc);
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
}
@ -11147,7 +11141,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
int max_insns;
TCGContext *tcg_ctx = env->uc->tcg_ctx;
bool block_full = false;
struct hook *hook;
/* generate intermediate code */
@ -11237,14 +11230,10 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
// Unicorn: trace this block on request
// Only hook this block if it is not broken from previous translation due to
// full translation cache
if (!env->uc->block_full) {
HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
if (! HOOK_BOUND_CHECK(hook, pc_start))
continue;
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
// save block address to see if we need to patch block size later
env->uc->block_addr = pc_start;
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
}
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
}
gen_tb_start(tcg_ctx);

View file

@ -1,4 +1,4 @@
DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr)
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_FLAGS_4(cc_compute_all, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int)
DEF_HELPER_FLAGS_4(cc_compute_c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int)

View file

@ -4745,7 +4745,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
TCGv cpu_tmp4 = *(TCGv *)tcg_ctx->cpu_tmp4;
TCGv **cpu_T = (TCGv **)tcg_ctx->cpu_T;
TCGv **cpu_regs = (TCGv **)tcg_ctx->cpu_regs;
struct hook *hook = NULL;
TCGArg *save_opparam_ptr = tcg_ctx->gen_opparam_ptr;
bool cc_op_dirty = s->cc_op_dirty;
bool changed_cc_op = false;
@ -4773,15 +4772,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
s->last_cc_op = s->cc_op;
changed_cc_op = true;
}
HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
if (! HOOK_BOUND_CHECK(hook, pc_start))
continue;
// generate code to call callback
gen_uc_tracecode(tcg_ctx, 0xf1f1f1f1, hook->callback, env->uc, pc_start, hook->user_data);
gen_uc_tracecode(tcg_ctx, 0xf1f1f1f1, UC_HOOK_CODE_IDX, env->uc, pc_start);
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
}
}
prefixes = 0;
s->override = -1;
@ -8173,7 +8167,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_helper_unlock(tcg_ctx, cpu_env);
// Unicorn: patch the callback for the instruction size
if (hook) {
if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, pc_start)) {
// int i;
// for(i = 0; i < 20; i++)
// printf("=== [%u] = %x\n", i, *(save_opparam_ptr + i));
@ -8282,7 +8276,6 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op,
int num_insns = 0;
int max_insns;
bool block_full = false;
struct hook *hook;
/* generate intermediate code */
pc_start = tb->pc;
@ -8388,13 +8381,9 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op,
// Unicorn: trace this block on request
// Only hook this block if it is not broken from previous translation due to
// full translation cache
if (!env->uc->block_full) {
HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
if (! HOOK_BOUND_CHECK(hook, pc_start))
continue;
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
env->uc->block_addr = pc_start;
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
}
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
}
gen_tb_start(tcg_ctx);

View file

@ -1,4 +1,4 @@
DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr)
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_1(bitrev, i32, i32)
DEF_HELPER_1(ff1, i32, i32)

View file

@ -3031,7 +3031,6 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
uint16_t insn;
struct hook *hook;
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
tcg_gen_debug_insn_start(tcg_ctx, s->pc);
@ -3044,10 +3043,8 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
}
// Unicorn: trace this instruction on request
HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
if (! HOOK_BOUND_CHECK(hook, s->pc))
continue;
gen_uc_tracecode(tcg_ctx, 2, hook->callback, env->uc, s->pc, hook->user_data);
if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, s->pc)) {
gen_uc_tracecode(tcg_ctx, 2, UC_HOOK_CODE_IDX, env->uc, s->pc);
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
}
@ -3075,7 +3072,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
int max_insns;
TCGContext *tcg_ctx = env->uc->tcg_ctx;
bool block_full = false;
struct hook *hook;
/* generate intermediate code */
pc_start = tb->pc;
@ -3110,14 +3106,10 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
// Unicorn: trace this block on request
// Only hook this block if it is not broken from previous translation due to
// full translation cache
if (!env->uc->block_full) {
HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
if (! HOOK_BOUND_CHECK(hook, pc_start))
continue;
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
// save block address to see if we need to patch block size later
env->uc->block_addr = pc_start;
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
}
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
}
gen_tb_start(tcg_ctx);

View file

@ -1,4 +1,4 @@
DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr)
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int)
DEF_HELPER_2(raise_exception, noreturn, env, i32)

View file

@ -11331,7 +11331,6 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool *insn_n
int op, cnvt_op, op1, offset;
int funct;
int n_bytes;
struct hook *hook;
op = (ctx->opcode >> 11) & 0x1f;
sa = (ctx->opcode >> 2) & 0x7;
@ -11344,10 +11343,8 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool *insn_n
n_bytes = 2;
// Unicorn: trace this instruction on request
HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
if (! HOOK_BOUND_CHECK(hook, ctx->pc))
continue;
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data);
if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) {
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc);
*insn_need_patch = true;
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
@ -13932,7 +13929,6 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins
TCGContext *tcg_ctx = env->uc->tcg_ctx;
TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr;
uint32_t op;
struct hook *hook;
/* make sure instructions are on a halfword boundary */
if (ctx->pc & 0x1) {
@ -13943,10 +13939,8 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins
}
// Unicorn: trace this instruction on request
HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
if (! HOOK_BOUND_CHECK(hook, ctx->pc))
continue;
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data);
if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) {
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc);
*insn_need_patch = true;
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
@ -18505,11 +18499,8 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
static void hook_insn(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_patch, int *insn_patch_offset, int offset_value)
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
struct hook *hook;
HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
if (! HOOK_BOUND_CHECK(hook, ctx->pc))
continue;
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data);
if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) {
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc);
*insn_need_patch = true;
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
@ -19178,7 +19169,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
TCGContext *tcg_ctx = env->uc->tcg_ctx;
TCGArg *save_opparam_ptr = NULL;
bool block_full = false;
struct hook *hook;
if (search_pc)
qemu_log("search pc %d\n", search_pc);
@ -19224,14 +19214,10 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
// Unicorn: trace this block on request
// Only hook this block if it is not broken from previous translation due to
// full translation cache
if (! env->uc->block_full) {
HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
if (! HOOK_BOUND_CHECK(hook, pc_start))
continue;
if (! env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
// save block address to see if we need to patch block size later
env->uc->block_addr = pc_start;
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
}
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
}
gen_tb_start(tcg_ctx);

View file

@ -1,4 +1,4 @@
DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr)
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_1(power_down, void, env)
#ifndef TARGET_SPARC64

View file

@ -2625,7 +2625,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins
TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
target_long simm;
struct hook *hook;
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
tcg_gen_debug_insn_start(tcg_ctx, dc->pc);
@ -2638,15 +2637,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins
}
// Unicorn: trace this instruction on request
if (hook_insn) {
HOOK_FOREACH(dc->uc, hook, UC_HOOK_CODE) {
if (! HOOK_BOUND_CHECK(hook, dc->pc))
continue;
gen_uc_tracecode(tcg_ctx, 4, hook->callback, dc->uc, dc->pc, hook->user_data);
if (hook_insn && HOOK_EXISTS_BOUNDED(dc->uc, UC_HOOK_CODE, dc->pc)) {
gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, dc->uc, dc->pc);
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
}
}
opc = GET_FIELD(insn, 0, 1);
rd = GET_FIELD(insn, 2, 6);
@ -5390,7 +5385,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
unsigned int insn;
TCGContext *tcg_ctx = env->uc->tcg_ctx;
bool block_full = false;
struct hook *hook;
memset(dc, 0, sizeof(DisasContext));
dc->uc = env->uc;
@ -5431,14 +5425,10 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
// Unicorn: trace this block on request
// Only hook this block if it is not broken from previous translation due to
// full translation cache
if (!env->uc->block_full) {
HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
if (! HOOK_BOUND_CHECK(hook, pc_start))
continue;
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
// save block address to see if we need to patch block size later
env->uc->block_addr = pc_start;
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
}
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
}
gen_tb_start(tcg_ctx);

View file

@ -27,14 +27,13 @@
int gen_new_label(TCGContext *);
static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, void *callback, void *uc, uint64_t pc, void *data)
static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, int32_t type, void *uc, uint64_t pc)
{
TCGv_i32 tsize = tcg_const_i32(tcg_ctx, size);
TCGv_ptr tcallback = tcg_const_ptr(tcg_ctx, callback);
TCGv_i32 ttype = tcg_const_i32(tcg_ctx, type);
TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, uc);
TCGv_i64 tpc = tcg_const_i64(tcg_ctx, pc);
TCGv_ptr tdata = tcg_const_ptr(tcg_ctx, data);
gen_helper_uc_tracecode(tcg_ctx, tsize, tcallback, tuc, tpc, tdata);
gen_helper_uc_tracecode(tcg_ctx, tsize, ttype, tuc, tpc);
}
static inline void tcg_gen_op0(TCGContext *s, TCGOpcode opc)

View file

@ -179,7 +179,7 @@ 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 (HOOK_EXISTS(env->uc, UC_HOOK_BLOCK) && env->uc->block_addr == tb->pc) {
if (env->uc->block_addr == tb->pc && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, tb->pc)) {
if (env->uc->block_full) // block size is unknown
*(s->gen_opparam_buf + 1) = 0;
else

12
uc.c
View file

@ -1009,17 +1009,23 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh)
}
// TCG helper
void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data);
void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data)
void helper_uc_tracecode(int32_t size, uc_hook_type type, void *handle, int64_t address);
void helper_uc_tracecode(int32_t size, uc_hook_type type, void *handle, int64_t address)
{
struct uc_struct *uc = handle;
struct list_item *cur = uc->hook[type].head;
struct hook *hook;
// sync PC in CPUArchState with address
if (uc->set_pc) {
uc->set_pc(uc, address);
}
((uc_cb_hookcode_t)callback)(uc, address, size, user_data);
while (cur != NULL && !uc->stop_request) {
hook = (struct hook *)cur->data;
((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data);
cur = cur->next;
}
}
UNICORN_EXPORT