/* 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(); }
void terminate_IPC(int idx) { ipc_channel_t *channel = &IPC[idx]; if (channel->standalone) { dr_raw_mem_free(channel->shared_mem, sizeof(Sigil2DBISharedData)); } else { /* send terminate sequence */ uint finished = SIGIL2_IPC_FINISHED; uint last_buffer = channel->shmem_buf_idx; if(dr_write_file(channel->full_fifo, &last_buffer, sizeof(last_buffer)) != sizeof(last_buffer) || dr_write_file(channel->full_fifo, &finished, sizeof(finished)) != sizeof(finished)) DR_ABORT_MSG("error writing finish sequence sigil2 fifos"); /* wait for sigil2 to disconnect */ while(dr_read_file(channel->empty_fifo, &finished, sizeof(finished)) > 0); dr_close_file(channel->empty_fifo); dr_close_file(channel->full_fifo); dr_unmap_file(channel->shared_mem, sizeof(Sigil2DBISharedData)); } dr_global_free((void*)channel->ticket_queue.head, sizeof(ticket_queue_t)); dr_mutex_destroy(channel->queue_lock); }
void instrace_thread_exit(void *drcontext) { per_thread_t *data; int i; if (client_arg->instrace_mode == INS_TRACE){ ins_trace(drcontext); } data = drmgr_get_tls_field(drcontext, tls_index); dr_mutex_lock(mutex); num_refs += data->num_refs; dr_mutex_unlock(mutex); dr_close_file(data->outfile); if (log_mode){ dr_close_file(data->logfile); } dr_thread_free(drcontext, data->buf_base, INSTR_BUF_SIZE); dr_thread_free(drcontext, data->output_array, OUTPUT_BUF_SIZE); DEBUG_PRINT("%s - thread id : %d, cloned instructions freeing now - %d\n",ins_pass_name, dr_get_thread_id(drcontext),data->static_ptr); for(i=0 ; i<data->static_ptr; i++){ instr_destroy(dr_get_current_drcontext(),data->static_array[i]); } dr_thread_free(drcontext, data->static_array, sizeof(instr_t *)*client_arg->static_info_size); dr_thread_free(drcontext, data, sizeof(per_thread_t)); DEBUG_PRINT("%s - exiting thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext)); }
void instrace_exit_event() { int i; DEBUG_PRINT("%s - total amount of instructions - %d\n",ins_pass_name, num_refs); if (client_arg->instrace_mode == OPCODE_TRACE){ dr_printf("opcodes that were covered in this part of the code - \n"); for (i = OP_FIRST; i <= OP_LAST; i++){ if (opcodes_visited[i]){ dr_printf(logfile,"%s - ", decode_opcode_name(i)); } } dr_printf("\n"); } md_delete_list(head, false); md_delete_list(instrace_head, false); dr_global_free(client_arg,sizeof(client_arg_t)); code_cache_exit(); drmgr_unregister_tls_field(tls_index); dr_mutex_destroy(mutex); if (log_mode){ dr_close_file(logfile); } drutil_exit(); drmgr_exit(); }
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); }
/* 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); }
static void event_exit(void) { file_t f; /* Display the results! */ char msg[512]; int len; len = dr_snprintf(msg, sizeof(msg)/sizeof(msg[0]), "Instrumentation results:\n" " saw %" STAT_FORMAT_CODE " flops\n", stats->num_flops); DR_ASSERT(len > 0); msg[sizeof(msg)/sizeof(msg[0])-1] = '\0'; #ifdef SHOW_RESULTS DISPLAY_STRING(msg); #endif /* SHOW_RESULTS */ /* On Windows we need an absolute path so we place it in * the same directory as our library. */ f = log_file_open(my_id, NULL, NULL /* client lib path */, "stats", 0); DR_ASSERT(f != INVALID_FILE); dr_fprintf(f, "%s\n", msg); dr_close_file(f); shared_memory_exit(); drx_exit(); if (!drmgr_unregister_bb_instrumentation_event(event_analyze_bb)) DR_ASSERT(false); drmgr_exit(); }
void memtrace_thread_exit(void *drcontext) { per_thread_t *data; memtrace(drcontext); data = drmgr_get_tls_field(drcontext, tls_index); dr_mutex_lock(mutex); num_refs += data->num_refs; dr_mutex_unlock(mutex); if (log_mode){ dr_close_file(data->logfile); } dr_close_file(data->outfile); dr_thread_free(drcontext, data->buf_base, MEM_BUF_SIZE); dr_thread_free(drcontext, data, sizeof(per_thread_t)); DEBUG_PRINT("%s - exiting thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext)); }
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); }
static client_stats_t * shared_memory_init(void) { bool is_NT = is_windows_NT(); int num; int pos; /* We do not want to rely on the registry. * Instead, a piece of shared memory with the key base name holds the * total number of stats instances. */ shared_map_count = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(client_stats_t), is_NT ? CLIENT_SHMEM_KEY_NT_L : CLIENT_SHMEM_KEY_L); DR_ASSERT(shared_map_count != NULL); shared_view_count = MapViewOfFile(shared_map_count, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 0); DR_ASSERT(shared_view_count != NULL); shared_count = (int *) shared_view_count; /* ASSUMPTION: memory is initialized to 0! * otherwise our protocol won't work * it's hard to build a protocol to initialize it to 0 -- if you want * to add one, feel free, but make sure it's correct */ do { pos = (int) atomic_swap(shared_count, (uint) -1); /* if get -1 back, someone else is looking at it */ } while (pos == -1); /* now increment it */ atomic_swap(shared_count, pos+1); num = 0; while (1) { _snwprintf(shared_keyname, KEYNAME_MAXLEN, L"%s.%03d", is_NT ? CLIENT_SHMEM_KEY_NT_L : CLIENT_SHMEM_KEY_L, num); shared_map = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(client_stats_t), shared_keyname); if (shared_map != NULL && GetLastError() == ERROR_ALREADY_EXISTS) { dr_close_file(shared_map); shared_map = NULL; } if (shared_map != NULL) break; num++; } dr_log(NULL, LOG_ALL, 1, "Shared memory key is: \"%S\"\n", shared_keyname); #ifdef SHOW_RESULTS dr_fprintf(STDERR, "Shared memory key is: \"%S\"\n", shared_keyname); #endif shared_view = MapViewOfFile(shared_map, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 0); DR_ASSERT(shared_view != NULL); return (client_stats_t *) shared_view; }
void <client_name>_exit_event(void) { md_delete_list(head, false); dr_global_free(client_arg, sizeof(client_arg_t)); drmgr_unregister_tls_field(tls_index); if (log_mode){ dr_close_file(logfile); } drmgr_exit(); }
void funcwrap_thread_exit(void *drcontext){ per_thread_t * data; data = drmgr_get_tls_field(drcontext, tls_index); if (log_mode){ dr_close_file(data->logfile); } dr_thread_free(drcontext, data, sizeof(per_thread_t)); DEBUG_PRINT("%s - exiting thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext)); }
static void exit_event(void) { if (outf != STDERR) dr_close_file(outf); if (drsys_exit() != DRMF_SUCCESS) ASSERT(false, "drsys failed to exit"); drsym_exit(); drx_exit(); drmgr_exit(); hashtable_delete(&nconsts_table); }
static void exit_event(void) { if (outfile != INVALID_FILE) { dr_fprintf(outfile, "exit while recording enabled\n"); dr_close_file(outfile); outfile = INVALID_FILE; } drsym_exit(); drreg_exit(); drwrap_exit(); drutil_exit(); drmgr_exit(); }
void memtrace_exit_event() { md_delete_list(head,false); code_cache_exit(); drmgr_unregister_tls_field(tls_index); if (log_mode){ dr_close_file(logfile); } dr_mutex_destroy(mutex); dr_global_free(client_arg, sizeof(client_arg_t)); drutil_exit(); drmgr_exit(); }
static void onExit() { dr_printf( "In onExit()\n" ); // Clean up hashtable. hashtable_delete( &wraps ); // Clean up output. dr_mutex_destroy( outMutex ); dr_close_file( outFile ); // Clean up extensions. drwrap_exit(); drsym_exit(); }
static void thread_data_destroy(void *drcontext, per_thread_t *data) { /* destroy the bb table */ bb_table_destroy(data->bb_table, data); dr_close_file(data->log); /* free thread data */ if (drcontext == NULL) { ASSERT(!drcov_per_thread, "drcov_per_thread should not be set"); dr_global_free(data, sizeof(*data)); } else { ASSERT(drcov_per_thread, "drcov_per_thread is not set"); dr_thread_free(drcontext, data, sizeof(*data)); } }
static void event_exit(void) { /* ensure our file was not closed by the app */ if (!dr_file_seek(file, 0, DR_SEEK_SET)) dr_fprintf(STDERR, "seek error in exit event\n"); dr_close_file(file); dr_fprintf(STDERR, "file separation check\n"); /* i#1213: test float i/o. * Technically we should save fpstate (for detach) but we're not bothering. */ dr_fprintf(STDERR, "float i/o test: %6.5g\n", 3.1415916); dr_fprintf(STDERR, "done\n"); }
/* 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; }
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; }
static void shared_memory_exit(void) { int pos; stats->exited = true; /* close down statistics */ UnmapViewOfFile(shared_view); dr_close_file(shared_map); /* decrement count, then unmap */ do { pos = atomic_swap(shared_count, (uint) -1); /* if get -1 back, someone else is looking at it */ } while (pos == -1); /* now increment it */ atomic_swap(shared_count, pos-1); UnmapViewOfFile(shared_view_count); CloseHandle(shared_map_count); }
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; } }
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++; }
void dr_exit() { dr_fprintf(STDERR, "info: stopping dtrace..\n"); tb_delete(trace_buffer); dr_mutex_destroy(trace_buffer_lock); dr_close_file(trace_file); dr_mutex_destroy(trace_file_lock); hashtable_delete(&tags); dr_mutex_destroy(tags_lock); dr_unregister_exit_event(&dr_exit); dr_unregister_thread_init_event(&handle_thread_init); dr_unregister_thread_exit_event(&handle_thread_exit); dr_unregister_bb_event(&handle_bb); dr_unregister_trace_event(&handle_trace); dr_unregister_delete_event(&handle_delete); dr_unregister_signal_event(&handle_signal); dr_unregister_restore_state_event(&handle_restore_state); }
/* * 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; }
void memdump_exit_event(void) { int i = 0; md_delete_list(filter_head, false); md_delete_list(done_head, false); md_delete_list(app_pc_head, false); dr_global_free(client_arg, sizeof(client_arg_t)); drmgr_unregister_tls_field(tls_index); if (log_mode){ dr_close_file(logfile); } for (i = 0; i < instr_clone_amount; i++){ instr_destroy(dr_get_current_drcontext(), instr_clones[i]); } dr_mutex_destroy(mutex); drutil_exit(); drmgr_exit(); drwrap_exit(); }
void inscount_exit_event(void) { #ifdef SHOW_RESULTS char msg[512]; int len; len = dr_snprintf(msg, sizeof(msg)/sizeof(msg[0]), "process name - %s\nInstrumentation results: %llu instructions executed - %d bbcount\n" ,dr_get_application_name(),global_count,bbcount); DR_ASSERT(len > 0); NULL_TERMINATE(msg); DISPLAY_STRING(msg); #endif /* SHOW_RESULTS */ md_delete_list(head,false); dr_global_free(client_arg, sizeof(client_arg_t)); if (log_mode){ dr_close_file(logfile); } drmgr_exit(); }
/* 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, ×tamp, &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, ×tamp) != 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, ×tamp, ¤t_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; }
/* 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); } }
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; }