2 * Server-side debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
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 */
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 */
37 /* size of the event data */
38 static const int event_sizes
[] =
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 */
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
)
59 /* some events need special handling */
62 case CREATE_THREAD_DEBUG_EVENT
:
63 if ((event
->data
.create_thread
.handle
= alloc_handle( debugger
->process
, thread
,
64 /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
65 THREAD_ALL_ACCESS
, FALSE
)) == -1)
68 case CREATE_PROCESS_DEBUG_EVENT
:
69 if ((handle
= event
->data
.create_process
.file
) != -1)
71 if ((handle
= duplicate_handle( thread
->process
, handle
, debugger
->process
,
72 GENERIC_READ
, FALSE
, 0 )) == -1)
74 event
->data
.create_process
.file
= handle
;
76 if ((event
->data
.create_process
.process
= alloc_handle( debugger
->process
, thread
->process
,
77 /* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
78 PROCESS_ALL_ACCESS
, FALSE
)) == -1)
80 if (handle
!= -1) close_handle( debugger
->process
, handle
);
83 if ((event
->data
.create_process
.thread
= alloc_handle( debugger
->process
, thread
,
84 /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
85 THREAD_ALL_ACCESS
, FALSE
)) == -1)
87 if (handle
!= -1) close_handle( debugger
->process
, handle
);
88 close_handle( debugger
->process
, event
->data
.create_process
.process
);
92 case LOAD_DLL_DEBUG_EVENT
:
93 if ((handle
= event
->data
.load_dll
.handle
) != -1)
95 if ((handle
= duplicate_handle( thread
->process
, handle
, debugger
->process
,
96 GENERIC_READ
, FALSE
, 0 )) == -1)
98 event
->data
.load_dll
.handle
= handle
;
105 /* free a debug event structure */
106 static void free_event( struct thread
*debugger
, struct debug_event
*event
)
108 /* 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 */
114 case CREATE_THREAD_DEBUG_EVENT
:
115 close_handle( debugger
->process
, event
->data
.create_thread
.handle
);
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
);
123 case LOAD_DLL_DEBUG_EVENT
:
124 if (event
->data
.load_dll
.handle
!= -1)
125 close_handle( debugger
->process
, event
->data
.load_dll
.handle
);
129 event
->thread
->debug_event
= NULL
;
130 release_object( event
->thread
);
134 /* unlink the first event from the queue */
135 static void unlink_event( struct debug_ctx
*debug_ctx
, struct debug_event
*event
)
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
;
144 /* link an event at the end of the queue */
145 static void link_event( struct debug_ctx
*debug_ctx
, struct debug_event
*event
)
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
;
154 /* send the first queue event as a reply */
155 static void build_event_reply( struct debug_ctx
*debug_ctx
)
157 struct debug_event
*event
= debug_ctx
->event_head
;
158 struct thread
*thread
= event
->thread
;
159 struct wait_debug_event_request
*req
= get_req_ptr( debug_ctx
->owner
);
162 assert( debug_ctx
->waiting
);
164 unlink_event( debug_ctx
, event
);
166 req
->code
= event
->code
;
167 req
->pid
= thread
->process
;
169 debug_ctx
->waiting
= 0;
170 if (debug_ctx
->timeout
)
172 remove_timeout_user( debug_ctx
->timeout
);
173 debug_ctx
->timeout
= NULL
;
175 debug_ctx
->owner
->error
= 0;
176 memcpy( req
+ 1, &event
->data
, event_sizes
[event
->code
] );
179 /* timeout callback while waiting for a debug event */
180 static void wait_event_timeout( void *ctx
)
182 struct debug_ctx
*debug_ctx
= (struct debug_ctx
*)ctx
;
183 struct wait_debug_event_request
*req
= get_req_ptr( debug_ctx
->owner
);
185 assert( debug_ctx
->waiting
);
190 debug_ctx
->waiting
= 0;
191 debug_ctx
->timeout
= NULL
;
192 debug_ctx
->owner
->error
= WAIT_TIMEOUT
;
193 send_reply( debug_ctx
->owner
);
196 /* wait for a debug event (or send a reply at once if one is pending) */
197 static int wait_for_debug_event( int timeout
)
199 struct debug_ctx
*debug_ctx
= current
->debug_ctx
;
202 if (!debug_ctx
) /* current thread is not a debugger */
204 set_error( ERROR_INVALID_HANDLE
);
207 assert( !debug_ctx
->waiting
);
208 if (debug_ctx
->event_head
) /* already have a pending event */
210 debug_ctx
->waiting
= 1;
211 build_event_reply( debug_ctx
);
214 if (!timeout
) /* no event and we don't want to wait */
216 set_error( WAIT_TIMEOUT
);
219 if (timeout
!= -1) /* start the timeout */
221 make_timeout( &when
, timeout
);
222 if (!(debug_ctx
->timeout
= add_timeout_user( &when
, wait_event_timeout
, debug_ctx
)))
225 debug_ctx
->waiting
= 1;
226 current
->state
= SLEEPING
;
230 /* continue a debug event */
231 static int continue_debug_event( struct process
*process
, struct thread
*thread
, int status
)
233 struct debug_event
*event
= thread
->debug_event
;
235 if (process
->debugger
!= current
|| !event
|| !event
->sent
)
237 /* not debugging this process, or no event pending */
238 set_error( ERROR_ACCESS_DENIED
); /* FIXME */
241 if (thread
->state
!= TERMINATED
)
243 /* only send a reply if the thread is still there */
244 /* (we can get a continue on an exit thread/process event) */
245 struct send_debug_event_request
*req
= get_req_ptr( thread
);
246 req
->status
= status
;
247 send_reply( thread
);
249 free_event( current
, event
);
250 resume_process( process
);
254 /* queue a debug event for a debugger */
255 static struct debug_event
*queue_debug_event( struct thread
*debugger
, struct thread
*thread
,
256 int code
, void *data
)
258 struct debug_ctx
*debug_ctx
= debugger
->debug_ctx
;
259 struct debug_event
*event
;
262 /* cannot queue a debug event for myself */
263 assert( debugger
->process
!= thread
->process
);
265 /* build the event */
266 if (!(event
= mem_alloc( sizeof(*event
) - sizeof(event
->data
) + event_sizes
[code
] )))
270 event
->thread
= (struct thread
*)grab_object( thread
);
271 memcpy( &event
->data
, data
, event_sizes
[code
] );
273 if (!fill_debug_event( debugger
, thread
, event
))
275 release_object( event
->thread
);
280 if (thread
->debug_event
)
282 /* only exit events can replace others */
283 assert( code
== EXIT_THREAD_DEBUG_EVENT
|| code
== EXIT_PROCESS_DEBUG_EVENT
);
284 if (!thread
->debug_event
->sent
) unlink_event( debug_ctx
, thread
->debug_event
);
285 free_event( debugger
, thread
->debug_event
);
288 link_event( debug_ctx
, event
);
289 thread
->debug_event
= event
;
290 suspend_process( thread
->process
);
291 if (debug_ctx
->waiting
)
293 build_event_reply( debug_ctx
);
294 send_reply( debug_ctx
->owner
);
299 /* attach a process to a debugger thread */
300 int debugger_attach( struct process
*process
, struct thread
*debugger
)
302 struct debug_ctx
*debug_ctx
;
303 struct thread
*thread
;
305 if (process
->debugger
) /* already being debugged */
307 set_error( ERROR_ACCESS_DENIED
);
310 /* make sure we don't create a debugging loop */
311 for (thread
= debugger
; thread
; thread
= thread
->process
->debugger
)
312 if (thread
->process
== process
)
314 set_error( ERROR_ACCESS_DENIED
);
318 if (!debugger
->debug_ctx
) /* need to allocate a context */
320 assert( !debugger
->debug_first
);
321 if (!(debug_ctx
= mem_alloc( sizeof(*debug_ctx
) ))) return 0;
322 debug_ctx
->owner
= current
;
323 debug_ctx
->waiting
= 0;
324 debug_ctx
->timeout
= NULL
;
325 debug_ctx
->event_head
= NULL
;
326 debug_ctx
->event_tail
= NULL
;
327 debugger
->debug_ctx
= debug_ctx
;
329 process
->debugger
= debugger
;
330 process
->debug_prev
= NULL
;
331 process
->debug_next
= debugger
->debug_first
;
332 debugger
->debug_first
= process
;
336 /* detach a process from its debugger thread */
337 static void debugger_detach( struct process
*process
)
339 struct thread
*debugger
= process
->debugger
;
343 if (process
->debug_next
) process
->debug_next
->debug_prev
= process
->debug_prev
;
344 if (process
->debug_prev
) process
->debug_prev
->debug_next
= process
->debug_next
;
345 else debugger
->debug_first
= process
->debug_next
;
346 process
->debugger
= NULL
;
349 /* a thread is exiting */
350 void debug_exit_thread( struct thread
*thread
, int exit_code
)
352 struct thread
*debugger
= current
->process
->debugger
;
353 struct debug_ctx
*debug_ctx
= thread
->debug_ctx
;
355 if (debugger
) /* being debugged -> send an event to the debugger */
357 struct debug_event_exit event
;
358 event
.exit_code
= exit_code
;
359 if (!thread
->proc_next
&& !thread
->proc_prev
)
361 assert( thread
->process
->thread_list
== thread
);
362 /* this is the last thread, send an exit process event and cleanup */
363 queue_debug_event( debugger
, current
, EXIT_PROCESS_DEBUG_EVENT
, &event
);
364 debugger_detach( thread
->process
);
366 else queue_debug_event( debugger
, current
, EXIT_THREAD_DEBUG_EVENT
, &event
);
369 if (debug_ctx
) /* this thread is a debugger */
371 struct debug_event
*event
;
373 /* kill all debugged processes */
374 while (thread
->debug_first
) kill_process( thread
->debug_first
, exit_code
);
375 /* free all pending events */
376 while ((event
= debug_ctx
->event_head
) != NULL
)
378 unlink_event( debug_ctx
, event
);
379 free_event( thread
, event
);
381 /* remove the timeout */
382 if (debug_ctx
->timeout
) remove_timeout_user( debug_ctx
->timeout
);
383 thread
->debug_ctx
= NULL
;
388 /* Wait for a debug event */
389 DECL_HANDLER(wait_debug_event
)
391 if (!wait_for_debug_event( req
->timeout
))
399 /* Continue a debug event */
400 DECL_HANDLER(continue_debug_event
)
402 struct process
*process
= get_process_from_id( req
->pid
);
405 struct thread
*thread
= get_thread_from_id( req
->tid
);
408 continue_debug_event( process
, thread
, req
->status
);
409 release_object( thread
);
411 release_object( process
);
415 /* Start debugging an existing process */
416 DECL_HANDLER(debug_process
)
418 struct process
*process
= get_process_from_id( req
->pid
);
421 debugger_attach( process
, current
);
422 /* FIXME: should notice the debugged process somehow */
423 release_object( process
);
427 /* Send a debug event */
428 DECL_HANDLER(send_debug_event
)
430 struct thread
*debugger
= current
->process
->debugger
;
432 assert( !current
->debug_event
);
433 if ((req
->code
<= 0) || (req
->code
> RIP_EVENT
))
435 fatal_protocol_error( current
, "send_debug_event: bad code %d\n", req
->code
);
439 if (debugger
&& queue_debug_event( debugger
, current
, req
->code
, req
+ 1 ))
441 /* wait for continue_debug_event */
442 current
->state
= SLEEPING
;