Beispiel #1
0
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);
}
Beispiel #2
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.");
}
/* 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;
}
Beispiel #4
0
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));
}
Beispiel #5
0
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;
}
Beispiel #6
0
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
}
Beispiel #7
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 */