Provides an instrumentation point for instruction fetch/decode events. Signed-off-by: Lluís Vilanova <vilan...@ac.upc.edu> --- target-i386/translate.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 113 insertions(+), 0 deletions(-)
diff --git a/target-i386/translate.c b/target-i386/translate.c index b54a823..02a93a4 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -32,6 +32,32 @@ #define GEN_HELPER 1 #include "helper.h" +#if defined(CONFIG_INSTRUMENT) +static inline void +mem_exchange (void * tmp, void * start1, size_t size1, + void * start2, size_t size2) +{ + memcpy(tmp , start2, size2); + memcpy(tmp+size2, start1, size1); + memcpy(start1 , tmp , size1+size2); +} +#endif + + +/* tracking of register usage */ +#if defined(CONFIG_INSTRUMENT) +struct DisasContext; +/* Have current context always accessible */ +struct DisasContext * instr_disas = NULL; +#endif + +#define INSTR_REGS_SET_GP(s, r) INSTR_REGS_SET(instr_disas->instr_regs_ ##s, r) +/* TODO: access to env->regs in helper functions */ +/* TODO: not tracking register sets for: eflags, segments, floating point, + * crX, ... + */ + + #define PREFIX_REPZ 0x01 #define PREFIX_REPNZ 0x02 #define PREFIX_LOCK 0x04 @@ -116,6 +142,11 @@ typedef struct DisasContext { int cpuid_ext_features; int cpuid_ext2_features; int cpuid_ext3_features; +#if defined(CONFIG_INSTRUMENT) + /* temporal vars for FETCH instrumentation */ + instr_regs_t instr_regs_used; + instr_regs_t instr_regs_defined; +#endif } DisasContext; static void gen_eob(DisasContext *s); @@ -281,9 +312,13 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0) tmp = tcg_temp_new(); tcg_gen_ext8u_tl(tmp, t0); if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) { + INSTR_REGS_SET_GP(used, reg); + INSTR_REGS_SET_GP(defined, reg); tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xff); tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp); } else { + INSTR_REGS_SET_GP(used, reg - 4); + INSTR_REGS_SET_GP(defined, reg - 4); tcg_gen_shli_tl(tmp, tmp, 8); tcg_gen_andi_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], ~0xff00); tcg_gen_or_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], tmp); @@ -293,6 +328,8 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0) case OT_WORD: tmp = tcg_temp_new(); tcg_gen_ext16u_tl(tmp, t0); + INSTR_REGS_SET_GP(used, reg); + INSTR_REGS_SET_GP(defined, reg); tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff); tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp); tcg_temp_free(tmp); @@ -301,10 +338,12 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0) case OT_LONG: /* For x86_64, this sets the higher half of register to zero. For i386, this is equivalent to a mov. */ + INSTR_REGS_SET_GP(defined, reg); tcg_gen_ext32u_tl(cpu_regs[reg], t0); break; #ifdef TARGET_X86_64 case OT_QUAD: + INSTR_REGS_SET_GP(defined, reg); tcg_gen_mov_tl(cpu_regs[reg], t0); break; #endif @@ -329,6 +368,8 @@ static inline void gen_op_mov_reg_A0(int size, int reg) case 0: tmp = tcg_temp_new(); tcg_gen_ext16u_tl(tmp, cpu_A0); + INSTR_REGS_SET_GP(used, reg); + INSTR_REGS_SET_GP(defined, reg); tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff); tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp); tcg_temp_free(tmp); @@ -337,10 +378,12 @@ static inline void gen_op_mov_reg_A0(int size, int reg) case 1: /* For x86_64, this sets the higher half of register to zero. For i386, this is equivalent to a mov. */ + INSTR_REGS_SET_GP(defined, reg); tcg_gen_ext32u_tl(cpu_regs[reg], cpu_A0); break; #ifdef TARGET_X86_64 case 2: + INSTR_REGS_SET_GP(defined, reg); tcg_gen_mov_tl(cpu_regs[reg], cpu_A0); break; #endif @@ -354,12 +397,14 @@ static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg) if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) { goto std_case; } else { + INSTR_REGS_SET_GP(used, reg - 4); tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8); tcg_gen_ext8u_tl(t0, t0); } break; default: std_case: + INSTR_REGS_SET_GP(used, reg); tcg_gen_mov_tl(t0, cpu_regs[reg]); break; } @@ -372,6 +417,7 @@ static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg) static inline void gen_op_movl_A0_reg(int reg) { + INSTR_REGS_SET_GP(used, reg); tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]); } @@ -414,12 +460,16 @@ static inline void gen_op_add_reg_im(int size, int reg, int32_t val) { switch(size) { case 0: + INSTR_REGS_SET_GP(used, reg); + INSTR_REGS_SET_GP(defined, reg); tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val); tcg_gen_ext16u_tl(cpu_tmp0, cpu_tmp0); tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff); tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0); break; case 1: + INSTR_REGS_SET_GP(used, reg); + INSTR_REGS_SET_GP(defined, reg); tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val); /* For x86_64, this sets the higher half of register to zero. For i386, this is equivalent to a nop. */ @@ -428,6 +478,8 @@ static inline void gen_op_add_reg_im(int size, int reg, int32_t val) break; #ifdef TARGET_X86_64 case 2: + INSTR_REGS_SET_GP(used, reg); + INSTR_REGS_SET_GP(defined, reg); tcg_gen_addi_tl(cpu_regs[reg], cpu_regs[reg], val); break; #endif @@ -438,12 +490,16 @@ static inline void gen_op_add_reg_T0(int size, int reg) { switch(size) { case 0: + INSTR_REGS_SET_GP(used, reg); + INSTR_REGS_SET_GP(defined, reg); tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]); tcg_gen_ext16u_tl(cpu_tmp0, cpu_tmp0); tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff); tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0); break; case 1: + INSTR_REGS_SET_GP(used, reg); + INSTR_REGS_SET_GP(defined, reg); tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]); /* For x86_64, this sets the higher half of register to zero. For i386, this is equivalent to a nop. */ @@ -452,6 +508,8 @@ static inline void gen_op_add_reg_T0(int size, int reg) break; #ifdef TARGET_X86_64 case 2: + INSTR_REGS_SET_GP(used, reg); + INSTR_REGS_SET_GP(defined, reg); tcg_gen_add_tl(cpu_regs[reg], cpu_regs[reg], cpu_T[0]); break; #endif @@ -465,6 +523,7 @@ static inline void gen_op_set_cc_op(int32_t val) static inline void gen_op_addl_A0_reg_sN(int shift, int reg) { + INSTR_REGS_SET_GP(used, reg); tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]); if (shift != 0) tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift); @@ -502,11 +561,13 @@ static inline void gen_op_addq_A0_seg(int reg) static inline void gen_op_movq_A0_reg(int reg) { + INSTR_REGS_SET_GP(used, reg); tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]); } static inline void gen_op_addq_A0_reg_sN(int shift, int reg) { + INSTR_REGS_SET_GP(used, reg); tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]); if (shift != 0) tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift); @@ -707,6 +768,7 @@ static void gen_exts(int ot, TCGv reg) static inline void gen_op_jnz_ecx(int size, int label1) { + INSTR_REGS_SET_GP(used, R_ECX); tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]); gen_extu(size + 1, cpu_tmp0); tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1); @@ -714,6 +776,7 @@ static inline void gen_op_jnz_ecx(int size, int label1) static inline void gen_op_jz_ecx(int size, int label1) { + INSTR_REGS_SET_GP(used, R_ECX); tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]); gen_extu(size + 1, cpu_tmp0); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1); @@ -4090,6 +4153,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) target_ulong next_eip, tval; int rex_w, rex_r; +#if defined(CONFIG_INSTRUMENT) + uint16_t * instr_gen_opc_ptr = gen_opc_ptr; + TCGArg * instr_gen_opparam_ptr = gen_opparam_ptr; +#endif + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) tcg_gen_debug_insn_start(pc_start); s->pc = pc_start; @@ -4105,6 +4173,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) x86_64_hregs = 0; #endif s->rip_offset = 0; /* for relative ip address */ +#if defined(CONFIG_INSTRUMENT) + s->instr_regs_used = 0; + s->instr_regs_defined = 0; +#endif #if defined(CONFIG_BACKDOOR) if (ldub_code(s->pc) == 0x0f && ldub_code(s->pc + 1) == 0x04) { @@ -4118,6 +4190,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; case 0x01: /* i8 v */ cmd = tcg_const_i32(ldub_code(s->pc + 3)); + INSTR_REGS_SET_GP(used, R_EAX); gen_helper_backdoor_i8_v(cmd, cpu_regs[R_EAX]); break; default: @@ -4901,6 +4974,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) rm = 0; /* avoid warning */ } label1 = gen_new_label(); + INSTR_REGS_SET_GP(used, R_EAX); tcg_gen_sub_tl(t2, cpu_regs[R_EAX], t0); gen_extu(ot, t2); tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1); @@ -5476,6 +5550,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) val = ldub_code(s->pc++); tcg_gen_movi_tl(cpu_T3, val); } else { + INSTR_REGS_SET_GP(used, R_ECX); tcg_gen_mov_tl(cpu_T3, cpu_regs[R_ECX]); } gen_shiftd_rm_T1_T3(s, ot, opreg, op); @@ -6386,6 +6461,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* XXX: specific Intel behaviour ? */ l1 = gen_new_label(); gen_jcc1(s, s->cc_op, b ^ 1, l1); + INSTR_REGS_SET_GP(defined, reg); tcg_gen_mov_tl(cpu_regs[reg], t0); gen_set_label(l1); tcg_gen_ext32u_tl(cpu_regs[reg], cpu_regs[reg]); @@ -7666,6 +7742,36 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) backdoor_done: #endif +#if defined(CONFIG_INSTRUMENT) + { + uint16_t * old_gen_opc_ptr = gen_opc_ptr; + TCGArg * old_gen_opparam_ptr = gen_opparam_ptr; + + INSTR_GEN_FETCH(TUL, pc_start, + I32, s->pc - pc_start, + REGS, s->instr_regs_used, + REGS, s->instr_regs_defined); + + /* Move TCG code generated by instrumentation callback */ + + if (old_gen_opc_ptr != gen_opc_ptr) { + typeof(*gen_opc_ptr) tmp[OPC_BUF_SIZE]; + mem_exchange(tmp, instr_gen_opc_ptr, + (old_gen_opc_ptr - instr_gen_opc_ptr) * sizeof(*gen_opc_ptr), + old_gen_opc_ptr, + (gen_opc_ptr - old_gen_opc_ptr) * sizeof(*gen_opc_ptr)); + } + + if (old_gen_opparam_ptr != gen_opparam_ptr) { + typeof(*gen_opparam_ptr) tmp[OPPARAM_BUF_SIZE]; + mem_exchange(tmp, instr_gen_opparam_ptr, + (old_gen_opparam_ptr - instr_gen_opparam_ptr) * sizeof(*gen_opparam_ptr), + old_gen_opparam_ptr, + (gen_opparam_ptr - old_gen_opparam_ptr) * sizeof(*gen_opparam_ptr)); + } + } +#endif + /* lock generation */ if (s->prefix & PREFIX_LOCK) gen_helper_unlock(); @@ -7812,6 +7918,9 @@ static inline void gen_intermediate_code_internal(CPUState *env, || (flags & HF_SOFTMMU_MASK) #endif ); +#if defined(CONFIG_INSTRUMENT) + instr_disas = dc; +#endif #if 0 /* check addseg logic */ if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32)) @@ -7930,6 +8039,10 @@ static inline void gen_intermediate_code_internal(CPUState *env, tb->size = pc_ptr - pc_start; tb->icount = num_insns; } + +#if defined(CONFIG_INSTRUMENT) + instr_disas = NULL; +#endif } void gen_intermediate_code(CPUState *env, TranslationBlock *tb) -- 1.7.1 -- "And it's much the same thing with knowledge, for whenever you learn something new, the whole world becomes that much richer." -- The Princess of Pure Reason, as told by Norton Juster in The Phantom Tollbooth