static dr_emit_flags_t event_bb_insert(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst, bool for_trace, bool translating, void *user_data) { static int freq; reg_id_t reg1 = IF_X86_ELSE(DR_REG_XAX, DR_REG_R0); reg_id_t reg2 = IF_X86_ELSE(DR_REG_XCX, DR_REG_R1); CHECK(drmgr_is_first_instr(drcontext, instrlist_first_app(bb)), "first incorrect"); CHECK(!drmgr_is_first_instr(drcontext, instrlist_last(bb)) || instrlist_first_app(bb) == instrlist_last(bb), "first incorrect"); CHECK(drmgr_is_last_instr(drcontext, instrlist_last(bb)), "last incorrect"); CHECK(!drmgr_is_last_instr(drcontext, instrlist_first_app(bb)) || instrlist_first_app(bb) == instrlist_last(bb), "last incorrect"); /* hack to instrument every nth bb. assumes DR serializes bb events. */ freq++; if (freq % 100 == 0 && inst == (instr_t*)user_data/*first instr*/) { /* test read from cache */ dr_save_reg(drcontext, bb, inst, reg1, SPILL_SLOT_1); drmgr_insert_read_tls_field(drcontext, tls_idx, bb, inst, reg1); dr_insert_clean_call(drcontext, bb, inst, (void *)check_tls_from_cache, false, 1, opnd_create_reg(reg1)); drmgr_insert_read_cls_field(drcontext, cls_idx, bb, inst, reg1); dr_insert_clean_call(drcontext, bb, inst, (void *)check_cls_from_cache, false, 1, opnd_create_reg(reg1)); dr_restore_reg(drcontext, bb, inst, reg1, SPILL_SLOT_1); } if (freq % 300 == 0 && inst == (instr_t*)user_data/*first instr*/) { instr_t *first, *second; /* test write from cache */ dr_save_reg(drcontext, bb, inst, reg1, SPILL_SLOT_1); dr_save_reg(drcontext, bb, inst, reg2, SPILL_SLOT_2); instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)MAGIC_NUMBER_FROM_CACHE, opnd_create_reg(reg1), bb, inst, &first, &second); instr_set_meta(first); if (second != NULL) instr_set_meta(second); drmgr_insert_write_tls_field(drcontext, tls_idx, bb, inst, reg1, reg2); dr_insert_clean_call(drcontext, bb, inst, (void *)check_tls_write_from_cache, false, 0); drmgr_insert_write_cls_field(drcontext, cls_idx, bb, inst, reg1, reg2); dr_insert_clean_call(drcontext, bb, inst, (void *)check_cls_write_from_cache, false, 0); dr_restore_reg(drcontext, bb, inst, reg2, SPILL_SLOT_2); dr_restore_reg(drcontext, bb, inst, reg1, SPILL_SLOT_1); } return DR_EMIT_DEFAULT; }
static dr_emit_flags_t event_app_instruction(void *drcontext, void *tag, instrlist_t *bb, instr_t *instr, bool for_trace, bool translating, void *user_data) { /* We test reserving across app instrs by reserving on each store and * unreserving on the subsequent instr. */ drvector_t allowed; if (reg != DR_REG_NULL) { if (drreg_unreserve_register(drcontext, bb, instr, reg) != DRREG_SUCCESS) CHECK(false, "failed to unreserve"); reg = DR_REG_NULL; } if (!instr_is_app(instr)) return DR_EMIT_DEFAULT; if (!instr_writes_memory(instr)) return DR_EMIT_DEFAULT; if (!drmgr_is_last_instr(drcontext, instr)) { drreg_init_and_fill_vector(&allowed, true); /* Limit the registers for more of a stress test: */ drreg_set_vector_entry(&allowed, IF_X86_ELSE(DR_REG_XCX, DR_REG_R0), false); drreg_set_vector_entry(&allowed, IF_X86_ELSE(DR_REG_XDX, DR_REG_R1), false); if (drreg_reserve_register(drcontext, bb, instr, &allowed, ®) != DRREG_SUCCESS) DR_ASSERT(false); drvector_delete(&allowed); } 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) { per_bb_data_t *per_bb = (per_bb_data_t *)user_data; /* We increment the per-bb counters just once, at the top of the bb. */ if (drmgr_is_first_instr(drcontext, instr)) { /* drx will analyze whether to save the flags for us. */ uint flags = DRX_COUNTER_LOCK; if (per_bb->num_instrs > 0) { drx_insert_counter_update(drcontext, bb, instr, SPILL_SLOT_MAX+1, &stats->num_instrs, per_bb->num_instrs, flags); } if (per_bb->num_flops > 0) { drx_insert_counter_update(drcontext, bb, instr, SPILL_SLOT_MAX+1, &stats->num_flops, per_bb->num_flops, flags); } if (per_bb->num_syscalls > 0) { drx_insert_counter_update(drcontext, bb, instr, SPILL_SLOT_MAX+1, &stats->num_syscalls, per_bb->num_syscalls, flags); } } if (drmgr_is_last_instr(drcontext, instr)) dr_thread_free(drcontext, per_bb, sizeof(*per_bb)); return DR_EMIT_DEFAULT; }