Esempio n. 1
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);

}
Esempio n. 2
0
static void
print_address(app_pc addr, int bits, double loss, double lossD)
{
	testarr[testcount] = lossD;
	testcount++;
	char key_string[KEY_MAX_LENGTH];
	snprintf(key_string, KEY_MAX_LENGTH, "%s", "main");//sym->name);


    const char* prefix = "PRINT ADDRESS: ";
    drsym_error_t symres;
    drsym_info_t *sym;
    char sbuf[sizeof(*sym) + MAX_SYM_RESULT];
    module_data_t *data;
    data = dr_lookup_module(addr);
    if (data == NULL) {
       // dr_fprintf(logF, "%s data is null "PFX" \n", prefix, addr);
        return;
    }
    snprintf(process_path, MAXIMUM_PATH,"%s",data->full_path);


    if(!callgrind_log_created){
	writeCallgrind(thread_id_for_log);
	callgrind_log_created = true;
    }

    sym = (drsym_info_t *) sbuf;
    sym->struct_size = sizeof(*sym);
    sym->name_size = MAX_SYM_RESULT;   

    symres = drsym_lookup_address(data->full_path, addr - data->start, sym,
                           DRSYM_DEFAULT_FLAGS);
/*

    if (symres == DRSYM_SUCCESS || symres == DRSYM_ERROR_LINE_NOT_AVAILABLE) {
        const char *modname = dr_module_preferred_name(data);
        if (modname == NULL)
            modname = "<noname>";
        //dr_fprintf(logF, "%s "PFX" %s, function name is: %s, "PIFX", line off "PFX" \n", prefix, addr,
                   //modname, sym->name, addr - data->start - sym->start_offs, sym->line_offs);


//printf("test ins %d\n", testcount);

//add check for line not available
       if (symres == DRSYM_ERROR_LINE_NOT_AVAILABLE) {
           // dr_fprintf(logF, "%s Line is not available\n", prefix);
        } else {
           // dr_fprintf(logF, "Line number is  %s:%"UINT64_FORMAT_CODE" %d\n",
                      // sym->file, sym->line, sym->line_offs);
        }
    } else
      //  dr_fprintf(logF, "%s some error "PFX" \n", prefix, addr);
  */
    dr_free_module_data(data);
}
Esempio n. 3
0
void clean_call_mem_information(instr_t * instr, app_pc mem_val, uint write){

	void * drcontext = dr_get_current_drcontext();
	module_data_t * data = dr_lookup_module(instr_get_app_pc(instr));
	uint offset;

	app_pc base_pc;
	size_t size;
	uint prot;
	file_t dump_file;
	char * dump_filename;
	
	DR_ASSERT(data != NULL);
	offset = instr_get_app_pc(instr) - data->start;

	dr_mutex_lock(mutex);

	//if (!md_lookup_bb_in_module(done_head, data->full_path, offset)){

		//md_add_bb_to_module(done_head, data->full_path, offset, MAX_BBS_PER_MODULE, false); 
		dr_query_memory(mem_val, &base_pc, &size, &prot);
		//DEBUG_PRINT("base pc - %x, size - %u, write - %u\n", base_pc, size, write);
		if (write){  /* postpone till the end of the function */
			if (!is_mem_region_present(write_regions, base_pc, size, write_region_size)){
				DEBUG_PRINT("write registered - offset - %x memval %x\n", offset, mem_val);
				add_to_mem_region(write_regions, base_pc, size, &write_region_size);
				DEBUG_PRINT("base pc %x, size %d\n", base_pc, size); 
			}
		}
		else{
			if (!is_mem_region_present(read_regions, base_pc, size, read_region_size)){
				add_to_mem_region(read_regions, base_pc, size, &read_region_size);
				//DEBUG_PRINT("size - %d\n", read_region_size);
				//DEBUG_PRINT("present - %d\n", is_mem_region_present(read_regions, base_pc, size, read_region_size));
				//dr_abort();
				DEBUG_PRINT("read registered - offset - %x memval %x\n", offset,  mem_val);
				DEBUG_PRINT("base pc %x, size %d\n", base_pc, size);
				dump_filename = get_mem_dump_filename(base_pc, size, write,0);
				dump_file = dr_open_file(dump_filename, DR_FILE_WRITE_OVERWRITE);
				DEBUG_PRINT("%s dumping file\n", dump_filename);
				do_mem_dump(dump_file, base_pc, size);
				DEBUG_PRINT("file dumped\n");
				dr_global_free(dump_filename, sizeof(char) * MAX_STRING_LENGTH);
				dr_close_file(dump_file);
			}
		}



	//}

	dr_mutex_unlock(mutex);
	dr_free_module_data(data);


}
Esempio n. 4
0
static
bool is_in_known_module(app_pc pc, bool *found_section, IMAGE_SECTION_HEADER *section)
{
    bool found = false;
    module_data_t *data = dr_lookup_module(pc);
    if (data != NULL) {
        found = true;
        *found_section = dr_lookup_module_section(data->handle, pc, section);
    }
    dr_free_module_data(data);
    return found;
}
Esempio n. 5
0
dr_emit_flags_t
funcwrap_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);
	app_pc pc = instr_get_app_pc(first);
	module_data_t * module_data;
	per_thread_t * data = drmgr_get_tls_field(dr_get_current_drcontext(), tls_index);
	module_t * md;
	app_pc offset;
	
	
	if (instr != first || data->nesting != 0){
		return DR_EMIT_DEFAULT;
	}

	module_data = dr_lookup_module(pc);
	data = drmgr_get_tls_field(drcontext, tls_index);

	
	if (module_data != NULL){
		md = md_lookup_module(head, module_data->full_path);
		if (md != NULL){
			offset = pc - module_data->start;
			
			for (int i = 1; i <= md->bbs[0].start_addr; i++){
				if (offset == md->bbs[i].start_addr){
					DEBUG_PRINT("bb instrumenting function\n");
					data->filter_func = true;
					dr_insert_clean_call(drcontext, bb, instr, clean_call, false, 1, OPND_CREATE_INTPTR(instr_get_app_pc(instr)));
					wrap_thread_id = dr_get_thread_id(drcontext);
					DEBUG_PRINT("done bb instrumenting function\n");

				}
			}
		}
	}

	

	/*if (data->filter_func){
		instrlist_disassemble(drcontext, instr_get_app_pc(instrlist_first(bb)), bb, logfile);
	}*/

	dr_free_module_data(module_data);


	return DR_EMIT_DEFAULT;

}
Esempio n. 6
0
app_pc
get_heap_start(void)
{
    static app_pc heap_start; /* cached value */
    if (heap_start == NULL) {
        app_pc cur_brk = get_brk(true/*pre-us*/);
        dr_mem_info_t info;
        module_data_t *data;
        /* Locate the heap */
        if (!dr_query_memory_ex(cur_brk - 1, &info)) {
            ASSERT(false, "cannot find heap region");
            return NULL;
        }
        if (info.type == DR_MEMTYPE_FREE || info.type == DR_MEMTYPE_IMAGE ||
            !TEST(DR_MEMPROT_WRITE, info.prot)) {
            /* Heap is empty */
            heap_start = cur_brk;
        } else {
            ASSERT(!dr_memory_is_dr_internal(info.base_pc), "heap location error");
            /* we no longer assert that these are equal b/c -replace_malloc
             * has extended the brk already
             */
            ASSERT(info.base_pc + info.size >= cur_brk, "heap location error");
            heap_start = info.base_pc;
            /* workaround for PR 618178 where /proc/maps is wrong on suse
             * and lists last 2 pages of executable as heap!
             */
            /* On some old Linux kernel, the heap might be right after the bss
             * segment. DR's map iterator used by dr_query_memory_ex cannot
             * split bss out of heap.
             * We use dr_lookup_module to find the right bounds of bss so that
             * we can check whether the base is bss, existing heap, or merge of
             * the two.
             */
            /* XXX: we still cannot handle the case that the application creates
             * memory right before the heap.
             */
            data = dr_lookup_module(info.base_pc);
            if (data != NULL) {
                if (data->start < heap_start && data->end > heap_start) {
                    heap_start = (byte *) ALIGN_FORWARD(data->end, PAGE_SIZE);
                    LOG(1, "WARNING: workaround for invalid heap_start "PFX" => "PFX"\n",
                        info.base_pc, heap_start);
                }
                dr_free_module_data(data);
            }
        }
    }
    return heap_start;
}
Esempio n. 7
0
/* Lookup the module containing addr and see if we have a table entry for it */
static table_entry_t *
get_entry_for_address(app_pc addr)
{
    module_data_t *data = dr_lookup_module(addr);
    table_entry_t *entry = NULL;
    if (data != NULL) {
        entry = table;
        while (entry != NULL &&
               _stricmp(dr_module_preferred_name(data), entry->value.module_name) != 0) {
            entry = entry->next;
        }
        dr_free_module_data(data);
    }
    return entry;
}
Esempio n. 8
0
/*
 * Make a string representation of the address of an instruction,
 * including a function name and/or a file+line combination if
 * possible. These will be logged alongside every act of interest
 * where we can make one.
 */
static void instr_format_location(instr_t *instr, char **outloc)
{
    app_pc addr = (app_pc)instr_get_app_pc(instr);
    char location[2048], symbol[512], fileline[1024];
    bool got_sym = false, got_line = false;

    if (*outloc)
        return;

    symbol[0] = '\0';
    fileline[0] = '\0';

    module_data_t *data = dr_lookup_module(addr);
    if (data) {
        drsym_info_t sym;
        char file[MAXIMUM_PATH];

        sym.struct_size = sizeof(sym);
        sym.name = symbol;
        sym.name_size = sizeof(symbol);
        sym.file = file;
        sym.file_size = sizeof(file);

        drsym_error_t status = drsym_lookup_address(
            data->full_path, addr - data->start, &sym, DRSYM_DEFAULT_FLAGS);

        got_line = (status == DRSYM_SUCCESS);
        got_sym = got_line || status == DRSYM_ERROR_LINE_NOT_AVAILABLE;

        if (got_line)
            snprintf(fileline, sizeof(fileline), " = %s:%"PRIu64,
                     file, (uint64_t)sym.line);
    }

    snprintf(location, sizeof(location),
             "%"PRIx64"%s%s%s",
             (uint64_t)addr, got_sym ? " = " : "", got_sym ? symbol : "",
             fileline);
    size_t len = strlen(location) + 1;
    char *loc = dr_global_alloc(len);
    memcpy(loc, location, len);
    *outloc = loc;
}
Esempio n. 9
0
static void
memtrace(void *drcontext)
{
    per_thread_t *data;
    int num_refs;
    mem_ref_t *mem_ref;
#ifdef READABLE_TRACE
    int i;
#endif

	module_data_t * mdata;

    data      = drmgr_get_tls_field(drcontext, tls_index);
    mem_ref   = (mem_ref_t *)data->buf_base;
    num_refs  = (int)((mem_ref_t *)data->buf_ptr - mem_ref);

#ifdef READABLE_TRACE
    /*dr_fprintf(data->log,
               "Format: <instr address>,<(r)ead/(w)rite>,<data size>,<data address>\n");*/

	for (i = 0; i < num_refs; i++) {
		mdata = dr_lookup_module(mem_ref->pc);
		if (mdata != NULL){
			if (((uint)mem_ref->addr > data->stack_base) || ((uint)mem_ref->addr < data->stack_limit)){
				dr_fprintf(data->outfile, "%x,%x,%d,%d,"PFX"\n", mdata->start, mem_ref->pc - mdata->start
					, mem_ref->write ? 1 : 0 , mem_ref->size, mem_ref->addr);
			}
			dr_free_module_data(mdata);
		}
			
		++mem_ref;
	}

#else
    dr_write_file(data->log, data->buf_base,
                  (size_t)(data->buf_ptr - data->buf_base));
#endif

    memset(data->buf_base, 0, MEM_BUF_SIZE);
    data->num_refs += num_refs;
    data->buf_ptr   = data->buf_base;
}
Esempio n. 10
0
/* this is only called when the instrace mode is disassembly trace (this happens at the analysis time)*/
static void clean_call_disassembly_trace(){

	char disassembly[SHORT_STRING_LENGTH];

	per_thread_t * data = drmgr_get_tls_field(dr_get_current_drcontext(), tls_index);
	instr_trace_t * trace = (instr_trace_t *)data->buf_ptr;
	module_data_t * md;

	md = dr_lookup_module(instr_get_app_pc(trace->static_info_instr));

	instr_disassemble_to_buffer(dr_get_current_drcontext(), trace->static_info_instr, disassembly, SHORT_STRING_LENGTH);

	dr_fprintf(data->outfile, "%s ", disassembly);

	if (md != NULL){
		dr_fprintf(data->outfile, "%x", instr_get_app_pc(trace->static_info_instr) - md->start);
		dr_free_module_data(md);
	}
	dr_fprintf(data->outfile, "\n");
}
Esempio n. 11
0
static void
print_address(file_t f, app_pc addr, const char *prefix)
{
    drsym_error_t symres;
    drsym_info_t sym;
    char name[MAX_SYM_RESULT];
    char file[MAXIMUM_PATH];
    module_data_t *data;
    data = dr_lookup_module(addr);
    if (data == NULL) {
        dr_fprintf(f, "%s "PFX" ? ??:0\n", prefix, addr);
        return;
    }
    sym.struct_size = sizeof(sym);
    sym.name = name;
    sym.name_size = MAX_SYM_RESULT;
    sym.file = file;
    sym.file_size = MAXIMUM_PATH;
    symres = drsym_lookup_address(data->full_path, addr - data->start, &sym,
                                  DRSYM_DEFAULT_FLAGS);
    if (symres == DRSYM_SUCCESS || symres == DRSYM_ERROR_LINE_NOT_AVAILABLE) {
        const char *modname = dr_module_preferred_name(data);
        if (modname == NULL)
            modname = "<noname>";
        dr_fprintf(f, "%s "PFX" %s!%s+"PIFX, prefix, addr,
                   modname, sym.name, addr - data->start - sym.start_offs);
        if (symres == DRSYM_ERROR_LINE_NOT_AVAILABLE) {
            dr_fprintf(f, " ??:0\n");
        } else {
            dr_fprintf(f, " %s:%"UINT64_FORMAT_CODE"+"PIFX"\n",
                       sym.file, sym.line, sym.line_offs);
        }
    } else
        dr_fprintf(f, "%s "PFX" ? ??:0\n", prefix, addr);
    dr_free_module_data(data);
}
Esempio n. 12
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);

}
Esempio n. 13
0
static dr_emit_flags_t
event_bb_analysis(void *drcontext, void *tag, instrlist_t *bb, bool for_trace,
                  bool translating, void **user_data)
{
    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
    /* Only count in app BBs */
    if (only_from_app.get_value()) {
        module_data_t *mod = dr_lookup_module(dr_fragment_app_pc(tag));
        if (mod != NULL) {
            bool from_exe = (mod->start == exe_start);
            dr_free_module_data(mod);
            if (!from_exe) {
                *user_data = NULL;
                return DR_EMIT_DEFAULT;
            }
        }
    }

    /* Count instructions. If an emulation client is running with this client,
     * we want to count all the original native instructions and the emulated
     * instruction but NOT the introduced native instructions used for emulation.
     */
    bool is_emulation = false;
    for (instr = instrlist_first(bb), num_instrs = 0; instr != NULL;
         instr = instr_get_next(instr)) {
        if (drmgr_is_emulation_start(instr)) {
            /* Each emulated instruction is replaced by a series of native
             * instructions delimited by labels indicating when the emulation
             * sequence begins and ends. It is the responsibility of the
             * emulation client to place the start/stop labels correctly.
             */
            num_instrs++;
            is_emulation = true;
            /* Data about the emulated instruction can be extracted from the
             * start label using the accessor function:
             * drmgr_get_emulated_instr_data()
             */
            continue;
        }
        if (drmgr_is_emulation_end(instr)) {
            is_emulation = false;
            continue;
        }
        if (is_emulation)
            continue;
        if (!instr_is_app(instr))
            continue;
        num_instrs++;
    }
    *user_data = (void *)(ptr_uint_t)num_instrs;

#if defined(VERBOSE) && defined(VERBOSE_VERBOSE)
    dr_printf("Finished counting for dynamorio_basic_block(tag=" PFX ")\n", tag);
    instrlist_disassemble(drcontext, tag, bb, STDOUT);
#endif
    return DR_EMIT_DEFAULT;
}