static print_base_disp_for_lea(file_t file, opnd_t opnd){ /* [base + index * scale + disp] */ dr_fprintf(file, " base - %d %s\n", opnd_get_base(opnd), get_register_name(opnd_get_base(opnd))); dr_fprintf(file, " index - %d %s\n", opnd_get_index(opnd), get_register_name(opnd_get_index(opnd))); dr_fprintf(file, "reg - %d\n", opnd_is_reg(opnd_create_reg(opnd_get_index(opnd)))); dr_fprintf(file, " scale - %d\n", opnd_get_scale(opnd)); dr_fprintf(file, " disp - %d\n", opnd_get_disp(opnd)); }
/* 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; }
void watchpoint_indirect_call_event(dcontext_t *drcontext, instrlist_t *ilist, instr_t *instr, instr_t *next_instr, bool mangle_calls, uint flags) { opnd_t instr_opnd; reg_id_t base_reg; unsigned long used_registers = 0; app_pc pc; struct memory_operand_modifier ops = {0}; instr_t *begin_instrumenting = INSTR_CREATE_label(drcontext); instr_t *done_instrumenting = INSTR_CREATE_label(drcontext); instr_t *nop = INSTR_CREATE_nop(drcontext); instr_t *emulated; memset(&ops, 0, sizeof(struct memory_operand_modifier)); if(instr_reads_memory(instr)) { instr_opnd = instr_get_src(instr, 0); if (opnd_is_rel_addr(instr_opnd) || opnd_is_abs_addr(instr_opnd)) { }else if (opnd_is_base_disp(instr_opnd)) { for_each_src_operand(instr, &ops, (opnd_callback_t *) memory_src_operand_finder); // base_reg = opnd_get_reg(instr_opnd); switch(ops.found_operand.value.base_disp.base_reg) { case DR_REG_RSP: case DR_REG_ESP: case DR_REG_SP: case DR_REG_RBP: case DR_REG_EBP: case DR_REG_BP: return; default: break; } collect_regs(&used_registers, instr, instr_num_srcs, instr_get_src ); collect_regs(&used_registers, instr, instr_num_dsts, instr_get_dst ); reg_id_t reg_watched_addr = get_next_free_reg(&used_registers); opnd_t opnd_watched_addr = opnd_create_reg(reg_watched_addr); reg_id_t reg_unwatched_addr = get_next_free_reg(&used_registers); opnd_t opnd_unwatched_addr = opnd_create_reg(reg_unwatched_addr); PRE(ilist, instr, begin_instrumenting); PRE(ilist, instr, INSTR_CREATE_push(drcontext, opnd_watched_addr)); PRE(ilist, instr, INSTR_CREATE_push(drcontext, opnd_unwatched_addr)); PRE(ilist, instr, INSTR_CREATE_pushf(drcontext)); PRE(ilist, instr, INSTR_CREATE_lea(drcontext, opnd_watched_addr, opnd_create_base_disp(opnd_get_base(ops.found_operand), opnd_get_index(ops.found_operand), opnd_get_scale(ops.found_operand), opnd_get_disp(ops.found_operand), OPSZ_lea))); PRE(ilist, instr, INSTR_CREATE_mov_imm(drcontext, opnd_unwatched_addr, OPND_CREATE_INT64(WATCHPOINT_INDEX_MASK))); PRE(ilist, instr, INSTR_CREATE_or(drcontext, opnd_unwatched_addr, opnd_watched_addr)); emulated = instr_clone(drcontext, instr); emulated->translation = 0; ops.replacement_operand = opnd_create_base_disp( reg_unwatched_addr, DR_REG_NULL,1, 0 , ops.found_operand.size); for_each_operand(emulated, &ops, (opnd_callback_t *) memory_operand_replacer); PRE(ilist, instr, INSTR_CREATE_popf(drcontext)); PRE(ilist, instr, emulated); PRE(ilist, instr, INSTR_CREATE_pop(drcontext, opnd_unwatched_addr)); PRE(ilist, instr, INSTR_CREATE_pop(drcontext, opnd_watched_addr)); PRE(ilist, instr, INSTR_CREATE_jmp_short(drcontext, opnd_create_instr(done_instrumenting))); pc = instr->translation; instr->translation = 0; // hack! instr_being_modified(instr, false); instr_set_ok_to_mangle(instr, false); if(NULL != pc){ nop->translation = pc + instr->length; } POST(ilist, instr, nop); POST(ilist, instr, done_instrumenting); } } }
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; }