コード例 #1
0
ファイル: instru_offline.cpp プロジェクト: mdlui/dynamorio
void
offline_instru_t::insert_save_pc(void *drcontext, instrlist_t *ilist, instr_t *where,
                                 reg_id_t reg_ptr, reg_id_t scratch, int adjust,
                                 uint64_t value)
{
    int disp = adjust;
#ifdef X64
    instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t) value,
                                     opnd_create_reg(scratch),
                                     ilist, where, NULL, NULL);
    MINSERT(ilist, where,
            XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(reg_ptr, disp),
                               opnd_create_reg(scratch)));
#else
    instrlist_insert_mov_immed_ptrsz(drcontext, (int)value,
                                     opnd_create_reg(scratch),
                                     ilist, where, NULL, NULL);
    MINSERT(ilist, where,
            XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(reg_ptr, disp),
                               opnd_create_reg(scratch)));
    instrlist_insert_mov_immed_ptrsz(drcontext, (int)(value >> 32),
                                     opnd_create_reg(scratch),
                                     ilist, where, NULL, NULL);
    MINSERT(ilist, where,
            XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(reg_ptr, disp + 4),
                               opnd_create_reg(scratch)));
#endif
}
コード例 #2
0
ファイル: memtrace_simple.c プロジェクト: DynamoRIO/dynamorio
static void
insert_save_size(void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t base,
                 reg_id_t scratch, ushort size)
{
    scratch = reg_resize_to_opsz(scratch, OPSZ_2);
    MINSERT(ilist, where,
            XINST_CREATE_load_int(drcontext, opnd_create_reg(scratch),
                                  OPND_CREATE_INT16(size)));
    MINSERT(ilist, where,
            XINST_CREATE_store_2bytes(drcontext,
                                      OPND_CREATE_MEM16(base, offsetof(mem_ref_t, size)),
                                      opnd_create_reg(scratch)));
}
コード例 #3
0
ファイル: drx.c プロジェクト: boolking/dynamorio
/* Insert arithmetic flags restore code with more control.
 * For x86:
 * - skip %eax restore if !restore_reg
 * - restore %eax from reg if reg is not DR_REG_NULL
 * - restore %eax from slot otherwise
 * For ARM:
 * - restores flags from reg
 * - restores reg to slot, unless !restore_reg.
 * Routine merge_prev_drx_aflags_switch looks for labels inserted by
 * drx_restore_arith_flags, so changes to this routine may affect
 * merge_prev_drx_aflags_switch.
 */
static void
drx_restore_arith_flags(void *drcontext, instrlist_t *ilist, instr_t *where,
                        bool restore_reg, bool restore_oflag,
                        dr_spill_slot_t slot, reg_id_t reg)
{
    instr_t *instr;
    ilist_insert_note_label(drcontext, ilist, where,
                            NOTE_VAL(DRX_NOTE_AFLAGS_RESTORE_BEGIN));
#ifdef X86
    if (restore_oflag) {
        /* add 0x7f, %al */
        instr = INSTR_CREATE_add(drcontext, opnd_create_reg(DR_REG_AL),
                                 OPND_CREATE_INT8(0x7f));
        MINSERT(ilist, where, instr);
    }
    /* sahf */
    instr = INSTR_CREATE_sahf(drcontext);
    instr_set_note(instr, NOTE_VAL(DRX_NOTE_AFLAGS_RESTORE_SAHF));
    MINSERT(ilist, where, instr);
    /* restore eax if necessary */
    if (restore_reg) {
        if (reg != DR_REG_NULL) {
            ASSERT(reg >= DR_REG_START_GPR && reg <= DR_REG_STOP_GPR &&
                   reg != DR_REG_XAX, "wrong dead reg");
            MINSERT(ilist, where,
                    INSTR_CREATE_mov_st(drcontext,
                                        opnd_create_reg(DR_REG_XAX),
                                        opnd_create_reg(reg)));
        } else {
            ASSERT(slot >= SPILL_SLOT_1 && slot <= SPILL_SLOT_MAX,
                   "wrong spill slot");
            dr_restore_reg(drcontext, ilist, where, DR_REG_XAX, slot);
        }
    }
#elif defined(ARM)
    ASSERT(reg >= DR_REG_START_GPR && reg <= DR_REG_STOP_GPR, "reg must be a GPR");
    instr = INSTR_CREATE_mrs(drcontext, opnd_create_reg(reg),
                             opnd_create_reg(DR_REG_CPSR));
    instr_set_note(instr, NOTE_VAL(DRX_NOTE_AFLAGS_RESTORE_SAHF));
    MINSERT(ilist, where, instr);
    if (restore_reg) {
        ASSERT(slot >= SPILL_SLOT_1 && slot <= SPILL_SLOT_MAX,
               "wrong spill slot");
        dr_restore_reg(drcontext, ilist, where, reg, slot);
    }
#endif
    ilist_insert_note_label(drcontext, ilist, where,
                            NOTE_VAL(DRX_NOTE_AFLAGS_RESTORE_END));
}
コード例 #4
0
ファイル: drx.c プロジェクト: boolking/dynamorio
/* insert a label instruction with note */
static void
ilist_insert_note_label(void *drcontext, instrlist_t *ilist, instr_t *where,
                        void *note)
{
    instr_t *instr = INSTR_CREATE_label(drcontext);
    instr_set_note(instr, note);
    MINSERT(ilist, where, instr);
}
コード例 #5
0
ファイル: memtrace_simple.c プロジェクト: DynamoRIO/dynamorio
static void
insert_update_buf_ptr(void *drcontext, instrlist_t *ilist, instr_t *where,
                      reg_id_t reg_ptr, int adjust)
{
    MINSERT(
        ilist, where,
        XINST_CREATE_add(drcontext, opnd_create_reg(reg_ptr), OPND_CREATE_INT16(adjust)));
    dr_insert_write_raw_tls(drcontext, ilist, where, tls_seg,
                            tls_offs + MEMTRACE_TLS_OFFS_BUF_PTR, reg_ptr);
}
コード例 #6
0
ファイル: fragdel.dll.c プロジェクト: Arunpreet/dynamorio
static
dr_emit_flags_t bb_event(void* drcontext, app_pc tag, instrlist_t* bb, bool for_trace, bool translating)
{
    if (tag >= start && tag < end) {
        instr_t* instr = instrlist_first(bb);

        dr_prepare_for_call(drcontext, bb, instr);
    
        MINSERT(bb, instr, INSTR_CREATE_push_imm
                (drcontext, OPND_CREATE_INT32((ptr_uint_t)tag)));
        MINSERT(bb, instr, INSTR_CREATE_push_imm
                (drcontext, OPND_CREATE_INT32((ptr_uint_t)drcontext)));
        MINSERT(bb, instr, INSTR_CREATE_call
                (drcontext, opnd_create_pc((void*)delete_fragment)));
        
        dr_cleanup_after_call(drcontext, bb, instr, 8);
    }
    return DR_EMIT_DEFAULT;
}
コード例 #7
0
ファイル: drx.c プロジェクト: boolking/dynamorio
/* Insert arithmetic flags saving code with more control.
 * For x86:
 * - skip %eax save if !save_reg
 * - save %eax to reg if reg is not DR_REG_NULL,
 * - save %eax to slot otherwise
 * For ARM:
 * - saves flags to reg
 * - saves reg first to slot, unless !save_reg.
 */
static void
drx_save_arith_flags(void *drcontext, instrlist_t *ilist, instr_t *where,
                     bool save_reg, bool save_oflag,
                     dr_spill_slot_t slot, reg_id_t reg)
{
#ifdef X86
    instr_t *instr;
    /* save %eax if necessary */
    if (save_reg) {
        if (reg != DR_REG_NULL) {
            ASSERT(reg >= DR_REG_START_GPR && reg <= DR_REG_STOP_GPR &&
                   reg != DR_REG_XAX, "wrong dead reg");
            MINSERT(ilist, where,
                    INSTR_CREATE_mov_st(drcontext,
                                        opnd_create_reg(reg),
                                        opnd_create_reg(DR_REG_XAX)));
        } else {
            ASSERT(slot >= SPILL_SLOT_1 && slot <= SPILL_SLOT_MAX,
                   "wrong spill slot");
            dr_save_reg(drcontext, ilist, where, DR_REG_XAX, slot);
        }
    }
    /* lahf */
    instr = INSTR_CREATE_lahf(drcontext);
    MINSERT(ilist, where, instr);
    if (save_oflag) {
        /* seto %al */
        instr = INSTR_CREATE_setcc(drcontext, OP_seto, opnd_create_reg(DR_REG_AL));
        MINSERT(ilist, where, instr);
    }
#elif defined(ARM)
    ASSERT(reg >= DR_REG_START_GPR && reg <= DR_REG_STOP_GPR, "reg must be a GPR");
    if (save_reg) {
        ASSERT(slot >= SPILL_SLOT_1 && slot <= SPILL_SLOT_MAX,
               "wrong spill slot");
        dr_save_reg(drcontext, ilist, where, reg, slot);
    }
    MINSERT(ilist, where, INSTR_CREATE_msr
            (drcontext, opnd_create_reg(DR_REG_CPSR), OPND_CREATE_INT_MSR_NZCVQG(),
             opnd_create_reg(reg)));
#endif
}
コード例 #8
0
ファイル: memtrace_simple.c プロジェクト: DynamoRIO/dynamorio
static void
insert_save_pc(void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t base,
               reg_id_t scratch, app_pc pc)
{
    instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)pc, opnd_create_reg(scratch),
                                     ilist, where, NULL, NULL);
    MINSERT(ilist, where,
            XINST_CREATE_store(drcontext,
                               OPND_CREATE_MEMPTR(base, offsetof(mem_ref_t, addr)),
                               opnd_create_reg(scratch)));
}
コード例 #9
0
ファイル: memtrace_simple.c プロジェクト: DynamoRIO/dynamorio
static void
insert_save_addr(void *drcontext, instrlist_t *ilist, instr_t *where, opnd_t ref,
                 reg_id_t reg_ptr, reg_id_t reg_addr)
{
    bool ok;
    /* we use reg_ptr as scratch to get addr */
    ok = drutil_insert_get_mem_addr(drcontext, ilist, where, ref, reg_addr, reg_ptr);
    DR_ASSERT(ok);
    insert_load_buf_ptr(drcontext, ilist, where, reg_ptr);
    MINSERT(ilist, where,
            XINST_CREATE_store(drcontext,
                               OPND_CREATE_MEMPTR(reg_ptr, offsetof(mem_ref_t, addr)),
                               opnd_create_reg(reg_addr)));
}
コード例 #10
0
ファイル: instru_offline.cpp プロジェクト: mdlui/dynamorio
int
offline_instru_t::instrument_memref(void *drcontext, instrlist_t *ilist, instr_t *where,
                                    reg_id_t reg_ptr, reg_id_t reg_tmp, int adjust,
                                    opnd_t ref, bool write, dr_pred_type_t pred)
{
    // Post-processor distinguishes read, write, prefetch, flush, and finds size.
    instr_t *label = INSTR_CREATE_label(drcontext);
    MINSERT(ilist, where, label);
    insert_save_addr(drcontext, ilist, where, reg_ptr, reg_tmp, adjust, ref);
#ifdef ARM // X86 does not support general predicated execution
    if (pred != DR_PRED_NONE) {
        instr_t *instr;
        for (instr  = instr_get_prev(where);
             instr != label;
             instr  = instr_get_prev(instr)) {
            DR_ASSERT(!instr_is_predicated(instr));
            instr_set_predicate(instr, pred);
        }
    }
#endif
    return (adjust + sizeof(offline_entry_t));
}
コード例 #11
0
ファイル: instru_offline.cpp プロジェクト: mdlui/dynamorio
void
offline_instru_t::insert_save_addr(void *drcontext, instrlist_t *ilist, instr_t *where,
                                   reg_id_t reg_ptr, reg_id_t reg_addr, int adjust,
                                   opnd_t ref)
{
    bool ok;
    int disp = adjust;
    if (opnd_uses_reg(ref, reg_ptr))
        drreg_get_app_value(drcontext, ilist, where, reg_ptr, reg_ptr);
    if (opnd_uses_reg(ref, reg_addr))
        drreg_get_app_value(drcontext, ilist, where, reg_addr, reg_addr);
    // We use reg_ptr as scratch to get the address.
    ok = drutil_insert_get_mem_addr(drcontext, ilist, where, ref, reg_addr, reg_ptr);
    DR_ASSERT(ok);
    // drutil_insert_get_mem_addr may clobber reg_ptr, so we need to re-load reg_ptr.
    // XXX i#2001: determine whether we have to and avoid it when we don't.
    insert_load_buf_ptr(drcontext, ilist, where, reg_ptr);
    MINSERT(ilist, where,
            XINST_CREATE_store(drcontext,
                               OPND_CREATE_MEMPTR(reg_ptr, disp),
                               opnd_create_reg(reg_addr)));
    // We allow either 0 or all 1's as the type so no need to write anything else.
}
コード例 #12
0
ファイル: bbbuf.c プロジェクト: Arunpreet/dynamorio
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;
}
コード例 #13
0
ファイル: memval_simple.c プロジェクト: DynamoRIO/dynamorio
static reg_id_t
instrument_mem(void *drcontext, instrlist_t *ilist, instr_t *where, opnd_t ref)
{
    reg_id_t reg_ptr, reg_tmp, reg_addr;
    ushort type, size;
    bool ok;

    if (drreg_reserve_register(drcontext, ilist, where, NULL, &reg_tmp) !=
        DRREG_SUCCESS) {
        DR_ASSERT(false);
        return DR_REG_NULL;
    }
    if (drreg_reserve_register(drcontext, ilist, where, NULL, &reg_ptr) !=
        DRREG_SUCCESS) {
        DR_ASSERT(false);
        return DR_REG_NULL;
    }

    /* i#2449: In the situation that instrument_post_write, instrument_mem and ref all
     * have the same register reserved, drutil_insert_get_mem_addr will compute the
     * address of an operand using an incorrect register value, as drreg will elide the
     * save/restore.
     */
    if (opnd_uses_reg(ref, reg_tmp) &&
        drreg_get_app_value(drcontext, ilist, where, reg_tmp, reg_tmp) != DRREG_SUCCESS) {
        DR_ASSERT(false);
        return DR_REG_NULL;
    }
    if (opnd_uses_reg(ref, reg_ptr) &&
        drreg_get_app_value(drcontext, ilist, where, reg_ptr, reg_ptr) != DRREG_SUCCESS) {
        DR_ASSERT(false);
        return DR_REG_NULL;
    }

    /* We use reg_ptr as scratch to get addr. Note we do this first as reg_ptr or reg_tmp
     * may be used in ref.
     */
    ok = drutil_insert_get_mem_addr(drcontext, ilist, where, ref, reg_tmp, reg_ptr);
    DR_ASSERT(ok);
    drx_buf_insert_load_buf_ptr(drcontext, trace_buffer, ilist, where, reg_ptr);
    /* inserts memref addr */
    drx_buf_insert_buf_store(drcontext, trace_buffer, ilist, where, reg_ptr, DR_REG_NULL,
                             opnd_create_reg(reg_tmp), OPSZ_PTR,
                             offsetof(mem_ref_t, addr));
    if (IF_AARCHXX_ELSE(true, false)) {
        /* At this point we save the write address for later, because reg_tmp's value
         * will get clobbered on ARM.
         */
        if (drreg_reserve_register(drcontext, ilist, where, NULL, &reg_addr) !=
            DRREG_SUCCESS) {
            DR_ASSERT(false);
            return DR_REG_NULL;
        }
        MINSERT(ilist, where,
                XINST_CREATE_move(drcontext, opnd_create_reg(reg_addr),
                                  opnd_create_reg(reg_tmp)));
    }
    /* inserts type */
    type = (ushort)instr_get_opcode(where);
    drx_buf_insert_buf_store(drcontext, trace_buffer, ilist, where, reg_ptr, reg_tmp,
                             OPND_CREATE_INT16(type), OPSZ_2, offsetof(mem_ref_t, type));
    /* inserts size */
    size = (ushort)drutil_opnd_mem_size_in_bytes(ref, where);
    drx_buf_insert_buf_store(drcontext, trace_buffer, ilist, where, reg_ptr, reg_tmp,
                             OPND_CREATE_INT16(size), OPSZ_2, offsetof(mem_ref_t, size));
    drx_buf_insert_update_buf_ptr(drcontext, trace_buffer, ilist, where, reg_ptr,
                                  DR_REG_NULL, sizeof(mem_ref_t));

    if (instr_is_call(where)) {
        app_pc pc;

        /* Note that on ARM the call instruction writes only to the link register, so
         * we would never even get into instrument_mem() on ARM if this was a call.
         */
        IF_AARCHXX(DR_ASSERT(false));
        /* We simulate the call instruction's written memory by writing the next app_pc
         * to the written buffer, since we can't do this after the call has happened.
         */
        drx_buf_insert_load_buf_ptr(drcontext, write_buffer, ilist, where, reg_ptr);
        pc = decode_next_pc(drcontext, instr_get_app_pc(where));
        /* note that for a circular buffer, we don't need to specify a scratch register */
        drx_buf_insert_buf_store(drcontext, trace_buffer, ilist, where, reg_ptr,
                                 DR_REG_NULL, OPND_CREATE_INTPTR((ptr_int_t)pc), OPSZ_PTR,
                                 0);
        drx_buf_insert_update_buf_ptr(drcontext, write_buffer, ilist, where, reg_ptr,
                                      reg_tmp, sizeof(app_pc));
        /* we don't need to persist reg_tmp to the next instruction */
        if (drreg_unreserve_register(drcontext, ilist, where, reg_tmp) != DRREG_SUCCESS)
            DR_ASSERT(false);
        reg_tmp = DR_REG_NULL;
    } else if (IF_AARCHXX_ELSE(true, false)) {
        /* Now reg_tmp has the address of the write again. */
        MINSERT(ilist, where,
                XINST_CREATE_move(drcontext, opnd_create_reg(reg_tmp),
                                  opnd_create_reg(reg_addr)));
        if (drreg_unreserve_register(drcontext, ilist, where, reg_addr) != DRREG_SUCCESS)
            DR_ASSERT(false);
    }
    if (drreg_unreserve_register(drcontext, ilist, where, reg_ptr) != DRREG_SUCCESS)
        DR_ASSERT(false);
    return reg_tmp;
}
コード例 #14
0
// 描画開始命令
void HERE::drawStartCall( int _layer, DrawInterface* _inter )
{
	MINSERT(HERE::m_inter,_layer,_inter);
}
コード例 #15
0
ファイル: drx_buf-test.dll.c プロジェクト: stoyannk/dynamorio
static dr_emit_flags_t
event_app_instruction(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst,
                      bool for_trace, bool translating, void *user_data)
{
    reg_id_t reg_ptr = IF_X86_ELSE(DR_REG_XDX, TEST_REG);
    reg_id_t reg_tmp = IF_X86_ELSE(DR_REG_XCX, DR_REG_R3);
    /* We need a third register on ARM, because updating the buf pointer
     * requires a second scratch reg.
     */
    reg_id_t scratch = IF_X86_ELSE(reg_tmp, DR_REG_R5);
    ptr_int_t subtest = (ptr_int_t) user_data;

    if (!instr_is_label(inst))
        return DR_EMIT_DEFAULT;

#ifdef X86
    scratch = reg_resize_to_opsz(scratch, OPSZ_4);
#endif
    if (subtest == DRX_BUF_TEST_1_C) {
        /* testing fast circular buffer */
        /* test to make sure that on first invocation, the buffer is empty */
        dr_insert_clean_call(drcontext, bb, inst, verify_buffers_empty, false, 1,
                             OPND_CREATE_INTPTR(circular_fast));

        /* load the buf pointer, and then write a garbage element to the buffer */
        drx_buf_insert_load_buf_ptr(drcontext, circular_fast, bb, inst, reg_ptr);
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 DR_REG_NULL, opnd_create_reg(scratch), OPSZ_4, 0);
        drx_buf_insert_update_buf_ptr(drcontext, circular_fast, bb, inst, reg_ptr,
                                      reg_tmp, sizeof(int));

        /* verify the buffer was written to */
        dr_insert_clean_call(drcontext, bb, inst, verify_buffers_dirty, false, 2,
                             OPND_CREATE_INTPTR(circular_fast),
                             opnd_create_reg(scratch));

        /* fast circular buffer: trigger an overflow */
        drx_buf_insert_load_buf_ptr(drcontext, circular_fast, bb, inst, reg_ptr);
        drx_buf_insert_update_buf_ptr(drcontext, circular_fast, bb, inst, reg_ptr,
                                      reg_tmp, CIRCULAR_FAST_SZ - sizeof(int));

        /* the buffer is now clean */
        dr_insert_clean_call(drcontext, bb, inst, verify_buffers_empty, false, 1,
                             OPND_CREATE_INTPTR(circular_fast));
    } else if (subtest == DRX_BUF_TEST_2_C) {
        /* testing slow circular buffer */
        /* test to make sure that on first invocation, the buffer is empty */
        dr_insert_clean_call(drcontext, bb, inst, verify_buffers_empty, false, 1,
                             OPND_CREATE_INTPTR(circular_slow));

        /* load the buf pointer, and then write an element to the buffer */
        drx_buf_insert_load_buf_ptr(drcontext, circular_slow, bb, inst, reg_ptr);
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 DR_REG_NULL, opnd_create_reg(scratch), OPSZ_4, 0);
        drx_buf_insert_update_buf_ptr(drcontext, circular_slow, bb, inst, reg_ptr,
                                      DR_REG_NULL, sizeof(int));

        /* verify the buffer was written to */
        dr_insert_clean_call(drcontext, bb, inst, verify_buffers_dirty, false, 2,
                             OPND_CREATE_INTPTR(circular_slow),
                             opnd_create_reg(scratch));

        /* slow circular buffer: trigger a fault */
        drx_buf_insert_load_buf_ptr(drcontext, circular_slow, bb, inst, reg_ptr);
        drx_buf_insert_update_buf_ptr(drcontext, circular_slow, bb, inst, reg_ptr,
                                      DR_REG_NULL, CIRCULAR_SLOW_SZ - sizeof(int));
        /* the "trigger" is a write, so we write whatever garbage is in reg_tmp */
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 DR_REG_NULL, opnd_create_reg(scratch), OPSZ_4, 0);

        /* the buffer is now clean */
        dr_insert_clean_call(drcontext, bb, inst, verify_buffers_empty, false, 1,
                             OPND_CREATE_INTPTR(circular_slow));
    } else if (subtest == DRX_BUF_TEST_3_C) {
        /* testing trace buffer */
        /* test to make sure that on first invocation, the buffer is empty */
        dr_insert_clean_call(drcontext, bb, inst, verify_buffers_empty, false, 1,
                             OPND_CREATE_INTPTR(trace));

        /* load the buf pointer, and then write an element to the buffer */
        drx_buf_insert_load_buf_ptr(drcontext, trace, bb, inst, reg_ptr);
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 DR_REG_NULL, opnd_create_reg(scratch), OPSZ_4, 0);
        drx_buf_insert_update_buf_ptr(drcontext, trace, bb, inst, reg_ptr,
                                      DR_REG_NULL, sizeof(int));

        /* verify the buffer was written to */
        dr_insert_clean_call(drcontext, bb, inst, verify_buffers_dirty, false, 2,
                             OPND_CREATE_INTPTR(trace),
                             opnd_create_reg(scratch));

        /* trace buffer: trigger a fault and verify */
        drx_buf_insert_load_buf_ptr(drcontext, trace, bb, inst, reg_ptr);
        drx_buf_insert_update_buf_ptr(drcontext, trace, bb, inst, reg_ptr,
                                      DR_REG_NULL, TRACE_SZ - sizeof(int));
        /* the "trigger" is a write, so we write whatever garbage is in reg_tmp */
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 DR_REG_NULL, opnd_create_reg(scratch), OPSZ_4, 0);

        /* the buffer is now clean */
        dr_insert_clean_call(drcontext, bb, inst, verify_buffers_empty, false, 1,
                             OPND_CREATE_INTPTR(trace));
    } else if (subtest == DRX_BUF_TEST_4_C) {
        /* test immediate store: 8 bytes (if possible), 4 bytes, 2 bytes and 1 byte */
        /* "ABCDEFGH\x00" (x2 for x64) */
        drx_buf_insert_load_buf_ptr(drcontext, circular_fast, bb, inst, reg_ptr);
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 scratch, opnd_create_immed_int(0x41, OPSZ_1),
                                 OPSZ_1, 0);
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 scratch, opnd_create_immed_int(0x42, OPSZ_1),
                                 OPSZ_1, 1);
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 scratch, opnd_create_immed_int(0x4443, OPSZ_2),
                                 OPSZ_2, 2);
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 scratch, opnd_create_immed_int(0x48474645, OPSZ_4),
                                 OPSZ_4, 4);
#ifdef X64
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 scratch, opnd_create_immed_int(0x4847464544434241,
                                                                  OPSZ_8),
                                 OPSZ_8, 8);
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 scratch, opnd_create_immed_int(0x00, OPSZ_1),
                                 OPSZ_1, 17);
#else
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 scratch, opnd_create_immed_int(0x00, OPSZ_1),
                                 OPSZ_1, 9);
#endif
        dr_insert_clean_call(drcontext, bb, inst, verify_store, false, 1,
                             OPND_CREATE_INTPTR(circular_fast));
    } else if (subtest == DRX_BUF_TEST_5_C) {
        /* test register store: 8 bytes (if possible), 4 bytes, 2 bytes and 1 byte */
        /* "ABCDEFGH\x00" (x2 for x64) */
        drx_buf_insert_load_buf_ptr(drcontext, circular_fast, bb, inst, reg_ptr);
        scratch = reg_resize_to_opsz(scratch, OPSZ_1);
        MINSERT(bb, inst, XINST_CREATE_load_int
                (drcontext,
                 opnd_create_reg(scratch),
                 opnd_create_immed_int(0x41, OPSZ_1)));
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 DR_REG_NULL, opnd_create_reg(scratch),
                                 OPSZ_1, 0);
        MINSERT(bb, inst, XINST_CREATE_load_int
                (drcontext,
                 opnd_create_reg(scratch),
                 opnd_create_immed_int(0x42, OPSZ_1)));
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 DR_REG_NULL, opnd_create_reg(scratch),
                                 OPSZ_1, 1);
        scratch = reg_resize_to_opsz(scratch, OPSZ_2);
        MINSERT(bb, inst, XINST_CREATE_load_int
                (drcontext,
                 opnd_create_reg(scratch),
                 opnd_create_immed_int(0x4443, OPSZ_2)));
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 DR_REG_NULL, opnd_create_reg(scratch),
                                 OPSZ_2, 2);
        scratch = reg_resize_to_opsz(scratch, OPSZ_4);
#ifdef X86
        MINSERT(bb, inst, XINST_CREATE_load_int
                (drcontext,
                 opnd_create_reg(scratch),
                 opnd_create_immed_int(0x48474645, OPSZ_4)));
#else
        instrlist_insert_mov_immed_ptrsz(drcontext, 0x48474645,
                                         opnd_create_reg(reg_resize_to_opsz
                                                         (scratch, OPSZ_PTR)),
                                         bb, inst, NULL, NULL);
#endif
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 DR_REG_NULL, opnd_create_reg(scratch),
                                 OPSZ_4, 4);
#ifdef X64
        scratch = reg_resize_to_opsz(scratch, OPSZ_8);
        /* only way to reliably move a 64 bit int into a register */
        instrlist_insert_mov_immed_ptrsz(drcontext, 0x4847464544434241,
                                         opnd_create_reg(scratch),
                                         bb, inst, NULL, NULL);
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 DR_REG_NULL, opnd_create_reg(scratch),
                                 OPSZ_8, 8);
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 scratch, opnd_create_immed_int(0x00, OPSZ_1),
                                 OPSZ_1, 17);
#else
        drx_buf_insert_buf_store(drcontext, circular_fast, bb, inst, reg_ptr,
                                 scratch, opnd_create_immed_int(0x00, OPSZ_1),
                                 OPSZ_1, 9);
#endif
        dr_insert_clean_call(drcontext, bb, inst, verify_store, false, 1,
                             OPND_CREATE_INTPTR(circular_fast));
    } else if (subtest == DRX_BUF_TEST_6_C) {
        /* Currently, the fast circular buffer does not recommend variable-size
         * writes, for good reason. We don't test the memcpy operation on the
         * fast circular buffer.
         */
        /* verify memcpy works on the slow clrcular buffer */
        drx_buf_insert_load_buf_ptr(drcontext, circular_slow, bb, inst, reg_ptr);
        instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)test_copy,
                                         opnd_create_reg(reg_resize_to_opsz
                                                         (scratch, OPSZ_PTR)),
                                         bb, inst, NULL, NULL);
        drx_buf_insert_buf_memcpy(drcontext, circular_slow, bb, inst,
                                  reg_ptr, reg_resize_to_opsz(scratch, OPSZ_PTR),
                                  sizeof(test_copy));
        /* NULL out the buffer */
        drx_buf_insert_load_buf_ptr(drcontext, circular_slow, bb, inst, reg_ptr);
        instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)test_null,
                                         opnd_create_reg(reg_resize_to_opsz
                                                         (scratch, OPSZ_PTR)),
                                         bb, inst, NULL, NULL);
        drx_buf_insert_buf_memcpy(drcontext, circular_slow, bb, inst,
                                  reg_ptr, reg_resize_to_opsz(scratch, OPSZ_PTR),
                                  sizeof(test_null));
        /* Unfortunately, we can't just use the check in verify_buffer_empty, because
         * drx_buf_insert_buf_memcpy() incrememnts the buffer pointer internally, unlike
         * drx_buf_insert_buf_store(). We simply check that the buffer was NULLed out.
         */
        dr_insert_clean_call(drcontext, bb, inst, (void *)verify_buffers_nulled, false, 1,
                             OPND_CREATE_INTPTR(circular_slow));
        /* verify memcpy works on the trace buffer */
        drx_buf_insert_load_buf_ptr(drcontext, trace, bb, inst, reg_ptr);
        instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)test_copy,
                                         opnd_create_reg(reg_resize_to_opsz
                                                         (scratch, OPSZ_PTR)),
                                         bb, inst, NULL, NULL);
        drx_buf_insert_buf_memcpy(drcontext, trace, bb, inst,
                                  reg_ptr, reg_resize_to_opsz(scratch, OPSZ_PTR),
                                  sizeof(test_copy));
        /* NULL out the buffer */
        drx_buf_insert_load_buf_ptr(drcontext, trace, bb, inst, reg_ptr);
        instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)test_null,
                                         opnd_create_reg(reg_resize_to_opsz
                                                         (scratch, OPSZ_PTR)),
                                         bb, inst, NULL, NULL);
        drx_buf_insert_buf_memcpy(drcontext, trace, bb, inst,
                                  reg_ptr, reg_resize_to_opsz(scratch, OPSZ_PTR),
                                  sizeof(test_null));
        /* verify buffer was NULLed */
        dr_insert_clean_call(drcontext, bb, inst, (void *)verify_buffers_nulled, false, 1,
                             OPND_CREATE_INTPTR(trace));
    }

    return DR_EMIT_DEFAULT;
}
コード例 #16
0
ファイル: cbr3.dll.c プロジェクト: djmott/dynamorio
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_meta(instr);
                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;
}
コード例 #17
0
ファイル: cbr.c プロジェクト: Arunpreet/dynamorio
static dr_emit_flags_t
bb_event(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating)
{
    instr_t *instr, *next_instr;
    
    for (instr = instrlist_first(bb); instr != NULL; instr = next_instr) {
        next_instr = instr_get_next(instr);

        if (instr_is_cbr(instr)) {
            /* Conditional branch.  We can determine the target and
             * fallthrough addresses here, but we want to note the
             * edge if and when 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 the instrumentation for an edge
             * after it executes.
             */
            cbr_state_t state;
            bool insert_taken, insert_not_taken;
            app_pc src = instr_get_app_pc(instr);
            
            /* 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_NEITHER;
                insert(table, src, CBR_NEITHER);
            }
            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 existing cbr to jump to a callout for
                 * the 'taken' case.  We'll insert a 'not-taken'
                 * callout at the fallthrough address.
                 */
                instr_t *label = INSTR_CREATE_label(drcontext);
                /* should be meta, and meta-instrs shouldn't have translations */
                instr_set_meta_no_translation(instr);
                /* it may not reach (in particular for x64) w/ our added clean call */
                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.  Insert after
                     * the cbr (i.e., 3rd argument is NULL). 
                     */
                    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(src),
                                         OPND_CREATE_INTPTR(fall));
                }
                
                /* After the callout, jump to the original fallthrough
                 * address.  Note that this is an exit cti, and should
                 * not be a meta-instruction.  Therefore, we use
                 * preinsert instead of meta_preinsert, and we must
                 * set the translation field.  On Windows, this jump
                 * and the final jump below never execute since the
                 * at_taken and at_not_taken callouts redirect
                 * execution and never return.  However, since the API
                 * expects clients to produced well-formed code, we
                 * insert explicit exits from the block for Windows as
                 * well as Linux.
                 */
                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(src),
                                         OPND_CREATE_INTPTR(targ));
                }
                
                /* After the callout, 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;
}
コード例 #18
0
ファイル: abort.dll.c プロジェクト: Arunpreet/dynamorio
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;
}