Пример #1
0
void
module_table_print(module_table_t *table, file_t log, bool print_all_info)
{
    uint i;
    module_entry_t *entry;
    if (log == INVALID_FILE) {
        /* It is possible that failure on log file creation is caused by the
         * running process not having enough privilege, so this is not a
         * release-build fatal error
         */
        ASSERT(false, "invalid log file");
        return;
    }
    drvector_lock(&table->vector);
    dr_fprintf(log, "Module Table: %u\n", table->vector.entries);

    if (print_all_info) {
        dr_fprintf(log, "Module Table: id, base, end, entry, unload, name, path");
#ifdef WINDOWS
        dr_fprintf(log, ", checksum, timestamp");
#endif
        dr_fprintf(log, "\n");
    }

    for (i = 0; i < table->vector.entries; i++) {
        entry = drvector_get_entry(&table->vector, i);
        module_table_entry_print(entry, log, print_all_info);
    }
    drvector_unlock(&table->vector);
}
Пример #2
0
drcovlib_status_t
drmodtrack_dump_buf(char *buf, size_t size) {
    uint i;
    module_entry_t *entry;
    int len;
    if (buf == NULL || size == 0)
        return DRCOVLIB_ERROR_INVALID_PARAMETER;
    size--;  /* for the terminating null character */
    drvector_lock(&module_table.vector);
    len = dr_snprintf(buf, size, "Module Table: version %u, count %u\n",
                      MODULE_FILE_VERSION, module_table.vector.entries);
    if (len == -1) {
        drvector_unlock(&module_table.vector);
        return DRCOVLIB_ERROR_BUF_TOO_SMALL;
    }
    buf += len;
    size -= len;

    len = dr_snprintf(buf, size, "Columns: id, base, end, entry");
    if (len == -1) {
        drvector_unlock(&module_table.vector);
        return DRCOVLIB_ERROR_BUF_TOO_SMALL;
    }
#ifdef WINDOWS
    buf += len;
    size -= len;

    len = dr_snprintf(buf, size, ", checksum, timestamp");
    if (len == -1) {
        drvector_unlock(&module_table.vector);
        return DRCOVLIB_ERROR_BUF_TOO_SMALL;
    }
#endif

    buf += len;
    size -= len;
    len = dr_snprintf(buf, size, ", path\n");
    if (len == -1) {
        drvector_unlock(&module_table.vector);
        return DRCOVLIB_ERROR_BUF_TOO_SMALL;
    }

    buf += len;
    size -= len;
    for (i = 0; i < module_table.vector.entries; i++) {
        entry = drvector_get_entry(&module_table.vector, i);
        len = module_table_entry_print(entry, buf, size);
        if (len == -1) {
            drvector_unlock(&module_table.vector);
            return DRCOVLIB_ERROR_BUF_TOO_SMALL;
        }
        buf += len;
        size -= len;
     }
    buf[0] = '\0';
    drvector_unlock(&module_table.vector);
    return DRCOVLIB_SUCCESS;
}
Пример #3
0
static void
event_module_load(void *drcontext, const module_data_t *data, bool loaded)
{
    module_entry_t *entry = NULL;
    module_data_t  *mod;
    int i;
    /* Some apps repeatedly unload and reload the same module,
     * so we will try to re-use the old one.
     */
    ASSERT(data != NULL, "data must not be NULL");
    drvector_lock(&module_table.vector);
    /* Assuming most recently loaded entries are most likely to be unloaded,
     * we iterate the module table in a backward way for better performance.
     */
    for (i = module_table.vector.entries-1; i >= 0; i--) {
        entry = drvector_get_entry(&module_table.vector, i);
        mod   = entry->data;
        if (entry->unload &&
            /* If the same module is re-loaded at the same address,
             * we will try to use the existing entry.
             */
            mod->start       == data->start        &&
            mod->end         == data->end          &&
            mod->entry_point == data->entry_point  &&
#ifdef WINDOWS
            mod->checksum    == data->checksum     &&
            mod->timestamp   == data->timestamp    &&
#endif
            /* If a module w/ no name (there are some) is loaded, we will
             * keep making new entries.
             */
            dr_module_preferred_name(data) != NULL &&
            dr_module_preferred_name(mod)  != NULL &&
            strcmp(dr_module_preferred_name(data),
                   dr_module_preferred_name(mod)) == 0) {
            entry->unload = false;
            break;
        }
        entry = NULL;
    }
    if (entry == NULL) {
        entry = dr_global_alloc(sizeof(*entry));
        entry->id = module_table.vector.entries;
        entry->unload = false;
        entry->data = dr_copy_module_data(data);
        drvector_append(&module_table.vector, entry);
    }
    drvector_unlock(&module_table.vector);
    global_module_cache_add(module_table.cache, entry);
}
Пример #4
0
drcovlib_status_t
drmodtrack_lookup(void *drcontext, app_pc pc, OUT uint *mod_index, OUT app_pc *mod_base)
{
    per_thread_t *data = (per_thread_t *)drmgr_get_tls_field(drcontext, tls_idx);
    module_entry_t *entry;
    int i;
    /* We assume we never change an entry's data field, even on unload,
     * and thus it is ok to check its value without a lock.
     */
    /* lookup thread module cache */
    for (i = 0; i < NUM_THREAD_MODULE_CACHE; i++) {
        entry = data->cache[i];
        if (pc_is_in_module(entry, pc)) {
            if (i > 0) {
                thread_module_cache_adjust(data->cache, entry, i,
                                           NUM_THREAD_MODULE_CACHE);
            }
            lookup_helper_set_fields(entry, mod_index, mod_base);
            return DRCOVLIB_SUCCESS;
        }
    }
    /* lookup global module cache */
    /* we use a direct map cache, so it is ok to access it without lock */
    for (i = 0; i < NUM_GLOBAL_MODULE_CACHE; i++) {
        entry = module_table.cache[i];
        if (pc_is_in_module(entry, pc)) {
            lookup_helper_set_fields(entry, mod_index, mod_base);
            return DRCOVLIB_SUCCESS;
        }
    }
    /* lookup module table */
    entry = NULL;
    drvector_lock(&module_table.vector);
    for (i = module_table.vector.entries - 1; i >= 0; i--) {
        entry = drvector_get_entry(&module_table.vector, i);
        ASSERT(entry != NULL, "fail to get module entry");
        if (pc_is_in_module(entry, pc)) {
            global_module_cache_add(module_table.cache, entry);
            thread_module_cache_add(data->cache, NUM_THREAD_MODULE_CACHE, entry);
            break;
        }
        entry = NULL;
    }
    if (entry != NULL)
        lookup_helper_set_fields(entry, mod_index, mod_base);
    drvector_unlock(&module_table.vector);
    return entry == NULL ? DRCOVLIB_ERROR_NOT_FOUND : DRCOVLIB_SUCCESS;
}
Пример #5
0
module_entry_t *
module_table_lookup(module_entry_t **cache, int cache_size,
                    module_table_t *table, app_pc pc)
{
    module_entry_t *entry;
    int i;

    /* We assume we never change an entry's data field, even on unload,
     * and thus it is ok to check its value without a lock.
     */
    /* lookup thread module cache */
    if (cache != NULL) {
        for (i = 0; i < cache_size; i++) {
            entry = cache[i];
            if (pc_is_in_module(entry, pc)) {
                if (i > 0)
                    thread_module_cache_adjust(cache, entry, i, cache_size);
                return entry;
            }
        }
    }
    /* lookup global module cache */
    /* we use a direct map cache, so it is ok to access it without lock */
    for (i = 0; i < NUM_GLOBAL_MODULE_CACHE; i++) {
        entry = table->cache[i];
        if (pc_is_in_module(entry, pc))
            return entry;
    }
    /* lookup module table */
    entry = NULL;
    drvector_lock(&table->vector);
    for (i = table->vector.entries - 1; i >= 0; i--) {
        entry = drvector_get_entry(&table->vector, i);
        ASSERT(entry != NULL, "fail to get module entry");
        if (pc_is_in_module(entry, pc)) {
            global_module_cache_add(table->cache, entry);
            if (cache != NULL)
                thread_module_cache_add(cache, cache_size, entry);
            break;
        }
        entry = NULL;
    }
    drvector_unlock(&table->vector);
    return entry;
}
Пример #6
0
static void
event_module_unload(void *drcontext, const module_data_t *data)
{
    module_entry_t *entry = NULL;
    int i;
    drvector_lock(&module_table.vector);
    for (i = module_table.vector.entries - 1; i >= 0; i--) {
        entry = drvector_get_entry(&module_table.vector, i);
        ASSERT(entry != NULL, "fail to get module entry");
        if (pc_is_in_module(entry, data->start))
            break;
        entry = NULL;
    }
    if (entry != NULL)
        entry->unload = true;
    else
        ASSERT(false, "fail to find the module to be unloaded");
    drvector_unlock(&module_table.vector);
}