/* 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; }
/* 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; }
/* 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; }