Added support for icons in property sheet tabs.
[wine] / server / debugger.c
1 /*
2  * Server-side debugger functions
3  *
4  * Copyright (C) 1999 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <string.h>
9
10 #include "winbase.h"
11 #include "winerror.h"
12
13 #include "handle.h"
14 #include "process.h"
15 #include "thread.h"
16 #include "request.h"
17
18 struct 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
28 struct 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 */
38 static 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 */
54 static 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,
64                   THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE )) == -1)
65             return 0;
66         break;
67     case CREATE_PROCESS_DEBUG_EVENT:
68         if ((handle = event->data.create_process.file) != -1)
69         {
70             if ((handle = duplicate_handle( thread->process, handle, debugger->process,
71                                             GENERIC_READ, FALSE, 0 )) == -1)
72                 return 0;
73             event->data.create_process.file = handle;
74         }
75         if ((event->data.create_process.process = alloc_handle( debugger->process, thread->process,
76                                               PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE )) == -1)
77         {
78             if (handle != -1) close_handle( debugger->process, handle );
79             return 0;
80         }
81         if ((event->data.create_process.thread = alloc_handle( debugger->process, thread,
82                   THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE )) == -1)
83         {
84             if (handle != -1) close_handle( debugger->process, handle );
85             close_handle( debugger->process, event->data.create_process.process );
86             return 0;
87         }
88         break;
89     case LOAD_DLL_DEBUG_EVENT:
90         if ((handle = event->data.load_dll.handle) != -1)
91         {
92             if ((handle = duplicate_handle( thread->process, handle, debugger->process,
93                                             GENERIC_READ, FALSE, 0 )) == -1)
94                 return 0;
95             event->data.load_dll.handle = handle;
96         }
97         break;
98     }
99     return 1;
100 }
101
102 /* free a debug event structure */
103 static void free_event( struct debug_event *event )
104 {
105     switch(event->code)
106     {
107     case CREATE_THREAD_DEBUG_EVENT:
108         close_handle( event->thread->process, event->data.create_thread.handle );
109         break;
110     case CREATE_PROCESS_DEBUG_EVENT:
111         if (event->data.create_process.file != -1)
112             close_handle( event->thread->process, event->data.create_process.file );
113         close_handle( event->thread->process, event->data.create_process.thread );
114         close_handle( event->thread->process, event->data.create_process.process );
115         break;
116     case LOAD_DLL_DEBUG_EVENT:
117         if (event->data.load_dll.handle != -1)
118             close_handle( event->thread->process, event->data.load_dll.handle );
119         break;
120     }
121     event->thread->debug_event = NULL;
122     release_object( event->thread );
123     free( event );
124 }
125
126 /* unlink the first event from the queue */
127 static void unlink_event( struct debug_ctx *debug_ctx, struct debug_event *event )
128 {
129     if (event->prev) event->prev->next = event->next;
130     else debug_ctx->event_head = event->next;
131     if (event->next) event->next->prev = event->prev;
132     else debug_ctx->event_tail = event->prev;
133     event->next = event->prev = NULL;
134 }
135
136 /* link an event at the end of the queue */
137 static void link_event( struct debug_ctx *debug_ctx, struct debug_event *event )
138 {
139     event->next = NULL;
140     event->prev = debug_ctx->event_tail;
141     if (event->prev) event->prev->next = event;
142     else debug_ctx->event_head = event;
143     debug_ctx->event_tail = event;
144 }
145
146 /* send the first queue event as a reply */
147 static void build_event_reply( struct debug_ctx *debug_ctx )
148 {
149     struct debug_event *event = debug_ctx->event_head;
150     struct thread *thread = event->thread;
151     struct wait_debug_event_request *req = get_req_ptr( debug_ctx->owner );
152
153     assert( event );
154     assert( debug_ctx->waiting );
155
156     unlink_event( debug_ctx, event );
157     event->sent = 1;
158     req->code = event->code;
159     req->pid  = thread->process;
160     req->tid  = thread;
161     debug_ctx->waiting = 0;
162     if (debug_ctx->timeout)
163     {
164         remove_timeout_user( debug_ctx->timeout );
165         debug_ctx->timeout = NULL;
166     }
167     debug_ctx->owner->error = 0;
168     memcpy( req + 1, &event->data, event_sizes[event->code] );
169 }
170
171 /* timeout callback while waiting for a debug event */
172 static void wait_event_timeout( void *ctx )
173 {
174     struct debug_ctx *debug_ctx = (struct debug_ctx *)ctx;
175     struct wait_debug_event_request *req = get_req_ptr( debug_ctx->owner );
176
177     assert( debug_ctx->waiting );
178
179     req->code = 0;
180     req->pid  = 0;
181     req->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 );
186 }
187
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 )
190 {
191     struct debug_ctx *debug_ctx = current->debug_ctx;
192     struct timeval when;
193
194     if (!debug_ctx)  /* current thread is not a debugger */
195     {
196         set_error( ERROR_ACCESS_DENIED ); /* FIXME */
197         return 0;
198     }
199     assert( !debug_ctx->waiting );
200     if (debug_ctx->event_head)  /* already have a pending event */
201     {
202         debug_ctx->waiting = 1;
203         build_event_reply( debug_ctx );
204         return 1;
205     }
206     if (!timeout)  /* no event and we don't want to wait */
207     {
208         set_error( WAIT_TIMEOUT );
209         return 0;
210     }
211     if (timeout != -1)  /* start the timeout */
212     {
213         make_timeout( &when, timeout );
214         if (!(debug_ctx->timeout = add_timeout_user( &when, wait_event_timeout, debug_ctx )))
215             return 0;
216     }
217     debug_ctx->waiting = 1;
218     current->state = SLEEPING;
219     return 1;
220 }
221
222 /* continue a debug event */
223 static int continue_debug_event( struct process *process, struct thread *thread, int status )
224 {
225     struct debug_event *event = thread->debug_event;
226
227     if (process->debugger != current || !event || !event->sent)
228     {
229         /* not debugging this process, or no event pending */
230         set_error( ERROR_ACCESS_DENIED );  /* FIXME */
231         return 0;
232     }
233     if (thread->state != TERMINATED)
234     {
235         /* only send a reply if the thread is still there */
236         /* (we can get a continue on an exit thread/process event) */
237         struct send_debug_event_request *req = get_req_ptr( thread );
238         req->status = status;
239         send_reply( thread );
240     }
241     free_event( event );
242     resume_process( process );
243     return 1;
244 }
245
246 /* queue a debug event for a debugger */
247 static struct debug_event *queue_debug_event( struct thread *debugger, struct thread *thread,
248                                               int code, void *data )
249 {
250     struct debug_ctx *debug_ctx = debugger->debug_ctx;
251     struct debug_event *event;
252
253     assert( debug_ctx );
254     /* cannot queue a debug event for myself */
255     assert( debugger->process != thread->process );
256
257     /* build the event */
258     if (!(event = mem_alloc( sizeof(*event) - sizeof(event->data) + event_sizes[code] )))
259         return NULL;
260     event->sent   = 0;
261     event->code   = code;
262     event->thread = (struct thread *)grab_object( thread );
263     memcpy( &event->data, data, event_sizes[code] );
264
265     if (!fill_debug_event( debugger, thread, event ))
266     {
267         release_object( event->thread );
268         free( event );
269         return NULL;
270     }
271
272     if (thread->debug_event)
273     {
274         /* only exit events can replace others */
275         assert( code == EXIT_THREAD_DEBUG_EVENT || code == EXIT_PROCESS_DEBUG_EVENT );
276         if (!thread->debug_event->sent) unlink_event( debug_ctx, thread->debug_event );
277         free_event( thread->debug_event );
278     }
279
280     link_event( debug_ctx, event );
281     thread->debug_event = event;
282     suspend_process( thread->process );
283     if (debug_ctx->waiting)
284     {
285         build_event_reply( debug_ctx );
286         send_reply( debug_ctx->owner );
287     }
288     return event;
289 }
290
291 /* attach a process to a debugger thread */
292 int debugger_attach( struct process *process, struct thread *debugger )
293 {
294     struct debug_ctx *debug_ctx;
295     struct thread *thread;
296
297     if (process->debugger)  /* already being debugged */
298     {
299         set_error( ERROR_ACCESS_DENIED );
300         return 0;
301     }
302     /* make sure we don't create a debugging loop */
303     for (thread = debugger; thread; thread = thread->process->debugger)
304         if (thread->process == process)
305         {
306             set_error( ERROR_ACCESS_DENIED );
307             return 0;
308         }
309
310     if (!debugger->debug_ctx)  /* need to allocate a context */
311     {
312         assert( !debugger->debug_first );
313         if (!(debug_ctx = mem_alloc( sizeof(*debug_ctx) ))) return 0;
314         debug_ctx->owner      = current;
315         debug_ctx->waiting    = 0;
316         debug_ctx->timeout    = NULL;
317         debug_ctx->event_head = NULL;
318         debug_ctx->event_tail = NULL;
319         debugger->debug_ctx = debug_ctx;
320     }
321     process->debugger   = debugger;
322     process->debug_prev = NULL;
323     process->debug_next = debugger->debug_first;
324     debugger->debug_first = process;
325     return 1;
326 }
327
328 /* detach a process from its debugger thread */
329 static void debugger_detach( struct process *process )
330 {
331     struct thread *debugger = process->debugger;
332
333     assert( debugger );
334
335     if (process->debug_next) process->debug_next->debug_prev = process->debug_prev;
336     if (process->debug_prev) process->debug_prev->debug_next = process->debug_next;
337     else debugger->debug_first = process;
338     process->debugger = NULL;
339 }
340
341 /* a thread is exiting */
342 void debug_exit_thread( struct thread *thread, int exit_code )
343 {
344     struct thread *debugger = current->process->debugger;
345     struct debug_ctx *debug_ctx = thread->debug_ctx;
346
347     if (debugger)  /* being debugged -> send an event to the debugger */
348     {
349         struct debug_event_exit event;
350         event.exit_code = exit_code;
351         if (!thread->proc_next && !thread->proc_prev)
352         {
353             assert( thread->process->thread_list == thread );
354             /* this is the last thread, send an exit process event and cleanup */
355             queue_debug_event( debugger, current, EXIT_PROCESS_DEBUG_EVENT, &event );
356             debugger_detach( thread->process );
357         }
358         else queue_debug_event( debugger, current, EXIT_THREAD_DEBUG_EVENT, &event );
359     }
360
361     if (debug_ctx)  /* this thread is a debugger */
362     {
363         struct debug_event *event;
364
365         /* kill all debugged processes */
366         while (thread->debug_first) kill_process( thread->debug_first, exit_code );
367         /* free all pending events */
368         while ((event = debug_ctx->event_head) != NULL)
369         {
370             unlink_event( debug_ctx, event );
371             free_event( event );
372         }
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 */
381 DECL_HANDLER(wait_debug_event)
382 {
383     if (!wait_for_debug_event( req->timeout ))
384     {
385         req->code = 0;
386         req->pid  = NULL;
387         req->tid  = NULL;
388     }
389 }
390
391 /* Continue a debug event */
392 DECL_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     }
405 }
406
407 /* Start debugging an existing process */
408 DECL_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     }
417 }
418
419 /* Send a debug event */
420 DECL_HANDLER(send_debug_event)
421 {
422     struct thread *debugger = current->process->debugger;
423
424     assert( !current->debug_event );
425     if ((req->code <= 0) || (req->code > RIP_EVENT))
426     {
427         fatal_protocol_error( current, "send_debug_event: bad code %d\n", req->code );
428         return;
429     }
430     req->status = 0;
431     if (debugger && queue_debug_event( debugger, current, req->code, req + 1 ))
432     {
433         /* wait for continue_debug_event */
434         current->state = SLEEPING;
435     }
436 }