/* event_bb_insert calls instrument_instr to instrument every * application memory reference. */ static dr_emit_flags_t event_bb_insert(void *drcontext, void *tag, instrlist_t *bb, instr_t *instr, bool for_trace, bool translating, void *user_data) { if (instr_get_app_pc(instr) == NULL || !instr_is_app(instr)) return DR_EMIT_DEFAULT; instrument_instr(drcontext, bb, instr); return DR_EMIT_DEFAULT; }
/* For each memory reference app instr, we insert inline code to fill the buffer * with an instruction entry and memory reference entries. */ 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) { int i; if (!instr_is_app(instr)) return DR_EMIT_DEFAULT; if (!instr_reads_memory(instr) && !instr_writes_memory(instr)) return DR_EMIT_DEFAULT; /* insert code to add an entry for app instruction */ instrument_instr(drcontext, bb, instr); /* insert code to add an entry for each memory reference opnd */ for (i = 0; i < instr_num_srcs(instr); i++) { if (opnd_is_memory_reference(instr_get_src(instr, i))) instrument_mem(drcontext, bb, instr, instr_get_src(instr, i), false); } for (i = 0; i < instr_num_dsts(instr); i++) { if (opnd_is_memory_reference(instr_get_dst(instr, i))) instrument_mem(drcontext, bb, instr, instr_get_dst(instr, i), true); } /* insert code to call clean_call for processing the buffer */ if (/* XXX i#1698: there are constraints for code between ldrex/strex pairs, * so we minimize the instrumentation in between by skipping the clean call. * As we're only inserting instrumentation on a memory reference, and the * app should be avoiding memory accesses in between the ldrex...strex, * the only problematic point should be before the strex. * However, there is still a chance that the instrumentation code may clear the * exclusive monitor state. * Using a fault to handle a full buffer should be more robust, and the * forthcoming buffer filling API (i#513) will provide that. */ IF_AARCHXX_ELSE(!instr_is_exclusive_store(instr), true)) dr_insert_clean_call(drcontext, bb, instr, (void *)clean_call, false, 0); return DR_EMIT_DEFAULT; }