/* This event is called separately for each individual instruction in the bb. */ static dr_emit_flags_t event_insert_instrumentation(void *drcontext, void *tag, instrlist_t *bb, instr_t *instr, bool for_trace, bool translating, void *user_data) { bool bb_in_app; if (dr_fragment_app_pc(tag) >= app_base && dr_fragment_app_pc(tag) < app_end) bb_in_app = true; else bb_in_app = false; if (drmgr_is_first_instr(drcontext, instr)) { uint num_instrs = (uint)(ptr_uint_t)user_data; dr_insert_clean_call(drcontext, bb, instr, (void *)(bb_in_app ? app_update : lib_update), false /* save fpstate */, 1, OPND_CREATE_INT32(num_instrs)); } if (instr_is_mbr(instr) && !instr_is_return(instr)) { /* Assuming most of the transfers between app and lib are paired, we * instrument indirect branches but not returns for better performance. */ dr_insert_mbr_instrumentation( drcontext, bb, instr, (void *)(bb_in_app ? app_mbr : lib_mbr), SPILL_SLOT_1); } return DR_EMIT_DEFAULT; }
static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { instr_t *instr, *mbr = NULL; uint num_instrs; bool bb_in_app; #ifdef VERBOSE dr_printf("in dynamorio_basic_block(tag="PFX")\n", tag); # ifdef VERBOSE_VERBOSE instrlist_disassemble(drcontext, tag, bb, STDOUT); # endif #endif for (instr = instrlist_first(bb), num_instrs = 0; instr != NULL; instr = instr_get_next(instr)) { /* only care about app instr */ if (!instr_ok_to_mangle(instr)) continue; num_instrs++; /* Assuming most of the transfers between app and lib are paired, we * instrument indirect branches but not returns for better performance. */ if (instr_is_mbr(instr) && !instr_is_return(instr)) mbr = instr; } if (dr_fragment_app_pc(tag) >= app_base && dr_fragment_app_pc(tag) < app_end) bb_in_app = true; else bb_in_app = false; dr_insert_clean_call(drcontext, bb, instrlist_first(bb), (void *)(bb_in_app ? app_update : lib_update), false /* save fpstate */, 1, OPND_CREATE_INT32(num_instrs)); if (mbr != NULL) { dr_insert_mbr_instrumentation(drcontext, bb, mbr, (void *)(bb_in_app ? app_mbr : lib_mbr), SPILL_SLOT_1); } #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; }
/* This event is called separately for each individual instruction in the bb. */ static dr_emit_flags_t event_insert_instrumentation(void *drcontext, void *tag, instrlist_t *bb, instr_t *instr, bool for_trace, bool translating, void *user_data) { if (drmgr_is_first_instr(drcontext, instr)) { uint num_instrs = (uint)(ptr_uint_t)user_data; int i; app_pc bb_addr = dr_fragment_app_pc(tag); for (i = 0; i < num_mods; i++) { if (mod_array[i].loaded && mod_array[i].base <= bb_addr && mod_array[i].end > bb_addr) break; } if (i == num_mods) i = UNKNOW_MODULE_IDX; /* We pass SPILL_SLOT_MAX+1 as drx will use drreg for spilling. */ drx_insert_counter_update(drcontext, bb, instr, SPILL_SLOT_MAX+1, (void *)&mod_cnt[i], num_instrs, DRX_COUNTER_64BIT); drx_insert_counter_update(drcontext, bb, instr, SPILL_SLOT_MAX+1, (void *)&ins_count, num_instrs, DRX_COUNTER_64BIT); } if (instr_is_mbr(instr) && !instr_is_return(instr)) { /* Assuming most of the transfers between modules are paired, we * instrument indirect branches but not returns for better performance. * We assume that most cross module transfers happens via indirect * branches. * Direct branch with DGC or self-modify may also cross modules, but * it should be ok to ignore, and we can handle them more efficiently. */ /* dr_insert_mbr_instrumentation is going to read app values, so we need a * drreg lazy restore "barrier" here. */ drreg_status_t res = drreg_restore_app_values(drcontext, bb, instr, instr_get_target(instr), NULL); DR_ASSERT(res == DRREG_SUCCESS || res == DRREG_ERROR_NO_APP_VALUE); dr_insert_mbr_instrumentation(drcontext, bb, instr, (void *)mbr_update, SPILL_SLOT_1); } return DR_EMIT_DEFAULT; }