static void instrument_post_write(void *drcontext, instrlist_t *ilist, instr_t *where, opnd_t memref, instr_t *write, reg_id_t reg_addr) { reg_id_t reg_ptr; ushort stride = (ushort)drutil_opnd_mem_size_in_bytes(memref, write); /* We want to use the same predicate as write when inserting the following * instrumentation. */ instrlist_set_auto_predicate(ilist, instr_get_predicate(write)); if (drreg_reserve_register(drcontext, ilist, where, NULL, ®_ptr) != DRREG_SUCCESS) { DR_ASSERT(false); return; } drx_buf_insert_load_buf_ptr(drcontext, write_buffer, ilist, where, reg_ptr); /* drx_buf_insert_buf_memcpy() internally updates the buffer pointer */ drx_buf_insert_buf_memcpy(drcontext, write_buffer, ilist, where, reg_ptr, reg_addr, stride); if (drreg_unreserve_register(drcontext, ilist, where, reg_ptr) != DRREG_SUCCESS) DR_ASSERT(false); if (drreg_unreserve_register(drcontext, ilist, where, reg_addr) != DRREG_SUCCESS) DR_ASSERT(false); /* Set the predicate back to the default */ instrlist_set_auto_predicate(ilist, instr_get_predicate(where)); }
/* 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)); }
bool instr_is_ubr_arch(instr_t *instr) { int opc = instr->opcode; /* caller ensures opcode is valid */ if (opc == OP_b || opc == OP_b_short) { dr_pred_type_t pred = instr_get_predicate(instr); return (pred == DR_PRED_NONE || pred == DR_PRED_AL); } return false; }
bool instr_is_cbr_arch(instr_t *instr) { int opc = instr->opcode; /* caller ensures opcode is valid */ if (opc == OP_cbnz || opc == OP_cbz) return true; /* We don't consider a predicated indirect branch to be a cbr */ if (opc == OP_b || opc == OP_b_short || /* Yes, conditional calls are considered cbr */ opc == OP_bl || opc == OP_blx) { dr_pred_type_t pred = instr_get_predicate(instr); return (pred != DR_PRED_NONE && pred != DR_PRED_AL); } /* XXX: should OP_it be considered a cbr? */ return false; }