Ejemplo n.º 1
0
/* Initializes a dcontext with the supplied state and calls dispatch */
void
dynamo_start(priv_mcontext_t *mc)
{
    priv_mcontext_t *mcontext;
    dcontext_t *dcontext = get_thread_private_dcontext();
    ASSERT(dcontext != NULL);
    thread_starting(dcontext);

    /* Signal other threads for take over. */
    dynamorio_take_over_threads(dcontext);

    /* Set return address */
    dcontext->next_tag = mc->pc;
    ASSERT(dcontext->next_tag != NULL);

    /* transfer exec state to mcontext */
    mcontext = get_mcontext(dcontext);
    *mcontext = *mc;

    /* clear pc */
    mcontext->pc = 0;

    /* Swap stacks so dispatch is invoked outside the application.
     * We begin interpretation at the application return point,
     * and thus we need to look like DR returned -- adjust the app
     * stack to account for the return address.
     */
    mcontext->xsp += XSP_SZ;
    call_switch_stack(dcontext, dcontext->dstack, dispatch,
                      false/*not on initstack*/, true/*return on error*/);
    /* In release builds, this will simply return and continue native
     * execution.  That's better than calling unexpected_return() which
     * goes into an infinite loop.
     */
    ASSERT_NOT_REACHED();
}
Ejemplo n.º 2
0
/* exit_process is only honored if dcontext != NULL, and exit_code is only honored
 * if exit_process is true
 */
bool
nudge_thread_cleanup(dcontext_t *dcontext, bool exit_process, uint exit_code)
{
    /* Note - for supporting detach with CLIENT_INTERFACE and nudge threads we need that
     * no lock grabbing or other actions that would interfere with the detaching process
     * occur in the cleanup path here. */

    /* Case 8901: this routine is currently called from the code cache, which may have
     * been reset underneath us, so we can't just blindly return.  This also gives us
     * consistent behavior for handling stack freeing. */

    /* Case 9020: no EXITING_DR() as os_terminate will do that for us */

    /* FIXME - these nudge threads do hit dll mains for thread attach so app may have
     * allocated some TLS memory which won't end up being freed since this won't go
     * through dll main thread detach. The app may also object to unbalanced attach to
     * detach ratio though we haven't seen that in practice. Long term we should take
     * over and redirect the thread at the init apc so it doesn't go through the
     * DllMains to start with. */

    /* We have a general problem on how to free the application stack for nudges.
     * Currently the app/os will never free a nudge thread's app stack:
     *  On NT and 2k ExitThread would normally free the app stack, but we always
     *  terminate nudge threads instead of allowing them to return and exit normally.
     *  On XP and 2k3 none of our nudge creation routines inform csrss of the new thread
     *  (which is who typically frees the stacks).
     *  On Vista we don't use NtCreateThreadEx to create the nudge threads so the kernel
     *  doesn't free the stack.
     * As such we are left with two options: free the app stack here (nudgee free) or
     * have the nudge thread creator free the app stack (nudger free).  Going with
     * nudgee free means we leak exit race nudge stacks whereas if we go with nudger free
     * for external nudges then we'll leak timed out nudge stacks (for internal nudges
     * we pretty much have to do nudgee free).  A nudge_arg_t flag is used to specify
     * which model we use, but currently we always nudgee free.
     *
     * dynamo_thread_exit_common() is where the app stack is actually freed, not here.
     */

    if (dynamo_exited || !dynamo_initialized || dcontext == NULL) {
        /* FIXME - no cleanup so we'll leak any memory allocated for this thread
         * including the application's stack and arg if we were supposed to free them.
         * We only expect to get here in rare races where the nudge thread was created
         * before dr exited (i.e. before drmarker was freed) but didn't end up getting
         * scheduled till after dr exited. */
        ASSERT(!exit_process); /* shouldn't happen */
#ifdef WINDOWS
        if (dcontext != NULL)
            swap_peb_pointer(dcontext, false/*to app*/);
#endif

        os_terminate(dcontext, TERMINATE_THREAD);
    } else {
        /* Nudge threads should exit without holding any locks. */
        ASSERT_OWN_NO_LOCKS();

#ifdef WINDOWS
        /* if exiting the process, os_loader_exit will swap to app, and we want to
         * remain private during exit (esp client exit)
         */
        if (!exit_process && dcontext != NULL)
            swap_peb_pointer(dcontext, false/*to app*/);
#endif

        /* if freeing the app stack we must be on the dstack when we cleanup */
        if (dcontext->free_app_stack && !is_currently_on_dstack(dcontext)) {
            if (exit_process) {
                /* XXX: wasteful to use two dcontext fields just for this.
                 * Extend call_switch_stack to support extra args or sthg?
                 */
                dcontext->nudge_terminate_process = true;
                dcontext->nudge_exit_code = exit_code;
            }
            call_switch_stack(dcontext, dcontext->dstack,
                              (void(*)(void*))nudge_terminate_on_dstack,
                              NULL /* not on initstack */, false /* don't return */);
        } else {
            /* Already on dstack or nudge creator will free app stack. */
            if (exit_process) {
                os_terminate_with_code(dcontext, TERMINATE_PROCESS|TERMINATE_CLEANUP,
                                       exit_code);
            } else {
                os_terminate(dcontext, TERMINATE_THREAD|TERMINATE_CLEANUP);
            }
        }
    }
    ASSERT_NOT_REACHED(); /* we should never return */
    return true;
}