Attaching the debugger to a running process should work again

(reported by Eric Pouech). Misc cleanups.
This commit is contained in:
Alexandre Julliard 2003-03-11 01:48:53 +00:00
parent cb816d2c3f
commit baf0a064db
7 changed files with 62 additions and 38 deletions

View File

@ -114,7 +114,7 @@ static inline int get_debug_reg( int pid, int num, DWORD *data )
/* retrieve a thread context */ /* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *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_FULL)
{ {
struct kernel_user_regs_struct regs; 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 */ /* set a thread context */
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *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_FULL)
{ {
struct kernel_user_regs_struct regs; 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 */ /* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *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_FULL)
{ {
struct regs regs; struct regs regs;
@ -281,7 +281,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE
/* set a thread context */ /* set a thread context */
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *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_FULL)
{ {
struct regs regs; struct regs regs;
@ -338,7 +338,7 @@ static void set_thread_context( struct thread *thread, unsigned int flags, const
/* retrieve a thread context */ /* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *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_FULL)
{ {
struct reg regs; struct reg regs;
@ -410,7 +410,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE
/* set a thread context */ /* set a thread context */
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *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_FULL)
{ {
struct reg regs; struct reg regs;

View File

@ -42,7 +42,7 @@
/* retrieve a thread context */ /* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *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_FULL)
{ {
if (flags & CONTEXT_INTEGER) if (flags & CONTEXT_INTEGER)
@ -117,7 +117,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE
/* set a thread context */ /* set a thread context */
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *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_FULL)
{ {
if (flags & CONTEXT_INTEGER) if (flags & CONTEXT_INTEGER)

View File

@ -45,7 +45,7 @@
/* retrieve a thread context */ /* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *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_FULL)
{ {
struct regs regs; struct regs regs;

View File

@ -429,20 +429,13 @@ static int debugger_attach( struct process *process, struct thread *debugger )
goto error; goto error;
suspend_process( process ); suspend_process( process );
if (!attach_process( process ) || !set_process_debugger( process, debugger ))
/* 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 (!thread->attached) goto error2;
}
if (set_process_debugger( process, debugger )) return 1;
resume_process( process ); resume_process( process );
return 0; return 0;
}
return 1;
error2:
resume_process( process );
error: error:
set_error( STATUS_ACCESS_DENIED ); set_error( STATUS_ACCESS_DENIED );
return 0; 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 ?) */ /* detach a process from a debugger thread (and resume it ?) */
int debugger_detach( struct process *process, struct thread *debugger ) int debugger_detach( struct process *process, struct thread *debugger )
{ {
struct thread *thread;
struct debug_event *event; struct debug_event *event;
struct debug_ctx *debug_ctx; struct debug_ctx *debug_ctx;
@ -488,15 +480,7 @@ int debugger_detach( struct process *process, struct thread *debugger )
process->debugger = NULL; process->debugger = NULL;
release_object( debugger->debug_ctx ); release_object( debugger->debug_ctx );
debugger->debug_ctx = NULL; debugger->debug_ctx = NULL;
detach_process( process );
/* now detach all the threads */
for (thread = process->thread_list; thread; thread = thread->proc_next)
{
if (thread->attached)
{
detach_thread( thread, 0 );
}
}
/* from this function */ /* from this function */
resume_process( process ); resume_process( process );

View File

@ -85,7 +85,7 @@ struct startup_info
int inherit_all; /* inherit all handles from parent */ int inherit_all; /* inherit all handles from parent */
int use_handles; /* use stdio handles */ int use_handles; /* use stdio handles */
int create_flags; /* creation flags */ 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 hstdin; /* handle for stdin */
obj_handle_t hstdout; /* handle for stdout */ obj_handle_t hstdout; /* handle for stdout */
obj_handle_t hstderr; /* handle for stderr */ 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 */ /* 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; struct list *ptr;

View File

@ -123,7 +123,7 @@ static void wait4_thread( struct thread *thread, int signal )
do 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 */ if (errno == ECHILD) /* must have died */
{ {
@ -137,6 +137,12 @@ static void wait4_thread( struct thread *thread, int signal )
} while (res && res != 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 */ /* send a Unix signal to a specific thread */
int send_thread_signal( struct thread *thread, int sig ) 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 */ /* this may fail if the client is already being debugged */
if (!use_ptrace) return 0; 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 */ if (errno == ESRCH) thread->unix_pid = -1; /* thread got killed */
return 0; return 0;
@ -181,12 +187,43 @@ void detach_thread( struct thread *thread, int sig )
if (sig) send_thread_signal( thread, sig ); if (sig) send_thread_signal( thread, sig );
if (thread->unix_pid == -1) return; if (thread->unix_pid == -1) return;
if (debug_level) fprintf( stderr, "%04x: *detached*\n", thread->id ); 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; thread->attached = 0;
} }
else if (sig) send_thread_signal( thread, sig ); 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 */ /* suspend a thread to allow using ptrace on it */
/* you must do a resume_after_ptrace when finished with the thread */ /* you must do a resume_after_ptrace when finished with the thread */
int suspend_for_ptrace( struct thread *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; if (thread->unix_pid == -1) return;
assert( thread->attached ); assert( thread->attached );
ptrace( get_thread_single_step(thread) ? PTRACE_SINGLESTEP : PTRACE_CONT, 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 */ /* read an int from a thread address space */
int read_thread_int( struct thread *thread, const int *addr, int *data ) int read_thread_int( struct thread *thread, const int *addr, int *data )
{ {
errno = 0; 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) if ( *data == -1 && errno)
{ {
file_set_error(); 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; if (read_thread_int( thread, addr, &res ) == -1) return -1;
data = (data & mask) | (res & ~mask); 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(); file_set_error();
return res; return res;
} }

View File

@ -126,7 +126,10 @@ extern struct thread_snapshot *thread_snap( int *count );
/* ptrace functions */ /* ptrace functions */
extern void sigchld_handler(); extern void sigchld_handler();
extern int get_ptrace_pid( struct thread *thread );
extern void detach_thread( struct thread *thread, int sig ); 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 int suspend_for_ptrace( struct thread *thread );
extern void resume_after_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 ); extern int read_thread_int( struct thread *thread, const int *addr, int *data );