server: Use the standard suspend mechanism to simulate a breakpoint
in an active process, instead of sending a SIGTRAP.
This commit is contained in:
parent
6f38489f91
commit
17de829096
|
@ -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,23 +694,13 @@ 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;
|
||||
|
||||
done:
|
||||
release_object( process );
|
||||
}
|
||||
}
|
||||
|
||||
/* set debugger kill on exit flag */
|
||||
DECL_HANDLER(set_debugger_kill_on_exit)
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue