static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { int i; instr_t *instr, *first = instrlist_first(bb); for (instr = first; instr != NULL; instr = instr_get_next(instr)) { if (instr_reads_memory(instr)) { for (i = 0; i < instr_num_srcs(instr); i++) { if (opnd_is_memory_reference(instr_get_src(instr, i))) { instrument_mem(drcontext, bb, instr, i, false); } } } if (instr_writes_memory(instr)) { for (i = 0; i < instr_num_dsts(instr); i++) { if (opnd_is_memory_reference(instr_get_dst(instr, i))) { instrument_mem(drcontext, bb, instr, i, true); } } } } // dr_printf("count %d\n",count); return DR_EMIT_DEFAULT; }
/* event_bb_insert calls instrument_mem to instrument every * application memory reference. */ dr_emit_flags_t memtrace_bb_instrumentation(void *drcontext, void *tag, instrlist_t *bb, instr_t *instr, bool for_trace, bool translating, void *user_data) { int i; reg_id_t reg; file_t out_file; instr_t * first = NULL; instr_t * current; //DR_ASSERT(instr_ok_to_mangle(instr)); if (instr_ok_to_mangle(instr)){ /* FIXME - need to generalize the filtering library */ for (current = instrlist_first(bb); current != NULL; current = instr_get_next(current)){ if (instr_ok_to_mangle(current)){ first = current; break; } } if ((first != NULL) && filter_from_list(head, first, client_arg->filter_mode)){ if (instr_reads_memory(instr)) { for (i = 0; i < instr_num_srcs(instr); i++) { if (opnd_is_memory_reference(instr_get_src(instr, i))) { instrument_mem(drcontext, bb, instr, i, false); } } } if (instr_writes_memory(instr)) { for (i = 0; i < instr_num_dsts(instr); i++) { if (opnd_is_memory_reference(instr_get_dst(instr, i))) { instrument_mem(drcontext, bb, instr, i, true); } } } } } 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; reg_id_t *reg_next = (reg_id_t *)user_data; bool seen_memref = false; /* If the previous instruction was a write, we should handle it. */ if (*reg_next != DR_REG_NULL) handle_post_write(drcontext, bb, instr, *reg_next); *reg_next = DR_REG_NULL; if (!instr_is_app(instr)) return DR_EMIT_DEFAULT; if (!instr_writes_memory(instr)) return DR_EMIT_DEFAULT; /* XXX: See above, in handle_post_write(). To simplify the handling of registers, we * assume no instruction has multiple distinct memory destination operands. */ for (i = 0; i < instr_num_dsts(instr); ++i) { if (opnd_is_memory_reference(instr_get_dst(instr, i))) { if (seen_memref) { DR_ASSERT_MSG(false, "Found inst with multiple memory destinations"); break; } *reg_next = instrument_mem(drcontext, bb, instr, instr_get_dst(instr, i)); seen_memref = true; } } 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; }
/* event_bb_insert calls instrument_mem 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) { int i; if (instr_get_app_pc(instr) == NULL) return DR_EMIT_DEFAULT; if (instr_reads_memory(instr)) { for (i = 0; i < instr_num_srcs(instr); i++) { if (opnd_is_memory_reference(instr_get_src(instr, i))) { instrument_mem(drcontext, bb, instr, i, false); } } } if (instr_writes_memory(instr)) { for (i = 0; i < instr_num_dsts(instr); i++) { if (opnd_is_memory_reference(instr_get_dst(instr, i))) { instrument_mem(drcontext, bb, instr, i, true); } } } return DR_EMIT_DEFAULT; }