Fixed a behavior of the focus when a parent window is disabled.
[wine/hacks.git] / server / debugger.c
blob3a85925d2fa59fbb965d8736cd66a4fd820f8264
1 /*
2 * Server-side debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include "winbase.h"
9 #include "winerror.h"
11 #include "server.h"
12 #include "handle.h"
13 #include "process.h"
14 #include "thread.h"
17 struct debug_event
19 struct debug_event *next; /* event queue */
20 struct debug_event *prev;
21 struct thread *thread; /* thread which sent this event */
22 int sent; /* already sent to the debugger? */
23 int code; /* event code */
24 union debug_event_data data; /* event data */
27 struct debug_ctx
29 struct thread *owner; /* thread owning this debug context */
30 int waiting; /* is thread waiting for an event? */
31 struct timeout_user *timeout; /* timeout user for wait timeout */
32 struct debug_event *event_head; /* head of pending events queue */
33 struct debug_event *event_tail; /* tail of pending events queue */
36 /* size of the event data */
37 static const int event_sizes[] =
40 sizeof(struct debug_event_exception), /* EXCEPTION_DEBUG_EVENT */
41 sizeof(struct debug_event_create_thread), /* CREATE_THREAD_DEBUG_EVENT */
42 sizeof(struct debug_event_create_process), /* CREATE_PROCESS_DEBUG_EVENT */
43 sizeof(struct debug_event_exit), /* EXIT_THREAD_DEBUG_EVENT */
44 sizeof(struct debug_event_exit), /* EXIT_PROCESS_DEBUG_EVENT */
45 sizeof(struct debug_event_load_dll), /* LOAD_DLL_DEBUG_EVENT */
46 sizeof(struct debug_event_unload_dll), /* UNLOAD_DLL_DEBUG_EVENT */
47 sizeof(struct debug_event_output_string), /* OUTPUT_DEBUG_STRING_EVENT */
48 sizeof(struct debug_event_rip_info) /* RIP_EVENT */
52 /* initialise the fields that do not need to be filled by the client */
53 static int fill_debug_event( struct thread *debugger, struct thread *thread,
54 struct debug_event *event )
56 int handle;
58 /* some events need special handling */
59 switch(event->code)
61 case CREATE_THREAD_DEBUG_EVENT:
62 if ((event->data.create_thread.handle = alloc_handle( debugger->process, thread,
63 THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE )) == -1)
64 return 0;
65 break;
66 case CREATE_PROCESS_DEBUG_EVENT:
67 if ((handle = event->data.create_process.file) != -1)
69 if ((handle = duplicate_handle( thread->process, handle, debugger->process,
70 GENERIC_READ, FALSE, 0 )) == -1)
71 return 0;
72 event->data.create_process.file = handle;
74 if ((event->data.create_process.process = alloc_handle( debugger->process, thread->process,
75 PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE )) == -1)
77 if (handle != -1) close_handle( debugger->process, handle );
78 return 0;
80 if ((event->data.create_process.thread = alloc_handle( debugger->process, thread,
81 THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE )) == -1)
83 if (handle != -1) close_handle( debugger->process, handle );
84 close_handle( debugger->process, event->data.create_process.process );
85 return 0;
87 break;
88 case LOAD_DLL_DEBUG_EVENT:
89 if ((handle = event->data.load_dll.handle) != -1)
91 if ((handle = duplicate_handle( thread->process, handle, debugger->process,
92 GENERIC_READ, FALSE, 0 )) == -1)
93 return 0;
94 event->data.load_dll.handle = handle;
96 break;
98 return 1;
101 /* free a debug event structure */
102 static void free_event( struct debug_event *event )
104 switch(event->code)
106 case CREATE_THREAD_DEBUG_EVENT:
107 close_handle( event->thread->process, event->data.create_thread.handle );
108 break;
109 case CREATE_PROCESS_DEBUG_EVENT:
110 if (event->data.create_process.file != -1)
111 close_handle( event->thread->process, event->data.create_process.file );
112 close_handle( event->thread->process, event->data.create_process.thread );
113 close_handle( event->thread->process, event->data.create_process.process );
114 break;
115 case LOAD_DLL_DEBUG_EVENT:
116 if (event->data.load_dll.handle != -1)
117 close_handle( event->thread->process, event->data.load_dll.handle );
118 break;
120 event->thread->debug_event = NULL;
121 release_object( event->thread );
122 free( event );
125 /* unlink the first event from the queue */
126 static void unlink_event( struct debug_ctx *debug_ctx, struct debug_event *event )
128 if (event->prev) event->prev->next = event->next;
129 else debug_ctx->event_head = event->next;
130 if (event->next) event->next->prev = event->prev;
131 else debug_ctx->event_tail = event->prev;
132 event->next = event->prev = NULL;
135 /* link an event at the end of the queue */
136 static void link_event( struct debug_ctx *debug_ctx, struct debug_event *event )
138 event->next = NULL;
139 event->prev = debug_ctx->event_tail;
140 if (event->prev) event->prev->next = event;
141 else debug_ctx->event_head = event;
142 debug_ctx->event_tail = event;
145 /* send the first queue event as a reply */
146 static void send_event_reply( struct debug_ctx *debug_ctx )
148 struct wait_debug_event_reply reply;
149 struct debug_event *event = debug_ctx->event_head;
150 struct thread *thread = event->thread;
152 assert( event );
153 assert( debug_ctx->waiting );
155 unlink_event( debug_ctx, event );
156 event->sent = 1;
157 reply.code = event->code;
158 reply.pid = thread->process;
159 reply.tid = thread;
160 debug_ctx->waiting = 0;
161 if (debug_ctx->timeout)
163 remove_timeout_user( debug_ctx->timeout );
164 debug_ctx->timeout = NULL;
166 debug_ctx->owner->error = 0;
167 send_reply( debug_ctx->owner, -1, 2, &reply, sizeof(reply),
168 &event->data, event_sizes[event->code] );
171 /* timeout callback while waiting for a debug event */
172 static void wait_event_timeout( void *ctx )
174 struct debug_ctx *debug_ctx = (struct debug_ctx *)ctx;
175 struct wait_debug_event_reply reply;
177 assert( debug_ctx->waiting );
179 reply.code = 0;
180 reply.pid = 0;
181 reply.tid = 0;
182 debug_ctx->waiting = 0;
183 debug_ctx->timeout = NULL;
184 debug_ctx->owner->error = WAIT_TIMEOUT;
185 send_reply( debug_ctx->owner, -1, 1, &reply, sizeof(reply) );
188 /* wait for a debug event (or send a reply at once if one is pending) */
189 static int wait_for_debug_event( int timeout )
191 struct debug_ctx *debug_ctx = current->debug_ctx;
192 struct timeval when;
194 if (!debug_ctx) /* current thread is not a debugger */
196 SET_ERROR( ERROR_ACCESS_DENIED ); /* FIXME */
197 return 0;
199 assert( !debug_ctx->waiting );
200 if (debug_ctx->event_head) /* already have a pending event */
202 debug_ctx->waiting = 1;
203 send_event_reply( debug_ctx );
204 return 1;
206 if (!timeout) /* no event and we don't want to wait */
208 SET_ERROR( WAIT_TIMEOUT );
209 return 0;
211 if (timeout != -1) /* start the timeout */
213 make_timeout( &when, timeout );
214 if (!(debug_ctx->timeout = add_timeout_user( &when, wait_event_timeout, debug_ctx )))
215 return 0;
217 debug_ctx->waiting = 1;
218 return 1;
221 /* continue a debug event */
222 static int continue_debug_event( struct process *process, struct thread *thread, int status )
224 struct debug_event *event = thread->debug_event;
226 if (process->debugger != current || !event || !event->sent)
228 /* not debugging this process, or no event pending */
229 SET_ERROR( ERROR_ACCESS_DENIED ); /* FIXME */
230 return 0;
232 if (thread->state != TERMINATED)
234 /* only send a reply if the thread is still there */
235 /* (we can get a continue on an exit thread/process event) */
236 struct send_debug_event_reply reply;
237 reply.status = status;
238 send_reply( thread, -1, 1, &reply, sizeof(reply) );
240 free_event( event );
241 resume_process( process );
242 return 1;
245 /* queue a debug event for a debugger */
246 static struct debug_event *queue_debug_event( struct thread *debugger, struct thread *thread,
247 int code, void *data )
249 struct debug_ctx *debug_ctx = debugger->debug_ctx;
250 struct debug_event *event;
252 assert( debug_ctx );
253 /* cannot queue a debug event for myself */
254 assert( debugger->process != thread->process );
256 /* build the event */
257 if (!(event = mem_alloc( sizeof(*event) - sizeof(event->data) + event_sizes[code] )))
258 return NULL;
259 event->sent = 0;
260 event->code = code;
261 event->thread = (struct thread *)grab_object( thread );
262 memcpy( &event->data, data, event_sizes[code] );
264 if (!fill_debug_event( debugger, thread, event ))
266 release_object( event->thread );
267 free( event );
268 return NULL;
271 if (thread->debug_event)
273 /* only exit events can replace others */
274 assert( code == EXIT_THREAD_DEBUG_EVENT || code == EXIT_PROCESS_DEBUG_EVENT );
275 if (!thread->debug_event->sent) unlink_event( debug_ctx, thread->debug_event );
276 free_event( thread->debug_event );
279 link_event( debug_ctx, event );
280 thread->debug_event = event;
281 suspend_process( thread->process );
282 if (debug_ctx->waiting) send_event_reply( debug_ctx );
283 return event;
286 /* attach a process to a debugger thread */
287 int debugger_attach( struct process *process, struct thread *debugger )
289 struct debug_ctx *debug_ctx;
290 struct thread *thread;
292 if (process->debugger) /* already being debugged */
294 SET_ERROR( ERROR_ACCESS_DENIED );
295 return 0;
297 /* make sure we don't create a debugging loop */
298 for (thread = debugger; thread; thread = thread->process->debugger)
299 if (thread->process == process)
301 SET_ERROR( ERROR_ACCESS_DENIED );
302 return 0;
305 if (!debugger->debug_ctx) /* need to allocate a context */
307 assert( !debugger->debug_first );
308 if (!(debug_ctx = mem_alloc( sizeof(*debug_ctx) ))) return 0;
309 debug_ctx->owner = current;
310 debug_ctx->waiting = 0;
311 debug_ctx->timeout = NULL;
312 debug_ctx->event_head = NULL;
313 debug_ctx->event_tail = NULL;
314 debugger->debug_ctx = debug_ctx;
316 process->debugger = debugger;
317 process->debug_prev = NULL;
318 process->debug_next = debugger->debug_first;
319 debugger->debug_first = process;
320 return 1;
323 /* detach a process from its debugger thread */
324 static void debugger_detach( struct process *process )
326 struct thread *debugger = process->debugger;
328 assert( debugger );
330 if (process->debug_next) process->debug_next->debug_prev = process->debug_prev;
331 if (process->debug_prev) process->debug_prev->debug_next = process->debug_next;
332 else debugger->debug_first = process;
333 process->debugger = NULL;
336 /* a thread is exiting */
337 void debug_exit_thread( struct thread *thread, int exit_code )
339 struct thread *debugger = current->process->debugger;
340 struct debug_ctx *debug_ctx = thread->debug_ctx;
342 if (debugger) /* being debugged -> send an event to the debugger */
344 struct debug_event_exit event;
345 event.exit_code = exit_code;
346 if (!thread->proc_next && !thread->proc_prev)
348 assert( thread->process->thread_list == thread );
349 /* this is the last thread, send an exit process event and cleanup */
350 queue_debug_event( debugger, current, EXIT_PROCESS_DEBUG_EVENT, &event );
351 debugger_detach( thread->process );
353 else queue_debug_event( debugger, current, EXIT_THREAD_DEBUG_EVENT, &event );
356 if (debug_ctx) /* this thread is a debugger */
358 struct debug_event *event;
360 /* kill all debugged processes */
361 while (thread->debug_first) kill_process( thread->debug_first, exit_code );
362 /* free all pending events */
363 while ((event = debug_ctx->event_head) != NULL)
365 unlink_event( debug_ctx, event );
366 free_event( event );
368 /* remove the timeout */
369 if (debug_ctx->timeout) remove_timeout_user( debug_ctx->timeout );
370 thread->debug_ctx = NULL;
371 free( debug_ctx );
375 /* Wait for a debug event */
376 DECL_HANDLER(wait_debug_event)
378 struct wait_debug_event_reply reply;
380 if (!wait_for_debug_event( req->timeout ))
382 reply.code = 0;
383 reply.pid = NULL;
384 reply.tid = NULL;
385 send_reply( current, -1, 1, &reply, sizeof(reply) );
389 /* Continue a debug event */
390 DECL_HANDLER(continue_debug_event)
392 struct process *process = get_process_from_id( req->pid );
393 if (process)
395 struct thread *thread = get_thread_from_id( req->tid );
396 if (thread)
398 continue_debug_event( process, thread, req->status );
399 release_object( thread );
401 release_object( process );
403 send_reply( current, -1, 0 );
406 /* Start debugging an existing process */
407 DECL_HANDLER(debug_process)
409 struct process *process = get_process_from_id( req->pid );
410 if (process)
412 debugger_attach( process, current );
413 /* FIXME: should notice the debugged process somehow */
414 release_object( process );
416 send_reply( current, -1, 0 );
419 /* Send a debug event */
420 DECL_HANDLER(send_debug_event)
422 struct thread *debugger = current->process->debugger;
423 struct send_debug_event_reply reply;
425 if ((req->code <= 0) || (req->code > RIP_EVENT))
426 fatal_protocol_error( "send_debug_event: bad event code %d\n", req->code );
427 if (len != event_sizes[req->code])
428 fatal_protocol_error( "send_debug_event: bad event length %d/%d\n",
429 len, event_sizes[req->code] );
430 assert( !current->debug_event );
431 reply.status = 0;
432 if (debugger)
434 if (queue_debug_event( debugger, current, req->code, data ))
435 return; /* don't reply now, wait for continue_debug_event */
437 send_reply( current, -1, 1, &reply, sizeof(reply) );