Esempio n. 1
0
/* attach a process to a debugger thread and suspend it */
static int debugger_attach( struct process *process, struct thread *debugger )
{
    struct thread *thread;

    if (process->debugger) goto error;  /* already being debugged */
    if (!is_process_init_done( process )) goto error;  /* still starting up */
    if (list_empty( &process->thread_list )) goto error;  /* no thread running in the process */

    /* make sure we don't create a debugging loop */
    for (thread = debugger; thread; thread = thread->process->debugger)
        if (thread->process == process) goto error;

    /* don't let a debugger debug its console... won't work */
    if (debugger->process->console && debugger->process->console->renderer->process == process)
        goto error;

    suspend_process( process );
    if (!set_process_debugger( process, debugger ))
    {
        resume_process( process );
        return 0;
    }
    if (!set_process_debug_flag( process, 1 ))
    {
        process->debugger = NULL;
        resume_process( process );
        return 0;
    }
    return 1;

 error:
    set_error( STATUS_ACCESS_DENIED );
    return 0;
}
Esempio n. 2
0
/* attach a process to a debugger thread and suspend it */
static int debugger_attach( struct process *process, struct thread *debugger )
{
    if (process->debugger) goto error;  /* already being debugged */
    if (debugger->process == process) goto error;
    if (!is_process_init_done( process )) goto error;  /* still starting up */
    if (list_empty( &process->thread_list )) goto error;  /* no thread running in the process */

    /* don't let a debugger debug its console... won't work */
    if (debugger->process->console)
    {
        struct thread *renderer = console_get_renderer(debugger->process->console);
        if (renderer && renderer->process == process)
            goto error;
    }

    suspend_process( process );
    if (!set_process_debugger( process, debugger ))
    {
        resume_process( process );
        return 0;
    }
    if (!set_process_debug_flag( process, 1 ))
    {
        process->debugger = NULL;
        resume_process( process );
        return 0;
    }
    return 1;

 error:
    set_error( STATUS_ACCESS_DENIED );
    return 0;
}
Esempio n. 3
0
/* you must do a resume_after_ptrace when finished with the thread */
static int suspend_for_ptrace( struct thread *thread )
{
    /* can't stop a thread while initialisation is in progress */
    if (thread->unix_pid == -1 || !is_process_init_done(thread->process)) goto error;

    /* this may fail if the client is already being debugged */
    if (ptrace( PTRACE_ATTACH, get_ptrace_pid(thread), 0, 0 ) == -1)
    {
        if (errno == ESRCH) thread->unix_pid = thread->unix_tid = -1;  /* thread got killed */
        goto error;
    }
    if (waitpid_thread( thread, SIGSTOP )) return 1;
    resume_after_ptrace( thread );
 error:
    set_error( STATUS_ACCESS_DENIED );
    return 0;
}
Esempio n. 4
0
/* detach a process from a debugger thread (and resume it ?) */
int debugger_detach( struct process *process, struct thread *debugger )
{
    struct debug_event *event;
    struct debug_ctx *debug_ctx;

    if (!process->debugger || process->debugger != debugger)
        goto error;  /* not currently debugged, or debugged by another debugger */
    if (!debugger->debug_ctx ) goto error; /* should be a debugger */
    /* init should be done, otherwise wouldn't be attached */
    assert(is_process_init_done(process));

    suspend_process( process );
    /* send continue indication for all events */
    debug_ctx = debugger->debug_ctx;

    /* find the event in the queue
     * FIXME: could loop on process' threads and look the debug_event field */
    LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry )
    {
        if (event->state != EVENT_QUEUED) continue;

        if (event->sender->process == process)
        {
            assert( event->sender->debug_event == event );
            event->status = DBG_CONTINUE;
            event->state  = EVENT_CONTINUED;
            wake_up( &event->obj, 0 );
            unlink_event( debug_ctx, event );
            /* from queued debug event */
            resume_process( process );
            break;
        }
    }

    /* remove relationships between process and its debugger */
    process->debugger = NULL;
    if (!set_process_debug_flag( process, 0 )) clear_error();  /* ignore error */

    /* from this function */
    resume_process( process );
    return 0;

 error:
    set_error( STATUS_ACCESS_DENIED );
    return 0;
}