static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { instr_t *instr; uint num_instrs; #ifdef VERBOSE dr_printf("in dynamorio_basic_block(tag="PFX")\n", tag); # ifdef VERBOSE_VERBOSE instrlist_disassemble(drcontext, tag, bb, STDOUT); # endif #endif for (instr = instrlist_first(bb), num_instrs = 0; instr != NULL; instr = instr_get_next(instr)) { num_instrs++; } dr_insert_clean_call(drcontext, bb, instrlist_first(bb), (void *)inscount, false /* save fpstate */, 1, OPND_CREATE_INT32(num_instrs)); #if defined(VERBOSE) && defined(VERBOSE_VERBOSE) dr_printf("Finished instrumenting dynamorio_basic_block(tag="PFX")\n", tag); instrlist_disassemble(drcontext, tag, bb, STDOUT); #endif return DR_EMIT_DEFAULT; }
/* replaces all inc with add 1, dec with sub 1 * if cannot replace (eflags constraints), leaves original instruction alone */ static dr_emit_flags_t event_trace(void *drcontext, void *tag, instrlist_t *trace, bool translating) { instr_t *instr, *next_instr; int opcode; if (!enable) return DR_EMIT_DEFAULT; #ifdef VERBOSE dr_printf("in dynamorio_trace(tag="PFX")\n", tag); instrlist_disassemble(drcontext, tag, trace, STDOUT); #endif for (instr = instrlist_first(trace); instr != NULL; instr = next_instr) { /* grab next now so we don't go over instructions we insert */ next_instr = instr_get_next(instr); opcode = instr_get_opcode(instr); if (opcode == OP_inc || opcode == OP_dec) { if (!translating) ATOMIC_INC(num_examined); if (replace_inc_with_add(drcontext, instr, trace)) { if (!translating) ATOMIC_INC(num_converted); } } } #ifdef VERBOSE dr_printf("after dynamorio_trace(tag="PFX"):\n", tag); instrlist_disassemble(drcontext, tag, trace, STDOUT); #endif return DR_EMIT_DEFAULT; }
static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { instr_t *instr, *mbr = NULL; uint num_instrs; bool bb_in_app; #ifdef VERBOSE dr_printf("in dynamorio_basic_block(tag="PFX")\n", tag); # ifdef VERBOSE_VERBOSE instrlist_disassemble(drcontext, tag, bb, STDOUT); # endif #endif for (instr = instrlist_first(bb), num_instrs = 0; instr != NULL; instr = instr_get_next(instr)) { /* only care about app instr */ if (!instr_ok_to_mangle(instr)) continue; num_instrs++; /* Assuming most of the transfers between app and lib are paired, we * instrument indirect branches but not returns for better performance. */ if (instr_is_mbr(instr) && !instr_is_return(instr)) mbr = instr; } if (dr_fragment_app_pc(tag) >= app_base && dr_fragment_app_pc(tag) < app_end) bb_in_app = true; else bb_in_app = false; dr_insert_clean_call(drcontext, bb, instrlist_first(bb), (void *)(bb_in_app ? app_update : lib_update), false /* save fpstate */, 1, OPND_CREATE_INT32(num_instrs)); if (mbr != NULL) { dr_insert_mbr_instrumentation(drcontext, bb, mbr, (void *)(bb_in_app ? app_mbr : lib_mbr), SPILL_SLOT_1); } #if defined(VERBOSE) && defined(VERBOSE_VERBOSE) dr_printf("Finished instrumenting dynamorio_basic_block(tag="PFX")\n", tag); instrlist_disassemble(drcontext, tag, bb, STDOUT); #endif return DR_EMIT_DEFAULT; }
static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { instr_t *instr, *next_instr; #ifdef VERBOSE dr_printf("in dr_basic_block(tag="PFX")\n", tag); # if VERBOSE_VERBOSE instrlist_disassemble(drcontext, tag, bb, STDOUT); # endif #endif for (instr = instrlist_first_app(bb); instr != NULL; instr = next_instr) { next_instr = instr_get_next_app(instr); if (!instr_opcode_valid(instr)) continue; /* instrument calls and returns -- ignore far calls/rets */ if (instr_is_call_direct(instr)) { dr_insert_call_instrumentation(drcontext, bb, instr, (app_pc)at_call); } else if (instr_is_call_indirect(instr)) { dr_insert_mbr_instrumentation(drcontext, bb, instr, (app_pc)at_call_ind, SPILL_SLOT_1); } else if (instr_is_return(instr)) { dr_insert_mbr_instrumentation(drcontext, bb, instr, (app_pc)at_return, SPILL_SLOT_1); } } return DR_EMIT_DEFAULT; }
static dr_emit_flags_t event_app_instruction(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst, bool for_trace, bool translating, void *user_data) { #ifdef SHOW_RESULTS bool aflags_dead; #endif if (!drmgr_is_first_instr(drcontext, inst)) return DR_EMIT_DEFAULT; #ifdef VERBOSE dr_printf("in dynamorio_basic_block(tag="PFX")\n", tag); # ifdef VERBOSE_VERBOSE instrlist_disassemble(drcontext, tag, bb, STDOUT); # endif #endif #ifdef SHOW_RESULTS if (drreg_are_aflags_dead(drcontext, inst, &aflags_dead) == DRREG_SUCCESS && !aflags_dead) bbs_eflags_saved++; else bbs_no_eflags_saved++; #endif /* We demonstrate how to use drreg for aflags save/restore here. * We could use drx_insert_counter_update instead of drreg. * Xref sample opcodes.c as an example of using drx_insert_counter_update. */ if (drreg_reserve_aflags(drcontext, bb, inst) != DRREG_SUCCESS) DR_ASSERT(false && "fail to reserve aflags!"); /* racy update on the counter for better performance */ instrlist_meta_preinsert (bb, inst, INSTR_CREATE_inc(drcontext, OPND_CREATE_ABSMEM ((byte *)&global_count, OPSZ_4))); if (drreg_unreserve_aflags(drcontext, bb, inst) != DRREG_SUCCESS) DR_ASSERT(false && "fail to unreserve aflags!"); #if defined(VERBOSE) && defined(VERBOSE_VERBOSE) dr_printf("Finished instrumenting dynamorio_basic_block(tag="PFX")\n", tag); instrlist_disassemble(drcontext, tag, bb, STDOUT); #endif return DR_EMIT_DEFAULT; }
static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { instr_t *instr, *next_instr; #ifdef VERBOSE dr_printf("in dynamorio_basic_block(tag="PFX")\n", tag); # ifdef VERBOSE_VERBOSE instrlist_disassemble(drcontext, tag, bb, STDOUT); # endif #endif for (instr = instrlist_first(bb); instr != NULL; instr = next_instr) { /* grab next now so we don't go over instructions we insert */ next_instr = instr_get_next(instr); /* instrument calls and returns -- ignore far calls/rets */ if (instr_is_call_direct(instr)) { insert_counter_update(drcontext, bb, instr, offsetof(per_thread_t, num_direct_calls)); } else if (instr_is_call_indirect(instr)) { insert_counter_update(drcontext, bb, instr, offsetof(per_thread_t, num_indirect_calls)); } else if (instr_is_return(instr)) { insert_counter_update(drcontext, bb, instr, offsetof(per_thread_t, num_returns)); } } #if defined(VERBOSE) && defined(VERBOSE_VERBOSE) dr_printf("Finished instrumenting dynamorio_basic_block(tag="PFX")\n", tag); instrlist_disassemble(drcontext, tag, bb, STDOUT); #endif return DR_EMIT_DEFAULT; }
static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { int i; const int MAX_INSTR_LEN = 64; char instr_name[MAX_INSTR_LEN]; instr_t *instr, *first = instrlist_first(bb); uint flags; uint cur_flop_count = 0; uint tracked_instr_count[tracked_instrs_len]; for( i = 0; i < tracked_instrs_len; i++ ) tracked_instr_count[i] = 0; #ifdef VERBOSE dr_printf("in dynamorio_basic_block(tag="PFX")\n", tag); # ifdef VERBOSE_VERBOSE instrlist_disassemble(drcontext, tag, bb, STDOUT); # endif #endif /* we use fp ops so we have to save fp state */ byte fp_raw[512 + 16]; byte *fp_align = (byte *) ( (((ptr_uint_t)fp_raw) + 16) & ((ptr_uint_t)-16) ); if (translating) { return DR_EMIT_DEFAULT; } proc_save_fpstate(fp_align); int my_readfrom[DR_REG_LAST_VALID_ENUM+MY_NUM_EFLAGS+1]; int my_writtento[DR_REG_LAST_VALID_ENUM+MY_NUM_EFLAGS+1]; for (i = 0; i < DR_REG_LAST_VALID_ENUM+MY_NUM_EFLAGS+1; i++) { my_readfrom[i] = 0; my_writtento[i] = 0; } t_glob_reg_state glob_reg_state = {0,0,0,0,0,0,my_readfrom,my_writtento}; int my_cur_size = 0; for (instr = instrlist_first(bb); instr != NULL; instr = instr_get_next(instr)) { my_cur_size++; /* ILP Calculations */ glob_reg_state.raw_setnr = 1; glob_reg_state.war_setnr = 1; glob_reg_state.waw_setnr = 1; glob_reg_state.else_setnr = 1; glob_reg_state.final_setnr = 1; calc_set_num(instr, &glob_reg_state); /* Count flop instr */ if( instr_is_floating( instr ) ) { cur_flop_count += 1; } /* Count mul instructions */ instr_disassemble_to_buffer( drcontext, instr, instr_name, MAX_INSTR_LEN ); for( i = 0; i < tracked_instrs_len; i++ ) { if( strncmp( instr_name, tracked_instrs[i], strlen(tracked_instrs[i])) == 0) { tracked_instr_count[i] += 1; } } } //now we can calculate the ILP. float ilp = ((float)my_cur_size) / ((float)(glob_reg_state.num_sets != 0 ? glob_reg_state.num_sets : 1)); dr_mutex_lock(stats_mutex); // Due to lack of memory, we only store the ILPs for the latest MY_MAX_BB // basic blocks. This enables us to run e.g. firefox. int my_cur_num = my_bbcount % MY_MAX_BB; my_bbcount++; if(my_cur_num == 0 && my_bbcount > 1) { dr_printf("Overflow at %d\n", my_bbcount); } my_bbexecs[my_cur_num] = 0; //initialize my_bbsizes[my_cur_num] = my_cur_size; bb_flop_count[my_cur_num] = cur_flop_count; for( i = 0; i < tracked_instrs_len; i++ ) { bb_instr_count[my_cur_num*tracked_instrs_len+i] = tracked_instr_count[i]; } my_bbilp[my_cur_num] = ilp; dr_mutex_unlock(stats_mutex); #ifdef USE_CLEAN_CALL dr_insert_clean_call(drcontext, bb, instrlist_first(bb), clean_call, false, 1, OPND_CREATE_INT32(my_cur_num)); #else #ifdef INSERT_AT_END instr = NULL; #else // Find place to insert inc instruction for (instr = first; instr != NULL; instr = instr_get_next(instr)) { flags = instr_get_arith_flags(instr); if (TESTALL(EFLAGS_WRITE_6, flags) && !TESTANY(EFLAGS_READ_6, flags)) break; } #endif if (instr == NULL) { // no suitable place found, save regs dr_save_reg(drcontext, bb, first, DR_REG_XAX, SPILL_SLOT_1); dr_save_arith_flags_to_xax(drcontext, bb, first); } // Increment my_bbexecs[my_current_bb] using the lock prefix instrlist_meta_preinsert (bb, (instr == NULL) ? first : instr, LOCK(INSTR_CREATE_inc(drcontext, OPND_CREATE_ABSMEM ((byte *)&(my_bbexecs[my_cur_num]), OPSZ_4)))); if (instr == NULL) { // no suitable place found earlier, restore regs dr_restore_arith_flags_from_xax(drcontext, bb, first); dr_restore_reg(drcontext, bb, first, DR_REG_XAX, SPILL_SLOT_1); } #endif proc_restore_fpstate(fp_align); #if defined(VERBOSE) && defined(VERBOSE_VERBOSE) dr_printf("Finished instrumenting dynamorio_basic_block(tag="PFX")\n", tag); instrlist_disassemble(drcontext, tag, bb, STDOUT); #endif return DR_EMIT_DEFAULT; }
/** Adds instrumentation that records fragment execution. */ struct instr_info_t instrument_frag(void* ctx, instrlist_t* frag, frag_id_t id) { const size_t offsetof_current = offsetof(struct trace_buffer_t, current); ptr_int_t frag_id = id; // sign-extended for OPND_CREATE_INT32 #ifdef TRACE_DEBUG app_pc frag_pc; #endif app_pc xl8_pc; instr_t* where; instr_t* before; struct instr_info_t instr_info; instr_t* store; instr_t* first; #ifdef TRACE_DEBUG dr_fprintf(STDERR, "debug: instrument_frag(0x%" PRIxPTR ")\n", frag_id); frag_pc = instr_get_app_pc(instrlist_first(frag)); instrlist_disassemble(ctx, frag_pc, frag, STDERR); #endif where = configure_instr(&instr_info, frag); xl8_pc = instr_get_app_pc(where); before = instr_get_prev(where); #define INSERT(instr) prexl8(frag, where, (instr), xl8_pc) // Add instrumentation. // save tls_reg if(instr_info.restore_tls_reg) { dr_save_reg(ctx, frag, where, instr_info.tls_reg, SPILL_SLOT_2); } // save current_reg if(instr_info.restore_current_reg) { dr_save_reg(ctx, frag, where, instr_info.current_reg, SPILL_SLOT_3); } // tls_reg = tb dr_insert_read_tls_field(ctx, frag, where, instr_info.tls_reg); // current_reg = tb->current INSERT( INSTR_CREATE_mov_ld( ctx, opnd_create_reg(instr_info.current_reg), OPND_CREATE_MEMPTR(instr_info.tls_reg, offsetof_current))); // *current_reg = bb_id store = INSERT( INSTR_CREATE_mov_st( ctx, OPND_CREATE_MEMPTR(instr_info.current_reg, 0), OPND_CREATE_INT32(frag_id))); // current_reg += sizeof(bb_id) INSERT( INSTR_CREATE_lea( ctx, opnd_create_reg(instr_info.current_reg), OPND_CREATE_MEM_lea(instr_info.current_reg, DR_REG_NULL, 0, sizeof(frag_id_t)))); // tb->current = current_reg INSERT( INSTR_CREATE_mov_st( ctx, OPND_CREATE_MEMPTR(instr_info.tls_reg, offsetof_current), opnd_create_reg(instr_info.current_reg))); // restore current_reg if(instr_info.restore_current_reg) { dr_restore_reg(ctx, frag, where, instr_info.current_reg, SPILL_SLOT_3); } // restore tls_reg if(instr_info.restore_tls_reg) { dr_restore_reg(ctx, frag, where, instr_info.tls_reg, SPILL_SLOT_2); } #undef INSERT // Compute instrumentation instructions offsets. if(before) { first = instr_get_next(before); } else { first = instrlist_first(frag); } instr_info.first_offset = get_offset(ctx, instrlist_first(frag), first); instr_info.store_offset = get_offset(ctx, instrlist_first(frag), store); #ifdef TRACE_DUMP_BB instrlist_disassemble(ctx, frag_pc, frag, STDERR); #endif #ifdef TRACE_DEBUG dr_fprintf(STDERR, "debug: instrument_frag() done," " first_offset=0x%" PRIx32 " store_offset=0x%" PRIx32 "\n", instr_info.first_offset, instr_info.store_offset); #endif return instr_info; }
static dr_emit_flags_t event_bb_analysis(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating, void **user_data) { instr_t *instr; uint num_instrs; #ifdef VERBOSE dr_printf("in dynamorio_basic_block(tag=" PFX ")\n", tag); # ifdef VERBOSE_VERBOSE instrlist_disassemble(drcontext, tag, bb, STDOUT); # endif #endif /* Only count in app BBs */ if (only_from_app.get_value()) { module_data_t *mod = dr_lookup_module(dr_fragment_app_pc(tag)); if (mod != NULL) { bool from_exe = (mod->start == exe_start); dr_free_module_data(mod); if (!from_exe) { *user_data = NULL; return DR_EMIT_DEFAULT; } } } /* Count instructions. If an emulation client is running with this client, * we want to count all the original native instructions and the emulated * instruction but NOT the introduced native instructions used for emulation. */ bool is_emulation = false; for (instr = instrlist_first(bb), num_instrs = 0; instr != NULL; instr = instr_get_next(instr)) { if (drmgr_is_emulation_start(instr)) { /* Each emulated instruction is replaced by a series of native * instructions delimited by labels indicating when the emulation * sequence begins and ends. It is the responsibility of the * emulation client to place the start/stop labels correctly. */ num_instrs++; is_emulation = true; /* Data about the emulated instruction can be extracted from the * start label using the accessor function: * drmgr_get_emulated_instr_data() */ continue; } if (drmgr_is_emulation_end(instr)) { is_emulation = false; continue; } if (is_emulation) continue; if (!instr_is_app(instr)) continue; num_instrs++; } *user_data = (void *)(ptr_uint_t)num_instrs; #if defined(VERBOSE) && defined(VERBOSE_VERBOSE) dr_printf("Finished counting for dynamorio_basic_block(tag=" PFX ")\n", tag); instrlist_disassemble(drcontext, tag, bb, STDOUT); #endif return DR_EMIT_DEFAULT; }