Bug fix: added temp structure to cope with debug traces during thread
[wine/hacks.git] / server / debugger.c
blob01ce211eb3b8458680aadee80df3634060534921
1 /*
2 * Server-side debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <string.h>
9 #include <stdio.h>
11 #include "winbase.h"
13 #include "handle.h"
14 #include "process.h"
15 #include "thread.h"
16 #include "request.h"
18 enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_CONTINUED };
20 /* debug event */
21 struct debug_event
23 struct object obj; /* object header */
24 struct debug_event *next; /* event queue */
25 struct debug_event *prev;
26 struct thread *sender; /* thread which sent this event */
27 struct thread *debugger; /* debugger thread receiving the event */
28 enum debug_event_state state; /* event state */
29 int status; /* continuation status */
30 debug_event_t data; /* event data */
33 /* debug context */
34 struct debug_ctx
36 struct object obj; /* object header */
37 struct debug_event *event_head; /* head of pending events queue */
38 struct debug_event *event_tail; /* tail of pending events queue */
39 struct debug_event *to_send; /* next event on the queue to send to debugger */
43 static void debug_event_dump( struct object *obj, int verbose );
44 static int debug_event_signaled( struct object *obj, struct thread *thread );
45 static void debug_event_destroy( struct object *obj );
47 static const struct object_ops debug_event_ops =
49 sizeof(struct debug_event), /* size */
50 debug_event_dump, /* dump */
51 add_queue, /* add_queue */
52 remove_queue, /* remove_queue */
53 debug_event_signaled, /* signaled */
54 no_satisfied, /* satisfied */
55 NULL, /* get_poll_events */
56 NULL, /* poll_event */
57 no_read_fd, /* get_read_fd */
58 no_write_fd, /* get_write_fd */
59 no_flush, /* flush */
60 no_get_file_info, /* get_file_info */
61 debug_event_destroy /* destroy */
64 static void debug_ctx_dump( struct object *obj, int verbose );
65 static int debug_ctx_signaled( struct object *obj, struct thread *thread );
66 static void debug_ctx_destroy( struct object *obj );
68 static const struct object_ops debug_ctx_ops =
70 sizeof(struct debug_ctx), /* size */
71 debug_ctx_dump, /* dump */
72 add_queue, /* add_queue */
73 remove_queue, /* remove_queue */
74 debug_ctx_signaled, /* signaled */
75 no_satisfied, /* satisfied */
76 NULL, /* get_poll_events */
77 NULL, /* poll_event */
78 no_read_fd, /* get_read_fd */
79 no_write_fd, /* get_write_fd */
80 no_flush, /* flush */
81 no_get_file_info, /* get_file_info */
82 debug_ctx_destroy /* destroy */
86 /* initialise the fields that do not need to be filled by the client */
87 static int fill_debug_event( struct thread *debugger, struct thread *thread,
88 struct debug_event *event )
90 int handle;
92 /* some events need special handling */
93 switch(event->data.code)
95 case CREATE_THREAD_DEBUG_EVENT:
96 if ((event->data.info.create_thread.handle = alloc_handle( debugger->process, thread,
97 /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
98 THREAD_ALL_ACCESS, FALSE )) == -1)
99 return 0;
100 break;
101 case CREATE_PROCESS_DEBUG_EVENT:
102 if ((handle = event->data.info.create_process.file) != -1)
104 if ((handle = duplicate_handle( thread->process, handle, debugger->process,
105 GENERIC_READ, FALSE, 0 )) == -1)
106 return 0;
107 event->data.info.create_process.file = handle;
109 if ((event->data.info.create_process.process = alloc_handle( debugger->process, thread->process,
110 /* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
111 PROCESS_ALL_ACCESS, FALSE )) == -1)
113 if (handle != -1) close_handle( debugger->process, handle );
114 return 0;
116 if ((event->data.info.create_process.thread = alloc_handle( debugger->process, thread,
117 /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
118 THREAD_ALL_ACCESS, FALSE )) == -1)
120 if (handle != -1) close_handle( debugger->process, handle );
121 close_handle( debugger->process, event->data.info.create_process.process );
122 return 0;
124 break;
125 case LOAD_DLL_DEBUG_EVENT:
126 if ((handle = event->data.info.load_dll.handle) != -1)
128 if ((handle = duplicate_handle( thread->process, handle, debugger->process,
129 GENERIC_READ, FALSE, 0 )) == -1)
130 return 0;
131 event->data.info.load_dll.handle = handle;
133 break;
135 return 1;
138 /* unlink the first event from the queue */
139 static void unlink_event( struct debug_ctx *debug_ctx, struct debug_event *event )
141 if (event->prev) event->prev->next = event->next;
142 else debug_ctx->event_head = event->next;
143 if (event->next) event->next->prev = event->prev;
144 else debug_ctx->event_tail = event->prev;
145 if (debug_ctx->to_send == event) debug_ctx->to_send = event->next;
146 event->next = event->prev = NULL;
147 release_object( event );
150 /* link an event at the end of the queue */
151 static void link_event( struct debug_ctx *debug_ctx, struct debug_event *event )
153 grab_object( event );
154 event->next = NULL;
155 event->prev = debug_ctx->event_tail;
156 debug_ctx->event_tail = event;
157 if (event->prev) event->prev->next = event;
158 else debug_ctx->event_head = event;
159 if (!debug_ctx->to_send)
161 debug_ctx->to_send = event;
162 wake_up( &debug_ctx->obj, 0 );
166 /* build a reply for the wait_debug_event request */
167 static void build_wait_debug_reply( struct thread *thread, struct object *obj, int signaled )
169 struct wait_debug_event_request *req = get_req_ptr( thread );
171 if (obj)
173 struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
174 struct debug_event *event = debug_ctx->to_send;
176 /* the object that woke us has to be our debug context */
177 assert( obj->ops == &debug_ctx_ops );
178 assert( event );
180 event->state = EVENT_SENT;
181 debug_ctx->to_send = event->next;
182 req->event.code = event->data.code;
183 req->pid = event->sender->process;
184 req->tid = event->sender;
185 memcpy( &req->event, &event->data, sizeof(req->event) );
187 else /* timeout or error */
189 req->event.code = 0;
190 req->pid = 0;
191 req->tid = 0;
192 thread->error = signaled;
196 /* build a reply for the send_event request */
197 static void build_send_event_reply( struct thread *thread, struct object *obj, int signaled )
199 struct send_debug_event_request *req = get_req_ptr( thread );
200 struct debug_event *event = (struct debug_event *)obj;
201 assert( obj->ops == &debug_event_ops );
203 req->status = event->status;
204 /* copy the context into the reply */
205 if (event->data.code == EXCEPTION_DEBUG_EVENT)
206 memcpy( &req->event.info.exception.context,
207 &event->data.info.exception.context,
208 sizeof(req->event.info.exception.context) );
211 static void debug_event_dump( struct object *obj, int verbose )
213 struct debug_event *debug_event = (struct debug_event *)obj;
214 assert( obj->ops == &debug_event_ops );
215 fprintf( stderr, "Debug event sender=%p code=%d state=%d\n",
216 debug_event->sender, debug_event->data.code, debug_event->state );
219 static int debug_event_signaled( struct object *obj, struct thread *thread )
221 struct debug_event *debug_event = (struct debug_event *)obj;
222 assert( obj->ops == &debug_event_ops );
223 return debug_event->state == EVENT_CONTINUED;
226 static void debug_event_destroy( struct object *obj )
228 struct debug_event *event = (struct debug_event *)obj;
229 assert( obj->ops == &debug_event_ops );
231 /* cannot still be in the queue */
232 assert( !event->next );
233 assert( !event->prev );
235 /* If the event has been sent already, the handles are now under the */
236 /* responsibility of the debugger process, so we don't touch them */
237 if (event->state == EVENT_QUEUED)
239 struct process *debugger = event->debugger->process;
240 switch(event->data.code)
242 case CREATE_THREAD_DEBUG_EVENT:
243 close_handle( debugger, event->data.info.create_thread.handle );
244 break;
245 case CREATE_PROCESS_DEBUG_EVENT:
246 if (event->data.info.create_process.file != -1)
247 close_handle( debugger, event->data.info.create_process.file );
248 close_handle( debugger, event->data.info.create_process.thread );
249 close_handle( debugger, event->data.info.create_process.process );
250 break;
251 case LOAD_DLL_DEBUG_EVENT:
252 if (event->data.info.load_dll.handle != -1)
253 close_handle( debugger, event->data.info.load_dll.handle );
254 break;
257 release_object( event->sender );
258 release_object( event->debugger );
261 static void debug_ctx_dump( struct object *obj, int verbose )
263 struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
264 assert( obj->ops == &debug_ctx_ops );
265 fprintf( stderr, "Debug context head=%p tail=%p to_send=%p\n",
266 debug_ctx->event_head, debug_ctx->event_tail, debug_ctx->to_send );
269 static int debug_ctx_signaled( struct object *obj, struct thread *thread )
271 struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
272 assert( obj->ops == &debug_ctx_ops );
273 return debug_ctx->to_send != NULL;
276 static void debug_ctx_destroy( struct object *obj )
278 struct debug_event *event;
279 struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
280 assert( obj->ops == &debug_ctx_ops );
282 /* free all pending events */
283 while ((event = debug_ctx->event_head) != NULL) unlink_event( debug_ctx, event );
286 /* wait for a debug event (or send a reply at once if one is pending) */
287 static int wait_for_debug_event( int timeout )
289 struct debug_ctx *debug_ctx = current->debug_ctx;
290 struct object *obj = &debug_ctx->obj;
291 int flags = 0;
293 if (!debug_ctx) /* current thread is not a debugger */
295 set_error( STATUS_INVALID_HANDLE );
296 return 0;
298 if (timeout != -1) flags = SELECT_TIMEOUT;
299 return sleep_on( 1, &obj, flags, timeout, build_wait_debug_reply );
302 /* continue a debug event */
303 static int continue_debug_event( struct process *process, struct thread *thread, int status )
305 struct debug_event *event;
306 struct debug_ctx *debug_ctx = current->debug_ctx;
308 if (!debug_ctx || process->debugger != current || thread->process != process) goto error;
310 /* find the event in the queue */
311 for (event = debug_ctx->event_head; event; event = event->next)
313 if (event == debug_ctx->to_send) goto error;
314 if (event->sender == thread) break;
315 event = event->next;
317 if (!event) goto error;
319 event->status = status;
320 event->state = EVENT_CONTINUED;
321 wake_up( &event->obj, 0 );
323 unlink_event( debug_ctx, event );
324 resume_process( process );
325 return 1;
326 error:
327 /* not debugging this process, or no such event */
328 set_error( STATUS_ACCESS_DENIED ); /* FIXME */
329 return 0;
332 /* queue a debug event for a debugger */
333 static struct debug_event *queue_debug_event( struct thread *debugger, struct thread *thread,
334 debug_event_t *data )
336 struct debug_ctx *debug_ctx = debugger->debug_ctx;
337 struct debug_event *event;
339 assert( debug_ctx );
340 /* cannot queue a debug event for myself */
341 assert( debugger->process != thread->process );
343 /* build the event */
344 if (!(event = alloc_object( &debug_event_ops, -1 ))) return NULL;
345 event->next = NULL;
346 event->prev = NULL;
347 event->state = EVENT_QUEUED;
348 event->sender = (struct thread *)grab_object( thread );
349 event->debugger = (struct thread *)grab_object( debugger );
350 memcpy( &event->data, data, sizeof(event->data) );
352 if (!fill_debug_event( debugger, thread, event ))
354 event->data.code = -1; /* make sure we don't attempt to close handles */
355 release_object( event );
356 return NULL;
359 link_event( debug_ctx, event );
360 suspend_process( thread->process );
361 return event;
364 /* return a pointer to the context in case the thread is inside an exception event */
365 CONTEXT *get_debug_context( struct thread *thread )
367 struct debug_event *event;
368 struct thread *debugger = thread->process->debugger;
370 if (!debugger) return NULL; /* not being debugged */
371 assert( debugger->debug_ctx );
373 /* find the exception event in the debugger's queue */
374 for (event = debugger->debug_ctx->event_head; event; event = event->next)
375 if (event->sender == thread && (event->data.code == EXCEPTION_DEBUG_EVENT))
376 return &event->data.info.exception.context;
377 return NULL;
380 /* attach a process to a debugger thread */
381 int debugger_attach( struct process *process, struct thread *debugger )
383 struct debug_ctx *debug_ctx;
384 struct thread *thread;
386 if (process->debugger) /* already being debugged */
388 set_error( STATUS_ACCESS_DENIED );
389 return 0;
391 /* make sure we don't create a debugging loop */
392 for (thread = debugger; thread; thread = thread->process->debugger)
393 if (thread->process == process)
395 set_error( STATUS_ACCESS_DENIED );
396 return 0;
399 if (!debugger->debug_ctx) /* need to allocate a context */
401 if (!(debug_ctx = alloc_object( &debug_ctx_ops, -1 ))) return 0;
402 debug_ctx->event_head = NULL;
403 debug_ctx->event_tail = NULL;
404 debug_ctx->to_send = NULL;
405 debugger->debug_ctx = debug_ctx;
407 process->debugger = debugger;
408 return 1;
411 /* a thread is exiting */
412 void debug_exit_thread( struct thread *thread, int exit_code )
414 struct thread *debugger = thread->process->debugger;
415 struct debug_ctx *debug_ctx = thread->debug_ctx;
417 if (debugger) /* being debugged -> send an event to the debugger */
419 struct debug_event *event;
420 debug_event_t exit;
421 exit.info.exit.exit_code = exit_code;
422 /* if this is the last thread, send an exit process event */
423 exit.code = ((thread->process->running_threads == 1) ?
424 EXIT_PROCESS_DEBUG_EVENT : EXIT_THREAD_DEBUG_EVENT);
425 event = queue_debug_event( debugger, thread, &exit );
426 if (event) release_object( event );
429 if (debug_ctx) /* this thread is a debugger */
431 /* kill all debugged processes */
432 kill_debugged_processes( thread, exit_code );
433 thread->debug_ctx = NULL;
434 release_object( debug_ctx );
438 /* Wait for a debug event */
439 DECL_HANDLER(wait_debug_event)
441 if (!wait_for_debug_event( req->timeout ))
443 req->event.code = 0;
444 req->pid = NULL;
445 req->tid = NULL;
449 /* Continue a debug event */
450 DECL_HANDLER(continue_debug_event)
452 struct process *process = get_process_from_id( req->pid );
453 if (process)
455 struct thread *thread = get_thread_from_id( req->tid );
456 if (thread)
458 continue_debug_event( process, thread, req->status );
459 release_object( thread );
461 release_object( process );
465 /* Start debugging an existing process */
466 DECL_HANDLER(debug_process)
468 struct process *process = get_process_from_id( req->pid );
469 if (process)
471 debugger_attach( process, current );
472 /* FIXME: should notify the debugged process somehow */
473 release_object( process );
477 /* Send a debug event */
478 DECL_HANDLER(send_debug_event)
480 struct thread *debugger = current->process->debugger;
481 struct debug_event *event;
483 if ((req->event.code <= 0) || (req->event.code > RIP_EVENT))
485 fatal_protocol_error( current, "send_debug_event: bad code %d\n", req->event.code );
486 return;
488 req->status = 0;
489 if (debugger && ((event = queue_debug_event( debugger, current, &req->event ))))
491 /* wait for continue_debug_event */
492 struct object *obj = &event->obj;
493 sleep_on( 1, &obj, 0, -1, build_send_event_reply );
494 release_object( event );