Attaching the debugger to a running process should work again
(reported by Eric Pouech). Misc cleanups.
diff --git a/server/context_i386.c b/server/context_i386.c
index 75028cf..903f576 100644
--- a/server/context_i386.c
+++ b/server/context_i386.c
@@ -114,7 +114,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 kernel_user_regs_struct regs;
@@ -170,7 +170,7 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 b6a2598..3d86c3d 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 @@
/* 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 20b4a26..173c3f7 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 0e9b875..29f92b2 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -429,20 +429,13 @@
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 @@
/* 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 @@
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 96482eb..9f26b8d 100644
--- a/server/process.c
+++ b/server/process.c
@@ -85,7 +85,7 @@
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 @@
}
/* 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 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;
}
diff --git a/server/thread.h b/server/thread.h
index bf83f0c..8050d81 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -126,7 +126,10 @@
/* 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 );