Пример #1
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*/);
}
Пример #2
0
/* return the branch type of the (branch) inst */
uint
instr_branch_type(instr_t *cti_instr)
{
    instr_get_opcode(cti_instr); /* ensure opcode is valid */
    if (instr_get_opcode(cti_instr) == OP_blx) {
        /* To handle the mode switch we go through the ibl.
         * FIXME i#1551: once we have far linking through stubs we should
         * remove this and have a faster link through the stub.
         */
        return LINK_INDIRECT|LINK_CALL;
    }
    /* We treate a predicated call as a cbr, not a call */
    else if (instr_is_cbr_arch(cti_instr) || instr_is_ubr_arch(cti_instr))
        return LINK_DIRECT|LINK_JMP;
    else if (instr_is_call_direct(cti_instr))
        return LINK_DIRECT|LINK_CALL;
    else if (instr_is_call_indirect(cti_instr))
        return LINK_INDIRECT|LINK_CALL;
    else if (instr_is_return(cti_instr))
        return LINK_INDIRECT|LINK_RETURN;
    else if (instr_is_mbr_arch(cti_instr))
        return LINK_INDIRECT|LINK_JMP;
    else
        CLIENT_ASSERT(false, "instr_branch_type: unknown opcode");
    return LINK_INDIRECT;
}
Пример #3
0
/* this is only called when the instrace mode is operand trace (this happens at the instrumentation time) */
static void operand_trace(instr_t * instr, void * drcontext){

	int i;
	char stringop[MAX_STRING_LENGTH];
	int pc = 0;
	per_thread_t * data = drmgr_get_tls_field(drcontext, tls_index);
	module_data_t * module_data = dr_lookup_module(instr_get_app_pc(instr));

	if (module_data != NULL){
		pc = instr_get_app_pc(instr) - module_data->start;
	}
	instr_disassemble_to_buffer(drcontext, instr, stringop, MAX_STRING_LENGTH);
	
	if (client_arg->instrace_mode == OPERAND_TRACE){

		dr_fprintf(data->outfile, "%s\n", stringop);

		for (i = 0; i < instr_num_dsts(instr); i++){
			opnd_disassemble_to_buffer(drcontext, instr_get_dst(instr, i), stringop, MAX_STRING_LENGTH);
			if ((instr_get_opcode(instr) == OP_lea) && opnd_is_base_disp(instr_get_dst(instr,i))){
				dr_fprintf(data->outfile, "dst-\n");
				print_base_disp_for_lea(data->outfile, instr_get_dst(instr, i));
			}
			else{
				dr_fprintf(data->outfile, "dst-%d-%s\n", i, stringop);
			}
		}

		for (i = 0; i < instr_num_srcs(instr); i++){
			opnd_disassemble_to_buffer(drcontext, instr_get_src(instr, i), stringop, MAX_STRING_LENGTH);
			if ((instr_get_opcode(instr) == OP_lea) && opnd_is_base_disp(instr_get_src(instr, i))){
				dr_fprintf(data->outfile, "src-\n");
				print_base_disp_for_lea(data->outfile, instr_get_src(instr, i));
			}
			else{
				dr_fprintf(data->outfile, "src-%d-%s\n", i, stringop);
			}
		}

		if (module_data != NULL){
			dr_fprintf(data->outfile, "app_pc-%d\n", pc);
		}
	}
	else if (client_arg->instrace_mode == INS_DISASM_TRACE){
		if (module_data != NULL){
			if (md_get_module_position(instrace_head, module_data->full_path) == -1){
				md_add_module(instrace_head, module_data->full_path, MAX_BBS_PER_MODULE);
			}
			dr_fprintf(data->outfile, "%d,%d,%s\n", md_get_module_position(instrace_head, module_data->full_path), pc, stringop);
		}
		else{
			dr_fprintf(data->outfile, "%d,%d,%s\n",0, 0, stringop);
		}
		
	}

	dr_free_module_data(module_data);

}
Пример #4
0
/* PR 332254: test xchg vs nop */
static void
test_nop_xchg(void *dc)
{
    /*   0x0000000000671460  87 c0                xchg   %eax %eax -> %eax %eax
     *   0x0000000000671460  48 87 c0             xchg   %rax %rax -> %rax %rax
     *   0x0000000000671460  41 87 c0             xchg   %r8d %eax -> %r8d %eax
     *   0x0000000000671460  46 90                nop
     *   0x0000000000671460  4e 90                nop
     *   0x0000000000671460  41 90                xchg   %r8d %eax -> %r8d %eax
     */
    instr_t *instr;
    instr = INSTR_CREATE_xchg(dc, opnd_create_reg(REG_EAX), opnd_create_reg(REG_EAX));
    test_instr_encode(dc, instr, 2);
#ifdef X64
    /* we don't do the optimal "48 90" instead of "48 87 c0" */
    instr = INSTR_CREATE_xchg(dc, opnd_create_reg(REG_RAX), opnd_create_reg(REG_RAX));
    test_instr_encode(dc, instr, 3);
    /* we don't do the optimal "41 90" instead of "41 87 c0" */
    instr = INSTR_CREATE_xchg(dc, opnd_create_reg(REG_R8D), opnd_create_reg(REG_EAX));
    test_instr_encode(dc, instr, 3);
    /* ensure we treat as nop and NOT xchg if doesn't have rex.b */
    buf[0] = 0x46;
    buf[1] = 0x90;
    instr = instr_create(dc);
# if VERBOSE
    disassemble_with_info(dc, buf, STDOUT, true, true);
# endif
    decode(dc, buf, instr);
    ASSERT(instr_get_opcode(instr) == OP_nop);
    instr_destroy(dc, instr);
    buf[0] = 0x4e;
    buf[1] = 0x90;
    instr = instr_create(dc);
# if VERBOSE
    disassemble_with_info(dc, buf, STDOUT, true, true);
# endif
    decode(dc, buf, instr);
    ASSERT(instr_get_opcode(instr) == OP_nop);
    instr_destroy(dc, instr);
    buf[0] = 0x41;
    buf[1] = 0x90;
    instr = instr_create(dc);
# if VERBOSE
    disassemble_with_info(dc, buf, STDOUT, true, true);
# endif
    decode(dc, buf, instr);
    ASSERT(instr_get_opcode(instr) == OP_xchg);
    instr_destroy(dc, instr);
#endif
}
Пример #5
0
/* Called by slow_path() after initial decode.  Expected to free inst. */
bool
slow_path_for_staleness(void *drcontext, dr_mcontext_t *mc, instr_t *inst,
                        app_loc_t *loc)
{
    opnd_t opnd;
    int opc, i, num_srcs, num_dsts;
    uint sz;
    bool pushpop_stackop;

    opc = instr_get_opcode(inst);
    num_srcs = num_true_srcs(inst, mc);
    for (i = 0; i < num_srcs; i++) {
        opnd = instr_get_src(inst, i);
        if (opnd_is_memory_reference(opnd)) {
            opnd = adjust_memop(inst, opnd, false, &sz, &pushpop_stackop);
            check_mem_opnd_nouninit(opc, 0, loc, opnd, sz, mc);
        }
    }

    num_dsts = num_true_dsts(inst, mc);
    for (i = 0; i < num_dsts; i++) {
        opnd = instr_get_dst(inst, i);
        if (opnd_is_memory_reference(opnd)) {
            opnd = adjust_memop(inst, opnd, true, &sz, &pushpop_stackop);
            check_mem_opnd_nouninit(opc, 0, loc, opnd, sz, mc);
        }
    }

    instr_free(drcontext, inst);
    /* we're not sharing xl8 so no need to call slow_path_xl8_sharing */

    return true;
}
Пример #6
0
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;
}
Пример #7
0
/* XXX: exporting this so drwrap can use it but I might prefer to have
 * this in drutil or the upcoming drsys
 */
DR_EXPORT
int
drmgr_decode_sysnum_from_wrapper(app_pc entry)
{
    void *drcontext = dr_get_current_drcontext();
    int num = -1;
    byte *pc = entry;
    uint opc;
    instr_t instr;
    instr_init(drcontext, &instr);
    do {
        instr_reset(drcontext, &instr);
        pc = decode(drcontext, pc, &instr);
        if (!instr_valid(&instr))
            break; /* unknown system call sequence */
        opc = instr_get_opcode(&instr);
        /* sanity check: wrapper should be short */
        if (pc - entry > 20)
            break; /* unknown system call sequence */
        if (opc == OP_mov_imm && opnd_is_reg(instr_get_dst(&instr, 0)) &&
            opnd_get_reg(instr_get_dst(&instr, 0)) == DR_REG_EAX &&
            opnd_is_immed_int(instr_get_src(&instr, 0))) {
            num = (int) opnd_get_immed_int(instr_get_src(&instr, 0));
            break; /* success */
        }
        /* stop at call to vsyscall (wow64) or at int itself */
    } while (opc != OP_call_ind && opc != OP_int &&
             opc != OP_sysenter && opc != OP_syscall);
    instr_free(drcontext, &instr);
    return num;
}
Пример #8
0
/* insert inline code to add an instruction entry into the buffer */
static void
instrument_instr(void *drcontext, instrlist_t *ilist, instr_t *where)
{
    /* We need two scratch registers */
    reg_id_t reg_ptr, reg_tmp;
    /* we don't want to predicate this, because an instruction fetch always occurs */
    instrlist_set_auto_predicate(ilist, DR_PRED_NONE);
    if (drreg_reserve_register(drcontext, ilist, where, NULL, &reg_ptr) !=
            DRREG_SUCCESS ||
        drreg_reserve_register(drcontext, ilist, where, NULL, &reg_tmp) !=
            DRREG_SUCCESS) {
        DR_ASSERT(false); /* cannot recover */
        return;
    }
    insert_load_buf_ptr(drcontext, ilist, where, reg_ptr);
    insert_save_type(drcontext, ilist, where, reg_ptr, reg_tmp,
                     (ushort)instr_get_opcode(where));
    insert_save_size(drcontext, ilist, where, reg_ptr, reg_tmp,
                     (ushort)instr_length(drcontext, where));
    insert_save_pc(drcontext, ilist, where, reg_ptr, reg_tmp, instr_get_app_pc(where));
    insert_update_buf_ptr(drcontext, ilist, where, reg_ptr, sizeof(mem_ref_t));
    /* Restore scratch registers */
    if (drreg_unreserve_register(drcontext, ilist, where, reg_ptr) != DRREG_SUCCESS ||
        drreg_unreserve_register(drcontext, ilist, where, reg_tmp) != DRREG_SUCCESS)
        DR_ASSERT(false);
    instrlist_set_auto_predicate(ilist, instr_get_predicate(where));
}
Пример #9
0
/*
 * Header: Decode the specified instruction
 *
 * Params: tsk    - the task to obtain an instruction from
 *         opcode - the addr at which to save opcode *mask*
 *         params - the addr at which to save the parameters
 * Return: 0      - success of execution
 *         ETRINS - malformed instruction
 *
 * Description:
 *
 * Decodes the fields of the instructions and saves them in the provided
 * locations. If any field is malformed, that error will be returned, and 
 * the state of opcode and params is undefined.
 */
static char task_instr_decode(struct task *tsk, 
	unsigned char *opcode, unsigned char *params)
{
	char result = 0;
	unsigned char instr = tsk->recipe[tsk->pc];

	switch(instr_get_opcode(instr, opcode)) {
	case EINVOP:
		led_set(tsk, LED_RECIPE_CMD_ERROR);
		tsk->state = ST_ERROR;

		result = ETRINS;
		goto yield;
	}

	switch(instr_get_params(instr, params)) {
	case EINVOP:
	case EINVTG:
	case EINVDL:
	case EINVLP:
		led_set(tsk, LED_RECIPE_CMD_ERROR);
		tsk->state = ST_ERROR;

		result = ETRINS;
		goto yield;
	case ENOPRM:
		/* ENOPRM just means the opcode has no param! */
		break;
	}

yield:	return result;
}
Пример #10
0
/* replaces all inc with add 1, dec with sub 1
 * if cannot replace (eflags constraints), leaves original instruction alone
 */
static dr_emit_flags_t
event_trace(void *drcontext, void *tag, instrlist_t *trace, bool translating)
{
    instr_t *instr, *next_instr;
    int opcode;

    if (!enable)
	return DR_EMIT_DEFAULT;

#ifdef VERBOSE
    dr_printf("in dynamorio_trace(tag="PFX")\n", tag);
    instrlist_disassemble(drcontext, tag, trace, STDOUT);
#endif

    for (instr = instrlist_first(trace); instr != NULL; instr = next_instr) {
	/* grab next now so we don't go over instructions we insert */
	next_instr = instr_get_next(instr);
	opcode = instr_get_opcode(instr);
	if (opcode == OP_inc || opcode == OP_dec) {
            if (!translating)
                ATOMIC_INC(num_examined);
	    if (replace_inc_with_add(drcontext, instr, trace)) {
                if (!translating)
                    ATOMIC_INC(num_converted);
            }
	}
    }

#ifdef VERBOSE
    dr_printf("after dynamorio_trace(tag="PFX"):\n", tag);
    instrlist_disassemble(drcontext, tag, trace, STDOUT);
#endif

    return DR_EMIT_DEFAULT;
}
Пример #11
0
bool
instr_is_mov_constant(instr_t *instr, ptr_int_t *value)
{
    int opc = instr_get_opcode(instr);
    if (opc == OP_eor) {
        /* We include OP_eor for symmetry w/ x86, but on ARM "mov reg, #0" is
         * just as compact and there's no reason to use an xor.
         */
        if (opnd_same(instr_get_src(instr, 0), instr_get_dst(instr, 0)) &&
            opnd_same(instr_get_src(instr, 0), instr_get_src(instr, 1)) &&
            /* Must be the form with "sh2, i5_7" and no shift */
            instr_num_srcs(instr) == 4 &&
            opnd_get_immed_int(instr_get_src(instr, 2)) == DR_SHIFT_NONE &&
            opnd_get_immed_int(instr_get_src(instr, 3)) == 0) {
            *value = 0;
            return true;
        } else
            return false;
    } else if (opc == OP_mvn || opc == OP_mvns) {
        opnd_t op = instr_get_src(instr, 0);
        if (opnd_is_immed_int(op)) {
            *value = -opnd_get_immed_int(op);
            return true;
        } else
            return false;
    } else if (opc == OP_mov || opc == OP_movs || opc == OP_movw) {
        opnd_t op = instr_get_src(instr, 0);
        if (opnd_is_immed_int(op)) {
            *value = opnd_get_immed_int(op);
            return true;
        } else
            return false;
    }
    return false;
}
Пример #12
0
bool
instr_is_cti_short_rewrite(instr_t *instr, byte *pc)
{
    /* We assume all app's cbz/cbnz have been mangled.
     * See comments in x86/'s version of this routine.
     */
    dcontext_t *dcontext;
    dr_isa_mode_t old_mode;
    if (pc == NULL) {
        if (instr == NULL || !instr_has_allocated_bits(instr) ||
            instr->length != CTI_SHORT_REWRITE_LENGTH)
            return false;
        pc = instr_get_raw_bits(instr);
    }
    if (instr != NULL && instr_opcode_valid(instr)) {
        int opc = instr_get_opcode(instr);
        if (opc != OP_cbz && opc != OP_cbnz)
            return false;
    }
    if ((*(pc+1) != CBNZ_BYTE_A && *(pc+1) != CBZ_BYTE_A) ||
        /* Further verify by checking for a disp of 1 */
        (*pc & 0xf8) != 0x08)
        return false;
    /* XXX: this would be easier if decode_raw_is_jmp took in isa_mode */
    dcontext = get_thread_private_dcontext();
    if (instr != NULL)
        dr_set_isa_mode(dcontext, instr_get_isa_mode(instr), &old_mode);
    if (!decode_raw_is_jmp(dcontext, pc + CTI_SHORT_REWRITE_B_OFFS))
        return false;
    if (instr != NULL)
        dr_set_isa_mode(dcontext, old_mode, NULL);
    return true;
}
Пример #13
0
bool instr_is_prefetch(instr_t *instr)
{
    int opcode = instr_get_opcode(instr);

    if (opcode == OP_pld || opcode == OP_pldw || opcode == OP_pli)
        return true;
    return false;
}
Пример #14
0
static dr_emit_flags_t
bb_event(void* drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating)
{
    instr_t *instr, *next_instr;
    int opcode;
    for (instr = instrlist_first(bb); instr != NULL; instr = next_instr) {
        next_instr = instr_get_next(instr);
        opcode = instr_get_opcode(instr);
	if(instr_is_floating(instr)){
   	//	dr_fprintf(logF, "Has seen FPU instruction with opcode %d\n",opcode);
	
	}
	else if(is_SIMD_packed(opcode)){
   	//	dr_fprintf(logF, "Has seen SIMD packed instruction with opcode %d\n",opcode);
	}
//AVX?rcpps?

	else if(is_SIMD_arithm(opcode)){
		int is_single = 0;
//		printf("opcode is   %d\n", opcode);
//    		printf("number of sources  %d\n", instr_num_srcs(instr));  
 //   		printf("number of dests  %d\n", instr_num_dsts(instr));
		//assert(number of sources = 2);
		opnd_t source1 = instr_get_src(instr,0);
		opnd_t source2 = instr_get_src(instr,1);
		opnd_t dest = instr_get_dst(instr,0);
		if(opnd_is_memory_reference(source1)){
	//		dr_print_instr(drcontext, logF, instr, "INSTR: ");
//			dr_print_opnd(drcontext, logF, source1, "OPND1: ");
//			dr_print_opnd(drcontext, logF, source2, "OPND2: ");
			reg_id_t rd = opnd_get_reg(source2);
			reg_id_t rs = opnd_get_reg_used(source1, 0);
			dr_insert_clean_call(drcontext, bb, instr, 
				(void*) callback, true, 5, 
				OPND_CREATE_INTPTR(rs), OPND_CREATE_INTPTR(opnd_get_disp(source1)),
				OPND_CREATE_INTPTR(rd), OPND_CREATE_INTPTR(opcode), OPND_CREATE_INTPTR(instr_get_app_pc(instr)));

		}
		else if(opnd_is_reg(source1) && opnd_is_reg(source2)){
			reg_id_t reg1 = opnd_get_reg(source1);
			reg_id_t reg2 = opnd_get_reg(source2);
			dr_insert_clean_call(drcontext,bb,instr, (void*)getRegReg, 
				true, 4, 
				OPND_CREATE_INTPTR(reg1), OPND_CREATE_INTPTR(reg2)
				,OPND_CREATE_INTPTR(opcode), OPND_CREATE_INTPTR(instr_get_app_pc(instr))
			); 
		}
		else{
		//should not be the case, throw an exception
		}
	        fp_count++; 
      }
    }

    return DR_EMIT_DEFAULT;
}
Пример #15
0
int
instr_length_arch(dcontext_t *dcontext, instr_t *instr)
{
    if (instr_get_opcode(instr) == OP_LABEL)
        return 0;
    /* Avoid encoding OP_b to avoid reachability checks for added fall-through
     * jumps, whose targets are later changed to the stub prior to emit.
     * Another option is to remove the assert on bad encoding, so that the
     * instr_encode_check_reachability() call in private_instr_encode() can
     * gracefully fail: which we now do, but this is a nice optimization.
     */
    if (instr_get_opcode(instr) == OP_b)
        return 4;
    if (instr_get_isa_mode(instr) == DR_ISA_ARM_THUMB) {
        /* We have to encode to find the size */
        return -1;
    } else
        return ARM_INSTR_SIZE;
}
Пример #16
0
bool
instr_is_near_call_direct(instr_t *instr)
{
    int opc = instr_get_opcode(instr);
    /* Mode-switch call is not "near".
     * FIXME i#1551: once we switch OP_blx to use far-stub linking instead of
     * ibl we can then consider it "near".
     */
    return (opc == OP_bl);
}
Пример #17
0
static bool
instr_is_rep_string(instr_t *instr)
{
#ifdef X86
    uint opc = instr_get_opcode(instr);
    return (opc == OP_rep_ins || opc == OP_rep_outs || opc == OP_rep_movs ||
            opc == OP_rep_stos || opc == OP_rep_lods || opc == OP_rep_cmps ||
            opc == OP_repne_cmps || opc == OP_rep_scas || opc == OP_repne_scas);
#else
    return false;
#endif
}
Пример #18
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)
{
    /* if find div, insert a clean call to our instrumentation routine */
    if (instr_get_opcode(instr) == OP_div) {
        dr_insert_clean_call(drcontext, bb, instr, (void *)callback,
                             false /*no fp save*/, 2,
                             OPND_CREATE_INTPTR(instr_get_app_pc(instr)),
                             instr_get_src(instr, 0) /*divisor is 1st src*/);
    }
    return DR_EMIT_DEFAULT;
}
Пример #19
0
/* Our version, versus Dr. Memory's version in drmemory/fastpath.c */
bool
instr_ok_for_instrument_fastpath(instr_t *inst, fastpath_info_t *mi, bb_info_t *bi)
{
    uint opc = instr_get_opcode(inst);
    int i;
    initialize_fastpath_info(mi, bi, inst);
    if (!options.fastpath)
        return false;
    if (opc == OP_xlat) {
        /* can't use base-disp "%ds:(%ebx,%al,1)" for lea: would have to expand
         * to multiple instrs.  not worth supporting since pretty rare though I
         * do see 3K in twolf test on windows.
         */
        return false;
    }

    /* We assume that any one memory reference, even in a rep string form,
     * will only access one heap allocation.  Since we're taking the most
     * recent access to any part of a heap alloc we thus don't care about the
     * size of a memory reference.
     */
    for (i=0; i<instr_num_dsts(inst); i++) {
        if (opnd_uses_memory_we_track(instr_get_dst(inst, i))) {
            mi->store = true;
            if (!opnd_is_null(mi->dst[0].app)) {
                /* FIXME: we could handle 2 dsts if no srcs easily,
                 * and even more dsts if we really wanted to w/o too
                 * much trouble.  also something like pusha w/
                 * consecutive dsts is easy: just take first one.
                 */
                return false;
            }
            mi->dst[0].app = instr_get_dst(inst, i);
        }
    }
    for (i=0; i<instr_num_srcs(inst); i++) {
        if (opnd_uses_memory_we_track(instr_get_src(inst, i))) {
            if (mi->store)
                mi->mem2mem = true;
            else
                mi->load = true;
            if (!opnd_is_null(mi->src[0].app)) {
                /* see notes above about handling this: in particular cmps */
                return false;
            }
            mi->src[0].app = instr_get_src(inst, i);
        }
    }
    return true;
}
Пример #20
0
static instr_t * static_info_instrumentation(void * drcontext, instr_t* instr){
	/*
		for each src and dest add the information accordingly
		this should return canonicalized static info about an instruction; breaking down any complex instructions if necessary

		1) check whether this instruction needs to be instrumented
		2) if yes, then get a location and then proceed to instrument -> return the struct
		3) if no, return null

	*/

	/* main variables */
	per_thread_t * data = drmgr_get_tls_field(drcontext,tls_index);

	/* helper variables */
	int opcode;
	instr_t * ret;
	
	/* loop variables */
	int i;

	/* 1) */

	opcode = instr_get_opcode(instr);

	if (client_arg->instrace_mode == OPCODE_TRACE){
		opcodes_visited[opcode] = true;
		return NULL;
	}

	if ( (client_arg->instrace_mode == OPERAND_TRACE) || (client_arg->instrace_mode == INS_DISASM_TRACE) ){
		operand_trace(instr, drcontext);
		return NULL;
	}

	/* check whether this instr needs instrumentation - check for ones to skip and skip if */
	/*switch(opcode){
	case OP_jecxz:
		return NULL;
	}*/
	
	/* 2) */

	data->static_array[data->static_ptr++] = instr_clone(drcontext,instr);
	DR_ASSERT(data->static_ptr < data->static_array_size);

	return data->static_array[data->static_ptr - 1];

}
Пример #21
0
static dr_emit_flags_t
drmgr_event_bb_insert(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst,
                      bool for_trace, bool translating, void *user_data)
{
    if (instr_get_app_pc(inst) == addr_KiCallback) {
        dr_insert_clean_call(drcontext, bb, inst, (void *)drmgr_cls_stack_push,
                             false, 0);
    }
    if (instr_get_opcode(inst) == OP_int &&
        opnd_get_immed_int(instr_get_src(inst, 0)) == CBRET_INTERRUPT_NUM) {
        dr_insert_clean_call(drcontext, bb, inst, (void *)drmgr_cls_stack_pop,
                             false, 0);
    }
    return DR_EMIT_DEFAULT;
}
Пример #22
0
static bool
instr_is_exclusive_load(instr_t *instr)
{
    switch (instr_get_opcode(instr)) {
    case OP_ldaxp:
    case OP_ldaxr:
    case OP_ldaxrb:
    case OP_ldaxrh:
    case OP_ldxp:
    case OP_ldxr:
    case OP_ldxrb:
    case OP_ldxrh:
        return true;
    }
    return false;
}
Пример #23
0
bool
instr_writes_gpr_list(instr_t *instr)
{
    int opc = instr_get_opcode(instr);
    switch (opc) {
    case OP_ldm:
    case OP_ldmib:
    case OP_ldmda:
    case OP_ldmdb:
    case OP_ldm_priv:
    case OP_ldmib_priv:
    case OP_ldmda_priv:
    case OP_ldmdb_priv: return true;
    default: return false;
    }
}
Пример #24
0
static void
look_for_usercall(void *dcontext, byte *entry, const char *sym, LOADED_IMAGE *img,
                  const char *modpath)
{
    bool found_push_imm = false;
    int imm = 0;
    app_pc pc, pre_pc;
    instr_t *instr;
    if (entry == NULL)
        return;
    instr = instr_create(dcontext);
    pc = entry;
    while (true) {
        instr_reset(dcontext, instr);
        pre_pc = pc;
        pc = decode(dcontext, pc, instr);
        if (verbose) {
            instr_set_translation(instr, pre_pc);
            dr_print_instr(dcontext, STDOUT, instr, "");
        }
        if (pc == NULL || !instr_valid(instr))
            break;
        if (instr_get_opcode(instr) == OP_push_imm) {
            found_push_imm = true;
            imm = (int) opnd_get_immed_int(instr_get_src(instr, 0));
        } else if (instr_is_call_direct(instr) && found_push_imm) {
            app_pc tgt = opnd_get_pc(instr_get_target(instr));
            bool found = false;
            int i;
            for (i = 0; i < NUM_USERCALL; i++) {
                if (tgt == usercall_addr[i]) {
                    dr_printf("Call #0x%02x to %s at %s+0x%x\n", imm, usercall_names[i],
                              sym, pre_pc - entry);
                    found = true;
                    break;
                }
            }
            if (found)
                break;
        } else if (instr_is_return(instr))
            break;
        if (pc - entry > MAX_BYTES_BEFORE_USERCALL)
            break;
    }
    instr_destroy(dcontext, instr);
}
Пример #25
0
bool
instr_uses_memory_we_track(instr_t *inst)
{
    int i;
    ASSERT(options.staleness, "should not be called");
    if (instr_get_opcode(inst) == OP_lea) /* not a real mem access */
        return false;
    for (i = 0; i < instr_num_srcs(inst); i++) {
        if (opnd_uses_memory_we_track(instr_get_src(inst, i)))
            return true;
    }
    for (i = 0; i < instr_num_dsts(inst); i++) {
        if (opnd_uses_memory_we_track(instr_get_dst(inst, i)))
            return true;
    }
    return false;
}
Пример #26
0
static bool
instr_is_reg_restore(instr_t *instr, reg_id_t reg, umbra_info_t *info)
{
    opnd_t opnd;
    int    slot;

    if (instr_get_opcode(instr) != OP_mov_ld)
        return false;
    opnd = instr_get_dst(instr, 0);
    if (!opnd_is_reg(opnd) || opnd_get_reg(opnd) != reg)
        return false;
    slot = reg - REG_SPILL_START;
    opnd = OPND_CREATE_ABSMEM(&info->spill_regs[slot], OPSZ_PTR);
    if (opnd_same(opnd, instr_get_src(instr, 0)))
        return true;
    return false;
}
Пример #27
0
bool
instr_reads_reg_list(instr_t *instr)
{
    int opc = instr_get_opcode(instr);
    switch (opc) {
    case OP_stm:
    case OP_stmib:
    case OP_stmda:
    case OP_stmdb:
    case OP_stm_priv:
    case OP_stmib_priv:
    case OP_stmda_priv:
    case OP_stmdb_priv:
    case OP_vstm:
    case OP_vstmdb: return true;
    default: return false;
    }
}
Пример #28
0
static app_pc
get_function_entry(app_pc C_var)
{
    void *drcontext = dr_get_current_drcontext();
    byte *pc;
    instr_t inst;
    instr_init(drcontext, &inst);
    pc = decode(drcontext, C_var, &inst);
    ASSERT(pc != NULL, "invalid instr at function entry");
    if (instr_get_opcode(&inst) == OP_jmp) {
        /* skip jmp in ILT */
        ASSERT(opnd_is_pc(instr_get_target(&inst)), "decoded jmp should have pc tgt");
        pc = opnd_get_pc(instr_get_target(&inst));
    } else
        pc = C_var;
    instr_free(drcontext, &inst);
    return pc;
}
Пример #29
0
bool
instr_is_return(instr_t *instr)
{
    /* There is no "return" opcode so we consider a return to be either:
     * A) An indirect branch through lr;
     * B) An instr that reads lr and writes pc;
     *    (XXX: should we limit to a move and rule out an add or shift or whatever?)
     * C) A pop into pc.
     */
    int opc = instr_get_opcode(instr);
    if ((opc == OP_bx || opc ==  OP_bxj) &&
        opnd_get_reg(instr_get_src(instr, 0)) == DR_REG_LR)
        return true;
    if (!instr_writes_to_reg(instr, DR_REG_PC, DR_QUERY_INCLUDE_ALL))
        return false;
    return (instr_reads_from_reg(instr, DR_REG_LR, DR_QUERY_INCLUDE_ALL) ||
            instr_is_pop(instr));
}
Пример #30
0
static
dr_emit_flags_t bb_event(void* drcontext, void *tag, instrlist_t *bb,
                         bool for_trace, bool translating)
{
    instr_t *instr;
    if (!translating)
        increment(tag);

    /* I'm looking for a specific BB in the test .exe.  I've marked
     * it with a couple nops.
     */
#ifdef WINDOWS
    if ((app_pc)tag >= start && (app_pc)tag < end) {
#endif
        instr = instrlist_first(bb);

        if (instr_is_nop(instr)) {
            instr_t *next = instr_get_next(instr);

            /* The test app uses two nops as a marker to identify a specific bb.  Since
             * 2 nop instructions in a row aren't that uncommon on Linux (where we can't
             * restrict our search to just the test.exe module) we use an unusual nop
             * for the second one: xchg xbp, xbp */
            if (next != NULL && instr_is_nop(next) &&
                instr_get_opcode(next) == OP_xchg &&
                instr_writes_to_exact_reg(next, REG_XBP, DR_QUERY_DEFAULT)) {

                bb_build_count++;

                if (delay_flush_at_next_build) {
                    delay_flush_at_next_build = false;
                    dr_delay_flush_region((app_pc)tag - 20, 30, callback_count, flush_event);
                }

                dr_insert_clean_call(drcontext, bb, instr, (void *)callback,
                                     false, 2, OPND_CREATE_INTPTR(tag),
                                     OPND_CREATE_INTPTR(instr_get_app_pc(instr)));
            }
        }
#ifdef WINDOWS
    }
#endif
    return DR_EMIT_DEFAULT;
}