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
drcovlib_status_t
drmodtrack_offline_exit(void *handle)
{
    module_read_info_t *info = (module_read_info_t *)handle;
    if (info == NULL)
        return DRCOVLIB_ERROR_INVALID_PARAMETER;
    dr_global_free(info->mod, info->num_mods * sizeof(*info->mod));
    if (info->map != NULL)
        dr_unmap_file((char *)info->map, info->map_size);
    dr_global_free(info, sizeof(*info));
    return DRCOVLIB_SUCCESS;
}
Beispiel #3
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;
}
Beispiel #4
0
drcovlib_status_t
drmodtrack_offline_read(file_t file, const char **map,
                        OUT void **handle, OUT uint *num_mods)
{
    module_read_info_t *info = NULL;
    uint i;
    uint64 file_size;
    size_t map_size = 0;
    const char *buf, *map_start;
    uint version;

    if (handle == NULL || num_mods == NULL)
        return DRCOVLIB_ERROR_INVALID_PARAMETER;
    if (file == INVALID_FILE) {
        if (map == NULL)
            return DRCOVLIB_ERROR_INVALID_PARAMETER;
        map_start = *map;
    } else {
        if (!dr_file_size(file, &file_size))
            return DRCOVLIB_ERROR_INVALID_PARAMETER;
        map_size = (size_t)file_size;
        map_start = (char *) dr_map_file(file, &map_size, 0, NULL, DR_MEMPROT_READ, 0);
        if (map_start == NULL || map_size < file_size)
            return DRCOVLIB_ERROR_INVALID_PARAMETER; /* assume bad perms or sthg */
    }
    if (map_start == NULL)
        return DRCOVLIB_ERROR_INVALID_PARAMETER;
    buf = map_start;

    /* Module table header, handling the pre-versioning legacy format. */
    if (dr_sscanf(buf, "Module Table: %u\n", num_mods) == 1)
        version = 1;
    else if (dr_sscanf(buf, "Module Table: version %u, count %u\n", &version,
                       num_mods) != 2 ||
             version != MODULE_FILE_VERSION)
        goto read_error;
    buf = move_to_next_line(buf);
    if (version > 1) {
        // Skip header line
        buf = move_to_next_line(buf);
    }

    info = (module_read_info_t *)dr_global_alloc(sizeof(*info));
    if (file != INVALID_FILE) {
        info->map = map_start;
        info->map_size = map_size;
    } else
        info->map = NULL;
    info->num_mods = *num_mods;
    info->mod = (module_read_entry_t *)dr_global_alloc(*num_mods * sizeof(*info->mod));

    /* module lists */
    for (i = 0; i < *num_mods; i++) {
        uint mod_id;
        if (version == 1) {
            if (dr_sscanf(buf, " %u, %" INT64_FORMAT"u, %[^\n\r]",
                          &mod_id, &info->mod[i].size, info->mod[i].path) != 3 ||
                mod_id != i)
                goto read_error;
        } else {
            app_pc end, entry;
#ifdef WINDOWS
            uint checksum, timestamp;
            if (dr_sscanf(buf, " %u, "PIFX", "PIFX", "PIFX", 0x%x, 0x%x, %[^\n\r]",
                          &mod_id, &info->mod[i].base, &end, &entry,
                          &checksum, &timestamp,
                          info->mod[i].path) != 7 ||
                mod_id != i)
                goto read_error;
#else
            if (dr_sscanf(buf, " %u, "PIFX", "PIFX", "PIFX", %[^\n\r]",
                          &mod_id, &info->mod[i].base, &end, &entry,
                          info->mod[i].path) != 5 ||
                mod_id != i)
                goto read_error;
#endif
            info->mod[i].size = end - info->mod[i].base;
        }
        buf = move_to_next_line(buf);
    }
    if (file == INVALID_FILE)
        *map = buf;
    *handle = (void *)info;
    return DRCOVLIB_SUCCESS;

 read_error:
    if (info != NULL) {
        dr_global_free(info->mod, *num_mods * sizeof(*info->mod));
        dr_global_free(info, sizeof(*info));
    }
    if (file != INVALID_FILE)
        dr_unmap_file((char *)map_start, map_size);
    return DRCOVLIB_ERROR;
}
Beispiel #5
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;
}
Beispiel #6
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 */
Beispiel #7
0
void tb_delete(struct trace_buffer_t* tb) {
  tb_flush(tb);
  if(!dr_unmap_file(tb, TRACE_BUFFER_SIZE)) {
      dr_fprintf(STDERR, "warning: dr_unmap_file() failed\n");
  }
}