Example #1
0
/*
 * Function that tests a single operand of an instruction to see if
 * it's a memory reference, and if so, adds a call to log_mem.
 */
static void try_mem_opnd(
    void *drcontext, instrlist_t *bb, instr_t *instr, char **loc,
    opnd_t opnd, bool write)
{
    if (!opnd_is_memory_reference(opnd))
        return;

    instr_format_location(instr, loc);

    reg_id_t r0, r1;
    drreg_status_t st;
    st = drreg_reserve_register(drcontext, bb, instr, NULL, &r0);
    DR_ASSERT(st == DRREG_SUCCESS);
    st = drreg_reserve_register(drcontext, bb, instr, NULL, &r1);
    DR_ASSERT(st == DRREG_SUCCESS);

    bool ok = drutil_insert_get_mem_addr(drcontext, bb, instr, opnd, r0, r1);
    DR_ASSERT(ok);

    uint size = drutil_opnd_mem_size_in_bytes(opnd, instr);

    dr_insert_clean_call(
        drcontext, bb, instr, (void *)log_mem, false,
        4, opnd_create_reg(r0), OPND_CREATE_INT32(size),
        OPND_CREATE_INT32(write), OPND_CREATE_INTPTR(*loc));

    st = drreg_unreserve_register(drcontext, bb, instr, r1);
    DR_ASSERT(st == DRREG_SUCCESS);
    st = drreg_unreserve_register(drcontext, bb, instr, r0);
    DR_ASSERT(st == DRREG_SUCCESS);
}
Example #2
0
/* This event is called separately for each individual instruction in the bb. */
static dr_emit_flags_t
event_insert_instrumentation(void *drcontext, void *tag, instrlist_t *bb, instr_t *instr,
                             bool for_trace, bool translating, void *user_data)
{
    bool bb_in_app;
    if (dr_fragment_app_pc(tag) >= app_base && dr_fragment_app_pc(tag) < app_end)
        bb_in_app = true;
    else
        bb_in_app = false;

    if (drmgr_is_first_instr(drcontext, instr)) {
        uint num_instrs = (uint)(ptr_uint_t)user_data;
        dr_insert_clean_call(drcontext, bb, instr,
                             (void *)(bb_in_app ? app_update : lib_update),
                             false /* save fpstate */, 1, OPND_CREATE_INT32(num_instrs));
    }

    if (instr_is_mbr(instr) && !instr_is_return(instr)) {
        /* Assuming most of the transfers between app and lib are paired, we
         * instrument indirect branches but not returns for better performance.
         */
        dr_insert_mbr_instrumentation(
            drcontext, bb, instr, (void *)(bb_in_app ? app_mbr : lib_mbr), SPILL_SLOT_1);
    }

    return DR_EMIT_DEFAULT;
}
Example #3
0
static void
test_x86_mode(void *dc)
{
    byte *pc, *end;
    instr_t *instr;

    /* create instr that looks different in x86 vs x64 */
    instr = INSTR_CREATE_add(dc, opnd_create_reg(REG_RAX), OPND_CREATE_INT32(42));
    end = instr_encode(dc, instr, buf);
    ASSERT(end - buf < BUFFER_SIZE_ELEMENTS(buf));

    /* read back in */
    set_x86_mode(dc, false/*64-bit*/);
    instr_reset(dc, instr);
    pc = decode(dc, buf, instr);
    ASSERT(pc != NULL);
    ASSERT(instr_get_opcode(instr) == OP_add);

    /* now interpret as 32-bit where rex will be an inc */
    set_x86_mode(dc, true/*32-bit*/);
    instr_reset(dc, instr);
    pc = decode(dc, buf, instr);
    ASSERT(pc != NULL);
    ASSERT(instr_get_opcode(instr) == OP_dec);

    instr_free(dc, instr);
    set_x86_mode(dc, false/*64-bit*/);
}
Example #4
0
static dr_emit_flags_t
event_basic_block(void *drcontext, void *tag, instrlist_t *bb,
                  bool for_trace, bool translating)
{
    instr_t *instr;
    uint num_instrs;
    
#ifdef VERBOSE
    dr_printf("in dynamorio_basic_block(tag="PFX")\n", tag);
# ifdef VERBOSE_VERBOSE
    instrlist_disassemble(drcontext, tag, bb, STDOUT);
# endif
#endif

    for (instr  = instrlist_first(bb), num_instrs = 0;
         instr != NULL;
         instr = instr_get_next(instr)) {
        num_instrs++;
    }

    dr_insert_clean_call(drcontext, bb, instrlist_first(bb), 
                         (void *)inscount, false /* save fpstate */, 1,
                         OPND_CREATE_INT32(num_instrs));

#if defined(VERBOSE) && defined(VERBOSE_VERBOSE)
    dr_printf("Finished instrumenting dynamorio_basic_block(tag="PFX")\n", tag);
    instrlist_disassemble(drcontext, tag, bb, STDOUT);
#endif
    return DR_EMIT_DEFAULT;
}
static
dr_emit_flags_t bb_event(void* drcontext, void *tag, instrlist_t* bb,
                         bool for_trace, bool translating)
{
    instr_t *instr;
    instr_t *next_instr;
    reg_t in_eax = -1;

    for (instr = instrlist_first(bb); instr != NULL; instr = next_instr) {
        next_instr = instr_get_next(instr);
        if (instr_get_opcode(instr) == OP_mov_imm &&
            opnd_get_reg(instr_get_dst(instr, 0)) == REG_EAX)
            in_eax = opnd_get_immed_int(instr_get_src(instr, 0));
        if (instr_is_syscall(instr) &&
            in_eax == SYS_getpid) {
            instr_t *myval = INSTR_CREATE_mov_imm
                (drcontext, opnd_create_reg(REG_EAX), OPND_CREATE_INT32(-7));
            instr_set_translation(myval, instr_get_app_pc(instr));
            instrlist_preinsert(bb, instr, myval);
            instrlist_remove(bb, instr);
            instr_destroy(drcontext, instr);
        }
    }
    return DR_EMIT_DEFAULT;
}
Example #6
0
dr_emit_flags_t
inscount_bb_instrumentation(void *drcontext, void *tag, instrlist_t *bb,
				instr_t *instr, bool for_trace, bool translating,
				void *user_data)
{

	instr_t *first = instrlist_first(bb);
	uint num_instrs = 0;

	if(instr != first)
		return DR_EMIT_DEFAULT;

	if(filter_from_list(head,instr,client_arg->filter_mode)){
		for(instr = first ; instr!=NULL ; instr = instr_get_next(instr)){
			num_instrs++;
		}
		bbcount++;
	}


	if(num_instrs > 0){
		dr_insert_clean_call(drcontext, bb, instrlist_first(bb),
							(void *)inscount, false /* save fpstate */, 1,
							OPND_CREATE_INT32(num_instrs));
	}







	return DR_EMIT_DEFAULT;
}
Example #7
0
static dr_emit_flags_t
event_basic_block(void *drcontext, void *tag, instrlist_t *bb,
                  bool for_trace, bool translating)
{
    instr_t *instr, *first = instrlist_first(bb), *point = NULL;
    uint num_instrs;
	uint flags;
	uint need_restore;

	/* count instruction */
    for (instr  = first, num_instrs = 0;
         instr != NULL;
         instr = instr_get_next(instr)) {

        num_instrs++;

    }
	
	need_restore = 0;
	flags = instr_get_arith_flags(instr);
	/* eflags are not dead save eflags to register */
	if (!(TESTALL(EFLAGS_WRITE_6, flags) && !TESTANY(EFLAGS_READ_6, flags))) {
		need_restore = 1;
		dr_save_reg(drcontext, bb, first, DR_REG_XAX, SPILL_SLOT_1);
		dr_save_arith_flags_to_xax(drcontext, bb, first);
	}

	/* add the instruction count */
    instrlist_meta_preinsert
        (bb, first,
         INSTR_CREATE_add(drcontext, OPND_CREATE_ABSMEM
                               ((byte *)&global_count, OPSZ_4), OPND_CREATE_INT32(num_instrs)));

	/* Need to carry since it is a 8 byte variable. */
    instrlist_meta_preinsert
        (bb, first,
         INSTR_CREATE_adc(drcontext, OPND_CREATE_ABSMEM
                               ((byte *)&global_count + 4, OPSZ_4), OPND_CREATE_INT32(0)));

	/* resotre eflags */
	if (need_restore) {
		dr_restore_arith_flags_from_xax(drcontext, bb, first);
		dr_restore_reg(drcontext, bb, first, DR_REG_XAX, SPILL_SLOT_1);
	}

    return DR_EMIT_DEFAULT;
}
Example #8
0
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;
}
Example #9
0
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);*/
}
Example #10
0
static dr_emit_flags_t
event_basic_block(void *drcontext, void *tag, instrlist_t *bb,
                  bool for_trace, bool translating)
{
    instr_t *instr, *mbr = NULL;
    uint num_instrs;
    bool bb_in_app;

#ifdef VERBOSE
    dr_printf("in dynamorio_basic_block(tag="PFX")\n", tag);
# ifdef VERBOSE_VERBOSE
    instrlist_disassemble(drcontext, tag, bb, STDOUT);
# endif
#endif

    for (instr  = instrlist_first(bb), num_instrs = 0;
         instr != NULL;
         instr = instr_get_next(instr)) {
        /* only care about app instr */
        if (!instr_ok_to_mangle(instr))
            continue;
        num_instrs++;
        /* Assuming most of the transfers between app and lib are paired, we
         * instrument indirect branches but not returns for better performance.
         */
        if (instr_is_mbr(instr) && !instr_is_return(instr))
            mbr = instr;
    }

    if (dr_fragment_app_pc(tag) >= app_base &&
        dr_fragment_app_pc(tag) <  app_end)
        bb_in_app = true;
    else
        bb_in_app = false;
    dr_insert_clean_call(drcontext, bb, instrlist_first(bb),
                         (void *)(bb_in_app ? app_update : lib_update),
                         false /* save fpstate */, 1,
                         OPND_CREATE_INT32(num_instrs));
    if (mbr != NULL) {
        dr_insert_mbr_instrumentation(drcontext, bb, mbr,
                                      (void *)(bb_in_app ? app_mbr : lib_mbr),
                                      SPILL_SLOT_1);
    }

#if defined(VERBOSE) && defined(VERBOSE_VERBOSE)
    dr_printf("Finished instrumenting dynamorio_basic_block(tag="PFX")\n", tag);
    instrlist_disassemble(drcontext, tag, bb, STDOUT);
#endif
    return DR_EMIT_DEFAULT;
}
Example #11
0
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)
{
    uint num_instrs;
    /* By default drmgr enables auto-predication, which predicates all instructions with
     * the predicate of the current instruction on ARM.
     * We disable it here because we want to unconditionally execute the following
     * instrumentation.
     */
    drmgr_disable_auto_predication(drcontext, bb);
    if (!drmgr_is_first_instr(drcontext, instr))
        return DR_EMIT_DEFAULT;
    /* Only insert calls for in-app BBs */
    if (user_data == NULL)
        return DR_EMIT_DEFAULT;
    /* Insert clean call */
    num_instrs = (uint)(ptr_uint_t)user_data;
    dr_insert_clean_call(drcontext, bb, instrlist_first_app(bb), (void *)inscount,
                         false /* save fpstate */, 1, OPND_CREATE_INT32(num_instrs));
    return DR_EMIT_DEFAULT;
}
Example #12
0
static dr_emit_flags_t
event_bb_insert(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst,
                bool for_trace, bool translating, void *user_data)
{
    /* hack to instrument every nth bb.  assumes DR serializes bb events. */
    static int freq;
    freq++;
    if (freq % 100 == 0 && inst == (instr_t*)user_data/*first instr*/) {
        /* test read from cache */
        dr_save_reg(drcontext, bb, inst, DR_REG_XAX, SPILL_SLOT_1);
        drmgr_insert_read_tls_field(drcontext, tls_idx, bb, inst, DR_REG_XAX);
        dr_insert_clean_call(drcontext, bb, inst, (void *)check_tls_from_cache,
                             false, 1, opnd_create_reg(DR_REG_XAX));
        drmgr_insert_read_cls_field(drcontext, cls_idx, bb, inst, DR_REG_XAX);
        dr_insert_clean_call(drcontext, bb, inst, (void *)check_cls_from_cache,
                             false, 1, opnd_create_reg(DR_REG_XAX));
        dr_restore_reg(drcontext, bb, inst, DR_REG_XAX, SPILL_SLOT_1);
    }
    if (freq % 300 == 0 && inst == (instr_t*)user_data/*first instr*/) {
        /* test write from cache */
        dr_save_reg(drcontext, bb, inst, DR_REG_XAX, SPILL_SLOT_1);
        dr_save_reg(drcontext, bb, inst, DR_REG_XCX, SPILL_SLOT_2);
        instrlist_meta_preinsert(bb, inst, INSTR_CREATE_mov_imm
                                 (drcontext, opnd_create_reg(DR_REG_EAX),
                                  OPND_CREATE_INT32(MAGIC_NUMBER_FROM_CACHE)));
        drmgr_insert_write_tls_field(drcontext, tls_idx, bb, inst, DR_REG_XAX,
                                     DR_REG_XCX);
        dr_insert_clean_call(drcontext, bb, inst, (void *)check_tls_write_from_cache,
                             false, 0);
        drmgr_insert_write_cls_field(drcontext, cls_idx, bb, inst, DR_REG_XAX,
                                     DR_REG_XCX);
        dr_insert_clean_call(drcontext, bb, inst, (void *)check_cls_write_from_cache,
                             false, 0);
        dr_restore_reg(drcontext, bb, inst, DR_REG_XCX, SPILL_SLOT_2);
        dr_restore_reg(drcontext, bb, inst, DR_REG_XAX, SPILL_SLOT_1);
    }
    return DR_EMIT_DEFAULT;
}
Example #13
0
/*
 * 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);
}
Example #14
0
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);
}
Example #15
0
/* instrument_instr 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_instr(void *drcontext, instrlist_t *ilist, instr_t *where)
{
    instr_t *instr, *call, *restore;
    opnd_t   opnd1, opnd2;
    reg_id_t reg1, reg2;
    drvector_t allowed;
    per_thread_t *data;
    app_pc pc;

    data = drmgr_get_tls_field(drcontext, tls_index);

    /* Steal two scratch registers.
     * reg2 must be ECX or RCX for jecxz.
     */
    drreg_init_and_fill_vector(&allowed, false);
    drreg_set_vector_entry(&allowed, DR_REG_XCX, true);
    if (drreg_reserve_register(drcontext, ilist, where, &allowed, &reg2) !=
        DRREG_SUCCESS ||
        drreg_reserve_register(drcontext, ilist, where, NULL, &reg1) != DRREG_SUCCESS) {
        DR_ASSERT(false); /* cannot recover */
        drvector_delete(&allowed);
        return;
    }
    drvector_delete(&allowed);

    /* The following assembly performs the following instructions
     * buf_ptr->pc = pc;
     * buf_ptr->opcode = opcode;
     * 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);

    /* Store pc */
    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(ins_ref_t, pc));
    instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t) pc, opnd1,
                                     ilist, where, NULL, NULL);

    /* Store opcode */
    opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(ins_ref_t, opcode));
    opnd2 = OPND_CREATE_INT32(instr_get_opcode(where));
    instr = INSTR_CREATE_mov_st(drcontext, opnd1, opnd2);
    instrlist_meta_preinsert(ilist, where, instr);

    /* 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(ins_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 the lea + jecxz trick for better performance.
     * lea and jecxz won't disturb the eflags, so we won't need
     * code to save and restore the 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 our generated lean procedure which performs a 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 the 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 scratch registers */
    instrlist_meta_preinsert(ilist, where, restore);
    if (drreg_unreserve_register(drcontext, ilist, where, reg1) != DRREG_SUCCESS ||
        drreg_unreserve_register(drcontext, ilist, where, reg2) != DRREG_SUCCESS)
        DR_ASSERT(false);
}
Example #16
0
/** Adds instrumentation that records fragment execution. */
struct instr_info_t instrument_frag(void* ctx,
                                    instrlist_t* frag,
                                    frag_id_t id) {
  const size_t offsetof_current = offsetof(struct trace_buffer_t, current);
  ptr_int_t frag_id = id; // sign-extended for OPND_CREATE_INT32
#ifdef TRACE_DEBUG
  app_pc frag_pc;
#endif
  app_pc xl8_pc;
  instr_t* where;
  instr_t* before;
  struct instr_info_t instr_info;
  instr_t* store;
  instr_t* first;

#ifdef TRACE_DEBUG
  dr_fprintf(STDERR, "debug: instrument_frag(0x%" PRIxPTR ")\n", frag_id);
  frag_pc = instr_get_app_pc(instrlist_first(frag));
  instrlist_disassemble(ctx, frag_pc, frag, STDERR);
#endif

  where = configure_instr(&instr_info, frag);
  xl8_pc = instr_get_app_pc(where);
  before = instr_get_prev(where);

#define INSERT(instr) prexl8(frag, where, (instr), xl8_pc)

  // Add instrumentation.
  // save tls_reg
  if(instr_info.restore_tls_reg) {
    dr_save_reg(ctx, frag, where, instr_info.tls_reg, SPILL_SLOT_2);
  }
  // save current_reg
  if(instr_info.restore_current_reg) {
    dr_save_reg(ctx, frag, where, instr_info.current_reg, SPILL_SLOT_3);
  }
  // tls_reg = tb
  dr_insert_read_tls_field(ctx, frag, where, instr_info.tls_reg);
  // current_reg = tb->current
  INSERT(
      INSTR_CREATE_mov_ld(
          ctx,
          opnd_create_reg(instr_info.current_reg),
          OPND_CREATE_MEMPTR(instr_info.tls_reg, offsetof_current)));
  // *current_reg = bb_id
  store = INSERT(
      INSTR_CREATE_mov_st(
          ctx,
          OPND_CREATE_MEMPTR(instr_info.current_reg, 0),
          OPND_CREATE_INT32(frag_id)));
  // current_reg += sizeof(bb_id)
  INSERT(
      INSTR_CREATE_lea(
          ctx,
          opnd_create_reg(instr_info.current_reg),
          OPND_CREATE_MEM_lea(instr_info.current_reg,
                              DR_REG_NULL,
                              0,
                              sizeof(frag_id_t))));
  // tb->current = current_reg
  INSERT(
      INSTR_CREATE_mov_st(
          ctx,
          OPND_CREATE_MEMPTR(instr_info.tls_reg, offsetof_current),
          opnd_create_reg(instr_info.current_reg)));
  // restore current_reg
  if(instr_info.restore_current_reg) {
    dr_restore_reg(ctx, frag, where, instr_info.current_reg, SPILL_SLOT_3);
  }
  // restore tls_reg
  if(instr_info.restore_tls_reg) {
    dr_restore_reg(ctx, frag, where, instr_info.tls_reg, SPILL_SLOT_2);
  }

#undef INSERT

  // Compute instrumentation instructions offsets.
  if(before) {
    first = instr_get_next(before);
  } else {
    first = instrlist_first(frag);
  }
  instr_info.first_offset = get_offset(ctx,
                                       instrlist_first(frag),
                                       first);
  instr_info.store_offset = get_offset(ctx,
                                       instrlist_first(frag),
                                       store);

#ifdef TRACE_DUMP_BB
  instrlist_disassemble(ctx, frag_pc, frag, STDERR);
#endif
#ifdef TRACE_DEBUG
  dr_fprintf(STDERR,
             "debug: instrument_frag() done,"
             " first_offset=0x%" PRIx32
             " store_offset=0x%" PRIx32
             "\n",
             instr_info.first_offset,
             instr_info.store_offset);
#endif

  return instr_info;
}
Example #17
0
static dr_emit_flags_t
event_basic_block(void *drcontext, void *tag, instrlist_t *bb,
                  bool for_trace, bool translating)
{
    int i;
    const int MAX_INSTR_LEN = 64;
    char instr_name[MAX_INSTR_LEN];
    instr_t *instr, *first = instrlist_first(bb);
    uint flags;
    uint cur_flop_count = 0;
    uint tracked_instr_count[tracked_instrs_len];
    for( i = 0; i < tracked_instrs_len; i++ ) tracked_instr_count[i] = 0;

#ifdef VERBOSE
    dr_printf("in dynamorio_basic_block(tag="PFX")\n", tag);
# ifdef VERBOSE_VERBOSE
    instrlist_disassemble(drcontext, tag, bb, STDOUT);
# endif
#endif

    /* we use fp ops so we have to save fp state */
    byte fp_raw[512 + 16];
    byte *fp_align = (byte *) ( (((ptr_uint_t)fp_raw) + 16) & ((ptr_uint_t)-16) );


    if (translating) {
        return DR_EMIT_DEFAULT;
    }
    proc_save_fpstate(fp_align);

    int my_readfrom[DR_REG_LAST_VALID_ENUM+MY_NUM_EFLAGS+1];
    int my_writtento[DR_REG_LAST_VALID_ENUM+MY_NUM_EFLAGS+1];

    for (i = 0; i < DR_REG_LAST_VALID_ENUM+MY_NUM_EFLAGS+1; i++) {
        my_readfrom[i] = 0;
        my_writtento[i] = 0;
    }

    t_glob_reg_state glob_reg_state = {0,0,0,0,0,0,my_readfrom,my_writtento};

    int my_cur_size = 0;
    for (instr = instrlist_first(bb); instr != NULL; instr = instr_get_next(instr)) {
        my_cur_size++;

        /* ILP Calculations */
        glob_reg_state.raw_setnr = 1;
        glob_reg_state.war_setnr = 1;
        glob_reg_state.waw_setnr = 1;
        glob_reg_state.else_setnr = 1;
        glob_reg_state.final_setnr = 1;
        calc_set_num(instr, &glob_reg_state);

        /* Count flop instr */
        if( instr_is_floating( instr ) ) {
            cur_flop_count += 1;
        }

        /* Count mul instructions */
        instr_disassemble_to_buffer( drcontext, instr, instr_name, MAX_INSTR_LEN );
        for( i = 0; i < tracked_instrs_len; i++ ) {
            if( strncmp( instr_name, tracked_instrs[i], strlen(tracked_instrs[i])) == 0) {
                tracked_instr_count[i] += 1;
            }
        }
    }

    //now we can calculate the ILP.
    float ilp = ((float)my_cur_size) / ((float)(glob_reg_state.num_sets != 0 ?
                glob_reg_state.num_sets : 1));

    dr_mutex_lock(stats_mutex);

    // Due to lack of memory, we only store the ILPs for the latest MY_MAX_BB
    // basic blocks. This enables us to run e.g. firefox.
    int my_cur_num = my_bbcount % MY_MAX_BB;
    my_bbcount++;
    if(my_cur_num == 0 && my_bbcount > 1) {
         dr_printf("Overflow at %d\n", my_bbcount);
    }
    my_bbexecs[my_cur_num] = 0; //initialize
    my_bbsizes[my_cur_num] = my_cur_size;
    bb_flop_count[my_cur_num] = cur_flop_count;
    for( i = 0; i < tracked_instrs_len; i++ ) {
        bb_instr_count[my_cur_num*tracked_instrs_len+i] = tracked_instr_count[i];
    }
    my_bbilp[my_cur_num] = ilp;

    dr_mutex_unlock(stats_mutex);

#ifdef USE_CLEAN_CALL
     dr_insert_clean_call(drcontext, bb, instrlist_first(bb), clean_call, false, 1,
                           OPND_CREATE_INT32(my_cur_num));
#else
#ifdef INSERT_AT_END
    instr = NULL;
#else
    // Find place to insert inc instruction
    for (instr = first; instr != NULL; instr = instr_get_next(instr)) {
        flags = instr_get_arith_flags(instr);
        if (TESTALL(EFLAGS_WRITE_6, flags) && !TESTANY(EFLAGS_READ_6, flags))
            break;
    }
#endif
    if (instr == NULL) { // no suitable place found, save regs
        dr_save_reg(drcontext, bb, first, DR_REG_XAX, SPILL_SLOT_1);
        dr_save_arith_flags_to_xax(drcontext, bb, first);
    }
    // Increment my_bbexecs[my_current_bb] using the lock prefix
    instrlist_meta_preinsert
        (bb, (instr == NULL) ? first : instr,
         LOCK(INSTR_CREATE_inc(drcontext, OPND_CREATE_ABSMEM
                               ((byte *)&(my_bbexecs[my_cur_num]), OPSZ_4))));
    if (instr == NULL) { // no suitable place found earlier, restore regs
        dr_restore_arith_flags_from_xax(drcontext, bb, first);
        dr_restore_reg(drcontext, bb, first, DR_REG_XAX, SPILL_SLOT_1);
    }
#endif

    proc_restore_fpstate(fp_align);
    
#if defined(VERBOSE) && defined(VERBOSE_VERBOSE)
    dr_printf("Finished instrumenting dynamorio_basic_block(tag="PFX")\n", tag);
    instrlist_disassemble(drcontext, tag, bb, STDOUT);
#endif
    return DR_EMIT_DEFAULT;
}
Example #18
0
static void dynamic_info_instrumentation(void *drcontext, instrlist_t *ilist, instr_t *where,
               instr_t * static_info)
{


	/* 
		issues that may arise
		1. pc and eflags is uint but in 64 bit mode 8 byte transfers are done -> so far no problem (need to see this)
			need to see whether there is a better way
		2. double check all the printing
	*/

	/*
		this function does the acutal instrumentation

		arguments - 

		we get a filled pointer here about the operand types for a given instruction (srcs and dests)
		1) increment the pointer to the instr_trace buffers
		2) add this pointer to instr_trace_t wrapper
		3) check whether any of the srcs and dests have memory operations; if so add a lea instruction and get the dynamic address
			Add this address to instr_trace_t structure
		4) if the buffer is full call a function to dump it to the file and restore the head ptr of the buffer 
			(lean function is used utilizing a code cache to limit code bloat needed for a clean call before every instruction.)
	*/

    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 */
	reg_id_t reg3 = DR_REG_XAX;
    per_thread_t *data;
    uint pc;
	uint i;

	module_data_t * module_data;

	if (client_arg->instrace_mode == DISASSEMBLY_TRACE){
		dr_insert_clean_call(drcontext, ilist, where, clean_call_disassembly_trace, false, 0);
		return;
	}

    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);
	dr_save_reg(drcontext, ilist, where, reg3, SPILL_SLOT_4);

	
	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);


	/* buf_ptr->static_info_instr = static_info; */
    /* Move static_info to static_info_instr field of buf (which is a instr_trace_t *) */
    opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(instr_trace_t, static_info_instr));
	instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)static_info, opnd1, ilist, where, &first, &second);

	/* buf_ptr->num_mem = 0; */
    opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(instr_trace_t, num_mem));
    
	instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)0, opnd1, ilist, where, &first, &second);

	for (i = 0; i<instr_num_dsts(where); i++){
		if (opnd_is_memory_reference(instr_get_dst(where, i))){
			ref = instr_get_dst(where, i);

			DR_ASSERT(opnd_is_null(ref) == false);


			dr_restore_reg(drcontext, ilist, where, reg1, SPILL_SLOT_2);
			dr_restore_reg(drcontext, ilist, where, reg2, SPILL_SLOT_3);

#ifdef DEBUG_MEM_REGS
			dr_insert_clean_call(drcontext, ilist, where, clean_call_disassembly_trace, false, 0);
			dr_insert_clean_call(drcontext, ilist, where, clean_call_print_regvalues, false, 0);
#endif
			
			drutil_insert_get_mem_addr(drcontext, ilist, where, ref, reg1, reg2);

#ifdef DEBUG_MEM_REGS
			dr_insert_clean_call(drcontext, ilist, where, clean_call_print_regvalues, false, 0);
#endif

#ifdef DEBUG_MEM_STATS
			dr_insert_clean_call(drcontext, ilist, where, clean_call_disassembly_trace, false, 0);
			dr_insert_clean_call(drcontext, ilist, where, clean_call_mem_stats, false, 1, opnd_create_reg(reg1));
#endif

			dr_insert_clean_call(drcontext, ilist, where, clean_call_populate_mem, false, 3, opnd_create_reg(reg1), OPND_CREATE_INT32(i), OPND_CREATE_INT32(DST_TYPE));

		}
	}

	for (i = 0; i<instr_num_srcs(where); i++){
		if (opnd_is_memory_reference(instr_get_src(where, i))){
			ref = instr_get_src(where, i);

			DR_ASSERT(opnd_is_null(ref) == false);			
			
			dr_restore_reg(drcontext, ilist, where, reg1, SPILL_SLOT_2);
			dr_restore_reg(drcontext, ilist, where, reg2, SPILL_SLOT_3);

#ifdef DEBUG_MEM_REGS
			dr_insert_clean_call(drcontext, ilist, where, clean_call_disassembly_trace, false, 0);
			dr_insert_clean_call(drcontext, ilist, where, clean_call_print_regvalues, false, 0);
#endif

			drutil_insert_get_mem_addr(drcontext, ilist, where, ref, reg1, reg2);

#ifdef DEBUG_MEM_REGS

			dr_insert_clean_call(drcontext, ilist, where, clean_call_print_regvalues, false, 0);
#endif

#ifdef DEBUG_MEM_STATS
			dr_insert_clean_call(drcontext, ilist, where, clean_call_disassembly_trace, false, 0);
			dr_insert_clean_call(drcontext, ilist, where, clean_call_mem_stats, false, 1, opnd_create_reg(reg1));
#endif

			dr_insert_clean_call(drcontext, ilist, where, clean_call_populate_mem, false, 3, opnd_create_reg(reg1), OPND_CREATE_INT32(i), OPND_CREATE_INT32(SRC_TYPE));

		}
	}
	

	

	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);

	/* arithmetic flags are saved here for buf_ptr->eflags filling */
	dr_save_arith_flags_to_xax(drcontext, ilist, where);

	/* load the eflags */
	opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(instr_trace_t, eflags));
	opnd2 = opnd_create_reg(reg3);
    instr = INSTR_CREATE_mov_st(drcontext, opnd1, opnd2);
    instrlist_meta_preinsert(ilist, where, instr);


	/* load the app_pc */
	opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(instr_trace_t, pc));
	module_data = dr_lookup_module(instr_get_app_pc(where));

	//dynamically generated code - module information not available - then just store 0 at the pc slot of the instr_trace data
	if (module_data != NULL){
		pc = instr_get_app_pc(where) - module_data->start;
		dr_free_module_data(module_data);
	}
	else{
		pc = 0;
	}

	instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)pc, opnd1, ilist, where, &first, &second);



	/* buf_ptr++; */
    /* 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(instr_trace_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_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);
	dr_restore_reg(drcontext, ilist, where, reg3, SPILL_SLOT_4);

	//instrlist_disassemble(drcontext, instr_get_app_pc(instrlist_first(ilist)), ilist, logfile);

}
Example #19
0
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;
}