Commit 17de8290 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Use the standard suspend mechanism to simulate a breakpoint

in an active process, instead of sending a SIGTRAP.
parent 6f38489f
......@@ -321,17 +321,10 @@ static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
to->ContextFlags |= flags;
}
/* retrieve the current instruction pointer of a thread */
void *get_thread_ip( struct thread *thread )
/* retrieve the current instruction pointer of a context */
void *get_context_ip( const CONTEXT *context )
{
CONTEXT context;
context.Fir = 0;
if (suspend_for_ptrace( thread ))
{
get_thread_context( thread, CONTEXT_CONTROL, &context );
resume_after_ptrace( thread );
}
return (void *)context.Fir;
return (void *)context->Fir;
}
/* retrieve the thread context */
......
......@@ -537,17 +537,10 @@ static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
to->ContextFlags |= flags & ~CONTEXT_DEBUG_REGISTERS;
}
/* retrieve the current instruction pointer of a thread */
void *get_thread_ip( struct thread *thread )
/* retrieve the current instruction pointer of a context */
void *get_context_ip( const CONTEXT *context )
{
CONTEXT context;
context.Eip = 0;
if (suspend_for_ptrace( thread ))
{
get_thread_context_ptrace( thread, CONTEXT_CONTROL, &context );
resume_after_ptrace( thread );
}
return (void *)context.Eip;
return (void *)context->Eip;
}
/* retrieve the thread context */
......
......@@ -260,17 +260,10 @@ static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
}
}
/* retrieve the current instruction pointer of a thread */
void *get_thread_ip( struct thread *thread )
/* retrieve the current instruction pointer of a context */
void *get_context_ip( const CONTEXT *context )
{
CONTEXT context;
context.Iar = 0;
if (suspend_for_ptrace( thread ))
{
get_thread_context_ptrace( thread, CONTEXT_CONTROL, &context );
resume_after_ptrace( thread );
}
return (void *)context.Iar;
return (void *)context->Iar;
}
/* retrieve the thread context */
......
......@@ -159,17 +159,10 @@ static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
context |= flags & (CONTEXT_CONTROL|CONTEXT_INTEGER);
}
/* retrieve the current instruction pointer of a thread */
void *get_thread_ip( struct thread *thread )
/* retrieve the current instruction pointer of a context */
void *get_context_ip( const CONTEXT *context )
{
CONTEXT context;
context.pc = 0;
if (suspend_for_ptrace( thread ))
{
get_thread_context_ptrace( thread, CONTEXT_CONTROL, &context );
resume_after_ptrace( thread );
}
return (void *)context.pc;
return (void *)context->pc;
}
/* retrieve the thread context */
......
......@@ -248,17 +248,10 @@ static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
to->ContextFlags |= flags & ~CONTEXT_DEBUG_REGISTERS;
}
/* retrieve the current instruction pointer of a thread */
void *get_thread_ip( struct thread *thread )
/* retrieve the current instruction pointer of a context */
void *get_context_ip( const CONTEXT *context )
{
CONTEXT context;
context.Rip = 0;
if (suspend_for_ptrace( thread ))
{
get_thread_context_ptrace( thread, CONTEXT_CONTROL, &context );
resume_after_ptrace( thread );
}
return (void *)context.Rip;
return (void *)context->Rip;
}
/* retrieve the thread context */
......
......@@ -616,19 +616,9 @@ DECL_HANDLER(debug_process)
}
else if (debugger_attach( process, current ))
{
struct debug_event_exception data;
struct thread *thread = get_process_first_thread( process );
generate_startup_debug_events( process, NULL );
break_process( process );
resume_process( process );
data.record.ExceptionCode = EXCEPTION_BREAKPOINT;
data.record.ExceptionFlags = EXCEPTION_CONTINUABLE;
data.record.ExceptionRecord = NULL;
data.record.ExceptionAddress = get_thread_ip( thread );
data.record.NumberParameters = 0;
data.first = 1;
generate_debug_event( thread, EXCEPTION_DEBUG_EVENT, &data );
}
release_object( process );
}
......@@ -704,22 +694,12 @@ DECL_HANDLER(debug_break)
struct process *process;
reply->self = 0;
if (!(process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION /*FIXME*/ )))
return;
if (process != current->process)
if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION /*FIXME*/ )))
{
/* find a suitable thread to signal */
struct thread *thread;
LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
{
if (send_thread_signal( thread, SIGTRAP )) goto done;
}
set_error( STATUS_ACCESS_DENIED );
if (process != current->process) break_process( process );
else reply->self = 1;
release_object( process );
}
else reply->self = 1;
done:
release_object( process );
}
/* set debugger kill on exit flag */
......
......@@ -683,6 +683,28 @@ void kill_debugged_processes( struct thread *debugger, int exit_code )
}
/* trigger a breakpoint event in a given process */
void break_process( struct process *process )
{
struct thread *thread;
suspend_process( process );
LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
{
if (thread->context) /* inside an exception event already */
{
break_thread( thread );
goto done;
}
}
if ((thread = get_process_first_thread( process ))) thread->debug_break = 1;
else set_error( STATUS_ACCESS_DENIED );
done:
resume_process( process );
}
/* detach a debugger from all its debuggees */
void detach_debugged_processes( struct thread *debugger )
{
......
......@@ -121,6 +121,7 @@ extern void kill_all_processes( struct process *skip, int exit_code );
extern void kill_process( struct process *process, struct thread *skip, int exit_code );
extern void kill_console_processes( struct thread *renderer, int exit_code );
extern void kill_debugged_processes( struct thread *debugger, int exit_code );
extern void break_process( struct process *process );
extern void detach_debugged_processes( struct thread *debugger );
extern struct process_snapshot *process_snap( int *count );
extern struct module_snapshot *module_snap( struct process *process, int *count );
......
......@@ -128,6 +128,7 @@ inline static void init_thread_structure( struct thread *thread )
thread->teb = NULL;
thread->debug_ctx = NULL;
thread->debug_event = NULL;
thread->debug_break = 0;
thread->queue = NULL;
thread->wait = NULL;
thread->error = 0;
......@@ -759,6 +760,23 @@ void kill_thread( struct thread *thread, int violent_death )
release_object( thread );
}
/* trigger a breakpoint event in a given thread */
void break_thread( struct thread *thread )
{
struct debug_event_exception data;
assert( thread->context );
data.record.ExceptionCode = EXCEPTION_BREAKPOINT;
data.record.ExceptionFlags = EXCEPTION_CONTINUABLE;
data.record.ExceptionRecord = NULL;
data.record.ExceptionAddress = get_context_ip( thread->context );
data.record.NumberParameters = 0;
data.first = 1;
generate_debug_event( thread, EXCEPTION_DEBUG_EVENT, &data );
thread->debug_break = 0;
}
/* take a snapshot of currently running threads */
struct thread_snapshot *thread_snap( int *count )
{
......@@ -1091,6 +1109,7 @@ DECL_HANDLER(set_thread_context)
{
memcpy( thread->suspend_context, get_req_data(), sizeof(CONTEXT) );
thread->context = thread->suspend_context;
if (thread->debug_break) break_thread( thread );
}
}
else if (thread != current && !thread->context)
......
......@@ -56,6 +56,7 @@ struct thread
struct list mutex_list; /* list of currently owned mutexes */
struct debug_ctx *debug_ctx; /* debugger context if this thread is a debugger */
struct debug_event *debug_event; /* debug event being sent to debugger */
int debug_break; /* debug breakpoint pending? */
struct msg_queue *queue; /* message queue */
struct thread_wait *wait; /* current wait condition if sleeping */
struct list system_apc; /* queue of system async procedure calls */
......@@ -108,6 +109,7 @@ extern int wake_thread( struct thread *thread );
extern int add_queue( struct object *obj, struct wait_queue_entry *entry );
extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );
extern void kill_thread( struct thread *thread, int violent_death );
extern void break_thread( struct thread *thread );
extern void wake_up( struct object *obj, int max );
extern int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
enum apc_type type, int system, void *arg1, void *arg2, void *arg3 );
......@@ -123,7 +125,7 @@ extern void sigchld_callback(void);
extern int get_ptrace_pid( struct thread *thread );
extern int suspend_for_ptrace( struct thread *thread );
extern void resume_after_ptrace( struct thread *thread );
extern void *get_thread_ip( struct thread *thread );
extern void *get_context_ip( const CONTEXT *context );
extern void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags );
extern void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags );
extern int send_thread_signal( struct thread *thread, int sig );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment