void check_opnd(opnd_t opnd, void *pc, int read, void *drcontext, dr_mcontext_t *mctx, void *prev_pc) { if (opnd_is_memory_reference(opnd) && opnd_is_base_disp(opnd)) add_hit(pc, opnd_size_in_bytes(opnd_get_size(opnd)), opnd_get_disp(opnd) + (void *)reg_get_value(opnd_get_base(opnd), mctx), read, drcontext, prev_pc); else if (opnd_is_memory_reference(opnd) && opnd_get_addr(opnd)) add_hit(pc, opnd_size_in_bytes(opnd_get_size(opnd)), opnd_get_addr(opnd), read, drcontext, prev_pc); // for now no other kind of memory reference was noticed to access heap data else if (opnd_is_memory_reference(opnd)) dr_printf("need to implem other memory ref\n"); }
/* emits the instruction to buf (for tests that wish to do additional checks on * the output) */ static void test_instr_encode_and_decode(void *dc, instr_t *instr, uint len_expect, /* also checks one operand's size */ bool src, uint opnum, opnd_size_t sz, uint bytes) { opnd_t op; opnd_size_t opsz; instr_t *decin; uint len; byte *pc = instr_encode(dc, instr, buf); len = (int) (pc - (byte *)buf); #if VERBOSE disassemble_with_info(dc, buf, STDOUT, true, true); #endif ASSERT(len == len_expect); decin = instr_create(dc); decode(dc, buf, decin); ASSERT(instr_same(instr, decin)); /* PR 245805: variable sizes should be resolved on decode */ if (src) op = instr_get_src(decin, opnum); else op = instr_get_dst(decin, opnum); opsz = opnd_get_size(op); ASSERT(opsz == sz && opnd_size_in_bytes(opsz) == bytes); instr_destroy(dc, instr); instr_destroy(dc, decin); }
static void memory_operand_replacer(instr_t *in, opnd_t *opnd, bool is_source, struct memory_operand_modifier *mod) { if(BASE_DISP_kind == opnd->kind) { const int orig_size = opnd_get_size(*opnd); *opnd = mod->replacement_operand; opnd_set_size(opnd, orig_size); instr_set_raw_bits_valid(in, false); } (void) is_source; }
std::string raw2trace_t::append_memref(INOUT trace_entry_t **buf_in, uint tidx, instr_t *instr, opnd_t ref, bool write) { trace_entry_t *buf = *buf_in; offline_entry_t in_entry; if (!thread_files[tidx]->read((char*)&in_entry, sizeof(in_entry))) return "Trace ends mid-block"; if (in_entry.addr.type != OFFLINE_TYPE_MEMREF && in_entry.addr.type != OFFLINE_TYPE_MEMREF_HIGH) { // This happens when there are predicated memrefs in the bb. // They could be earlier, so "instr" may not itself be predicated. // XXX i#2015: if there are multiple predicated memrefs, our instr vs // data stream may not be in the correct order here. VPRINT(4, "Missing memref (next type is 0x" ZHEX64_FORMAT_STRING ")\n", in_entry.combined_value); // Put back the entry. thread_files[tidx]->seekg(-(std::streamoff)sizeof(in_entry), thread_files[tidx]->cur); return ""; } if (instr_is_prefetch(instr)) { buf->type = instru_t::instr_to_prefetch_type(instr); buf->size = 1; } else if (instru_t::instr_is_flush(instr)) { buf->type = TRACE_TYPE_DATA_FLUSH; buf->size = (ushort) opnd_size_in_bytes(opnd_get_size(ref)); } else { if (write) buf->type = TRACE_TYPE_WRITE; else buf->type = TRACE_TYPE_READ; buf->size = (ushort) opnd_size_in_bytes(opnd_get_size(ref)); } // We take the full value, to handle low or high. buf->addr = (addr_t) in_entry.combined_value; VPRINT(4, "Appended memref to " PFX "\n", (ptr_uint_t)buf->addr); *buf_in = ++buf; return ""; }
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 } }
/* First tried something like this, but we hit too many issues in decode and encode */ bool compare_pages(void *drcontext, byte *start1, byte *start2) { byte *p1 = start1, *p2 = start2; int skipped_bytes = 0, identical_skipped_bytes = 0; while (p1 < start1 + PAGE_SIZE) { int instr_size = decode_sizeof(drcontext, p1, NULL _IF_X64(NULL)); if (p1 + instr_size > start1 + PAGE_SIZE) { /* We're overlapping the end of the page, skip these. */ int end_skip = start1 + PAGE_SIZE - p1; VVERBOSE_PRINT("Passing PAGE_END %d bytes", end_skip); skipped_bytes += end_skip; if (memcmp(p1, p2, end_skip) == 0) identical_skipped_bytes += end_skip; break; } if (decode_sizeof(drcontext, p2, NULL _IF_X64(NULL)) != instr_size) { VVERBOSE_PRINT("Instruction alignment mismatch\n"); return false; } /* assumption - instructions <= 4 bytes in size won't have relocations */ if (instr_size < 5) { if (memcmp(p1, p2, instr_size) != 0) { VVERBOSE_PRINT("Difference found in small instr\n"); return false; } p1 += size; p2 += size; } else { /* guess if there could be a relocation */ instr_t *instr1 = instr_create(drcontext); instr_t *instr2 = instr_create(drcontext); p1 = decode(drcontext, p1, instr1); p2 = decode(drcontext, p2, instr2); if (p1 - start1 != p2 - start2) { VVERBOSE_PRINT("Instruction alignment mismatch on full decode\n"); /* Fixme - free instr, don't expect this to happen */ return false; } if (instr_get_num_srcs(instr1) != instr_get_num_srcs(instr2) || instr_get_num_dsts(instr1) != instr_get_num_dsts(instr2)) { VVERBOSE_PRINT("Full decode operand mismatch"); return false; } for (i = instr_get_num_srcs(instr1); i > 0; i--) { opnd_t opnd = instr_get_src(instr1, i); if (opnd_is_immed_int(opnd) && opnd_get_immed_int(opnd) > 0x10000) { instr_set_src(instr1, i, opnd_create_immed_int(opnd_get_immed_int(opnd), opnd_get_size(opnd))); } } } } }