Attaching the debugger to a running process should work again
(reported by Eric Pouech). Misc cleanups.
diff --git a/server/ptrace.c b/server/ptrace.c
index ae35c23..e2b19fc 100644
--- a/server/ptrace.c
+++ b/server/ptrace.c
@@ -123,7 +123,7 @@
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 @@
} 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 @@
{
/* 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 @@
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 @@
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 @@
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;
}