Ejemplo n.º 1
0
void inscount_init(client_id_t id, const char * name,  const char * arguments)
{

	file_t in_file;
	char logfilename[MAX_STRING_LENGTH];

	drmgr_init();

	global_count = 0;

	DR_ASSERT(parse_commandline_args(arguments) == true);
	head = md_initialize();


	if(client_arg->filter_mode != FILTER_NONE){
		in_file = dr_open_file(client_arg->filter_filename,DR_FILE_READ);
		DR_ASSERT(in_file != INVALID_FILE);
		md_read_from_file(head,in_file,false);
		dr_close_file(in_file);
	}

	if (log_mode){
		populate_conv_filename(logfilename, logdir, name, NULL);
		logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE);
	}
	strncpy(ins_pass_name, name, MAX_STRING_LENGTH);



}
Ejemplo n.º 2
0
/* callbacks for the entire process */
void funcwrap_init(client_id_t id, const char * name, const char * arguments)
{

	file_t in_file;
	char logfilename[MAX_STRING_LENGTH];

	drmgr_init();
	drwrap_init();
	tls_index = drmgr_register_tls_field();

	DR_ASSERT(parse_commandline_args(arguments) == true);
	head = md_initialize();
	if (!dr_file_exists(client_arg->filter_filename)){
		file_registered = false;
	}
	/* we expect the filter file to be of the form for function filtering */
	else{
		file_registered = true;
		in_file = dr_open_file(client_arg->filter_filename, DR_FILE_READ);
		DR_ASSERT(in_file != INVALID_FILE);
		md_read_from_file(head, in_file, false);
		dr_close_file(in_file);
	}

	if (log_mode){
		populate_conv_filename(logfilename, logdir, name, NULL);
		logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE);
	}
	strncpy(ins_pass_name, name, MAX_STRING_LENGTH);
	

}
Ejemplo n.º 3
0
/* callbacks for the entire process */
void memdump_init(client_id_t id, const char * name, const char * arguments)
{

	char logfilename[MAX_STRING_LENGTH];
	file_t in_file;

	drmgr_init();
	drutil_init();
	drwrap_init();
	tls_index = drmgr_register_tls_field();
	DR_ASSERT(parse_commandline_args(arguments) == true);

	filter_head = md_initialize();
	done_head = md_initialize();
	app_pc_head = md_initialize();
	
	in_file = dr_open_file(client_arg->filter_filename, DR_FILE_READ);
	md_read_from_file(filter_head, in_file, false);
	dr_close_file(in_file);
	
	in_file = dr_open_file(client_arg->app_pc_filename, DR_FILE_READ);
	md_read_from_file(app_pc_head, in_file, false);
	dr_close_file(in_file);


	if (log_mode){
		populate_conv_filename(logfilename, logdir, name, NULL);
		logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE);
	}
	strncpy(ins_pass_name, name, MAX_STRING_LENGTH);
	mutex = dr_mutex_create();

}
Ejemplo n.º 4
0
void
writeLog(void* drcontext){
	char logname[MAXIMUM_PATH];
	char *dirsep;
    	int len;
	len = dr_snprintf(logname, sizeof(logname)/sizeof(logname[0]),
                      "%s", dr_get_client_path(client_id));
	DR_ASSERT(len > 0);
	for (dirsep = logname + len; *dirsep != '/'; dirsep--)
        DR_ASSERT(dirsep > logname);
    	len = dr_snprintf(dirsep + 1,
                      (sizeof(logname) - (dirsep - logname))/sizeof(logname[0]),
                      "floatingpoint.%d.log", dr_get_thread_id(drcontext));
    	DR_ASSERT(len > 0);
    	NULL_TERMINATE(logname);
    	logF = dr_open_file(logname, 
                             DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE);
    	DR_ASSERT(logF != INVALID_FILE);
    	dr_log(drcontext, LOG_ALL, 1, 
           "floating point: log for thread %d is fp.%03d\n",
           dr_get_thread_id(drcontext), dr_get_thread_id(drcontext));
	#ifdef SHOW_RESULTS
    	if (dr_is_notify_on()) {
//        	dr_fprintf(STDERR, "<floating point instruction operands for thread %d in %s>\n",
//                  dr_get_thread_id(drcontext), logname);
    	}
	#endif	
	thread_id_for_log = dr_get_thread_id(drcontext);
}
Ejemplo n.º 5
0
static file_t
open_sigil2_fifo(const char *path, int flags)
{
    /* Wait for Sigil2 to create pipes
     * Timeout is empirical */
    uint max_tests = 10;
    for(uint i=0; i<max_tests+1; ++i)
    {
        if(dr_file_exists(path))
            break;

        if(i == max_tests)
        {
            dr_printf("%s\n", path);
            DR_ASSERT_MSG(false, "DrSigil timed out waiting for sigil2 fifos");
        }

        struct timespec ts;
        ts.tv_sec  = 0;
        ts.tv_nsec = 200000000L;
        nanosleep(&ts, NULL);
    }

    file_t f = dr_open_file(path, flags);
    if(f == INVALID_FILE)
        DR_ABORT_MSG("error opening empty fifo");

    return f;
}
Ejemplo n.º 6
0
DR_EXPORT void dr_init(client_id_t id) {
  dr_fprintf(STDERR, "info: starting dtrace, &dr_init=%p..\n", &dr_init);

  trace_file = dr_open_file(TRACE_FILE_NAME,
                            DR_FILE_ALLOW_LARGE | DR_FILE_WRITE_OVERWRITE);
  if(trace_file == INVALID_FILE) {
    dr_fprintf(STDERR, "fatal: dr_open_file() failed\n");
    dr_exit_process(1);
  }
  trace_file_lock = dr_mutex_create();

  trace_buffer = tb_create(-1);
  trace_buffer_lock = dr_mutex_create();

  hashtable_init_ex(&tags,
                    16,
                    HASH_INTPTR,
                    false,
                    false,
                    &tag_info_free_raw,
                    NULL,
                    NULL);
  tags_lock = dr_mutex_create();

  dr_register_exit_event(&dr_exit);
  dr_register_thread_init_event(&handle_thread_init);
  dr_register_thread_exit_event(&handle_thread_exit);
  dr_register_bb_event(&handle_bb);
  dr_register_trace_event(&handle_trace);
  dr_register_delete_event(&handle_delete);
  dr_register_signal_event(&handle_signal);
  dr_register_restore_state_event(&handle_restore_state);
}
Ejemplo n.º 7
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);


}
Ejemplo n.º 8
0
void instrace_init(client_id_t id, const char * name, const char * arguments)
{

	file_t in_file;
	file_t out_file;
	int i;
	char logfilename[MAX_STRING_LENGTH];

    drmgr_init();
    drutil_init();
    client_id = id;

	DR_ASSERT(parse_commandline_args(arguments)==true);

	head = md_initialize();
	instrace_head = md_initialize();

	if(client_arg->filter_mode != FILTER_NONE){
		in_file = dr_open_file(client_arg->filter_filename,DR_FILE_READ);
		DR_ASSERT(in_file != INVALID_FILE);
		md_read_from_file(head,in_file,false);
		dr_close_file(in_file);
	}

	mutex = dr_mutex_create();
    tls_index = drmgr_register_tls_field();
    DR_ASSERT(tls_index != -1);
    code_cache_init();

	if (log_mode){
		populate_conv_filename(logfilename, logdir, name, NULL);
		logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE);
	}
	strncpy(ins_pass_name, name, MAX_STRING_LENGTH);

	for(i=OP_FIRST;i<=OP_LAST; i++){
		opcodes_visited[i] = false;
	}

	
	

}
Ejemplo n.º 9
0
/* Library offset has to be computed before the probe library is loaded
 * into memory.  Reading it from the map file is one of the easiest ways to
 * do it.
 */
unsigned int get_symbol_offset_from_map(const char *map_file, const char *symbol)
{
    const char *pref_addr_str = "Preferred load address is ";
    unsigned int pref_base, sym_addr, offset = 0xdeadc0de;
    ssize_t file_sz;
    file_t fd = INVALID_FILE;
    char *buf, *temp;

    fd = dr_open_file(map_file, DR_FILE_READ);
    if (fd == INVALID_FILE)
        goto _get_module_offset_exit; 

    /* This seems to be the easiest way to get the size of the file. */
    if (!dr_file_seek(fd, 0, DR_SEEK_END))
        goto _get_module_offset_exit; 
    file_sz = (ssize_t) dr_file_tell(fd);
    if (file_sz <= 0)
        goto _get_module_offset_exit; 
    if (!dr_file_seek(fd, 0, DR_SEEK_SET))
        goto _get_module_offset_exit; 

    /* Read the whole file. */
    buf = dr_global_alloc(file_sz + 1);
    if (buf == NULL)
        goto _get_module_offset_exit; 
    dr_read_file(fd, buf, file_sz);
    buf[file_sz] = '\0';

    /* Locate preferred base & symbol address. */
    temp = strstr(buf, pref_addr_str);
    if (temp != NULL)
    {
        pref_base = strtoul(temp + strlen(pref_addr_str), NULL, 16);
        temp = strstr(buf, symbol);
        if (temp != NULL)
            sym_addr = strtoul(temp + strlen(symbol), NULL, 16);
        offset = sym_addr - pref_base;
    }

    dr_global_free(buf, file_sz + 1);

 _get_module_offset_exit:
    if (fd != INVALID_FILE)
        dr_close_file(fd);
    return offset;
}
Ejemplo n.º 10
0
static void
read_table()
{
    file_t file;
    bool read_entry = true;

    file = dr_open_file(table_def_file_name, DR_FILE_READ);
    if (file == INVALID_FILE) {
        DISPLAY_FUNC(NAME" error opening config file \"%s\"\n", table_def_file_name);
        return;
    }

    VVDISPLAY_FUNC(NAME" reading config file: \"%s\"\n", table_def_file_name);

    do {
        table_entry_t *entry = (table_entry_t *)dr_global_alloc(sizeof(table_entry_t));
        if (dr_read_file(file, &entry->value, sizeof(table_value_t)) !=
            sizeof(table_value_t)) {
            /* end of file */
            read_entry = false;
            dr_global_free(entry, sizeof(table_entry_t));
        } else {
            int i;
            /* insert NULL termination for module name (including space padding) */
            for (i = sizeof(entry->value.module_name) - 1;
                 i >= 0 && entry->value.module_name[i] == ' '; i--) {
                entry->value.module_name[i] = '\0';
            }
            /* just in case */
            entry->value.module_name[sizeof(entry->value.module_name)-1] = '\0';

            /* add to the table */
            entry->next = table;
            table = entry;
            VVDISPLAY_FUNC(NAME" read entry for module=\"%s\" to_stack=%s to_heap=%s "
                           "transfer_to_here=%s\n", entry->value.module_name,
                           (entry->value.allow_to_stack == 'y' ||
                            entry->value.allow_to_stack == 'Y') ? "yes" : "no",
                           (entry->value.allow_to_heap == 'y' ||
                            entry->value.allow_to_heap == 'Y') ? "yes" : "no",
                           (entry->value.allow_to_here == 'y' ||
                            entry->value.allow_to_here == 'Y') ? "yes" : "no");
        }
    } while (read_entry);
    VVDISPLAY_FUNC(NAME" done reading config file.");
}
Ejemplo n.º 11
0
int
main(int argc, char *argv[])
{
    file_t f;
    void *drcontext = dr_standalone_init();
    if (argc != 2) {
        dr_fprintf(STDERR, "Usage: %s <objfile>\n", argv[0]);
        return 1;
    }
    f = dr_open_file(argv[1], DR_FILE_READ | DR_FILE_ALLOW_LARGE);
    if (f == INVALID_FILE) {
        dr_fprintf(STDERR, "Error opening %s\n", argv[1]);
        return 1;
    }
    read_data(f, drcontext);
    dr_close_file(f);
    return 0;
}
Ejemplo n.º 12
0
file_t
umbra_open_proc_log(process_id_t pid)
{
    char   name[128];
    int    len;
    file_t logfile;

    /* XXX: Windows need a absolute path */
    name[0] = '\0';
    len = dr_snprintf(name, sizeof(name)/sizeof(name[0]),
                      "umbra.%s.%d.proc.log",
                      dr_get_application_name(), pid);
    DR_ASSERT(len > 0);
    name[sizeof(name)/sizeof(name[0])-1] = '\0';
    logfile = dr_open_file(name, DR_FILE_READ | DR_FILE_WRITE_APPEND);
    DR_ASSERT(logfile != INVALID_FILE);
    return logfile;
}
Ejemplo n.º 13
0
static void post_func_cb(void * wrapcxt, void ** user_data){
	//do the dump for the written app_pcs
	int i = 0;
	file_t dump_file;
	char * dump_filename;

	DEBUG_PRINT("post function call for dumping\n");

	/* if for same memdump it is overwritten */
		for (i = 0; i < write_region_size; i++){
			dump_filename = get_mem_dump_filename(write_regions[i].base_pc, write_regions[i].size, true, written_count);
			dump_file = dr_open_file(dump_filename, DR_FILE_WRITE_OVERWRITE);
			do_mem_dump(dump_file, write_regions[i].base_pc, write_regions[i].size);
			dr_global_free(dump_filename, sizeof(char) * MAX_STRING_LENGTH);
			dr_close_file(dump_file);
		}
		written_count++;
	

}
Ejemplo n.º 14
0
/*
 * Wrap the log_set_file() function in testsc.c, and respond to it by
 * opening or closing log files.
 */
static void wrap_logsetfile(void *wrapctx, void **user_data)
{
    if (outfile) {
        dr_close_file(outfile);
        outfile = INVALID_FILE;
    }

    const char *outfilename = drwrap_get_arg(wrapctx, 0);
    if (outfilename) {
        outfile = dr_open_file(outfilename, DR_FILE_WRITE_OVERWRITE);
        DR_ASSERT(outfile != INVALID_FILE);
    }

    /*
     * Reset the allocation list to empty, whenever we open or close a
     * log file.
     */
    while (alloc_ends->next != alloc_ends)
        free_allocation(alloc_ends->next);
    next_alloc_index = 0;
}
Ejemplo n.º 15
0
file_t
umbra_open_thread_log(thread_id_t tid)
{
#ifdef LINUX_KERNEL
    return our_stdout;
#else
    char   name[128];
    int    len;
    file_t logfile;

    /* XXX: Windows need a absolute path */
    name[0] = '\0';
    len = dr_snprintf(name, sizeof(name)/sizeof(name[0]),
                      "umbra.%s.%d.thread.log", 
                      dr_get_application_name(), tid);
    DR_ASSERT(len > 0);
    name[sizeof(name)/sizeof(name[0])-1] = '\0';
    logfile = dr_open_file(name, DR_FILE_READ | DR_FILE_WRITE_APPEND);
    DR_ASSERT(logfile != INVALID_FILE);
    return logfile;
#endif
}
Ejemplo n.º 16
0
DR_EXPORT void dr_init( client_id_t id ) {
  dr_printf( "In dr_init()\n" );

  // Initialize extensions.
  drsym_error_t rc = drsym_init( 0 );
  if( DRSYM_SUCCESS != rc ) {
    dr_printf( "drsym_init() failed: %i\n", rc );
    exit( 1 );
  }

  bool wrapInit = drwrap_init();
  if( !wrapInit ) {
    dr_printf( "drwrap_init() failed\n" );
    exit( 1 );
  }

  // Set up output.
  char fileName[256];
  unsigned int pid = (unsigned int)dr_get_process_id();
  dr_snprintf( fileName, sizeof( fileName ), "objcount-%u.out", pid );
  fileName[sizeof( fileName ) - 1] = 0;
  outFile = dr_open_file( fileName, DR_FILE_WRITE_OVERWRITE );
  outMutex = dr_mutex_create();

  // Set up hashtable.
  hashtable_init_ex( &wraps,      // table
                     16,          // num_bits
                     HASH_INTPTR, // hashtype
                     false,       // str_dup
                     false,       // synch
                     &free_wrap,  // free_payload_func
                     NULL,        // hash_key_func
                     NULL );      // cmp_key_func

  // Register for events.
  dr_register_module_load_event( onLoad );
  dr_register_exit_event( onExit );
}
Ejemplo n.º 17
0
/* callbacks for threads */
void funcwrap_thread_init(void *drcontext){
	
	per_thread_t * data;
	char logfilename[MAX_STRING_LENGTH];
	char thread_id[MAX_STRING_LENGTH];

	DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext));
	
	data = dr_thread_alloc(drcontext, sizeof(per_thread_t));
	if (log_mode){
		dr_snprintf(thread_id, MAX_STRING_LENGTH, "%d", dr_get_thread_id(drcontext));
		populate_conv_filename(logfilename, logdir, ins_pass_name, thread_id);
		data->logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE);
	}

	

	data->filter_func = false;
	data->nesting = 0;
	drmgr_set_tls_field(drcontext, tls_index, data);

	DEBUG_PRINT("%s - initializing thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext));

}
Ejemplo n.º 18
0
void
writeCallgrind(int thread_id){
	char logname[MAXIMUM_PATH];
	char *dirsep;
    	int len;
	char * tmp = process_path;

	len = dr_snprintf(logname, sizeof(logname)/sizeof(logname[0]),
                      "%s", tmp);

	DR_ASSERT(len > 0);
	for (dirsep = logname + len; *dirsep != '/'; dirsep--)
        DR_ASSERT(dirsep > logname);
    	len = dr_snprintf(dirsep + 1,
                      (sizeof(logname) - (dirsep - logname))/sizeof(logname[0]),
                      "callgrind.%d.out", thread_id);
    	DR_ASSERT(len > 0);
    	NULL_TERMINATE(logname);
    	logOut = dr_open_file(logname, 
                             DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE);
    	DR_ASSERT(logOut != INVALID_FILE);
//    	dr_log(drcontext, LOG_ALL, 1, 
 //          "floating point: log for thread %d is fp.%03d\n",thread_id, thread_id);
	#ifdef SHOW_RESULTS
    	if (dr_is_notify_on()) {
//        	dr_fprintf(STDERR, "<floating point instruction operands for thread %d in %s>\n",
//                  dr_get_thread_id(drcontext), logname);
    	}
	#endif	

       	dr_fprintf(logOut, "version: 1\n");
       	dr_fprintf(logOut, "creator: callgrind-3.6.1-Debian\n");
       	dr_fprintf(logOut, "positions: instr line\n");
       	dr_fprintf(logOut, "events: Average Max\n\n\n");

}
Ejemplo n.º 19
0
            add_new_bb = bb_table_add(tables[entry->mod_id], entry) || add_new_bb;
    }
    free(tables);
    return add_new_bb;
}

static file_t
open_input_file(const char *fname, char **map_out OUT,
                size_t *map_size OUT, uint64 *file_sz OUT)
{
    uint64 file_size;
    char *map;
    file_t f;

    ASSERT(map_out != NULL && map_size != NULL, "map_out must not be NULL");
    f = dr_open_file(fname, DR_FILE_READ | DR_FILE_ALLOW_LARGE);
    if (f == INVALID_FILE) {
        WARN(2, "Failed to open file %s\n", fname);
        return INVALID_FILE;
    }
    if (!dr_file_size(f, &file_size)) {
        WARN(2, "Failed to get input file size for %s\n", fname);
        dr_close_file(f);
        return INVALID_FILE;
    }
    if (file_size <= MIN_LOG_FILE_SIZE) {
        WARN(2, "File size is 0 for %s\n", fname);
        dr_close_file(f);
        return INVALID_FILE;
    }
    *map_size = (size_t)file_size;
Ejemplo n.º 20
0
void instrace_thread_init(void *drcontext)
{
    char outfilename[MAX_STRING_LENGTH];
	char logfilename[MAX_STRING_LENGTH];
	char thread_id[MAX_STRING_LENGTH];
	char extra_info[MAX_STRING_LENGTH];

    char *dirsep;
    int len;
    per_thread_t *data;
	char * mode;

	uint * stack_base;
	uint * deallocation_stack;

	DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext));

    /* allocate thread private data */
    data = dr_thread_alloc(drcontext, sizeof(per_thread_t));
    drmgr_set_tls_field(drcontext, tls_index, data);
    data->buf_base = dr_thread_alloc(drcontext, INSTR_BUF_SIZE);
    data->buf_ptr  = data->buf_base;
    /* set buf_end to be negative of address of buffer end for the lea later */
	data->buf_end  = -(ptr_int_t)(data->buf_base + INSTR_BUF_SIZE);
    data->num_refs = 0;

    /* We're going to dump our data to a per-thread file.
     * On Windows we need an absolute path so we place it in
     * the same directory as our library. We could also pass
     * in a path and retrieve with dr_get_options().
     */
	dr_snprintf(thread_id, MAX_STRING_LENGTH, "%d", dr_get_thread_id(drcontext));
	if (log_mode){
		populate_conv_filename(logfilename, logdir, ins_pass_name, thread_id);
		data->logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE);
	}

	/* instrace types */
	if (client_arg->instrace_mode == OPERAND_TRACE){
		mode = "opnd";
	}
	else if (client_arg->instrace_mode == OPCODE_TRACE){
		mode = "opcode";
	}
	else if (client_arg->instrace_mode == DISASSEMBLY_TRACE){
		mode = "disasm";
	}
	else if (client_arg->instrace_mode == INS_DISASM_TRACE){
		mode = "asm_instr";
	}
	else{
		mode = "instr";
	}
	
	

	dr_snprintf(extra_info, MAX_STRING_LENGTH, "%s_%s_%s", client_arg->extra_info, mode, thread_id);

	populate_conv_filename(outfilename, client_arg->output_folder, ins_pass_name, extra_info);
	data->outfile = dr_open_file(outfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE);
	DR_ASSERT(data->outfile != INVALID_FILE);

	DEBUG_PRINT("%s - thread id : %d, new thread logging at - %s\n",ins_pass_name, dr_get_thread_id(drcontext),logfilename);

	data->static_array = (instr_t **)dr_thread_alloc(drcontext,sizeof(instr_t *)*client_arg->static_info_size);
	data->static_array_size = client_arg->static_info_size;
	data->static_ptr = 0;

	data->output_array = (output_t *)dr_thread_alloc(drcontext,OUTPUT_BUF_SIZE);

	deallocation_stack = &data->deallocation_stack;
	stack_base = &data->stack_base;

	__asm{
		mov EAX, FS : [0x04]
		mov EBX, stack_base
		mov [EBX], EAX
		mov EAX, FS : [0xE0C]
		mov EBX, deallocation_stack
		mov [EBX], EAX
	}

	DEBUG_PRINT("%s - thread %d stack information - stack_base %x stack_reserve %x\n", ins_pass_name,
		dr_get_thread_id(drcontext), data->stack_base, data->deallocation_stack);

	DEBUG_PRINT("%s - initializing thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext));


}
Ejemplo n.º 21
0
static bool
symcache_read_symfile(const module_data_t *mod, const char *modname, mod_cache_t *modcache)
{
    hashtable_t *symtable = &modcache->table;
    bool res = false;
    const char *line, *next_line;
    char symbol[MAX_SYMLEN];
    size_t offs;
    uint64 map_size;
    size_t actual_size;
    bool ok;
    void *map = NULL;
    char symfile[MAXIMUM_PATH];
    file_t f;

    symcache_get_filename(modname, symfile, BUFFER_SIZE_ELEMENTS(symfile));
    f = dr_open_file(symfile, DR_FILE_READ);
    if (f == INVALID_FILE)
        return res;
    LOG(2, "processing symbol cache file for %s\n", modname);
    /* we avoid having to do our own buffering by just mapping the whole file */
    ok = dr_file_size(f, &map_size);
    if (ok) {
        actual_size = (size_t) map_size;
        ASSERT(actual_size == map_size, "file size too large");
        map = dr_map_file(f, &actual_size, 0, NULL, DR_MEMPROT_READ, 0);
    }
    if (!ok || map == NULL || actual_size < map_size) {
        NOTIFY_ERROR("Error mapping symcache file for %s"NL, modname);
        goto symcache_read_symfile_done;
    }
    if (strncmp((char *)map, SYMCACHE_FILE_HEADER, strlen(SYMCACHE_FILE_HEADER)) != 0) {
        WARN("WARNING: symbol cache file is corrupted\n");
        goto symcache_read_symfile_done;
    }
    if (sscanf((char *)map + strlen(SYMCACHE_FILE_HEADER) + 1, "%d", &offs) != 1 ||
        /* neither forward nor backward compatible */
        offs != SYMCACHE_VERSION) {
        WARN("WARNING: symbol cache file has wrong version\n");
        goto symcache_read_symfile_done;
    }
    line = strchr((char *) map, '\n');
    if (line != NULL)
        line++;

    if (line != NULL) {
        /* Module consistency checks */
        uint cache_file_size;
        uint64 module_file_size;
#ifdef WINDOWS
        version_number_t file_version;
        version_number_t product_version;
        uint checksum;
        uint timestamp;
        size_t module_internal_size;
        if (sscanf(line, " %u,"UINT64_FORMAT_STRING","UINT64_FORMAT_STRING","
                   UINT64_FORMAT_STRING",%u,%u,%lu",
                   &cache_file_size, &module_file_size, &file_version.version,
                   &product_version.version, &checksum, &timestamp,
                   &module_internal_size) != 7) {
            WARN("WARNING: %s symbol cache file has bad consistency header\n", modname);
            goto symcache_read_symfile_done;
        }
        if (module_file_size != modcache->module_file_size ||
            file_version.version != modcache->file_version.version ||
            product_version.version != modcache->product_version.version ||
            checksum != modcache->checksum ||
            timestamp != modcache->timestamp ||
            module_internal_size != modcache->module_internal_size) {
            LOG(1, "module version mismatch: %s symbol cache file is stale\n", modname);
            LOG(2, "\t"UINT64_FORMAT_STRING" vs "UINT64_FORMAT_STRING", "
                UINT64_FORMAT_STRING" vs "UINT64_FORMAT_STRING", "
                UINT64_FORMAT_STRING" vs "UINT64_FORMAT_STRING", "
                "%u vs %u, %u vs %u, %lu vs %lu\n",
                module_file_size, modcache->module_file_size,
                file_version.version, modcache->file_version.version,
                product_version.version, modcache->product_version.version,
                checksum, modcache->checksum,
                timestamp, modcache->timestamp,
                module_internal_size, modcache->module_internal_size);
            goto symcache_read_symfile_done;
        }
#else
        if (sscanf(line, "%u,"UINT64_FORMAT_STRING,
                   &cache_file_size, &module_file_size) != 2) {
            WARN("WARNING: %s symbol cache file has bad consistency header\n", modname);
            goto symcache_read_symfile_done;
        }
        if (module_file_size != modcache->module_file_size) {
            LOG(1, "module version mismatch: %s symbol cache file is stale\n", modname);
            goto symcache_read_symfile_done;
        }
#endif
        /* We could go further w/ CRC or even MD5 but not worth it for dev tool */
        if (cache_file_size != (uint)map_size) {
            WARN("WARNING: %s symbol cache file is corrupted\n", modname);
            goto symcache_read_symfile_done;
        }
    }
    line = strchr(line, '\n');
    if (line != NULL)
        line++;

    symbol[0] = '\0';
    for (; line != NULL && line < ((char *)map) + map_size; line = next_line) {
        const char *newline = strchr(line, '\n');
        if (newline == NULL) {
            next_line = ((char *)map) + map_size + 1; /* handle EOF w/o trailing \n */
        } else {
            next_line = newline + 1;
        }
        if (sscanf(line, "%"MAX_SYMLEN_MINUS_1_STR"[^,],0x%x", symbol, &offs) == 2) {
            symcache_symbol_add(modname, symtable, symbol, offs);
        } else if (symbol[0] != '\0' && sscanf(line, ",0x%x", &offs) == 1) {
            /* duplicate entries are allowed to not list the symbol, to save
             * space in the file (mainly for post-call caching i#669)
             */
            symcache_symbol_add(modname, symtable, symbol, offs);
        } else {
            WARN("WARNING: malformed symbol cache line \"%.*s\"\n",
                 next_line - line - 1, line);
            /* We abort in case there were two dueling writes to the file
             * and it somehow got past the self-consistency check,
             * putting a header in the middle of the file, and we can't
             * trust subsequent lines since they may belong to a different
             * version of the module
             */
            break; /* res should still be true */
        }
    }
    res = true;
 symcache_read_symfile_done:
    if (map != NULL)
        dr_unmap_file(map, actual_size);
    if (f != INVALID_FILE)
        dr_close_file(f);
    return res;
}
Ejemplo n.º 22
0
DR_EXPORT
void dr_init(client_id_t id)
{
    char buf[MAXIMUM_PATH];
    int64 pos;
    int i;
    uint prot;
    byte *base_pc;
    size_t size;
    size_t bytes_read, bytes_written;
    byte *edge, *mbuf;
    bool ok;
    byte *f_map;

    /* The Makefile will pass a full absolute path (for Windows and Linux) as the client
     * option to a dummy file in the which we use to exercise the file api routines.
     * TODO - these tests should be a lot more thorough, but the basic functionality
     * is there (should add write tests, file_exists, directory etc. tests). */
    file = dr_open_file(dr_get_options(id), DR_FILE_READ);
    if (file == INVALID_FILE)
        dr_fprintf(STDERR, "Error opening file\n");
    memset(buf, 0, sizeof(buf));
    dr_read_file(file, buf, 10);
    pos = dr_file_tell(file);
    if (pos < 0)
        dr_fprintf(STDERR, "tell error\n");
    dr_fprintf(STDERR, "%s\n", buf);
    if (!dr_file_seek(file, 0, DR_SEEK_SET))
        dr_fprintf(STDERR, "seek error\n");
    memset(buf, 0, sizeof(buf));
    dr_read_file(file, buf, 5);
    dr_fprintf(STDERR, "%s\n", buf);
    for (i = 0; i < 100; i++) buf[i] = 0;
    if (!dr_file_seek(file, pos - 5, DR_SEEK_CUR))
        dr_fprintf(STDERR, "seek error\n");
    memset(buf, 0, sizeof(buf));
    dr_read_file(file, buf, 7);
    dr_fprintf(STDERR, "%s\n", buf);
    if (!dr_file_seek(file, -6, DR_SEEK_END))
        dr_fprintf(STDERR, "seek error\n");
    memset(buf, 0, sizeof(buf));
    /* read "x\nEOF\n" from the data file */
    dr_read_file(file, buf, 6);
    /* check for DOS line ending */
    if (buf[4] == '\r') {
        /* Account for two line endings: the snippet is "x\r\nEOF\r\n".
         * No conversion required--ctest will discard the '\r' when comparing results.
         */
        if (!dr_file_seek(file, -8, DR_SEEK_END))
            dr_fprintf(STDERR, "seek error\n");
            memset(buf, 0, sizeof(buf));
            dr_read_file(file, buf, 8);
    }
    dr_fprintf(STDERR, "%s\n", buf);
#define EXTRA_SIZE 0x60
    size  = PAGE_SIZE + EXTRA_SIZE;
    f_map = dr_map_file(file, &size, 0, NULL, DR_MEMPROT_READ, DR_MAP_PRIVATE);
    if (f_map == NULL || size < (PAGE_SIZE + EXTRA_SIZE))
        dr_fprintf(STDERR, "map error\n");
    /* test unaligned unmap */
    if (!dr_unmap_file(f_map + PAGE_SIZE, EXTRA_SIZE))
        dr_fprintf(STDERR, "unmap error\n");

    /* leave file open and check in exit event that it's still open after
     * app tries to close it
     */
    dr_register_exit_event(event_exit);

    /* Test dr_rename_file. */
    test_dr_rename_delete();

    /* Test the memory query routines */
    dummy_func();
    if (!dr_memory_is_readable((byte *)dummy_func, 1) ||
        !dr_memory_is_readable(read_only_buf+1000, 4000) ||
        !dr_memory_is_readable(writable_buf+1000, 4000)) {
        dr_fprintf(STDERR, "ERROR : dr_memory_is_readable() incorrect results\n");
    }

    if (!dr_query_memory((byte *)dummy_func, &base_pc, &size, &prot))
        dr_fprintf(STDERR, "ERROR : can't find dummy_func mem region\n");
    dr_fprintf(STDERR, "dummy_func is %s%s%s\n", TEST(DR_MEMPROT_READ, prot) ? "r" : "",
              TEST(DR_MEMPROT_WRITE, prot) ? "w" : "",
              TEST(DR_MEMPROT_EXEC, prot) ? "x" : "");
    if (base_pc > (byte *)dummy_func || base_pc + size < (byte *)dummy_func)
        dr_fprintf(STDERR, "dummy_func region mismatch");

    memset(writable_buf, 0, sizeof(writable_buf)); /* strip off write copy */
    if (!dr_query_memory(writable_buf+100, &base_pc, &size, &prot))
        dr_fprintf(STDERR, "ERROR : can't find dummy_func mem region\n");
    dr_fprintf(STDERR, "writable_buf is %s%s%s\n", TEST(DR_MEMPROT_READ, prot) ? "r" : "",
              TEST(DR_MEMPROT_WRITE, prot) ? "w" : "",
#ifdef UNIX
              /* Linux sometimes (probably depends on version and hardware NX
               * support) lists all readable regions as also exectuable in the
               * maps file.  We just skip checking here for Linux to make
               * matching the template file easier. */
              ""
#else
              TEST(DR_MEMPROT_EXEC, prot) ? "x" : ""
#endif
              );
    if (base_pc > writable_buf || base_pc + size < writable_buf)
        dr_fprintf(STDERR, "writable_buf region mismatch\n");
    if (base_pc + size < writable_buf + sizeof(writable_buf))
        dr_fprintf(STDERR, "writable_buf size mismatch "PFX" "PFX" "PFX" "PFX"\n",
                  base_pc, size, writable_buf, sizeof(writable_buf));

    if (!dr_query_memory(read_only_buf+100, &base_pc, &size, &prot))
        dr_fprintf(STDERR, "ERROR : can't find dummy_func mem region\n");
    dr_fprintf(STDERR, "read_only_buf is %s%s\n", TEST(DR_MEMPROT_READ, prot) ? "r" : "",
              TEST(DR_MEMPROT_WRITE, prot) ? "w" : "");
    if (base_pc > read_only_buf || base_pc + size < read_only_buf)
        dr_fprintf(STDERR, "read_only_buf region mismatch");
    if (base_pc + size < read_only_buf + sizeof(read_only_buf))
        dr_fprintf(STDERR, "read_only_buf size mismatch");

    /* test the safe_read functions */
    /* TODO - extend test to cover racy writes and reads (won't work on Linux yet). */
    memset(safe_buf, 0xcd, sizeof(safe_buf));
    if (!dr_safe_read(read_only_buf + 4000, 1000, safe_buf, &bytes_read) ||
        bytes_read != 1000 || !memchk(safe_buf, 0, 1000) || *(safe_buf+1000) != 0xcd) {
        dr_fprintf(STDERR, "ERROR in plain dr_safe_read()\n");
    }
    memset(safe_buf, 0xcd, sizeof(safe_buf));
    /* read_only_buf will be in .rodata on Linux, and can be followed by string
     * constants with the same page protections.  In order to be sure that we're
     * copying zeroes, we map our own memory.
     */
    mbuf = dr_nonheap_alloc(PAGE_SIZE*3, DR_MEMPROT_READ|DR_MEMPROT_WRITE);
    memset(mbuf, 0, PAGE_SIZE*3);
    dr_memory_protect(mbuf + PAGE_SIZE*2, PAGE_SIZE, DR_MEMPROT_NONE);
    edge = find_prot_edge(mbuf, DR_MEMPROT_READ);
    bytes_read = 0xcdcdcdcd;
    if (dr_safe_read(edge - (PAGE_SIZE + 10), PAGE_SIZE+20, safe_buf, &bytes_read) ||
        bytes_read == 0xcdcdcdcd || bytes_read > PAGE_SIZE+10 ||
        !memchk(safe_buf, 0, bytes_read)) {
        dr_fprintf(STDERR, "ERROR in overlap dr_safe_read()\n");
    }
    dr_nonheap_free(mbuf, PAGE_SIZE*3);
    dr_fprintf(STDERR, "dr_safe_read() check\n");

    /* test DR_TRY_EXCEPT */
    DR_TRY_EXCEPT(dr_get_current_drcontext(), {
        ok = false;
        *((int *)4) = 37;
    }, { /* EXCEPT */
Ejemplo n.º 23
0
void memtrace_thread_init(void *drcontext)
{
    char logfilename[MAX_STRING_LENGTH];
	char outfilename[MAX_STRING_LENGTH];
	char thread_id[MAX_STRING_LENGTH];
	char extra_info[MAX_STRING_LENGTH];

    char *dirsep;
    int len;
    per_thread_t *data;

	uint * stack_base;
	uint * deallocation_stack;

	int i = 0;

	DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext));

    /* allocate thread private data */
    data = dr_thread_alloc(drcontext, sizeof(per_thread_t));
    drmgr_set_tls_field(drcontext, tls_index, data);
    data->buf_base = dr_thread_alloc(drcontext, MEM_BUF_SIZE);
    data->buf_ptr  = data->buf_base;
    /* set buf_end to be negative of address of buffer end for the lea later */
    data->buf_end  = -(ptr_int_t)(data->buf_base + MEM_BUF_SIZE);
    data->num_refs = 0;

    /* We're going to dump our data to a per-thread file.
     * On Windows we need an absolute path so we place it in
     * the same directory as our library. We could also pass
     * in a path and retrieve with dr_get_options().
     */

	dr_snprintf(thread_id, MAX_STRING_LENGTH, "%d", dr_get_thread_id(drcontext));

	if (log_mode){
		populate_conv_filename(logfilename, logdir, ins_pass_name, thread_id);
		data->logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE);
	}



	dr_snprintf(extra_info, MAX_STRING_LENGTH, "%s_%s", client_arg->extra_info, thread_id);

	populate_conv_filename(outfilename, client_arg->output_folder, ins_pass_name, extra_info);
	data->outfile = dr_open_file(outfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE);
	DR_ASSERT(data->outfile != INVALID_FILE);

	/* this is done for 32 bit applications */
	deallocation_stack = &data->stack_limit;
	stack_base = &data->stack_base;

	__asm{
			mov EAX, FS : [0x04]
			mov EBX, stack_base
			mov[EBX], EAX
			mov EAX, FS : [0xE0C]
			mov EBX, deallocation_stack
			mov[EBX], EAX
	}

	DEBUG_PRINT("%s - stack boundaries - %x,%x\n", ins_pass_name, data->stack_base, data->stack_limit);

	DEBUG_PRINT("%s - initializing thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext));

}
Ejemplo n.º 24
0
/* Sets modcache->has_debug_info.
 * No lock is needed as we assume the caller hasn't exposed modcache outside this
 * thread yet.
 */
static bool
symcache_read_symfile(const module_data_t *mod, const char *modname,
                      mod_cache_t *modcache)
{
    hashtable_t *symtable = &modcache->table;
    bool res = false;
    const char *line, *next_line;
    char symbol[MAX_SYMLEN];
    size_t offs;
    uint64 map_size;
    size_t actual_size;
    bool ok;
    void *map = NULL;
    char symfile[MAXIMUM_PATH];
    file_t f;

    symcache_get_filename(modname, symfile, BUFFER_SIZE_ELEMENTS(symfile));
    f = dr_open_file(symfile, DR_FILE_READ);
    if (f == INVALID_FILE)
        goto symcache_read_symfile_done;
    LOG(2, "processing symbol cache file for %s\n", modname);
    /* we avoid having to do our own buffering by just mapping the whole file */
    ok = dr_file_size(f, &map_size);
    if (ok) {
        actual_size = (size_t) map_size;
        ASSERT(actual_size == map_size, "file size too large");
        map = dr_map_file(f, &actual_size, 0, NULL, DR_MEMPROT_READ, 0);
    }
    if (!ok || map == NULL || actual_size < map_size) {
        NOTIFY_ERROR("Error mapping symcache file for %s"NL, modname);
        goto symcache_read_symfile_done;
    }
    if (strncmp((char *)map, SYMCACHE_FILE_HEADER, strlen(SYMCACHE_FILE_HEADER)) != 0) {
        WARN("WARNING: symbol cache file is corrupted\n");
        goto symcache_read_symfile_done;
    }
    /* i#1057: We use dr_sscanf() because sscanf() from ntdll will call strlen()
     * and read off the end of the mapped file if it doesn't hit a null.
     */
    if (dr_sscanf((char *)map + strlen(SYMCACHE_FILE_HEADER) + 1, "%d",
                  (uint *)&offs) != 1 ||
        /* neither forward nor backward compatible */
        offs != SYMCACHE_VERSION) {
        WARN("WARNING: symbol cache file has wrong version\n");
        goto symcache_read_symfile_done;
    }
    line = strchr((char *) map, '\n');
    if (line != NULL)
        line++;

    if (line != NULL) {
        /* Module consistency checks */
        uint cache_file_size;
        uint64 module_file_size;
        uint timestamp;
#ifdef WINDOWS
        version_number_t file_version;
        version_number_t product_version;
        uint checksum;
        size_t module_internal_size;
        if (dr_sscanf(line, "%u,"UINT64_FORMAT_STRING","UINT64_FORMAT_STRING","
                      UINT64_FORMAT_STRING",%u,%u,%lu",
                      &cache_file_size, &module_file_size, &file_version.version,
                      &product_version.version, &checksum, &timestamp,
                      &module_internal_size) != 7) {
            WARN("WARNING: %s symbol cache file has bad consistency header\n", modname);
            goto symcache_read_symfile_done;
        }
        if (module_file_size != modcache->module_file_size ||
            file_version.version != modcache->file_version.version ||
            product_version.version != modcache->product_version.version ||
            checksum != modcache->checksum ||
            timestamp != modcache->timestamp ||
            module_internal_size != modcache->module_internal_size) {
            LOG(1, "module version mismatch: %s symbol cache file is stale\n", modname);
            LOG(2, "\t"UINT64_FORMAT_STRING" vs "UINT64_FORMAT_STRING", "
                UINT64_FORMAT_STRING" vs "UINT64_FORMAT_STRING", "
                UINT64_FORMAT_STRING" vs "UINT64_FORMAT_STRING", "
                "%u vs %u, %u vs %u, %lu vs %lu\n",
                module_file_size, modcache->module_file_size,
                file_version.version, modcache->file_version.version,
                product_version.version, modcache->product_version.version,
                checksum, modcache->checksum,
                timestamp, modcache->timestamp,
                module_internal_size, modcache->module_internal_size);
            goto symcache_read_symfile_done;
        }
#elif defined(LINUX)
        if (dr_sscanf(line, "%u,"UINT64_FORMAT_STRING",%u",
                      &cache_file_size, &module_file_size, &timestamp) != 3) {
            WARN("WARNING: %s symbol cache file has bad consistency header\n", modname);
            goto symcache_read_symfile_done;
        }
        if (module_file_size != modcache->module_file_size ||
            timestamp != modcache->timestamp) {
            LOG(1, "module version mismatch: %s symbol cache file is stale\n", modname);
            goto symcache_read_symfile_done;
        }
#elif defined(MACOS)
        uint current_version;
        uint compatibility_version;
        byte uuid[16];
        /* XXX: if dr_sscanf supported %n maybe we could split these into
         * separate scans on the same string and share code w/ Linux.
         */
        if (dr_sscanf(line, "%u,"UINT64_FORMAT_STRING",%u,%u,%u,%x,%x,%x,%x",
                      &cache_file_size, &module_file_size, &timestamp,
                      &current_version, &compatibility_version,
                      (uint*)(&uuid[0]), (uint*)(&uuid[4]),
                      (uint*)(&uuid[8]), (uint*)(&uuid[12])) != 9) {
            WARN("WARNING: %s symbol cache file has bad consistency header B\n", modname);
            goto symcache_read_symfile_done;
        }
        if (current_version != modcache->current_version ||
            compatibility_version != modcache->compatibility_version ||
            memcmp(uuid, modcache->uuid, sizeof(uuid)) != 0) {
            LOG(1, "module version mismatch: %s symbol cache file is stale\n", modname);
            goto symcache_read_symfile_done;
        }
#endif
        /* We could go further w/ CRC or even MD5 but not worth it for dev tool */
        if (cache_file_size != (uint)map_size) {
            WARN("WARNING: %s symbol cache file is corrupted: map=%d vs file=%d\n",
                 modname, (uint)map_size, cache_file_size);
            goto symcache_read_symfile_done;
        }
    }
    line = strchr(line, '\n');
    if (line != NULL)
        line++;
    if (line != NULL) {
        uint has_debug_info;
        if (dr_sscanf(line, "%u", &has_debug_info) != 1) {
            WARN("WARNING: %s symbol cache file has bad consistency header\n", modname);
            goto symcache_read_symfile_done;
        }
        if (has_debug_info) {
            /* We assume that the current availability of debug info doesn't matter */
            modcache->has_debug_info = true;
        } else {
            /* We delay the costly check for symbols until we've read the symcache
             * b/c if its entry indicates symbols we don't need to look
             */
            if (module_has_symbols(mod)) {
                LOG(1, "module now has debug info: %s symbol cache is stale\n", modname);
                goto symcache_read_symfile_done;
            }
        }
    }
    line = strchr(line, '\n');
    if (line != NULL)
        line++;

    symbol[0] = '\0';
    for (; line != NULL && line < ((char *)map) + map_size; line = next_line) {
        const char *comma = strchr(line, ',');
        const char *newline = strchr(line, '\n');
        size_t symlen = (comma != NULL ? comma - line : 0);
        if (newline == NULL) {
            next_line = ((char *)map) + map_size + 1; /* handle EOF w/o trailing \n */
        } else {
            next_line = newline + 1;
        }
        if (symlen > 0 && symlen < MAX_SYMLEN) {
            strncpy(symbol, line, symlen);
            symbol[symlen] = '\0';
        }
        if (comma != NULL && symlen < MAX_SYMLEN && symbol[0] != '\0' &&
            dr_sscanf(comma, ",0x%x", (uint *)&offs) == 1) {
#ifdef WINDOWS
            /* Guard against corrupted files that cause DrMem to crash (i#1465) */
            if (offs >= modcache->module_internal_size) {
                /* This one we want to know about */
                NOTIFY("SYMCACHE ERROR: %s file has too-large entry "PIFX" for %s"NL,
                       modname, offs, symbol);
                goto symcache_read_symfile_done;
            }
#endif
            symcache_symbol_add(modname, symtable, symbol, offs);
        } else {
            WARN("WARNING: malformed symbol cache line \"%.*s\"\n",
                 next_line - line - 1, line);
            /* We abort in case there were two dueling writes to the file
             * and it somehow got past the self-consistency check,
             * putting a header in the middle of the file, and we can't
             * trust subsequent lines since they may belong to a different
             * version of the module
             */
            break; /* res should still be true */
        }
    }
    res = true;
 symcache_read_symfile_done:
    if (map != NULL)
        dr_unmap_file(map, actual_size);
    if (f != INVALID_FILE)
        dr_close_file(f);
    if (!res)
        modcache->has_debug_info = module_has_symbols(mod);

    return res;
}
Ejemplo n.º 25
0
/* caller must hold symcache_lock */
static void
symcache_write_symfile(const char *modname, mod_cache_t *modcache)
{
    uint i;
    file_t f;
    hashtable_t *symtable = &modcache->table;
    char buf[SYMCACHE_BUFFER_SIZE];
    size_t sofar = 0;
    ssize_t len;
    size_t bsz = BUFFER_SIZE_ELEMENTS(buf);
    size_t filesz_loc;
    char symfile[MAXIMUM_PATH];
    char symfile_tmp[MAXIMUM_PATH];
    int64 file_size;

    ASSERT(dr_mutex_self_owns(symcache_lock), "missing symcache lock");

    /* if from file, we assume it's a waste of time to re-write file:
     * the version matched after all, unless we appended to it.
     */
    if (modcache->from_file && !modcache->appended)
        return;
    if (symtable->entries == 0)
        return; /* nothing to write */

    /* Open the temp symcache that we will rename.  */
    symcache_get_filename(modname, symfile, BUFFER_SIZE_ELEMENTS(symfile));
    f = INVALID_FILE;
    i = 0;
    while (f == INVALID_FILE && i < SYMCACHE_MAX_TMP_TRIES) {
        dr_snprintf(symfile_tmp, BUFFER_SIZE_ELEMENTS(symfile_tmp),
                    "%s.%04d.tmp", symfile, i);
        NULL_TERMINATE_BUFFER(symfile_tmp);
        f = dr_open_file(symfile_tmp, DR_FILE_WRITE_REQUIRE_NEW);
        i++;
    }
    if (f == INVALID_FILE) {
        NOTIFY("WARNING: Unable to create symcache temp file %s"NL,
               symfile_tmp);
        return;
    }

    BUFFERED_WRITE(f, buf, bsz, sofar, len, "%s %d\n",
                   SYMCACHE_FILE_HEADER, SYMCACHE_VERSION);
    /* Leave room for file size for self-consistency check */
    filesz_loc = sofar;  /* XXX: Assumes that the buffer hasn't been flushed. */
    BUFFERED_WRITE(f, buf, bsz, sofar, len,
                   "%"STRINGIFY(SYMCACHE_SIZE_DIGITS)"u,", 0);
#ifdef WINDOWS
    BUFFERED_WRITE(f, buf, bsz, sofar, len,
                   UINT64_FORMAT_STRING","UINT64_FORMAT_STRING","
                   UINT64_FORMAT_STRING",%u,%u,%lu\n",
                   modcache->module_file_size, modcache->file_version.version,
                   modcache->product_version.version,
                   modcache->checksum, modcache->timestamp,
                   modcache->module_internal_size);
#else
    BUFFERED_WRITE(f, buf, bsz, sofar, len, UINT64_FORMAT_STRING",%u",
                   modcache->module_file_size, modcache->timestamp);
# ifdef MACOS
    BUFFERED_WRITE(f, buf, bsz, sofar, len, ",%u,%u,",
                   modcache->current_version, modcache->compatibility_version);
    /* For easy sscanf we print as 4 ints */
    for (i = 0; i < 4; i++)
        BUFFERED_WRITE(f, buf, bsz, sofar, len, "%08x,", *(int*)(&modcache->uuid[i*4]));
# endif
    BUFFERED_WRITE(f, buf, bsz, sofar, len, "\n");
#endif
    BUFFERED_WRITE(f, buf, bsz, sofar, len, "%u\n", modcache->has_debug_info);
    for (i = 0; i < HASHTABLE_SIZE(symtable->table_bits); i++) {
        hash_entry_t *he;
        for (he = symtable->table[i]; he != NULL; he = he->next) {
            offset_list_t *olist = (offset_list_t *) he->payload;
            offset_entry_t *e;
            if (olist == NULL)
                continue;
            /* skip symbol in dup entries to save space */
            BUFFERED_WRITE(f, buf, bsz, sofar, len, "%s", he->key);
            e = olist->list;
            while (e != NULL) {
                BUFFERED_WRITE(f, buf, bsz, sofar, len, ",0x%x\n", e->offs);
                e = e->next;
            }
        }
    }

    /* now update size */
    FLUSH_BUFFER(f, buf, sofar);
    if ((file_size = dr_file_tell(f)) < 0 ||
        dr_snprintf(buf, BUFFER_SIZE_ELEMENTS(buf),
                    "%"STRINGIFY(SYMCACHE_SIZE_DIGITS)"u", (uint)file_size) < 0 ||
        !dr_file_seek(f, filesz_loc, DR_SEEK_SET) ||
        dr_write_file(f, buf, SYMCACHE_SIZE_DIGITS) != SYMCACHE_SIZE_DIGITS) {
        /* If any steps fail, warn and give up. */
        NOTIFY("WARNING: Unable to write symcache file size."NL);
        dr_close_file(f);
        dr_delete_file(symfile_tmp);
        return;
    } else {
        LOG(3, "Wrote symcache %s file size %u to pos "SZFMT"\n",
            modname, (uint)file_size, filesz_loc);
        ASSERT(strlen(buf) <= SYMCACHE_SIZE_DIGITS, "not enough space for file size");
    }

    dr_close_file(f);

    if (!dr_rename_file(symfile_tmp, symfile, /*replace*/true)) {
        NOTIFY_ERROR("WARNING: Failed to rename the symcache file."NL);
        dr_delete_file(symfile_tmp);
    }
}
Ejemplo n.º 26
0
void
init_IPC(int idx, const char *path, bool standalone)
{
    DR_ASSERT(idx < MAX_IPC_CHANNELS);

    int path_len, pad_len, shmem_len, fullfifo_len, emptyfifo_len;
    ipc_channel_t *channel = &IPC[idx];

    channel->standalone = standalone;

    /* Initialize channel state */
    ticket_node_t *node = dr_global_alloc(sizeof(ticket_node_t));
    if (node == NULL)
        DR_ABORT_MSG("Failed to allocate ticket node\n");
    node->next = NULL;
    node->dr_event = NULL;
    node->waiting = false;
    node->thread_id = 0;
    channel->ticket_queue.head = node;
    channel->ticket_queue.tail = node;
    channel->ticket_queue.locked = false;
    channel->queue_lock = dr_mutex_create();

    channel->shared_mem = NULL;
    channel->full_fifo = -1;
    channel->empty_fifo = -1;
    channel->shmem_buf_idx = 0;

    for(uint i=0; i<sizeof(channel->empty_buf_idx)/sizeof(channel->empty_buf_idx[0]); ++i)
        channel->empty_buf_idx[i] = true;

    channel->last_active_tid = 0;
    channel->initialized     = false;

    if (standalone)
    {
        /* mimic shared memory writes */
        channel->shared_mem = dr_raw_mem_alloc(sizeof(Sigil2DBISharedData),
                                               DR_MEMPROT_READ | DR_MEMPROT_WRITE,
                                               NULL);
        if (channel->shared_mem == NULL)
            DR_ABORT_MSG("Failed to allocate pseudo shared memory buffer\n");
        for (int i=0; i<SIGIL2_IPC_BUFFERS; ++i)
            channel->shared_mem->eventBuffers[i].used = 0;
    }
    else
    {
        /* Connect to Sigil2 */
        path_len = strlen(path);
        pad_len = 4; /* extra space for '/', 2x'-', '\0' */
        shmem_len     = (path_len + pad_len +
                         sizeof(SIGIL2_IPC_SHMEM_BASENAME) +
                         sizeof(STRINGIFY(MAX_IPC_CHANNELS)));
        fullfifo_len  = (path_len + pad_len +
                         sizeof(SIGIL2_IPC_FULLFIFO_BASENAME) +
                         sizeof(STRINGIFY(MAX_IPC_CHANNELS)));
        emptyfifo_len = (path_len + pad_len +
                         sizeof(SIGIL2_IPC_EMPTYFIFO_BASENAME) +
                         sizeof(STRINGIFY(MAX_IPC_CHANNELS)));

        /* set up names of IPC files */
        char shmem_name[shmem_len];
        sprintf(shmem_name, "%s/%s-%d", path, SIGIL2_IPC_SHMEM_BASENAME, idx);

        char fullfifo_name[fullfifo_len];
        sprintf(fullfifo_name, "%s/%s-%d", path, SIGIL2_IPC_FULLFIFO_BASENAME, idx);

        char emptyfifo_name[emptyfifo_len];
        sprintf(emptyfifo_name, "%s/%s-%d", path, SIGIL2_IPC_EMPTYFIFO_BASENAME, idx);


        /* initialize read/write pipes */
        channel->empty_fifo = open_sigil2_fifo(emptyfifo_name, DR_FILE_READ);
        channel->full_fifo = open_sigil2_fifo(fullfifo_name, DR_FILE_WRITE_ONLY);

        /* no need to timeout on file because shared memory MUST be initialized
         * by Sigil2 before the fifos are created */
        file_t map_file = dr_open_file(shmem_name, DR_FILE_READ|DR_FILE_WRITE_APPEND);
        if(map_file == INVALID_FILE)
            DR_ABORT_MSG("error opening shared memory file");

        size_t mapped_size = sizeof(Sigil2DBISharedData);
        channel->shared_mem = dr_map_file(map_file, &mapped_size,
                                          0, 0, /* assume this is not honored */
                                          DR_MEMPROT_READ|DR_MEMPROT_WRITE, 0);

        if(mapped_size != sizeof(Sigil2DBISharedData) || channel->shared_mem == NULL)
            DR_ABORT_MSG("error mapping shared memory");

        dr_close_file(map_file);
    }

    channel->initialized = true;
}
Ejemplo n.º 27
0
void
symcache_module_load(void *drcontext, const module_data_t *mod, bool loaded)
{
    /* look for cache file for this module.
     * fill in hashtable: key is string, value is list of offsets
     */
    mod_cache_t *modcache;
    const char *modname = dr_module_preferred_name(mod);
    file_t f;
    if (modname == NULL)
        return; /* don't support caching */

    /* if smaller than threshold, not worth caching */
    if (mod->end - mod->start < op_modsize_cache_threshold) {
        LOG(1, "%s: module %s too small to cache\n", __FUNCTION__, modname);
        return;
    }

    ASSERT(initialized, "symcache was not initialized");

    /* support initializing prior to module events => called twice */
    dr_mutex_lock(symcache_lock);
    modcache = (mod_cache_t *) hashtable_lookup(&symcache_table,
                                                (void *)mod->full_path);
    dr_mutex_unlock(symcache_lock);
    if (modcache != NULL)
        return;

    modcache = (mod_cache_t *) global_alloc(sizeof(*modcache), HEAPSTAT_HASHTABLE);
    memset(modcache, 0, sizeof(*modcache));
    hashtable_init_ex(&modcache->table, SYMCACHE_MODULE_TABLE_HASH_BITS,
                      HASH_STRING, true/*strdup*/, true/*synch*/,
                      symcache_free_list, NULL, NULL);

    /* store consistency fields */
    f = dr_open_file(mod->full_path, DR_FILE_READ);
    if (f != INVALID_FILE) {
        bool ok = dr_file_size(f, &modcache->module_file_size);
        if (!ok)
            WARN("WARNING: unable to determine size of %s\n", mod->full_path);
        dr_close_file(f);
    } else
        WARN("WARNING: unable to open %s\n", mod->full_path);
#ifdef WINDOWS
    modcache->file_version = mod->file_version;
    modcache->product_version = mod->product_version;
    modcache->checksum = mod->checksum;
    modcache->timestamp = mod->timestamp;
    modcache->module_internal_size = mod->module_internal_size;
#endif

    modcache->modname = drmem_strdup(modname, HEAPSTAT_HASHTABLE);
    modcache->from_file = symcache_read_symfile(mod, modname, modcache);

    dr_mutex_lock(symcache_lock);
    if (!hashtable_add(&symcache_table, (void *)mod->full_path, (void *)modcache)) {
        /* this should be really rare to have dup paths (xref i#729) -- and
         * actually we now have a lookup up above so we should only get here
         * on a race while we let go of the lock
         */
        WARN("WARNING: duplicate module paths: only caching symbols from first\n");
        hashtable_delete(&modcache->table);
        global_free(modcache, sizeof(*modcache), HEAPSTAT_HASHTABLE);
    }
    dr_mutex_unlock(symcache_lock);
}