Built a complete translation table for RtlNtStatusToDosError.
[wine.git] / server / debugger.c
blob7cbf1836836af822ee7592860302723e5bd3dccd
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"
12 #include "winerror.h"
14 #include "handle.h"
15 #include "process.h"
16 #include "thread.h"
17 #include "request.h"
19 enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_CONTINUED };
21 /* debug event */
22 struct debug_event
24 struct object obj; /* object header */
25 struct debug_event *next; /* event queue */
26 struct debug_event *prev;
27 struct thread *sender; /* thread which sent this event */
28 struct thread *debugger; /* debugger thread receiving the event */
29 enum debug_event_state state; /* event state */
30 int status; /* continuation status */
31 debug_event_t data; /* event data */
34 /* debug context */
35 struct debug_ctx
37 struct object obj; /* object header */
38 struct debug_event *event_head; /* head of pending events queue */
39 struct debug_event *event_tail; /* tail of pending events queue */
40 struct debug_event *to_send; /* next event on the queue to send to debugger */
44 static void debug_event_dump( struct object *obj, int verbose );
45 static int debug_event_signaled( struct object *obj, struct thread *thread );
46 static void debug_event_destroy( struct object *obj );
48 static const struct object_ops debug_event_ops =
50 sizeof(struct debug_event), /* size */
51 debug_event_dump, /* dump */
52 add_queue, /* add_queue */
53 remove_queue, /* remove_queue */
54 debug_event_signaled, /* signaled */
55 no_satisfied, /* satisfied */
56 NULL, /* get_poll_events */
57 NULL, /* poll_event */
58 no_read_fd, /* get_read_fd */
59 no_write_fd, /* get_write_fd */
60 no_flush, /* flush */
61 no_get_file_info, /* get_file_info */
62 debug_event_destroy /* destroy */
65 static void debug_ctx_dump( struct object *obj, int verbose );
66 static int debug_ctx_signaled( struct object *obj, struct thread *thread );
67 static void debug_ctx_destroy( struct object *obj );
69 static const struct object_ops debug_ctx_ops =
71 sizeof(struct debug_ctx), /* size */
72 debug_ctx_dump, /* dump */
73 add_queue, /* add_queue */
74 remove_queue, /* remove_queue */
75 debug_ctx_signaled, /* signaled */
76 no_satisfied, /* satisfied */
77 NULL, /* get_poll_events */
78 NULL, /* poll_event */
79 no_read_fd, /* get_read_fd */
80 no_write_fd, /* get_write_fd */
81 no_flush, /* flush */
82 no_get_file_info, /* get_file_info */
83 debug_ctx_destroy /* destroy */
87 /* initialise the fields that do not need to be filled by the client */
88 static int fill_debug_event( struct thread *debugger, struct thread *thread,
89 struct debug_event *event )
91 int handle;
93 /* some events need special handling */
94 switch(event->data.code)
96 case CREATE_THREAD_DEBUG_EVENT:
97 if ((event->data.info.create_thread.handle = alloc_handle( debugger->process, thread,
98 /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
99 THREAD_ALL_ACCESS, FALSE )) == -1)
100 return 0;
101 break;
102 case CREATE_PROCESS_DEBUG_EVENT:
103 if ((handle = event->data.info.create_process.file) != -1)
105 if ((handle = duplicate_handle( thread->process, handle, debugger->process,
106 GENERIC_READ, FALSE, 0 )) == -1)
107 return 0;
108 event->data.info.create_process.file = handle;
110 if ((event->data.info.create_process.process = alloc_handle( debugger->process, thread->process,
111 /* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
112 PROCESS_ALL_ACCESS, FALSE )) == -1)
114 if (handle != -1) close_handle( debugger->process, handle );
115 return 0;
117 if ((event->data.info.create_process.thread = alloc_handle( debugger->process, thread,
118 /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
119 THREAD_ALL_ACCESS, FALSE )) == -1)
121 if (handle != -1) close_handle( debugger->process, handle );
122 close_handle( debugger->process, event->data.info.create_process.process );
123 return 0;
125 break;
126 case LOAD_DLL_DEBUG_EVENT:
127 if ((handle = event->data.info.load_dll.handle) != -1)
129 if ((handle = duplicate_handle( thread->process, handle, debugger->process,
130 GENERIC_READ, FALSE, 0 )) == -1)
131 return 0;
132 event->data.info.load_dll.handle = handle;
134 break;
136 return 1;
139 /* unlink the first event from the queue */
140 static void unlink_event( struct debug_ctx *debug_ctx, struct debug_event *event )
142 if (event->prev) event->prev->next = event->next;
143 else debug_ctx->event_head = event->next;
144 if (event->next) event->next->prev = event->prev;
145 else debug_ctx->event_tail = event->prev;
146 if (debug_ctx->to_send == event) debug_ctx->to_send = event->next;
147 event->next = event->prev = NULL;
148 release_object( event );
151 /* link an event at the end of the queue */
152 static void link_event( struct debug_ctx *debug_ctx, struct debug_event *event )
154 grab_object( event );
155 event->next = NULL;
156 event->prev = debug_ctx->event_tail;
157 debug_ctx->event_tail = event;
158 if (event->prev) event->prev->next = event;
159 else debug_ctx->event_head = event;
160 if (!debug_ctx->to_send)
162 debug_ctx->to_send = event;
163 wake_up( &debug_ctx->obj, 0 );
167 /* build a reply for the wait_debug_event request */
168 static void build_wait_debug_reply( struct thread *thread, struct object *obj, int signaled )
170 struct wait_debug_event_request *req = get_req_ptr( thread );
172 if (obj)
174 struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
175 struct debug_event *event = debug_ctx->to_send;
177 /* the object that woke us has to be our debug context */
178 assert( obj->ops == &debug_ctx_ops );
179 assert( event );
181 event->state = EVENT_SENT;
182 debug_ctx->to_send = event->next;
183 req->event.code = event->data.code;
184 req->pid = event->sender->process;
185 req->tid = event->sender;
186 memcpy( &req->event, &event->data, sizeof(req->event) );
188 else /* timeout or error */
190 req->event.code = 0;
191 req->pid = 0;
192 req->tid = 0;
193 thread->error = signaled;
197 /* build a reply for the send_event request */
198 static void build_send_event_reply( struct thread *thread, struct object *obj, int signaled )
200 struct send_debug_event_request *req = get_req_ptr( thread );
201 struct debug_event *event = (struct debug_event *)obj;
202 assert( obj->ops == &debug_event_ops );
204 req->status = event->status;
205 /* copy the context into the reply */
206 if (event->data.code == EXCEPTION_DEBUG_EVENT)
207 memcpy( &req->event.info.exception.context,
208 &event->data.info.exception.context,
209 sizeof(req->event.info.exception.context) );
212 static void debug_event_dump( struct object *obj, int verbose )
214 struct debug_event *debug_event = (struct debug_event *)obj;
215 assert( obj->ops == &debug_event_ops );
216 fprintf( stderr, "Debug event sender=%p code=%d state=%d\n",
217 debug_event->sender, debug_event->data.code, debug_event->state );
220 static int debug_event_signaled( struct object *obj, struct thread *thread )
222 struct debug_event *debug_event = (struct debug_event *)obj;
223 assert( obj->ops == &debug_event_ops );
224 return debug_event->state == EVENT_CONTINUED;
227 static void debug_event_destroy( struct object *obj )
229 struct debug_event *event = (struct debug_event *)obj;
230 assert( obj->ops == &debug_event_ops );
232 /* cannot still be in the queue */
233 assert( !event->next );
234 assert( !event->prev );
236 /* If the event has been sent already, the handles are now under the */
237 /* responsibility of the debugger process, so we don't touch them */
238 if (event->state == EVENT_QUEUED)
240 struct process *debugger = event->debugger->process;
241 switch(event->data.code)
243 case CREATE_THREAD_DEBUG_EVENT:
244 close_handle( debugger, event->data.info.create_thread.handle );
245 break;
246 case CREATE_PROCESS_DEBUG_EVENT:
247 if (event->data.info.create_process.file != -1)
248 close_handle( debugger, event->data.info.create_process.file );
249 close_handle( debugger, event->data.info.create_process.thread );
250 close_handle( debugger, event->data.info.create_process.process );
251 break;
252 case LOAD_DLL_DEBUG_EVENT:
253 if (event->data.info.load_dll.handle != -1)
254 close_handle( debugger, event->data.info.load_dll.handle );
255 break;
258 release_object( event->sender );
259 release_object( event->debugger );
262 static void debug_ctx_dump( struct object *obj, int verbose )
264 struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
265 assert( obj->ops == &debug_ctx_ops );
266 fprintf( stderr, "Debug context head=%p tail=%p to_send=%p\n",
267 debug_ctx->event_head, debug_ctx->event_tail, debug_ctx->to_send );
270 static int debug_ctx_signaled( struct object *obj, struct thread *thread )
272 struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
273 assert( obj->ops == &debug_ctx_ops );
274 return debug_ctx->to_send != NULL;
277 static void debug_ctx_destroy( struct object *obj )
279 struct debug_event *event;
280 struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
281 assert( obj->ops == &debug_ctx_ops );
283 /* free all pending events */
284 while ((event = debug_ctx->event_head) != NULL) unlink_event( debug_ctx, event );
287 /* wait for a debug event (or send a reply at once if one is pending) */
288 static int wait_for_debug_event( int timeout )
290 struct debug_ctx *debug_ctx = current->debug_ctx;
291 struct object *obj = &debug_ctx->obj;
292 int flags = 0;
294 if (!debug_ctx) /* current thread is not a debugger */
296 set_error( ERROR_INVALID_HANDLE );
297 return 0;
299 if (timeout != -1) flags = SELECT_TIMEOUT;
300 return sleep_on( 1, &obj, flags, timeout, build_wait_debug_reply );
303 /* continue a debug event */
304 static int continue_debug_event( struct process *process, struct thread *thread, int status )
306 struct debug_event *event;
307 struct debug_ctx *debug_ctx = current->debug_ctx;
309 if (!debug_ctx || process->debugger != current || thread->process != process) goto error;
311 /* find the event in the queue */
312 for (event = debug_ctx->event_head; event; event = event->next)
314 if (event == debug_ctx->to_send) goto error;
315 if (event->sender == thread) break;
316 event = event->next;
318 if (!event) goto error;
320 event->status = status;
321 event->state = EVENT_CONTINUED;
322 wake_up( &event->obj, 0 );
324 unlink_event( debug_ctx, event );
325 resume_process( process );
326 return 1;
327 error:
328 /* not debugging this process, or no such event */
329 set_error( ERROR_ACCESS_DENIED ); /* FIXME */
330 return 0;
333 /* queue a debug event for a debugger */
334 static struct debug_event *queue_debug_event( struct thread *debugger, struct thread *thread,
335 debug_event_t *data )
337 struct debug_ctx *debug_ctx = debugger->debug_ctx;
338 struct debug_event *event;
340 assert( debug_ctx );
341 /* cannot queue a debug event for myself */
342 assert( debugger->process != thread->process );
344 /* build the event */
345 if (!(event = alloc_object( &debug_event_ops, -1 ))) return NULL;
346 event->next = NULL;
347 event->prev = NULL;
348 event->state = EVENT_QUEUED;
349 event->sender = (struct thread *)grab_object( thread );
350 event->debugger = (struct thread *)grab_object( debugger );
351 memcpy( &event->data, data, sizeof(event->data) );
353 if (!fill_debug_event( debugger, thread, event ))
355 event->data.code = -1; /* make sure we don't attempt to close handles */
356 release_object( event );
357 return NULL;
360 link_event( debug_ctx, event );
361 suspend_process( thread->process );
362 return event;
365 /* return a pointer to the context in case the thread is inside an exception event */
366 CONTEXT *get_debug_context( struct thread *thread )
368 struct debug_event *event;
369 struct thread *debugger = thread->process->debugger;
371 if (!debugger) return NULL; /* not being debugged */
372 assert( debugger->debug_ctx );
374 /* find the exception event in the debugger's queue */
375 for (event = debugger->debug_ctx->event_head; event; event = event->next)
376 if (event->sender == thread && (event->data.code == EXCEPTION_DEBUG_EVENT))
377 return &event->data.info.exception.context;
378 return NULL;
381 /* attach a process to a debugger thread */
382 int debugger_attach( struct process *process, struct thread *debugger )
384 struct debug_ctx *debug_ctx;
385 struct thread *thread;
387 if (process->debugger) /* already being debugged */
389 set_error( ERROR_ACCESS_DENIED );
390 return 0;
392 /* make sure we don't create a debugging loop */
393 for (thread = debugger; thread; thread = thread->process->debugger)
394 if (thread->process == process)
396 set_error( ERROR_ACCESS_DENIED );
397 return 0;
400 if (!debugger->debug_ctx) /* need to allocate a context */
402 if (!(debug_ctx = alloc_object( &debug_ctx_ops, -1 ))) return 0;
403 debug_ctx->event_head = NULL;
404 debug_ctx->event_tail = NULL;
405 debug_ctx->to_send = NULL;
406 debugger->debug_ctx = debug_ctx;
408 process->debugger = debugger;
409 return 1;
412 /* a thread is exiting */
413 void debug_exit_thread( struct thread *thread, int exit_code )
415 struct thread *debugger = thread->process->debugger;
416 struct debug_ctx *debug_ctx = thread->debug_ctx;
418 if (debugger) /* being debugged -> send an event to the debugger */
420 struct debug_event *event;
421 debug_event_t exit;
422 exit.info.exit.exit_code = exit_code;
423 /* if this is the last thread, send an exit process event */
424 exit.code = ((thread->process->running_threads == 1) ?
425 EXIT_PROCESS_DEBUG_EVENT : EXIT_THREAD_DEBUG_EVENT);
426 event = queue_debug_event( debugger, thread, &exit );
427 if (event) release_object( event );
430 if (debug_ctx) /* this thread is a debugger */
432 /* kill all debugged processes */
433 kill_debugged_processes( thread, exit_code );
434 thread->debug_ctx = NULL;
435 release_object( debug_ctx );
439 /* Wait for a debug event */
440 DECL_HANDLER(wait_debug_event)
442 if (!wait_for_debug_event( req->timeout ))
444 req->event.code = 0;
445 req->pid = NULL;
446 req->tid = NULL;
450 /* Continue a debug event */
451 DECL_HANDLER(continue_debug_event)
453 struct process *process = get_process_from_id( req->pid );
454 if (process)
456 struct thread *thread = get_thread_from_id( req->tid );
457 if (thread)
459 continue_debug_event( process, thread, req->status );
460 release_object( thread );
462 release_object( process );
466 /* Start debugging an existing process */
467 DECL_HANDLER(debug_process)
469 struct process *process = get_process_from_id( req->pid );
470 if (process)
472 debugger_attach( process, current );
473 /* FIXME: should notify the debugged process somehow */
474 release_object( process );
478 /* Send a debug event */
479 DECL_HANDLER(send_debug_event)
481 struct thread *debugger = current->process->debugger;
482 struct debug_event *event;
484 if ((req->event.code <= 0) || (req->event.code > RIP_EVENT))
486 fatal_protocol_error( current, "send_debug_event: bad code %d\n", req->event.code );
487 return;
489 req->status = 0;
490 if (debugger && ((event = queue_debug_event( debugger, current, &req->event ))))
492 /* wait for continue_debug_event */
493 struct object *obj = &event->obj;
494 sleep_on( 1, &obj, 0, -1, build_send_event_reply );
495 release_object( event );