diff --git a/server/context_i386.c b/server/context_i386.c index 75028cf1376..903f576b1b1 100644 --- a/server/context_i386.c +++ b/server/context_i386.c @@ -114,7 +114,7 @@ static inline int get_debug_reg( int pid, int num, DWORD *data ) /* retrieve a thread context */ static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context ) { - int pid = thread->unix_pid; + int pid = get_ptrace_pid(thread); if (flags & CONTEXT_FULL) { struct kernel_user_regs_struct regs; @@ -170,7 +170,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE /* set a thread context */ static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context ) { - int pid = thread->unix_pid; + int pid = get_ptrace_pid(thread); if (flags & CONTEXT_FULL) { struct kernel_user_regs_struct regs; @@ -230,7 +230,7 @@ static void set_thread_context( struct thread *thread, unsigned int flags, const /* retrieve a thread context */ static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context ) { - int pid = thread->unix_pid; + int pid = get_ptrace_pid(thread); if (flags & CONTEXT_FULL) { struct regs regs; @@ -281,7 +281,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE /* set a thread context */ static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context ) { - int pid = thread->unix_pid; + int pid = get_ptrace_pid(thread); if (flags & CONTEXT_FULL) { struct regs regs; @@ -338,7 +338,7 @@ static void set_thread_context( struct thread *thread, unsigned int flags, const /* retrieve a thread context */ static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context ) { - int pid = thread->unix_pid; + int pid = get_ptrace_pid(thread); if (flags & CONTEXT_FULL) { struct reg regs; @@ -410,7 +410,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE /* set a thread context */ static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context ) { - int pid = thread->unix_pid; + int pid = get_ptrace_pid(thread); if (flags & CONTEXT_FULL) { struct reg regs; diff --git a/server/context_powerpc.c b/server/context_powerpc.c index b6a2598881d..3d86c3d8d01 100644 --- a/server/context_powerpc.c +++ b/server/context_powerpc.c @@ -42,7 +42,7 @@ /* retrieve a thread context */ static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context ) { - int pid = thread->unix_pid; + int pid = get_ptrace_pid(thread); if (flags & CONTEXT_FULL) { if (flags & CONTEXT_INTEGER) @@ -117,7 +117,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE /* set a thread context */ static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context ) { - int pid = thread->unix_pid; + int pid = get_ptrace_pid(thread); if (flags & CONTEXT_FULL) { if (flags & CONTEXT_INTEGER) diff --git a/server/context_sparc.c b/server/context_sparc.c index 20b4a26f45f..173c3f74db2 100644 --- a/server/context_sparc.c +++ b/server/context_sparc.c @@ -45,7 +45,7 @@ /* retrieve a thread context */ static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context ) { - int pid = thread->unix_pid; + int pid = get_ptrace_pid(thread); if (flags & CONTEXT_FULL) { struct regs regs; diff --git a/server/debugger.c b/server/debugger.c index 0e9b875037c..29f92b2439a 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -429,20 +429,13 @@ static int debugger_attach( struct process *process, struct thread *debugger ) goto error; suspend_process( process ); - - /* we must have been able to attach all threads */ - if (!process->thread_list) goto error2; - for (thread = process->thread_list; thread; thread = thread->proc_next) + if (!attach_process( process ) || !set_process_debugger( process, debugger )) { - if (!thread->attached) goto error2; + resume_process( process ); + return 0; } + return 1; - if (set_process_debugger( process, debugger )) return 1; - resume_process( process ); - return 0; - - error2: - resume_process( process ); error: set_error( STATUS_ACCESS_DENIED ); return 0; @@ -452,7 +445,6 @@ static int debugger_attach( struct process *process, struct thread *debugger ) /* detach a process from a debugger thread (and resume it ?) */ int debugger_detach( struct process *process, struct thread *debugger ) { - struct thread *thread; struct debug_event *event; struct debug_ctx *debug_ctx; @@ -488,15 +480,7 @@ int debugger_detach( struct process *process, struct thread *debugger ) process->debugger = NULL; release_object( debugger->debug_ctx ); debugger->debug_ctx = NULL; - - /* now detach all the threads */ - for (thread = process->thread_list; thread; thread = thread->proc_next) - { - if (thread->attached) - { - detach_thread( thread, 0 ); - } - } + detach_process( process ); /* from this function */ resume_process( process ); diff --git a/server/process.c b/server/process.c index 96482ebc882..9f26b8d43ba 100644 --- a/server/process.c +++ b/server/process.c @@ -85,7 +85,7 @@ struct startup_info int inherit_all; /* inherit all handles from parent */ int use_handles; /* use stdio handles */ int create_flags; /* creation flags */ - pid_t unix_pid; /* Unix pid of new process */ + int unix_pid; /* Unix pid of new process */ obj_handle_t hstdin; /* handle for stdin */ obj_handle_t hstdout; /* handle for stdout */ obj_handle_t hstderr; /* handle for stderr */ @@ -331,7 +331,7 @@ struct thread *create_process( int fd ) } /* find the startup info for a given Unix process */ -inline static struct startup_info *find_startup_info( pid_t unix_pid ) +inline static struct startup_info *find_startup_info( int unix_pid ) { struct list *ptr; diff --git a/server/ptrace.c b/server/ptrace.c index ae35c23d6ab..e2b19fc773d 100644 --- a/server/ptrace.c +++ b/server/ptrace.c @@ -123,7 +123,7 @@ static void wait4_thread( struct thread *thread, int signal ) do { - if ((res = wait4( thread->unix_pid, &status, WUNTRACED, NULL )) == -1) + if ((res = wait4( get_ptrace_pid(thread), &status, WUNTRACED, NULL )) == -1) { if (errno == ECHILD) /* must have died */ { @@ -137,6 +137,12 @@ static void wait4_thread( struct thread *thread, int signal ) } while (res && res != signal); } +/* return the Unix pid to use in ptrace calls for a given thread */ +int get_ptrace_pid( struct thread *thread ) +{ + return thread->unix_pid; +} + /* send a Unix signal to a specific thread */ int send_thread_signal( struct thread *thread, int sig ) { @@ -159,7 +165,7 @@ static int attach_thread( struct thread *thread ) { /* this may fail if the client is already being debugged */ if (!use_ptrace) return 0; - if (ptrace( PTRACE_ATTACH, thread->unix_pid, 0, 0 ) == -1) + if (ptrace( PTRACE_ATTACH, get_ptrace_pid(thread), 0, 0 ) == -1) { if (errno == ESRCH) thread->unix_pid = -1; /* thread got killed */ return 0; @@ -181,12 +187,43 @@ void detach_thread( struct thread *thread, int sig ) if (sig) send_thread_signal( thread, sig ); if (thread->unix_pid == -1) return; if (debug_level) fprintf( stderr, "%04x: *detached*\n", thread->id ); - ptrace( PTRACE_DETACH, thread->unix_pid, (caddr_t)1, sig ); + ptrace( PTRACE_DETACH, get_ptrace_pid(thread), (caddr_t)1, sig ); thread->attached = 0; } else if (sig) send_thread_signal( thread, sig ); } +/* attach to a Unix process with ptrace */ +int attach_process( struct process *process ) +{ + struct thread *thread; + int ret = 1; + + if (!process->thread_list) /* need at least one running thread */ + { + set_error( STATUS_ACCESS_DENIED ); + return 0; + } + for (thread = process->thread_list; thread; thread = thread->proc_next) + { + if (thread->attached) continue; + if (suspend_for_ptrace( thread )) resume_after_ptrace( thread ); + else ret = 0; + } + return ret; +} + +/* detach from a ptraced Unix process */ +void detach_process( struct process *process ) +{ + struct thread *thread; + + for (thread = process->thread_list; thread; thread = thread->proc_next) + { + if (thread->attached) detach_thread( thread, 0 ); + } +} + /* suspend a thread to allow using ptrace on it */ /* you must do a resume_after_ptrace when finished with the thread */ int suspend_for_ptrace( struct thread *thread ) @@ -212,14 +249,14 @@ void resume_after_ptrace( struct thread *thread ) if (thread->unix_pid == -1) return; assert( thread->attached ); ptrace( get_thread_single_step(thread) ? PTRACE_SINGLESTEP : PTRACE_CONT, - thread->unix_pid, (caddr_t)1, 0 /* cancel the SIGSTOP */ ); + get_ptrace_pid(thread), (caddr_t)1, 0 /* cancel the SIGSTOP */ ); } /* read an int from a thread address space */ int read_thread_int( struct thread *thread, const int *addr, int *data ) { errno = 0; - *data = ptrace( PTRACE_PEEKDATA, thread->unix_pid, (caddr_t)addr, 0 ); + *data = ptrace( PTRACE_PEEKDATA, get_ptrace_pid(thread), (caddr_t)addr, 0 ); if ( *data == -1 && errno) { file_set_error(); @@ -237,7 +274,7 @@ int write_thread_int( struct thread *thread, int *addr, int data, unsigned int m if (read_thread_int( thread, addr, &res ) == -1) return -1; data = (data & mask) | (res & ~mask); } - if ((res = ptrace( PTRACE_POKEDATA, thread->unix_pid, (caddr_t)addr, data )) == -1) + if ((res = ptrace( PTRACE_POKEDATA, get_ptrace_pid(thread), (caddr_t)addr, data )) == -1) file_set_error(); return res; } diff --git a/server/thread.h b/server/thread.h index bf83f0c0998..8050d81b43b 100644 --- a/server/thread.h +++ b/server/thread.h @@ -126,7 +126,10 @@ extern struct thread_snapshot *thread_snap( int *count ); /* ptrace functions */ extern void sigchld_handler(); +extern int get_ptrace_pid( struct thread *thread ); extern void detach_thread( struct thread *thread, int sig ); +extern int attach_process( struct process *process ); +extern void detach_process( struct process *process ); extern int suspend_for_ptrace( struct thread *thread ); extern void resume_after_ptrace( struct thread *thread ); extern int read_thread_int( struct thread *thread, const int *addr, int *data );