void cfi_call_instrumentation_snapahot(void *dcontext, instrlist_t *ilist, instr_t *where, void *callee) { uint dstack_offs = 0, pad = 0; unsigned int eflags_offs; CFI_ASSERT(dcontext != NULL, "cfi_call_instrumentation_snapahot: dcontext cannot be NULL"); instr_t *next_snapshot = INSTR_CREATE_label(dcontext); PRE(ilist, where, INSTR_CREATE_pushf(dcontext)); dstack_offs += XSP_SZ; eflags_offs = dstack_offs; PRE(ilist, where, INSTR_CREATE_push(dcontext, opnd_create_reg(DR_REG_RDI))); dstack_offs += XSP_SZ; PRE(ilist, where, INSTR_CREATE_mov_imm(dcontext, opnd_create_reg(DR_REG_RDI), OPND_CREATE_INT64(&flag_memory_snapshot))); PRE(ilist, where, INSTR_CREATE_mov_ld(dcontext, opnd_create_reg(DR_REG_RDI), opnd_create_base_disp(DR_REG_RDI, DR_REG_NULL, 0, 0, OPSZ_PTR))); PRE(ilist, where, INSTR_CREATE_cmp(dcontext, opnd_create_reg(DR_REG_RDI), OPND_CREATE_INT8(0x0))); PRE(ilist, where, INSTR_CREATE_jcc(dcontext, OP_je, opnd_create_instr(next_snapshot))); PRE(ilist, where, INSTR_CREATE_push(dcontext, opnd_create_base_disp(DR_REG_RSP, DR_REG_NULL, 0, dstack_offs - eflags_offs, OPSZ_STACK))); PRE(ilist, where, INSTR_CREATE_and(dcontext, opnd_create_base_disp(DR_REG_RSP, DR_REG_NULL, 0, 0, OPSZ_STACK), OPND_CREATE_INT32(~(EFLAGS_NON_SYSTEM | EFLAGS_IF)))); PRE(ilist, where, INSTR_CREATE_popf(dcontext)); instrlist_set_our_mangling(ilist, true); cfi_insert_meta_native_call_vargs(dcontext, ilist, where, true/*clean*/, callee); instrlist_set_our_mangling(ilist, false); cfi_insert_native_call(dcontext, ilist, where, callee /*, opnd_create_reg(DR_REG_RAX)*/); PRE(ilist, where, next_snapshot); PRE(ilist, where, INSTR_CREATE_pop(dcontext, opnd_create_reg(DR_REG_RDI))); PRE(ilist, where, INSTR_CREATE_popf(dcontext)); /* dstack_offs = cfi_prepare_for_native_call(dcontext, ilist, where); instrlist_set_our_mangling(ilist, true); cfi_insert_meta_native_call_vargs(dcontext, ilist, where, true*//*clean*//*, callee); instrlist_set_our_mangling(ilist, false); cfi_cleanup_after_native_call(dcontext, ilist, where);*/ }
static void instrument_mem(void *drcontext, instrlist_t *ilist, instr_t *where, int pos, bool write) { instr_t *instr; opnd_t ref, opnd1, opnd2; reg_id_t reg1 = DR_REG_XAX; /* We can optimize it by picking dead reg */ reg_id_t reg2 = DR_REG_XCX; /* reg2 must be ECX or RCX for jecxz */ if (write) ref = instr_get_dst(where, pos); else ref = instr_get_src(where, pos); dr_save_reg(drcontext, ilist, where, reg1, SPILL_SLOT_2); dr_save_reg(drcontext, ilist, where, reg2, SPILL_SLOT_3); // reg2 = RBufIdx opnd1 = opnd_create_reg(reg2); opnd2 = OPND_CREATE_ABSMEM((byte *)&RBufIdx, OPSZ_4); instr = INSTR_CREATE_mov_ld(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); // save flags since we are using inc, and dr_save_arith_flags_to_xax(drcontext, ilist, where); // reg2 = reg2 & RBUF_SIZE opnd1 = opnd_create_reg(reg2); opnd2 = OPND_CREATE_INT32(RBUF_SIZE); instr = INSTR_CREATE_and(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); dr_restore_arith_flags_from_xax(drcontext, ilist, where); // reg1 = &RBuf opnd1 = opnd_create_reg(reg1); opnd2 = OPND_CREATE_INTPTR(RBuf); instr = INSTR_CREATE_mov_imm(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); // reg1 = reg1 + reg2 * sizeof(uint) // = RBuf + RBufIdx * sizeof(uint) // = RBuf[RBufIdx] opnd1 = opnd_create_reg(reg1); opnd2 = opnd_create_base_disp(reg1, reg2, sizeof(uint), 0, OPSZ_lea); instr = INSTR_CREATE_lea(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); // RBuf[RBufIdx].addr = addr; opnd1 = OPND_CREATE_MEMPTR(reg1, 0); drutil_insert_get_mem_addr(drcontext, ilist, where, ref, reg2, reg1); opnd2 = opnd_create_reg(reg2); instr = INSTR_CREATE_mov_st(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); dr_save_arith_flags_to_xax(drcontext, ilist, where); // reg2 = RBufIdx opnd1 = opnd_create_reg(reg2); opnd2 = OPND_CREATE_ABSMEM((byte *)&RBufIdx, OPSZ_4); instr = INSTR_CREATE_mov_ld(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); // reg2 = reg2 + 1 opnd1 = opnd_create_reg(reg2); instr = INSTR_CREATE_inc(drcontext, opnd1); instrlist_meta_preinsert(ilist, where, instr); // RBufIdx = reg2 opnd1 = OPND_CREATE_ABSMEM((byte *)&RBufIdx, OPSZ_4); opnd2 = opnd_create_reg(reg2); instr = INSTR_CREATE_mov_st(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); dr_restore_arith_flags_from_xax(drcontext, ilist, where); dr_restore_reg(drcontext, ilist, where, reg1, SPILL_SLOT_2); dr_restore_reg(drcontext, ilist, where, reg2, SPILL_SLOT_3); }
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; }