/* insert inline code to add an instruction entry into the buffer */ static void instrument_instr(void *drcontext, instrlist_t *ilist, instr_t *where) { /* We need two scratch registers */ reg_id_t reg_ptr, reg_tmp; /* we don't want to predicate this, because an instruction fetch always occurs */ instrlist_set_auto_predicate(ilist, DR_PRED_NONE); if (drreg_reserve_register(drcontext, ilist, where, NULL, ®_ptr) != DRREG_SUCCESS || drreg_reserve_register(drcontext, ilist, where, NULL, ®_tmp) != DRREG_SUCCESS) { DR_ASSERT(false); /* cannot recover */ return; } insert_load_buf_ptr(drcontext, ilist, where, reg_ptr); insert_save_type(drcontext, ilist, where, reg_ptr, reg_tmp, (ushort)instr_get_opcode(where)); insert_save_size(drcontext, ilist, where, reg_ptr, reg_tmp, (ushort)instr_length(drcontext, where)); insert_save_pc(drcontext, ilist, where, reg_ptr, reg_tmp, instr_get_app_pc(where)); insert_update_buf_ptr(drcontext, ilist, where, reg_ptr, sizeof(mem_ref_t)); /* Restore scratch registers */ if (drreg_unreserve_register(drcontext, ilist, where, reg_ptr) != DRREG_SUCCESS || drreg_unreserve_register(drcontext, ilist, where, reg_tmp) != DRREG_SUCCESS) DR_ASSERT(false); instrlist_set_auto_predicate(ilist, instr_get_predicate(where)); }
// We stored the instr count in *bb_field in bb_analysis(). int offline_instru_t::instrument_instr(void *drcontext, void *tag, void **bb_field, instrlist_t *ilist, instr_t *where, reg_id_t reg_ptr, reg_id_t reg_tmp, int adjust, instr_t *app) { app_pc pc, modbase; uint modidx; offline_entry_t entry; // We write just once per bb. if ((ptr_uint_t)*bb_field > MAX_INSTR_COUNT) return adjust; pc = dr_fragment_app_pc(tag); if (drmodtrack_lookup(drcontext, pc, &modidx, &modbase) != DRCOVLIB_SUCCESS) { // FIXME i#2062: add non-module support. The plan for instrs is to have // one entry w/ the start abs pc, and subsequent entries that pack the instr // length for 10 instrs, 4 bits each, into a pc.modoffs field. We will // also need to store the type (read/write/prefetch*) and size for the // memrefs. modidx = 0; modbase = pc; } entry.pc.type = OFFLINE_TYPE_PC; // We put the ARM vs Thumb mode into the modoffs to ensure proper decoding. entry.pc.modoffs = dr_app_pc_as_jump_target(instr_get_isa_mode(where), pc) - modbase; entry.pc.modidx = modidx; entry.pc.instr_count = (ptr_uint_t)*bb_field; insert_save_pc(drcontext, ilist, where, reg_ptr, reg_tmp, adjust, entry.combined_value); *(ptr_uint_t*)bb_field = MAX_INSTR_COUNT + 1; return (adjust + sizeof(offline_entry_t)); }