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); }
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."); }
/* 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; }
static void read_data(file_t f, void *drcontext) { byte sbuf[BUF_SIZE]; byte *pc, *prev_pc; int len, prev_buf_len = 0; /* FIXME: re-run 64-bit asking for 32-bit mode */ do { len = dr_read_file(f, sbuf, sizeof(sbuf)); pc = sbuf; while (pc < sbuf+len) { /* FIXME: want to cut it off instead of reading beyond for * end of file! If weren't printing it out as go along could * mark invalid after seeing whether instr overflows. */ prev_pc = pc; #if VERBOSE dr_printf("+0x%04x ", prev_pc - sbuf + prev_buf_len); #endif pc = disassemble_from_copy(drcontext, pc, ORIG_PC, STDOUT, false/*don't show pc*/, #if VERBOSE true/*show bytes*/ #else false/*do not show bytes*/ #endif ); /* If invalid, try next byte */ /* FIXME: udis86 is going to byte after the one that makes it * invalid: so if 1st byte is invalid opcode, go to 2nd; * if modrm makes it invalid (0xc5 0xc5), go to 3rd. * not clear that's nec. better but we need to reconcile that w/ * their diff for automated testing. */ if (pc == NULL) pc = prev_pc + 1; } prev_buf_len += sizeof(sbuf); } while (len == sizeof(sbuf)); }
static inline EventBuffer* get_next_buffer(ipc_channel_t *channel) { /* Increment to the next buffer and try to acquire it for writing */ /* Circular buffer, must be power of 2 */ channel->shmem_buf_idx = (channel->shmem_buf_idx+1) & (SIGIL2_IPC_BUFFERS-1); /* Sigil2 tells us when it's finished with a shared memory buffer */ if(channel->empty_buf_idx[channel->shmem_buf_idx] == false) { if (channel->standalone == false) dr_read_file(channel->empty_fifo, &channel->shmem_buf_idx, sizeof(channel->shmem_buf_idx)); channel->empty_buf_idx[channel->shmem_buf_idx] = true; } channel->shared_mem->eventBuffers[channel->shmem_buf_idx].used = 0; channel->shared_mem->nameBuffers[channel->shmem_buf_idx].used = 0; return channel->shared_mem->eventBuffers + channel->shmem_buf_idx; }
void wait_for_user(const char *message) { #ifdef WINDOWS dr_messagebox(message); #else if (op_pause_via_loop) { /* PR 406725: on Linux, infinite loop rather than waiting for stdin */ bool forever = true; /* make it easy to break out in gdb */ dr_fprintf(STDERR, "%s\n", message); dr_fprintf(STDERR, "<in infinite loop>\n"); while (forever) { dr_thread_yield(); } } else { char keypress; dr_fprintf(STDERR, "%s\n", message); dr_fprintf(STDERR, "<press enter to continue>\n"); dr_read_file(stdin->_fileno, &keypress, sizeof(keypress)); } #endif }
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 */