Attaching the debugger to a running process should work again
(reported by Eric Pouech). Misc cleanups.
This commit is contained in:
parent
cb816d2c3f
commit
baf0a064db
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue