/* this is only called when the instrace mode is operand trace (this happens at the instrumentation time) */ static void operand_trace(instr_t * instr, void * drcontext){ int i; char stringop[MAX_STRING_LENGTH]; int pc = 0; per_thread_t * data = drmgr_get_tls_field(drcontext, tls_index); module_data_t * module_data = dr_lookup_module(instr_get_app_pc(instr)); if (module_data != NULL){ pc = instr_get_app_pc(instr) - module_data->start; } instr_disassemble_to_buffer(drcontext, instr, stringop, MAX_STRING_LENGTH); if (client_arg->instrace_mode == OPERAND_TRACE){ dr_fprintf(data->outfile, "%s\n", stringop); for (i = 0; i < instr_num_dsts(instr); i++){ opnd_disassemble_to_buffer(drcontext, instr_get_dst(instr, i), stringop, MAX_STRING_LENGTH); if ((instr_get_opcode(instr) == OP_lea) && opnd_is_base_disp(instr_get_dst(instr,i))){ dr_fprintf(data->outfile, "dst-\n"); print_base_disp_for_lea(data->outfile, instr_get_dst(instr, i)); } else{ dr_fprintf(data->outfile, "dst-%d-%s\n", i, stringop); } } for (i = 0; i < instr_num_srcs(instr); i++){ opnd_disassemble_to_buffer(drcontext, instr_get_src(instr, i), stringop, MAX_STRING_LENGTH); if ((instr_get_opcode(instr) == OP_lea) && opnd_is_base_disp(instr_get_src(instr, i))){ dr_fprintf(data->outfile, "src-\n"); print_base_disp_for_lea(data->outfile, instr_get_src(instr, i)); } else{ dr_fprintf(data->outfile, "src-%d-%s\n", i, stringop); } } if (module_data != NULL){ dr_fprintf(data->outfile, "app_pc-%d\n", pc); } } else if (client_arg->instrace_mode == INS_DISASM_TRACE){ if (module_data != NULL){ if (md_get_module_position(instrace_head, module_data->full_path) == -1){ md_add_module(instrace_head, module_data->full_path, MAX_BBS_PER_MODULE); } dr_fprintf(data->outfile, "%d,%d,%s\n", md_get_module_position(instrace_head, module_data->full_path), pc, stringop); } else{ dr_fprintf(data->outfile, "%d,%d,%s\n",0, 0, stringop); } } dr_free_module_data(module_data); }
static void print_instr(byte *address, instr_t *instr) { char buffer[0x100]; instr_disassemble_to_buffer(0, instr, buffer, 0x100); Shade::code_log << "0x" << (void *)address << " " << buffer << std::endl; }
/* this is only called when the instrace mode is disassembly trace (this happens at the analysis time)*/ static void clean_call_disassembly_trace(){ char disassembly[SHORT_STRING_LENGTH]; per_thread_t * data = drmgr_get_tls_field(dr_get_current_drcontext(), tls_index); instr_trace_t * trace = (instr_trace_t *)data->buf_ptr; module_data_t * md; md = dr_lookup_module(instr_get_app_pc(trace->static_info_instr)); instr_disassemble_to_buffer(dr_get_current_drcontext(), trace->static_info_instr, disassembly, SHORT_STRING_LENGTH); dr_fprintf(data->outfile, "%s ", disassembly); if (md != NULL){ dr_fprintf(data->outfile, "%x", instr_get_app_pc(trace->static_info_instr) - md->start); dr_free_module_data(md); } dr_fprintf(data->outfile, "\n"); }
/* prints the trace and empties the instruction buffer */ static void ins_trace(void *drcontext) { per_thread_t *data; int num_refs; instr_trace_t *instr_trace; instr_t * instr; int i; int j; #ifdef READABLE_TRACE char disassembly[SHORT_STRING_LENGTH]; #else output_t * output; #endif data = drmgr_get_tls_field(drcontext, tls_index); instr_trace = (instr_trace_t *)data->buf_base; num_refs = (int)((instr_trace_t *)data->buf_ptr - instr_trace); uint mem_type; uint64 mem_addr; opnd_t opnd; #ifdef READABLE_TRACE //TODO for (i = 0; i < num_refs; i++) { instr = instr_trace->static_info_instr; instr_disassemble_to_buffer(drcontext,instr,disassembly,SHORT_STRING_LENGTH); dr_fprintf(data->outfile,"%u",instr_get_opcode(instr)); dr_fprintf(data->outfile,",%u",calculate_operands(instr,DST_TYPE)); for(j=0; j<instr_num_dsts(instr); j++){ get_address(instr_trace, j, DST_TYPE, &mem_type, &mem_addr); output_populator_printer(drcontext,instr_get_dst(instr,j),instr,mem_addr,mem_type,NULL); } dr_fprintf(data->outfile,",%u",calculate_operands(instr,SRC_TYPE)); for(j=0; j<instr_num_srcs(instr); j++){ get_address(instr_trace, j, SRC_TYPE, &mem_type, &mem_addr); opnd = instr_get_src(instr, j); if (instr_get_opcode(instr) == OP_lea && opnd_is_base_disp(opnd)){ /* four operands here for [base + index * scale + disp] */ output_populator_printer(drcontext, opnd_create_reg(opnd_get_base(opnd)), instr, mem_addr, mem_type, NULL); output_populator_printer(drcontext, opnd_create_reg(opnd_get_index(opnd)), instr, mem_addr, mem_type, NULL); output_populator_printer(drcontext, opnd_create_immed_int(opnd_get_scale(opnd),OPSZ_PTR), instr, mem_addr, mem_type, NULL); output_populator_printer(drcontext, opnd_create_immed_int(opnd_get_disp(opnd), OPSZ_PTR), instr, mem_addr, mem_type, NULL); } else{ output_populator_printer(drcontext, opnd, instr, mem_addr, mem_type, NULL); } } dr_fprintf(data->outfile,",%u,%u\n",instr_trace->eflags,instr_trace->pc); ++instr_trace; } #else /* we need to fill up the output array here */ for(i = 0; i< num_refs; i++){ instr = instr_trace->static_info_instr; output = &data->output_array[i]; //opcode output->opcode = instr_get_opcode(instr); output->num_dsts = 0; output->num_srcs = 0; for(j=0; j<instr_num_dsts(instr); j++){ output_populator_printer(drcontext,instr_get_dst(instr,j),instr,get_address(instr_trace,j,DST_TYPE),&output->dsts[output->num_dsts]); output->num_dsts++; } for(j=0; j<instr_num_srcs(instr); j++){ output_populator_printer(drcontext,instr_get_src(instr,j),instr,get_address(instr_trace,j,SRC_TYPE),&output->srcs[output->num_srcs]); output->num_srcs++; } output->eflags = instr_trace->eflags; ++instr_trace; } dr_write_file(data->outfile,data->output_array,num_refs * sizeof(output_t)); #endif memset(data->buf_base, 0, INSTR_BUF_SIZE); data->num_refs += num_refs; data->buf_ptr = data->buf_base; }
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; }