Fixed crash due to invalid GDI_Obj.
[wine/wine-kai.git] / server / debugger.c
blob404206e8a23d7fa0156a6464e1a23dd68791df0e
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 "handle.h"
12 #include "process.h"
13 #include "thread.h"
14 #include "request.h"
16 struct debug_event
18 struct debug_event *next; /* event queue */
19 struct debug_event *prev;
20 struct thread *thread; /* thread which sent this event */
21 int sent; /* already sent to the debugger? */
22 int code; /* event code */
23 union debug_event_data data; /* event data */
26 struct debug_ctx
28 struct thread *owner; /* thread owning this debug context */
29 int waiting; /* is thread waiting for an event? */
30 struct timeout_user *timeout; /* timeout user for wait timeout */
31 struct debug_event *event_head; /* head of pending events queue */
32 struct debug_event *event_tail; /* tail of pending events queue */
35 /* size of the event data */
36 static const int event_sizes[] =
39 sizeof(struct debug_event_exception), /* EXCEPTION_DEBUG_EVENT */
40 sizeof(struct debug_event_create_thread), /* CREATE_THREAD_DEBUG_EVENT */
41 sizeof(struct debug_event_create_process), /* CREATE_PROCESS_DEBUG_EVENT */
42 sizeof(struct debug_event_exit), /* EXIT_THREAD_DEBUG_EVENT */
43 sizeof(struct debug_event_exit), /* EXIT_PROCESS_DEBUG_EVENT */
44 sizeof(struct debug_event_load_dll), /* LOAD_DLL_DEBUG_EVENT */
45 sizeof(struct debug_event_unload_dll), /* UNLOAD_DLL_DEBUG_EVENT */
46 sizeof(struct debug_event_output_string), /* OUTPUT_DEBUG_STRING_EVENT */
47 sizeof(struct debug_event_rip_info) /* RIP_EVENT */
51 /* initialise the fields that do not need to be filled by the client */
52 static int fill_debug_event( struct thread *debugger, struct thread *thread,
53 struct debug_event *event )
55 int handle;
57 /* some events need special handling */
58 switch(event->code)
60 case CREATE_THREAD_DEBUG_EVENT:
61 if ((event->data.create_thread.handle = alloc_handle( debugger->process, thread,
62 THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE )) == -1)
63 return 0;
64 break;
65 case CREATE_PROCESS_DEBUG_EVENT:
66 if ((handle = event->data.create_process.file) != -1)
68 if ((handle = duplicate_handle( thread->process, handle, debugger->process,
69 GENERIC_READ, FALSE, 0 )) == -1)
70 return 0;
71 event->data.create_process.file = handle;
73 if ((event->data.create_process.process = alloc_handle( debugger->process, thread->process,
74 PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE )) == -1)
76 if (handle != -1) close_handle( debugger->process, handle );
77 return 0;
79 if ((event->data.create_process.thread = alloc_handle( debugger->process, thread,
80 THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE )) == -1)
82 if (handle != -1) close_handle( debugger->process, handle );
83 close_handle( debugger->process, event->data.create_process.process );
84 return 0;
86 break;
87 case LOAD_DLL_DEBUG_EVENT:
88 if ((handle = event->data.load_dll.handle) != -1)
90 if ((handle = duplicate_handle( thread->process, handle, debugger->process,
91 GENERIC_READ, FALSE, 0 )) == -1)
92 return 0;
93 event->data.load_dll.handle = handle;
95 break;
97 return 1;
100 /* free a debug event structure */
101 static void free_event( struct debug_event *event )
103 switch(event->code)
105 case CREATE_THREAD_DEBUG_EVENT:
106 close_handle( event->thread->process, event->data.create_thread.handle );
107 break;
108 case CREATE_PROCESS_DEBUG_EVENT:
109 if (event->data.create_process.file != -1)
110 close_handle( event->thread->process, event->data.create_process.file );
111 close_handle( event->thread->process, event->data.create_process.thread );
112 close_handle( event->thread->process, event->data.create_process.process );
113 break;
114 case LOAD_DLL_DEBUG_EVENT:
115 if (event->data.load_dll.handle != -1)
116 close_handle( event->thread->process, event->data.load_dll.handle );
117 break;
119 event->thread->debug_event = NULL;
120 release_object( event->thread );
121 free( event );
124 /* unlink the first event from the queue */
125 static void unlink_event( struct debug_ctx *debug_ctx, struct debug_event *event )
127 if (event->prev) event->prev->next = event->next;
128 else debug_ctx->event_head = event->next;
129 if (event->next) event->next->prev = event->prev;
130 else debug_ctx->event_tail = event->prev;
131 event->next = event->prev = NULL;
134 /* link an event at the end of the queue */
135 static void link_event( struct debug_ctx *debug_ctx, struct debug_event *event )
137 event->next = NULL;
138 event->prev = debug_ctx->event_tail;
139 if (event->prev) event->prev->next = event;
140 else debug_ctx->event_head = event;
141 debug_ctx->event_tail = event;
144 /* send the first queue event as a reply */
145 static void build_event_reply( struct debug_ctx *debug_ctx )
147 struct debug_event *event = debug_ctx->event_head;
148 struct thread *thread = event->thread;
149 struct wait_debug_event_request *req = get_req_ptr( debug_ctx->owner );
151 assert( event );
152 assert( debug_ctx->waiting );
154 unlink_event( debug_ctx, event );
155 event->sent = 1;
156 req->code = event->code;
157 req->pid = thread->process;
158 req->tid = thread;
159 debug_ctx->waiting = 0;
160 if (debug_ctx->timeout)
162 remove_timeout_user( debug_ctx->timeout );
163 debug_ctx->timeout = NULL;
165 debug_ctx->owner->error = 0;
166 memcpy( req + 1, &event->data, event_sizes[event->code] );
169 /* timeout callback while waiting for a debug event */
170 static void wait_event_timeout( void *ctx )
172 struct debug_ctx *debug_ctx = (struct debug_ctx *)ctx;
173 struct wait_debug_event_request *req = get_req_ptr( debug_ctx->owner );
175 assert( debug_ctx->waiting );
177 req->code = 0;
178 req->pid = 0;
179 req->tid = 0;
180 debug_ctx->waiting = 0;
181 debug_ctx->timeout = NULL;
182 debug_ctx->owner->error = WAIT_TIMEOUT;
183 send_reply( debug_ctx->owner );
186 /* wait for a debug event (or send a reply at once if one is pending) */
187 static int wait_for_debug_event( int timeout )
189 struct debug_ctx *debug_ctx = current->debug_ctx;
190 struct timeval when;
192 if (!debug_ctx) /* current thread is not a debugger */
194 set_error( ERROR_ACCESS_DENIED ); /* FIXME */
195 return 0;
197 assert( !debug_ctx->waiting );
198 if (debug_ctx->event_head) /* already have a pending event */
200 debug_ctx->waiting = 1;
201 build_event_reply( debug_ctx );
202 return 1;
204 if (!timeout) /* no event and we don't want to wait */
206 set_error( WAIT_TIMEOUT );
207 return 0;
209 if (timeout != -1) /* start the timeout */
211 make_timeout( &when, timeout );
212 if (!(debug_ctx->timeout = add_timeout_user( &when, wait_event_timeout, debug_ctx )))
213 return 0;
215 debug_ctx->waiting = 1;
216 current->state = SLEEPING;
217 return 1;
220 /* continue a debug event */
221 static int continue_debug_event( struct process *process, struct thread *thread, int status )
223 struct debug_event *event = thread->debug_event;
225 if (process->debugger != current || !event || !event->sent)
227 /* not debugging this process, or no event pending */
228 set_error( ERROR_ACCESS_DENIED ); /* FIXME */
229 return 0;
231 if (thread->state != TERMINATED)
233 /* only send a reply if the thread is still there */
234 /* (we can get a continue on an exit thread/process event) */
235 struct send_debug_event_request *req = get_req_ptr( thread );
236 req->status = status;
237 send_reply( thread );
239 free_event( event );
240 resume_process( process );
241 return 1;
244 /* queue a debug event for a debugger */
245 static struct debug_event *queue_debug_event( struct thread *debugger, struct thread *thread,
246 int code, void *data )
248 struct debug_ctx *debug_ctx = debugger->debug_ctx;
249 struct debug_event *event;
251 assert( debug_ctx );
252 /* cannot queue a debug event for myself */
253 assert( debugger->process != thread->process );
255 /* build the event */
256 if (!(event = mem_alloc( sizeof(*event) - sizeof(event->data) + event_sizes[code] )))
257 return NULL;
258 event->sent = 0;
259 event->code = code;
260 event->thread = (struct thread *)grab_object( thread );
261 memcpy( &event->data, data, event_sizes[code] );
263 if (!fill_debug_event( debugger, thread, event ))
265 release_object( event->thread );
266 free( event );
267 return NULL;
270 if (thread->debug_event)
272 /* only exit events can replace others */
273 assert( code == EXIT_THREAD_DEBUG_EVENT || code == EXIT_PROCESS_DEBUG_EVENT );
274 if (!thread->debug_event->sent) unlink_event( debug_ctx, thread->debug_event );
275 free_event( thread->debug_event );
278 link_event( debug_ctx, event );
279 thread->debug_event = event;
280 suspend_process( thread->process );
281 if (debug_ctx->waiting)
283 build_event_reply( debug_ctx );
284 send_reply( debug_ctx->owner );
286 return event;
289 /* attach a process to a debugger thread */
290 int debugger_attach( struct process *process, struct thread *debugger )
292 struct debug_ctx *debug_ctx;
293 struct thread *thread;
295 if (process->debugger) /* already being debugged */
297 set_error( ERROR_ACCESS_DENIED );
298 return 0;
300 /* make sure we don't create a debugging loop */
301 for (thread = debugger; thread; thread = thread->process->debugger)
302 if (thread->process == process)
304 set_error( ERROR_ACCESS_DENIED );
305 return 0;
308 if (!debugger->debug_ctx) /* need to allocate a context */
310 assert( !debugger->debug_first );
311 if (!(debug_ctx = mem_alloc( sizeof(*debug_ctx) ))) return 0;
312 debug_ctx->owner = current;
313 debug_ctx->waiting = 0;
314 debug_ctx->timeout = NULL;
315 debug_ctx->event_head = NULL;
316 debug_ctx->event_tail = NULL;
317 debugger->debug_ctx = debug_ctx;
319 process->debugger = debugger;
320 process->debug_prev = NULL;
321 process->debug_next = debugger->debug_first;
322 debugger->debug_first = process;
323 return 1;
326 /* detach a process from its debugger thread */
327 static void debugger_detach( struct process *process )
329 struct thread *debugger = process->debugger;
331 assert( debugger );
333 if (process->debug_next) process->debug_next->debug_prev = process->debug_prev;
334 if (process->debug_prev) process->debug_prev->debug_next = process->debug_next;
335 else debugger->debug_first = process;
336 process->debugger = NULL;
339 /* a thread is exiting */
340 void debug_exit_thread( struct thread *thread, int exit_code )
342 struct thread *debugger = current->process->debugger;
343 struct debug_ctx *debug_ctx = thread->debug_ctx;
345 if (debugger) /* being debugged -> send an event to the debugger */
347 struct debug_event_exit event;
348 event.exit_code = exit_code;
349 if (!thread->proc_next && !thread->proc_prev)
351 assert( thread->process->thread_list == thread );
352 /* this is the last thread, send an exit process event and cleanup */
353 queue_debug_event( debugger, current, EXIT_PROCESS_DEBUG_EVENT, &event );
354 debugger_detach( thread->process );
356 else queue_debug_event( debugger, current, EXIT_THREAD_DEBUG_EVENT, &event );
359 if (debug_ctx) /* this thread is a debugger */
361 struct debug_event *event;
363 /* kill all debugged processes */
364 while (thread->debug_first) kill_process( thread->debug_first, exit_code );
365 /* free all pending events */
366 while ((event = debug_ctx->event_head) != NULL)
368 unlink_event( debug_ctx, event );
369 free_event( event );
371 /* remove the timeout */
372 if (debug_ctx->timeout) remove_timeout_user( debug_ctx->timeout );
373 thread->debug_ctx = NULL;
374 free( debug_ctx );
378 /* Wait for a debug event */
379 DECL_HANDLER(wait_debug_event)
381 if (!wait_for_debug_event( req->timeout ))
383 req->code = 0;
384 req->pid = NULL;
385 req->tid = NULL;
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 );
405 /* Start debugging an existing process */
406 DECL_HANDLER(debug_process)
408 struct process *process = get_process_from_id( req->pid );
409 if (process)
411 debugger_attach( process, current );
412 /* FIXME: should notice the debugged process somehow */
413 release_object( process );
417 /* Send a debug event */
418 DECL_HANDLER(send_debug_event)
420 struct thread *debugger = current->process->debugger;
422 assert( !current->debug_event );
423 if ((req->code <= 0) || (req->code > RIP_EVENT))
425 fatal_protocol_error( current, "send_debug_event: bad code %d\n", req->code );
426 return;
428 req->status = 0;
429 if (debugger && queue_debug_event( debugger, current, req->code, req + 1 ))
431 /* wait for continue_debug_event */
432 current->state = SLEEPING;