static uint calculate_operands(instr_t * instr,uint dst_or_src){ opnd_t op; int i; int ret = 0; if(dst_or_src == DST_TYPE){ for(i=0; i<instr_num_dsts(instr); i++){ op = instr_get_dst(instr,i); if(opnd_is_immed(op) || opnd_is_memory_reference(op) || opnd_is_reg(op)){ ret++; } } } else if(dst_or_src == SRC_TYPE){ for(i=0; i<instr_num_srcs(instr); i++){ op = instr_get_src(instr,i); if (instr_get_opcode(instr) == OP_lea && opnd_is_base_disp(op)){ ret += 4; } else if (opnd_is_immed(op) || opnd_is_memory_reference(op) || opnd_is_reg(op)){ ret++; } } } return ret; }
void modify_instr_for_relocations(void *drcontext, instr_t *inst, ptr_uint_t *immed, ptr_uint_t *disp) { int i; ptr_uint_t limmed = 0, ldisp = 0; for (i = instr_num_srcs(inst) - 1; i >= 0; i--) { opnd_t opnd = instr_get_src(inst, i); if (opnd_is_immed_int(opnd) && opnd_get_immed_int(opnd) > 0x10000) { if (limmed != 0) { ASSERT(false); } else { limmed = opnd_get_immed_int(opnd); } instr_set_src(inst, i, opnd_create_immed_int(0, opnd_get_size(opnd))); } if (opnd_is_base_disp(opnd) && opnd_get_disp(opnd) > 0x10000) { if (ldisp != 0 && ldisp != opnd_get_disp(opnd)) { ASSERT(false); } else { ldisp = opnd_get_disp(opnd); } instr_set_src(inst, i, opnd_create_base_disp(opnd_get_base(opnd), opnd_get_index(opnd), opnd_get_scale(opnd), 0, opnd_get_size(opnd))); } } for (i = instr_num_dsts(inst) - 1; i >= 0; i--) { opnd_t opnd = instr_get_dst(inst, i); ASSERT(!opnd_is_immed(opnd)); if (opnd_is_base_disp(opnd) && opnd_get_disp(opnd) > 0x10000) { if (ldisp != 0 && ldisp != opnd_get_disp(opnd)) { ASSERT(false); } else { ldisp = opnd_get_disp(opnd); } instr_set_dst(inst, i, opnd_create_base_disp(opnd_get_base(opnd), opnd_get_index(opnd), opnd_get_scale(opnd), 0, opnd_get_size(opnd))); } } if (limmed != 0) *immed = limmed; if (ldisp != 0) *disp = ldisp; }
/* prints out the operands / populates the operands in the instrace mode */ static void output_populator_printer(void * drcontext, opnd_t opnd, instr_t * instr, uint64 addr, uint mem_type, operand_t * output){ int value; float float_value; uint width; int i; per_thread_t * data = drmgr_get_tls_field(drcontext,tls_index); if(opnd_is_reg(opnd)){ value = opnd_get_reg(opnd); if (value != DR_REG_NULL){ width = opnd_size_in_bytes(reg_get_size(value)); } else{ width = 0; } #ifdef READABLE_TRACE dr_fprintf(data->outfile,",%u,%u,%u",REG_TYPE, width, value); #else output->type = REG_TYPE; output->width = width; output->value = value; #endif } else if(opnd_is_immed(opnd)){ //DR_ASSERT(opnd_is_immed_float(opnd) == false); if(opnd_is_immed_float(opnd)){ width = opnd_size_in_bytes(opnd_get_size(opnd)); if (instr_get_opcode(instr) == OP_fld1){ dr_fprintf(data->outfile, ",%u,%u,1", IMM_FLOAT_TYPE, width); } else if (instr_get_opcode(instr) == OP_fldz){ dr_fprintf(data->outfile, ",%u,%u,0", IMM_FLOAT_TYPE, width); } else{ dr_messagebox("immediate float unknown\n"); dr_abort(); } //float_value = opnd_get_immed_float(opnd); #ifdef READABLE_TRACE //dr_fprintf(data->outfile,",%u,%u,%.4f",IMM_FLOAT_TYPE,width,float_value); #else output->type = IMM_FLOAT_TYPE; output->width = width; output->float_value = float_value; #endif } if(opnd_is_immed_int(opnd)){ width = opnd_size_in_bytes(opnd_get_size(opnd)); value = opnd_get_immed_int(opnd); #ifdef READABLE_TRACE dr_fprintf(data->outfile,",%u,%u,%d",IMM_INT_TYPE,width,value); #else output->type = IMM_INT_TYPE; output->width = width; output->value = value; #endif } } else if(opnd_is_memory_reference(opnd)){ width = drutil_opnd_mem_size_in_bytes(opnd,instr); #ifdef READABLE_TRACE dr_fprintf(data->outfile, ",%u,%u,%llu",mem_type,width,addr); #else output->type = mem_type; output->width = width; output->float_value = addr; #endif } }
/* * The main function called to instrument each machine instruction. */ static dr_emit_flags_t instrument_instr( void *drcontext, void *tag, instrlist_t *bb, instr_t *instr, bool for_trace, bool translating, void *user_data) { char *loc = NULL; /* * If this instruction is the first in its basic block, call * log_pc to record that we're executing this block at all. */ if (drmgr_is_first_instr(drcontext, instr)) { instr_format_location(instr, &loc); dr_insert_clean_call( drcontext, bb, instr, (void *)log_pc, false, 1, OPND_CREATE_INTPTR(loc)); } /* * If the instruction reads or writes memory, log its access. */ if (instr_reads_memory(instr) || instr_writes_memory(instr)) { for (int i = 0, limit = instr_num_srcs(instr); i < limit; i++) try_mem_opnd(drcontext, bb, instr, &loc, instr_get_src(instr, i), false); for (int i = 0, limit = instr_num_dsts(instr); i < limit; i++) try_mem_opnd(drcontext, bb, instr, &loc, instr_get_dst(instr, i), false); } /* * Now do opcode-specific checks. */ int opcode = instr_get_opcode(instr); switch (opcode) { case OP_div: case OP_idiv: /* * x86 hardware divisions. The operand order for DR's * representation of these seem to be: 0 = denominator, 1 = * numerator MSW, 2 = numerator LSW. */ instr_format_location(instr, &loc); dr_insert_clean_call( drcontext, bb, instr, (void *)log_div, false, 3, instr_get_src(instr, 2), instr_get_src(instr, 0), OPND_CREATE_INTPTR(loc)); break; case OP_shl: case OP_shr: case OP_sar: case OP_shlx: case OP_shrx: case OP_sarx: case OP_rol: case OP_ror: case OP_rcl: case OP_rcr: /* * Shift instructions. If they're register-controlled, log the * shift count. */ { opnd_t shiftcount = instr_get_src(instr, 0); if (!opnd_is_immed(shiftcount)) { reg_id_t r0; drreg_status_t st; st = drreg_reserve_register(drcontext, bb, instr, NULL, &r0); DR_ASSERT(st == DRREG_SUCCESS); opnd_t op_r0 = opnd_create_reg(r0); instrlist_preinsert(bb, instr, INSTR_CREATE_movzx( drcontext, op_r0, shiftcount)); instr_format_location(instr, &loc); dr_insert_clean_call( drcontext, bb, instr, (void *)log_var_shift, false, 2, op_r0, OPND_CREATE_INTPTR(loc)); st = drreg_unreserve_register(drcontext, bb, instr, r0); DR_ASSERT(st == DRREG_SUCCESS); } } break; } return DR_EMIT_DEFAULT; }