blob: fd9d8f6c9b24fbdf519a6e946cef47294b8e224e [file] [log] [blame]
Alexandre Julliarde712e071999-05-23 19:53:30 +00001/*
2 * Server-side debugger functions
3 *
4 * Copyright (C) 1999 Alexandre Julliard
5 */
6
7#include <assert.h>
Patrik Stridvall2c684081999-07-31 17:36:48 +00008#include <string.h>
9
Alexandre Julliarde712e071999-05-23 19:53:30 +000010#include "winbase.h"
11#include "winerror.h"
12
Alexandre Julliarde712e071999-05-23 19:53:30 +000013#include "handle.h"
14#include "process.h"
15#include "thread.h"
Alexandre Julliard5bc78081999-06-22 17:26:53 +000016#include "request.h"
Alexandre Julliarde712e071999-05-23 19:53:30 +000017
18struct debug_event
19{
20 struct debug_event *next; /* event queue */
21 struct debug_event *prev;
22 struct thread *thread; /* thread which sent this event */
23 int sent; /* already sent to the debugger? */
24 int code; /* event code */
25 union debug_event_data data; /* event data */
26};
27
28struct debug_ctx
29{
30 struct thread *owner; /* thread owning this debug context */
31 int waiting; /* is thread waiting for an event? */
32 struct timeout_user *timeout; /* timeout user for wait timeout */
33 struct debug_event *event_head; /* head of pending events queue */
34 struct debug_event *event_tail; /* tail of pending events queue */
35};
36
37/* size of the event data */
38static const int event_sizes[] =
39{
40 0,
41 sizeof(struct debug_event_exception), /* EXCEPTION_DEBUG_EVENT */
42 sizeof(struct debug_event_create_thread), /* CREATE_THREAD_DEBUG_EVENT */
43 sizeof(struct debug_event_create_process), /* CREATE_PROCESS_DEBUG_EVENT */
44 sizeof(struct debug_event_exit), /* EXIT_THREAD_DEBUG_EVENT */
45 sizeof(struct debug_event_exit), /* EXIT_PROCESS_DEBUG_EVENT */
46 sizeof(struct debug_event_load_dll), /* LOAD_DLL_DEBUG_EVENT */
47 sizeof(struct debug_event_unload_dll), /* UNLOAD_DLL_DEBUG_EVENT */
48 sizeof(struct debug_event_output_string), /* OUTPUT_DEBUG_STRING_EVENT */
49 sizeof(struct debug_event_rip_info) /* RIP_EVENT */
50};
51
52
53/* initialise the fields that do not need to be filled by the client */
54static int fill_debug_event( struct thread *debugger, struct thread *thread,
55 struct debug_event *event )
56{
57 int handle;
58
59 /* some events need special handling */
60 switch(event->code)
61 {
62 case CREATE_THREAD_DEBUG_EVENT:
63 if ((event->data.create_thread.handle = alloc_handle( debugger->process, thread,
Alexandre Julliard3b832221999-11-14 21:02:04 +000064 /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
65 THREAD_ALL_ACCESS, FALSE )) == -1)
Alexandre Julliarde712e071999-05-23 19:53:30 +000066 return 0;
67 break;
68 case CREATE_PROCESS_DEBUG_EVENT:
69 if ((handle = event->data.create_process.file) != -1)
70 {
71 if ((handle = duplicate_handle( thread->process, handle, debugger->process,
72 GENERIC_READ, FALSE, 0 )) == -1)
73 return 0;
74 event->data.create_process.file = handle;
75 }
76 if ((event->data.create_process.process = alloc_handle( debugger->process, thread->process,
Alexandre Julliard3b832221999-11-14 21:02:04 +000077 /* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
78 PROCESS_ALL_ACCESS, FALSE )) == -1)
Alexandre Julliarde712e071999-05-23 19:53:30 +000079 {
80 if (handle != -1) close_handle( debugger->process, handle );
81 return 0;
82 }
83 if ((event->data.create_process.thread = alloc_handle( debugger->process, thread,
Alexandre Julliard3b832221999-11-14 21:02:04 +000084 /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
85 THREAD_ALL_ACCESS, FALSE )) == -1)
Alexandre Julliarde712e071999-05-23 19:53:30 +000086 {
87 if (handle != -1) close_handle( debugger->process, handle );
88 close_handle( debugger->process, event->data.create_process.process );
89 return 0;
90 }
91 break;
92 case LOAD_DLL_DEBUG_EVENT:
93 if ((handle = event->data.load_dll.handle) != -1)
94 {
95 if ((handle = duplicate_handle( thread->process, handle, debugger->process,
96 GENERIC_READ, FALSE, 0 )) == -1)
97 return 0;
98 event->data.load_dll.handle = handle;
99 }
100 break;
101 }
102 return 1;
103}
104
105/* free a debug event structure */
Alexandre Julliard1d22c531999-11-04 02:31:10 +0000106static void free_event( struct thread *debugger, struct debug_event *event )
Alexandre Julliarde712e071999-05-23 19:53:30 +0000107{
Alexandre Julliardc61eb031999-11-07 23:59:08 +0000108 /* If the event has been sent already, the handles are now under the */
109 /* responsibility of the debugger process, so we don't touch them */
110 if (!event->sent)
Alexandre Julliarde712e071999-05-23 19:53:30 +0000111 {
Alexandre Julliardc61eb031999-11-07 23:59:08 +0000112 switch(event->code)
113 {
114 case CREATE_THREAD_DEBUG_EVENT:
115 close_handle( debugger->process, event->data.create_thread.handle );
116 break;
117 case CREATE_PROCESS_DEBUG_EVENT:
118 if (event->data.create_process.file != -1)
119 close_handle( debugger->process, event->data.create_process.file );
120 close_handle( debugger->process, event->data.create_process.thread );
121 close_handle( debugger->process, event->data.create_process.process );
122 break;
123 case LOAD_DLL_DEBUG_EVENT:
124 if (event->data.load_dll.handle != -1)
125 close_handle( debugger->process, event->data.load_dll.handle );
126 break;
127 }
Alexandre Julliarde712e071999-05-23 19:53:30 +0000128 }
129 event->thread->debug_event = NULL;
130 release_object( event->thread );
131 free( event );
132}
133
134/* unlink the first event from the queue */
135static void unlink_event( struct debug_ctx *debug_ctx, struct debug_event *event )
136{
137 if (event->prev) event->prev->next = event->next;
138 else debug_ctx->event_head = event->next;
139 if (event->next) event->next->prev = event->prev;
140 else debug_ctx->event_tail = event->prev;
141 event->next = event->prev = NULL;
142}
143
144/* link an event at the end of the queue */
145static void link_event( struct debug_ctx *debug_ctx, struct debug_event *event )
146{
147 event->next = NULL;
148 event->prev = debug_ctx->event_tail;
149 if (event->prev) event->prev->next = event;
150 else debug_ctx->event_head = event;
151 debug_ctx->event_tail = event;
152}
153
154/* send the first queue event as a reply */
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000155static void build_event_reply( struct debug_ctx *debug_ctx )
Alexandre Julliarde712e071999-05-23 19:53:30 +0000156{
Alexandre Julliarde712e071999-05-23 19:53:30 +0000157 struct debug_event *event = debug_ctx->event_head;
158 struct thread *thread = event->thread;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000159 struct wait_debug_event_request *req = get_req_ptr( debug_ctx->owner );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000160
161 assert( event );
162 assert( debug_ctx->waiting );
163
164 unlink_event( debug_ctx, event );
165 event->sent = 1;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000166 req->code = event->code;
167 req->pid = thread->process;
168 req->tid = thread;
Alexandre Julliarde712e071999-05-23 19:53:30 +0000169 debug_ctx->waiting = 0;
170 if (debug_ctx->timeout)
171 {
172 remove_timeout_user( debug_ctx->timeout );
173 debug_ctx->timeout = NULL;
174 }
175 debug_ctx->owner->error = 0;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000176 memcpy( req + 1, &event->data, event_sizes[event->code] );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000177}
178
179/* timeout callback while waiting for a debug event */
180static void wait_event_timeout( void *ctx )
181{
182 struct debug_ctx *debug_ctx = (struct debug_ctx *)ctx;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000183 struct wait_debug_event_request *req = get_req_ptr( debug_ctx->owner );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000184
185 assert( debug_ctx->waiting );
186
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000187 req->code = 0;
188 req->pid = 0;
189 req->tid = 0;
Alexandre Julliarde712e071999-05-23 19:53:30 +0000190 debug_ctx->waiting = 0;
191 debug_ctx->timeout = NULL;
192 debug_ctx->owner->error = WAIT_TIMEOUT;
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000193 send_reply( debug_ctx->owner );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000194}
195
196/* wait for a debug event (or send a reply at once if one is pending) */
197static int wait_for_debug_event( int timeout )
198{
199 struct debug_ctx *debug_ctx = current->debug_ctx;
200 struct timeval when;
201
202 if (!debug_ctx) /* current thread is not a debugger */
203 {
Alexandre Julliard3b832221999-11-14 21:02:04 +0000204 set_error( ERROR_INVALID_HANDLE );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000205 return 0;
206 }
207 assert( !debug_ctx->waiting );
208 if (debug_ctx->event_head) /* already have a pending event */
209 {
210 debug_ctx->waiting = 1;
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000211 build_event_reply( debug_ctx );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000212 return 1;
213 }
214 if (!timeout) /* no event and we don't want to wait */
215 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000216 set_error( WAIT_TIMEOUT );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000217 return 0;
218 }
219 if (timeout != -1) /* start the timeout */
220 {
Alexandre Julliard247b8ae1999-12-13 00:16:44 +0000221 gettimeofday( &when, 0 );
222 add_timeout( &when, timeout );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000223 if (!(debug_ctx->timeout = add_timeout_user( &when, wait_event_timeout, debug_ctx )))
224 return 0;
225 }
226 debug_ctx->waiting = 1;
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000227 current->state = SLEEPING;
Alexandre Julliarde712e071999-05-23 19:53:30 +0000228 return 1;
229}
230
231/* continue a debug event */
232static int continue_debug_event( struct process *process, struct thread *thread, int status )
233{
234 struct debug_event *event = thread->debug_event;
235
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000236 if (process->debugger != current || thread->process != process || !event || !event->sent)
Alexandre Julliarde712e071999-05-23 19:53:30 +0000237 {
238 /* not debugging this process, or no event pending */
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000239 set_error( ERROR_ACCESS_DENIED ); /* FIXME */
Alexandre Julliarde712e071999-05-23 19:53:30 +0000240 return 0;
241 }
242 if (thread->state != TERMINATED)
243 {
244 /* only send a reply if the thread is still there */
245 /* (we can get a continue on an exit thread/process event) */
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000246 struct send_debug_event_request *req = get_req_ptr( thread );
247 req->status = status;
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000248 /* copy the context into the reply */
249 if (event->code == EXCEPTION_DEBUG_EVENT)
250 memcpy( req + 1, &event->data, event_sizes[event->code] );
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000251 send_reply( thread );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000252 }
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000253
Alexandre Julliard1d22c531999-11-04 02:31:10 +0000254 free_event( current, event );
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000255
256 if (thread->exit_event)
257 {
258 /* we still have a queued exit event, promote it to normal event */
259 thread->debug_event = thread->exit_event;
260 thread->exit_event = NULL;
261 }
Alexandre Julliarde712e071999-05-23 19:53:30 +0000262 resume_process( process );
263 return 1;
264}
265
266/* queue a debug event for a debugger */
267static struct debug_event *queue_debug_event( struct thread *debugger, struct thread *thread,
268 int code, void *data )
269{
270 struct debug_ctx *debug_ctx = debugger->debug_ctx;
271 struct debug_event *event;
272
273 assert( debug_ctx );
274 /* cannot queue a debug event for myself */
275 assert( debugger->process != thread->process );
276
277 /* build the event */
278 if (!(event = mem_alloc( sizeof(*event) - sizeof(event->data) + event_sizes[code] )))
279 return NULL;
280 event->sent = 0;
281 event->code = code;
282 event->thread = (struct thread *)grab_object( thread );
283 memcpy( &event->data, data, event_sizes[code] );
284
285 if (!fill_debug_event( debugger, thread, event ))
286 {
287 release_object( event->thread );
288 free( event );
289 return NULL;
290 }
291
292 if (thread->debug_event)
293 {
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000294 /* exit events can happen while another one is still queued */
Alexandre Julliarde712e071999-05-23 19:53:30 +0000295 assert( code == EXIT_THREAD_DEBUG_EVENT || code == EXIT_PROCESS_DEBUG_EVENT );
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000296 thread->exit_event = event;
Alexandre Julliarde712e071999-05-23 19:53:30 +0000297 }
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000298 else thread->debug_event = event;
Alexandre Julliarde712e071999-05-23 19:53:30 +0000299
300 link_event( debug_ctx, event );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000301 suspend_process( thread->process );
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000302 if (debug_ctx->waiting)
303 {
304 build_event_reply( debug_ctx );
305 send_reply( debug_ctx->owner );
306 }
Alexandre Julliarde712e071999-05-23 19:53:30 +0000307 return event;
308}
309
310/* attach a process to a debugger thread */
311int debugger_attach( struct process *process, struct thread *debugger )
312{
313 struct debug_ctx *debug_ctx;
314 struct thread *thread;
315
316 if (process->debugger) /* already being debugged */
317 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000318 set_error( ERROR_ACCESS_DENIED );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000319 return 0;
320 }
321 /* make sure we don't create a debugging loop */
322 for (thread = debugger; thread; thread = thread->process->debugger)
323 if (thread->process == process)
324 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000325 set_error( ERROR_ACCESS_DENIED );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000326 return 0;
327 }
328
329 if (!debugger->debug_ctx) /* need to allocate a context */
330 {
Alexandre Julliarde712e071999-05-23 19:53:30 +0000331 if (!(debug_ctx = mem_alloc( sizeof(*debug_ctx) ))) return 0;
332 debug_ctx->owner = current;
333 debug_ctx->waiting = 0;
334 debug_ctx->timeout = NULL;
335 debug_ctx->event_head = NULL;
336 debug_ctx->event_tail = NULL;
337 debugger->debug_ctx = debug_ctx;
338 }
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000339 process->debugger = debugger;
Alexandre Julliarde712e071999-05-23 19:53:30 +0000340 return 1;
341}
342
Alexandre Julliarde712e071999-05-23 19:53:30 +0000343/* a thread is exiting */
344void debug_exit_thread( struct thread *thread, int exit_code )
345{
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000346 struct thread *debugger = thread->process->debugger;
Alexandre Julliarde712e071999-05-23 19:53:30 +0000347 struct debug_ctx *debug_ctx = thread->debug_ctx;
348
349 if (debugger) /* being debugged -> send an event to the debugger */
350 {
351 struct debug_event_exit event;
352 event.exit_code = exit_code;
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000353 if (thread->process->running_threads == 1)
354 /* this is the last thread, send an exit process event */
355 queue_debug_event( debugger, thread, EXIT_PROCESS_DEBUG_EVENT, &event );
356 else
357 queue_debug_event( debugger, thread, EXIT_THREAD_DEBUG_EVENT, &event );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000358 }
359
360 if (debug_ctx) /* this thread is a debugger */
361 {
362 struct debug_event *event;
363
364 /* kill all debugged processes */
Alexandre Julliard17cf8101999-11-24 01:22:14 +0000365 kill_debugged_processes( thread, exit_code );
366
Alexandre Julliarde712e071999-05-23 19:53:30 +0000367 /* free all pending events */
368 while ((event = debug_ctx->event_head) != NULL)
369 {
370 unlink_event( debug_ctx, event );
Alexandre Julliard1d22c531999-11-04 02:31:10 +0000371 free_event( thread, event );
Alexandre Julliarde712e071999-05-23 19:53:30 +0000372 }
373 /* remove the timeout */
374 if (debug_ctx->timeout) remove_timeout_user( debug_ctx->timeout );
375 thread->debug_ctx = NULL;
376 free( debug_ctx );
377 }
378}
379
380/* Wait for a debug event */
381DECL_HANDLER(wait_debug_event)
382{
Alexandre Julliarde712e071999-05-23 19:53:30 +0000383 if (!wait_for_debug_event( req->timeout ))
384 {
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000385 req->code = 0;
386 req->pid = NULL;
387 req->tid = NULL;
Alexandre Julliarde712e071999-05-23 19:53:30 +0000388 }
389}
390
391/* Continue a debug event */
392DECL_HANDLER(continue_debug_event)
393{
394 struct process *process = get_process_from_id( req->pid );
395 if (process)
396 {
397 struct thread *thread = get_thread_from_id( req->tid );
398 if (thread)
399 {
400 continue_debug_event( process, thread, req->status );
401 release_object( thread );
402 }
403 release_object( process );
404 }
Alexandre Julliarde712e071999-05-23 19:53:30 +0000405}
406
407/* Start debugging an existing process */
408DECL_HANDLER(debug_process)
409{
410 struct process *process = get_process_from_id( req->pid );
411 if (process)
412 {
413 debugger_attach( process, current );
414 /* FIXME: should notice the debugged process somehow */
415 release_object( process );
416 }
Alexandre Julliarde712e071999-05-23 19:53:30 +0000417}
418
419/* Send a debug event */
420DECL_HANDLER(send_debug_event)
421{
422 struct thread *debugger = current->process->debugger;
Alexandre Julliarde712e071999-05-23 19:53:30 +0000423
Alexandre Julliarde712e071999-05-23 19:53:30 +0000424 assert( !current->debug_event );
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000425 if ((req->code <= 0) || (req->code > RIP_EVENT))
Alexandre Julliarde712e071999-05-23 19:53:30 +0000426 {
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000427 fatal_protocol_error( current, "send_debug_event: bad code %d\n", req->code );
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000428 return;
Alexandre Julliarde712e071999-05-23 19:53:30 +0000429 }
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000430 req->status = 0;
431 if (debugger && queue_debug_event( debugger, current, req->code, req + 1 ))
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000432 {
433 /* wait for continue_debug_event */
434 current->state = SLEEPING;
435 }
Alexandre Julliarde712e071999-05-23 19:53:30 +0000436}