void cfi_cleanup_after_native_call(void *drcontext, instrlist_t *ilist, instr_t *where) { instr_t *in = (where == NULL) ? instrlist_last(ilist) : instr_get_prev(where); CFI_ASSERT(drcontext != NULL, "dr_cleanup_after_call: drcontext cannot be NULL"); /* PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RDI))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RSI))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RBP)));*/ /* skip xsp by popping into dead rbx */ /* PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RBX))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RBX))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RDX))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RCX))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RAX))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R8))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R9))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R10))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R11))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R12))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R13))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R14))); PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R15))); PRE(ilist, where, INSTR_CREATE_lea (drcontext, opnd_create_reg(REG_XSP), OPND_CREATE_MEM_lea(REG_XSP, REG_NULL, 0, XMM_SLOTS_SIZE))); */ PRE(ilist, where, INSTR_CREATE_popf(drcontext)); /* now go through and mark inserted instrs as meta */ if (in == NULL) in = instrlist_first(ilist); else in = instr_get_next(in); while (in != where) { instr_set_ok_to_mangle(in, false); in = instr_get_next(in); } }
void cfi_insert_meta_native_call_vargs(void *dcontext, instrlist_t *bb, instr_t *cursor, bool clean_call, void *callee) { instr_t *in = (cursor == NULL) ? instrlist_last(bb) : instr_get_prev(cursor); // PRE(ilist, instr, INSTR_CREATE_mov_ld(dcontext, opnd_create_reg(REG_RDI), opnd_create_reg(REG_RSP))); PRE(bb, cursor, INSTR_CREATE_call(dcontext, opnd_create_pc(callee))); /* mark it all meta */ if (in == NULL) in = instrlist_first(bb); else in = instr_get_next(in); while (in != cursor) { instr_set_ok_to_mangle(in, false); in = instr_get_next(in); } }
/* To support multiple non-meta ctis in app2app phase, we mark them meta * before handing to DR to satisfy its bb constraints */ static void drmgr_fix_app_ctis(void *drcontext, instrlist_t *bb) { instr_t *inst; for (inst = instrlist_first(bb); inst != NULL; inst = instr_get_next(inst)) { /* Any CTI with an instr target must have an intra-bb target and thus * we assume it should not be mangled. We mark it meta. */ if (instr_ok_to_mangle(inst) && instr_is_cti(inst) && opnd_is_instr(instr_get_target(inst))) { instr_set_ok_to_mangle(inst, false); /* instrumentation passes should set the translation field * so other passes can see what app pc these app instrs * correspond to: but DR complains if there's a meta instr * w/ a translation but no restore_state event */ instr_set_translation(inst, NULL); } } }
static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { instr_t *first = instrlist_first(bb); app_pc pc = dr_fragment_app_pc(tag); instr_t *mov1, *mov2; /* We try to avoid register stealing by using "dead" register if possible. * However, technically, a fault could come in and want the original value * of the "dead" register, but that's too corner-case for us. */ reg_id_t reg = bb_find_dead_reg(bb); bool steal = (reg == DR_REG_NULL); if (reg == DR_REG_NULL) reg = DR_REG_XCX; /* randomly use one if no dead reg found */ /* save register if necessary */ if (steal) dr_save_reg(drcontext, bb, first, reg, SPILL_SLOT_1); /* load buffer pointer from TLS field */ MINSERT(bb, first, INSTR_CREATE_mov_ld (drcontext, opnd_create_reg(reg), opnd_create_far_base_disp(tls_seg, DR_REG_NULL, DR_REG_NULL, 0, tls_offs, OPSZ_PTR))); /* store bb's start pc into the buffer */ instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)pc, OPND_CREATE_MEMPTR(reg, 0), bb, first, &mov1, &mov2); DR_ASSERT(mov1 != NULL); instr_set_ok_to_mangle(mov1, false); if (mov2 != NULL) instr_set_ok_to_mangle(mov2, false); /* update the TLS buffer pointer by incrementing just the bottom 16 bits of * the pointer */ if (bb_aflags_are_dead(bb, first)) { /* if aflags are dead, we use add directly */ MINSERT(bb, first, INSTR_CREATE_add (drcontext, opnd_create_far_base_disp(tls_seg, DR_REG_NULL, DR_REG_NULL, 0, tls_offs, OPSZ_2), OPND_CREATE_INT8(sizeof(app_pc)))); } else { reg_id_t reg_16; #ifdef X64 reg_16 = reg_32_to_16(reg_64_to_32(reg)); #else reg_16 = reg_32_to_16(reg); #endif /* we use lea to avoid aflags save/restore */ MINSERT(bb, first, INSTR_CREATE_lea (drcontext, opnd_create_reg(reg_16), opnd_create_base_disp(reg, DR_REG_NULL, 0, sizeof(app_pc), OPSZ_lea))); MINSERT(bb, first, INSTR_CREATE_mov_st (drcontext, opnd_create_far_base_disp(tls_seg, DR_REG_NULL, DR_REG_NULL, 0, tls_offs, OPSZ_PTR), opnd_create_reg(reg))); } /* restore register if necessary */ if (steal) dr_restore_reg(drcontext, bb, first, reg, SPILL_SLOT_1); return DR_EMIT_DEFAULT; }
unsigned int cfi_prepare_for_native_call(void *drcontext, instrlist_t *ilist, instr_t *where) { unsigned int eflags_offs, dstack_offs = 0; instr_t *in = (where == NULL) ? instrlist_last(ilist) : instr_get_prev(where); CFI_ASSERT(drcontext != NULL, "cfi_prepare_for_native_call: drcontext cannot be NULL"); //PRE(ilist, where, INSTR_CREATE_push_imm(dcontext, OPND_CREATE_INT32(0))); //dstack_offs += XSP_SZ; PRE(ilist, where, INSTR_CREATE_pushf(drcontext)); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_base_disp(REG_XSP, REG_NULL, 0, 0, OPSZ_STACK))); PRE(ilist, where, INSTR_CREATE_and(drcontext, opnd_create_base_disp(REG_XSP, REG_NULL, 0, 0, OPSZ_STACK), OPND_CREATE_INT32(~(EFLAGS_NON_SYSTEM | EFLAGS_IF)))); PRE(ilist, where, INSTR_CREATE_popf(drcontext)); /* dstack_offs += XSP_SZ; eflags_offs = dstack_offs; PRE(ilist, where, INSTR_CREATE_lea(drcontext, opnd_create_reg(REG_XSP), OPND_CREATE_MEM_lea(REG_XSP, REG_NULL, 0, - XMM_SLOTS_SIZE))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R15))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R14))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R13))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R12))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R11))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R10))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R9))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R8))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RAX))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RCX))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RDX))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RBX)));*/ /* we do NOT match pusha xsp value *//* PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RSP))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RBP))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RSI))); PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RDI))); dstack_offs += 16*XSP_SZ + XMM_SLOTS_SIZE; PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_base_disp(REG_XSP, REG_NULL, 0, dstack_offs - eflags_offs, OPSZ_STACK))); PRE(ilist, where, INSTR_CREATE_and(drcontext, opnd_create_base_disp(REG_XSP, REG_NULL, 0, 0, OPSZ_STACK), OPND_CREATE_INT32(~(EFLAGS_NON_SYSTEM | EFLAGS_IF)))); PRE(ilist, where, INSTR_CREATE_popf(drcontext));*/ /* now go through and mark inserted instrs as meta */ if (in == NULL) in = instrlist_first(ilist); else in = instr_get_next(in); while (in != where) { instr_set_ok_to_mangle(in, false); in = instr_get_next(in); } return dstack_offs; }
dr_emit_flags_t bb_event(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { instr_t *instr, *next_instr; app_pc bb_addr = dr_fragment_app_pc(tag); if (bb_addr == start_pc) { instrument = true; } else if (bb_addr == stop_pc) { instrument = false; } if (!instrument) { return DR_EMIT_DEFAULT; } for (instr = instrlist_first(bb); instr != NULL; instr = next_instr) { next_instr = instr_get_next(instr); /* * Conditional branch. We can determine the target and * fallthrough addresses here, but we need to instrument if we * want to record the edge only if it actually executes at * runtime. Instead of using dr_insert_cbr_instrumentation, * we'll insert separate instrumentation for the taken and not * taken cases and remove it separately after we see each * case. */ if (instr_is_cbr(instr)) { app_pc src = instr_get_app_pc(instr); cbr_state_t state; bool insert_taken, insert_not_taken; /* First look up the state of this branch so we * know what instrumentation to insert, if any. */ elem_t *elem = lookup(table, src); if (elem == NULL) { state = CBR_NONE; insert(table, src, CBR_NONE); } else { state = elem->state; } insert_taken = (state & CBR_TAKEN) == 0; insert_not_taken = (state & CBR_NOT_TAKEN) == 0; if (insert_taken || insert_not_taken) { app_pc fall = (app_pc)decode_next_pc(drcontext, (byte *)src); app_pc targ = instr_get_branch_target_pc(instr); /* * Redirect the cbr to jump to the 'taken' callout. * We'll insert a 'not-taken' callout at fallthrough * address. */ instr_t *label = INSTR_CREATE_label(drcontext); instr_set_ok_to_mangle(instr, false); instr_set_translation(instr, NULL); /* If this is a short cti, make sure it can reach its new target */ if (instr_is_cti_short(instr)) { /* if jecxz/loop we want to set the target of the long-taken * so set instr to the return value */ instr = instr_convert_short_meta_jmp_to_long(drcontext, bb, instr); } instr_set_target(instr, opnd_create_instr(label)); if (insert_not_taken) { /* * Callout for the not-taken case */ dr_insert_clean_call(drcontext, bb, NULL, (void*)at_not_taken, false /* don't save fp state */, 2 /* 2 args for at_not_taken */, OPND_CREATE_INTPTR((ptr_uint_t)src), OPND_CREATE_INTPTR((ptr_uint_t)fall)); } /* * Jump to the original fall-through address. * (This should not be a meta-instruction). */ instrlist_preinsert (bb, NULL, INSTR_XL8 (INSTR_CREATE_jmp(drcontext, opnd_create_pc(fall)), fall)); /* label goes before the 'taken' callout */ MINSERT(bb, NULL, label); if (insert_taken) { /* * Callout for the taken case */ dr_insert_clean_call(drcontext, bb, NULL, (void*)at_taken, false /* don't save fp state */, 2 /* 2 args for at_taken */, OPND_CREATE_INTPTR((ptr_uint_t)src), OPND_CREATE_INTPTR((ptr_uint_t)targ)); } /* * Jump to the original target block (this should * not be a meta-instruction). */ instrlist_preinsert (bb, NULL, INSTR_XL8 (INSTR_CREATE_jmp(drcontext, opnd_create_pc(targ)), targ)); } } } /* since our added instrumentation is not constant, we ask to store * translations now */ return DR_EMIT_STORE_TRANSLATIONS; }
void watchpoint_indirect_call_event(dcontext_t *drcontext, instrlist_t *ilist, instr_t *instr, instr_t *next_instr, bool mangle_calls, uint flags) { opnd_t instr_opnd; reg_id_t base_reg; unsigned long used_registers = 0; app_pc pc; struct memory_operand_modifier ops = {0}; instr_t *begin_instrumenting = INSTR_CREATE_label(drcontext); instr_t *done_instrumenting = INSTR_CREATE_label(drcontext); instr_t *nop = INSTR_CREATE_nop(drcontext); instr_t *emulated; memset(&ops, 0, sizeof(struct memory_operand_modifier)); if(instr_reads_memory(instr)) { instr_opnd = instr_get_src(instr, 0); if (opnd_is_rel_addr(instr_opnd) || opnd_is_abs_addr(instr_opnd)) { }else if (opnd_is_base_disp(instr_opnd)) { for_each_src_operand(instr, &ops, (opnd_callback_t *) memory_src_operand_finder); // base_reg = opnd_get_reg(instr_opnd); switch(ops.found_operand.value.base_disp.base_reg) { case DR_REG_RSP: case DR_REG_ESP: case DR_REG_SP: case DR_REG_RBP: case DR_REG_EBP: case DR_REG_BP: return; default: break; } collect_regs(&used_registers, instr, instr_num_srcs, instr_get_src ); collect_regs(&used_registers, instr, instr_num_dsts, instr_get_dst ); reg_id_t reg_watched_addr = get_next_free_reg(&used_registers); opnd_t opnd_watched_addr = opnd_create_reg(reg_watched_addr); reg_id_t reg_unwatched_addr = get_next_free_reg(&used_registers); opnd_t opnd_unwatched_addr = opnd_create_reg(reg_unwatched_addr); PRE(ilist, instr, begin_instrumenting); PRE(ilist, instr, INSTR_CREATE_push(drcontext, opnd_watched_addr)); PRE(ilist, instr, INSTR_CREATE_push(drcontext, opnd_unwatched_addr)); PRE(ilist, instr, INSTR_CREATE_pushf(drcontext)); PRE(ilist, instr, INSTR_CREATE_lea(drcontext, opnd_watched_addr, opnd_create_base_disp(opnd_get_base(ops.found_operand), opnd_get_index(ops.found_operand), opnd_get_scale(ops.found_operand), opnd_get_disp(ops.found_operand), OPSZ_lea))); PRE(ilist, instr, INSTR_CREATE_mov_imm(drcontext, opnd_unwatched_addr, OPND_CREATE_INT64(WATCHPOINT_INDEX_MASK))); PRE(ilist, instr, INSTR_CREATE_or(drcontext, opnd_unwatched_addr, opnd_watched_addr)); emulated = instr_clone(drcontext, instr); emulated->translation = 0; ops.replacement_operand = opnd_create_base_disp( reg_unwatched_addr, DR_REG_NULL,1, 0 , ops.found_operand.size); for_each_operand(emulated, &ops, (opnd_callback_t *) memory_operand_replacer); PRE(ilist, instr, INSTR_CREATE_popf(drcontext)); PRE(ilist, instr, emulated); PRE(ilist, instr, INSTR_CREATE_pop(drcontext, opnd_unwatched_addr)); PRE(ilist, instr, INSTR_CREATE_pop(drcontext, opnd_watched_addr)); PRE(ilist, instr, INSTR_CREATE_jmp_short(drcontext, opnd_create_instr(done_instrumenting))); pc = instr->translation; instr->translation = 0; // hack! instr_being_modified(instr, false); instr_set_ok_to_mangle(instr, false); if(NULL != pc){ nop->translation = pc + instr->length; } POST(ilist, instr, nop); POST(ilist, instr, done_instrumenting); } } }
/* * instrument_mem is called whenever a memory reference is identified. * It inserts code before the memory reference to to fill the memory buffer * and jump to our own code cache to call the clean_call when the buffer is full. */ static void instrument_mem(void *drcontext, instrlist_t *ilist, instr_t *where, int pos, bool write) { instr_t *instr, *call, *restore, *first, *second; opnd_t ref, opnd1, opnd2; reg_id_t reg1 = DR_REG_XBX; /* We can optimize it by picking dead reg */ reg_id_t reg2 = DR_REG_XCX; /* reg2 must be ECX or RCX for jecxz */ per_thread_t *data; app_pc pc; data = drmgr_get_tls_field(drcontext, tls_index); /* Steal the register for memory reference address * * We can optimize away the unnecessary register save and restore * by analyzing the code and finding the register is dead. */ dr_save_reg(drcontext, ilist, where, reg1, SPILL_SLOT_2); dr_save_reg(drcontext, ilist, where, reg2, SPILL_SLOT_3); if (write) ref = instr_get_dst(where, pos); else ref = instr_get_src(where, pos); /* use drutil to get mem address */ drutil_insert_get_mem_addr(drcontext, ilist, where, ref, reg1, reg2); /* The following assembly performs the following instructions * buf_ptr->write = write; * buf_ptr->addr = addr; * buf_ptr->size = size; * buf_ptr->pc = pc; * buf_ptr++; * if (buf_ptr >= buf_end_ptr) * clean_call(); */ drmgr_insert_read_tls_field(drcontext, tls_index, ilist, where, reg2); /* Load data->buf_ptr into reg2 */ opnd1 = opnd_create_reg(reg2); opnd2 = OPND_CREATE_MEMPTR(reg2, offsetof(per_thread_t, buf_ptr)); instr = INSTR_CREATE_mov_ld(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* Move write/read to write field */ opnd1 = OPND_CREATE_MEM32(reg2, offsetof(mem_ref_t, write)); opnd2 = OPND_CREATE_INT32(write); instr = INSTR_CREATE_mov_imm(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* Store address in memory ref */ opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(mem_ref_t, addr)); opnd2 = opnd_create_reg(reg1); instr = INSTR_CREATE_mov_st(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* Store size in memory ref */ opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(mem_ref_t, size)); /* drutil_opnd_mem_size_in_bytes handles OP_enter */ opnd2 = OPND_CREATE_INT32(drutil_opnd_mem_size_in_bytes(ref, where)); instr = INSTR_CREATE_mov_st(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* Store pc in memory ref */ pc = instr_get_app_pc(where); /* For 64-bit, we can't use a 64-bit immediate so we split pc into two halves. * We could alternatively load it into reg1 and then store reg1. * We use a convenience routine that does the two-step store for us. */ opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(mem_ref_t, pc)); instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t) pc, opnd1, ilist, where, &first, &second); instr_set_ok_to_mangle(first, false/*meta*/); if (second != NULL) instr_set_ok_to_mangle(second, false/*meta*/); /* Increment reg value by pointer size using lea instr */ opnd1 = opnd_create_reg(reg2); opnd2 = opnd_create_base_disp(reg2, DR_REG_NULL, 0, sizeof(mem_ref_t), OPSZ_lea); instr = INSTR_CREATE_lea(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* Update the data->buf_ptr */ drmgr_insert_read_tls_field(drcontext, tls_index, ilist, where, reg1); opnd1 = OPND_CREATE_MEMPTR(reg1, offsetof(per_thread_t, buf_ptr)); opnd2 = opnd_create_reg(reg2); instr = INSTR_CREATE_mov_st(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* we use lea + jecxz trick for better performance * lea and jecxz won't disturb the eflags, so we won't insert * code to save and restore application's eflags. */ /* lea [reg2 - buf_end] => reg2 */ opnd1 = opnd_create_reg(reg1); opnd2 = OPND_CREATE_MEMPTR(reg1, offsetof(per_thread_t, buf_end)); instr = INSTR_CREATE_mov_ld(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); opnd1 = opnd_create_reg(reg2); opnd2 = opnd_create_base_disp(reg1, reg2, 1, 0, OPSZ_lea); instr = INSTR_CREATE_lea(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* jecxz call */ call = INSTR_CREATE_label(drcontext); opnd1 = opnd_create_instr(call); instr = INSTR_CREATE_jecxz(drcontext, opnd1); instrlist_meta_preinsert(ilist, where, instr); /* jump restore to skip clean call */ restore = INSTR_CREATE_label(drcontext); opnd1 = opnd_create_instr(restore); instr = INSTR_CREATE_jmp(drcontext, opnd1); instrlist_meta_preinsert(ilist, where, instr); /* clean call */ /* We jump to lean procedure which performs full context switch and * clean call invocation. This is to reduce the code cache size. */ instrlist_meta_preinsert(ilist, where, call); /* mov restore DR_REG_XCX */ opnd1 = opnd_create_reg(reg2); /* this is the return address for jumping back from lean procedure */ opnd2 = opnd_create_instr(restore); /* We could use instrlist_insert_mov_instr_addr(), but with a register * destination we know we can use a 64-bit immediate. */ instr = INSTR_CREATE_mov_imm(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* jmp code_cache */ opnd1 = opnd_create_pc(code_cache); instr = INSTR_CREATE_jmp(drcontext, opnd1); instrlist_meta_preinsert(ilist, where, instr); /* restore %reg */ instrlist_meta_preinsert(ilist, where, restore); dr_restore_reg(drcontext, ilist, where, reg1, SPILL_SLOT_2); dr_restore_reg(drcontext, ilist, where, reg2, SPILL_SLOT_3); }
/* Inserts inst as a non-application instruction into ilist after "where" */ void instrlist_meta_postinsert(instrlist_t *ilist, instr_t *where, instr_t *inst) { instr_set_ok_to_mangle(inst, false); instrlist_postinsert(ilist, where, inst); }
static dr_emit_flags_t bb_event(void* drcontext, void *tag, instrlist_t* bb, bool for_trace, bool translating) { instr_t* instr = instrlist_first(bb); instr_t *ins1, *ins2; global_var = (ptr_uint_t)INT_MAX + 1; dr_prepare_for_call(drcontext, bb, instr); /* test push_imm */ instrlist_insert_push_immed_ptrsz(drcontext, (ptr_int_t)1, bb, instr, &ins1, &ins2); instr_set_ok_to_mangle(ins1, false); if (ins2 != NULL) /* ins2 should be NULL */ dr_fprintf(STDERR, "Error on push 1\n"); #ifdef X64 MINSERT(bb, instr, INSTR_CREATE_mov_ld (drcontext, opnd_create_reg(IF_LINUX_ELSE(DR_REG_RDX, DR_REG_R8)), OPND_CREATE_MEMPTR(DR_REG_RSP, 0))); #endif instrlist_insert_push_immed_ptrsz(drcontext, (ptr_int_t)-1, bb, instr, &ins1, &ins2); instr_set_ok_to_mangle(ins1, false); if (ins2 != NULL) /* ins2 should be NULL */ dr_fprintf(STDERR, "Error on push -1\n"); #ifdef X64 MINSERT(bb, instr, INSTR_CREATE_mov_ld (drcontext, opnd_create_reg(IF_LINUX_ELSE(DR_REG_RSI, DR_REG_RDX)), OPND_CREATE_MEMPTR(DR_REG_RSP, 0))); #endif instrlist_insert_push_immed_ptrsz(drcontext, global_var, bb, instr, &ins1, &ins2); instr_set_ok_to_mangle(ins1, false); #ifdef X64 if (ins2 == NULL) /* ins2 should not be NULL */ dr_fprintf(STDERR, "Error on push tag\n"); else instr_set_ok_to_mangle(ins2, false); #endif #ifdef X64 MINSERT(bb, instr, INSTR_CREATE_mov_ld (drcontext, opnd_create_reg(IF_LINUX_ELSE(DR_REG_RDI, DR_REG_RCX)), OPND_CREATE_MEMPTR(DR_REG_RSP, 0))); #endif /* test mov_imm */ instrlist_insert_mov_immed_ptrsz(drcontext, global_var, OPND_CREATE_ABSMEM(&var0, OPSZ_PTR), bb, instr, &ins1, &ins2); instr_set_ok_to_mangle(ins1, false); #ifdef X64 if (ins2 == NULL) /* ins2 should not be NULL */ dr_fprintf(STDERR, "Error on mov %p\n", global_var); else instr_set_ok_to_mangle(ins2, false); #endif instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)-1, OPND_CREATE_ABSMEM(&var1, OPSZ_PTR), bb, instr, &ins1, &ins2); instr_set_ok_to_mangle(ins1, false); if (ins2 != NULL) /* ins2 should be NULL */ dr_fprintf(STDERR, "Error on mov -1\n"); instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)1, OPND_CREATE_ABSMEM(&var2, OPSZ_PTR), bb, instr, &ins1, &ins2); instr_set_ok_to_mangle(ins1, false); if (ins2 != NULL) /* ins2 should be NULL */ dr_fprintf(STDERR, "Error on mov 1\n"); /* call */ MINSERT(bb, instr, INSTR_CREATE_call (drcontext, opnd_create_pc((void*)my_abort))); dr_cleanup_after_call(drcontext, bb, instr, 0); return DR_EMIT_DEFAULT; }