Exemple #1
0
void
loader_thread_exit(dcontext_t *dcontext)
{
    privmod_t *mod;
    /* assuming context swap have happened when entered DR */
    if (privload_has_thread_entry() &&
        /* Only call if we're cleaning up the currently executing thread, as
         * that's what the entry routine is going to do!  Calling on other
         * threads results in problems like double frees (i#969).  Exiting
         * another thread should only happen on process exit or forced thread
         * termination.  The former can technically continue (app could call
         * NtTerminateProcess(0) but then keep going) but we have never seen
         * that; and the latter doesn't do full native cleanups anyway.  Thus
         * we're not worried about leaks from not calling DLL_THREAD_EXIT.
         * (We can't check get_thread_private_dcontext() b/c it's already cleared.)
         */
        dcontext->owning_thread == get_thread_id()) {
        acquire_recursive_lock(&privload_lock);
        /* Walk forward and call independent libs last */
        for (mod = modlist; mod != NULL; mod = mod->next) {
            if (!mod->externally_loaded)
                privload_call_entry(mod, DLL_THREAD_EXIT);
        }
        release_recursive_lock(&privload_lock);
    }
    /* os specific thread exit for loader, holding no lock */
    os_loader_thread_exit(dcontext);
}
Exemple #2
0
void
os_loader_thread_init_prologue(dcontext_t *dcontext)
{
    if (!privmod_initialized) {
        /* Because TLS is not setup at loader_init, we cannot call 
         * loaded libraries' init functions there, so have to postpone
         * the invocation until here. 
         */
        acquire_recursive_lock(&privload_lock);
        privmod_t *mod = privload_first_module();
        privload_call_modules_entry(mod, DLL_PROCESS_INIT);
        release_recursive_lock(&privload_lock);
        privmod_initialized = true;
    }
}
void
loader_init(void)
{
    uint i;
    privmod_t *mod;

    acquire_recursive_lock(&privload_lock);
    VMVECTOR_ALLOC_VECTOR(modlist_areas, GLOBAL_DCONTEXT,
                          VECTOR_SHARED | VECTOR_NEVER_MERGE
                          /* protected by privload_lock */
                          | VECTOR_NO_LOCK,
                          modlist_areas);
    /* os specific loader initialization prologue before finalize the load */
    os_loader_init_prologue();

    /* Process client libs we loaded early but did not finalize */
    for (i = 0; i < privmod_static_idx; i++) {
        /* Transfer to real list so we can do normal processing */
        char name_copy[MAXIMUM_PATH];
        mod = privload_insert(NULL,
                              privmod_static[i].base,
                              privmod_static[i].size,
                              privmod_static[i].name,
                              privmod_static[i].path);
        LOG(GLOBAL, LOG_LOADER, 1, "%s: processing imports for %s\n",
            __FUNCTION__, mod->name);
        /* save a copy for error msg, b/c mod will be unloaded (i#643) */
        snprintf(name_copy, BUFFER_SIZE_ELEMENTS(name_copy), "%s", mod->name);
        NULL_TERMINATE_BUFFER(name_copy);
        if (!privload_load_finalize(mod)) {
            mod = NULL; /* it's been unloaded! */
#ifdef CLIENT_INTERFACE
            SYSLOG(SYSLOG_ERROR, CLIENT_LIBRARY_UNLOADABLE, 5,
                   get_application_name(), get_application_pid(), name_copy,
                   "\n\tUnable to locate imports of client library");
#endif
            os_terminate(NULL, TERMINATE_PROCESS);
            ASSERT_NOT_REACHED();
        }
    }
    /* os specific loader initialization epilogue after finalize the load */
    os_loader_init_epilogue();
    /* FIXME i#338: call loader_thread_init here once get
     * loader_init called after dynamo_thread_init but in a way that
     * works with Windows
     */
    release_recursive_lock(&privload_lock);
}
Exemple #4
0
void
loader_exit(void)
{
    /* We must unload for detach so can't leave them loaded */
    acquire_recursive_lock(&privload_lock);
    /* The list is kept in reverse-dependent order so we can unload from the
     * front without breaking dependencies.
     */
    while (modlist != NULL)
        privload_unload(modlist);
    /* os related loader finalization */
    os_loader_exit();
    vmvector_delete_vector(GLOBAL_DCONTEXT, modlist_areas);
    release_recursive_lock(&privload_lock);
    DELETE_RECURSIVE_LOCK(privload_lock);
}
Exemple #5
0
void
loader_thread_exit(dcontext_t *dcontext)
{
    privmod_t *mod;
    /* assuming context swap have happened when entered DR */
    if (privload_has_thread_entry()) {
        acquire_recursive_lock(&privload_lock);
        /* Walk forward and call independent libs last */
         for (mod = modlist; mod != NULL; mod = mod->next) {
            if (!mod->externally_loaded)
                privload_call_entry(mod, DLL_THREAD_EXIT);
        }
        release_recursive_lock(&privload_lock);
    }
    /* os specific thread exit for loader, holding no lock */
    os_loader_thread_exit(dcontext);
}
Exemple #6
0
void
loader_thread_init(dcontext_t *dcontext)
{
    privmod_t *mod;

    if (modlist == NULL) {
#ifdef WINDOWS
        /* FIXME i#338: once restore order this will become nop */
        /* os specific thread initilization prologue for loader with no lock */
        os_loader_thread_init_prologue(dcontext);
        /* os specific thread initilization epilogue for loader with no lock */
        os_loader_thread_init_epilogue(dcontext);
#endif /* WINDOWS */
    } else {
        /* os specific thread initilization prologue for loader with no lock */
        os_loader_thread_init_prologue(dcontext);
        if (privload_has_thread_entry()) {
            /* We rely on lock isolation to prevent deadlock while we're here
             * holding privload_lock and the priv lib
             * DllMain may acquire the same lock that another thread acquired
             * in its app code before requesting a synchall (flush, exit).
             * FIXME i#875: we do not have ntdll!RtlpFlsLock isolated.
             * Living w/ it for now.  It should be unlikely for the app to
             * hold RtlpFlsLock and then acquire privload_lock: privload_lock
             * is used for import redirection but those don't apply within
             * ntdll.
             */
            ASSERT_OWN_NO_LOCKS();
            acquire_recursive_lock(&privload_lock);
            /* Walk forward and call independent libs last.
             * We do notify priv libs of client threads.
             */
            for (mod = modlist; mod != NULL; mod = mod->next) {
                if (!mod->externally_loaded)
                    privload_call_entry(mod, DLL_THREAD_INIT);
            }
            release_recursive_lock(&privload_lock);
        }
        /* os specific thread initilization epilogue for loader with no lock */
        os_loader_thread_init_epilogue(dcontext);
    }
}
Exemple #7
0
/* os specific loader initialization epilogue after finalizing the load. */
void
os_loader_init_epilogue(void)
{
#ifdef INTERNAL
    /* Print the add-symbol-file commands so they can be copy-pasted into gdb.
     * We have to do it in a single syslog so they can be copy pasted.  Since
     * info syslogs are only in internal builds, we only do this work in an
     * internal build.  To debug an external build, we rely on the gdb script to
     * find text_addr in opd.
     * FIXME i#531: Support attaching from the gdb script.
     */
    privmod_t *mod;
    size_t sofar = 0;
    size_t bufsz = 4096;  /* Should be enough, but too much for stack. */
    char *buf;

    /* FIXME: Skip this work if we're not going to print or log. */
    ASSERT(dynamo_heap_initialized);
    ASSERT(!printed_gdb_commands);
    buf = HEAP_ARRAY_ALLOC(GLOBAL_DCONTEXT, char, bufsz, ACCT_OTHER, PROTECTED);
    acquire_recursive_lock(&privload_lock);
    for (mod = privload_first_module(); mod != NULL;
         mod = privload_next_module(mod)) {
        os_privmod_data_t *opd = (os_privmod_data_t *) mod->os_privmod_data;
        /* GDB already finds externally loaded modules (e.g. DR). */
        if (mod->externally_loaded)
            continue;
        print_to_buffer(buf, bufsz, &sofar, "add-symbol-file '%s' %p\n",
                        mod->path, opd->text_addr);
    }
    printed_gdb_commands = true;
    release_recursive_lock(&privload_lock);
    if (sofar > 0) {
        SYSLOG_INTERNAL_INFO("Paste into GDB to debug DynamoRIO clients:\n"
                             /* Need to turn off confirm for paste to work. */
                             "set confirm off\n"
                             "%s", buf);
    }
    HEAP_ARRAY_FREE(GLOBAL_DCONTEXT, buf, char, bufsz, ACCT_OTHER, PROTECTED);
#endif /* INTERNAL */
}