2 * Server-side debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
19 struct debug_event
*next
; /* event queue */
20 struct debug_event
*prev
;
21 struct thread
*thread
; /* thread which sent this event */
22 int sent
; /* already sent to the debugger? */
23 int code
; /* event code */
24 union debug_event_data data
; /* event data */
29 struct thread
*owner
; /* thread owning this debug context */
30 int waiting
; /* is thread waiting for an event? */
31 struct timeout_user
*timeout
; /* timeout user for wait timeout */
32 struct debug_event
*event_head
; /* head of pending events queue */
33 struct debug_event
*event_tail
; /* tail of pending events queue */
36 /* size of the event data */
37 static const int event_sizes
[] =
40 sizeof(struct debug_event_exception
), /* EXCEPTION_DEBUG_EVENT */
41 sizeof(struct debug_event_create_thread
), /* CREATE_THREAD_DEBUG_EVENT */
42 sizeof(struct debug_event_create_process
), /* CREATE_PROCESS_DEBUG_EVENT */
43 sizeof(struct debug_event_exit
), /* EXIT_THREAD_DEBUG_EVENT */
44 sizeof(struct debug_event_exit
), /* EXIT_PROCESS_DEBUG_EVENT */
45 sizeof(struct debug_event_load_dll
), /* LOAD_DLL_DEBUG_EVENT */
46 sizeof(struct debug_event_unload_dll
), /* UNLOAD_DLL_DEBUG_EVENT */
47 sizeof(struct debug_event_output_string
), /* OUTPUT_DEBUG_STRING_EVENT */
48 sizeof(struct debug_event_rip_info
) /* RIP_EVENT */
52 /* initialise the fields that do not need to be filled by the client */
53 static int fill_debug_event( struct thread
*debugger
, struct thread
*thread
,
54 struct debug_event
*event
)
58 /* some events need special handling */
61 case CREATE_THREAD_DEBUG_EVENT
:
62 if ((event
->data
.create_thread
.handle
= alloc_handle( debugger
->process
, thread
,
63 THREAD_GET_CONTEXT
| THREAD_SET_CONTEXT
| THREAD_SUSPEND_RESUME
, FALSE
)) == -1)
66 case CREATE_PROCESS_DEBUG_EVENT
:
67 if ((handle
= event
->data
.create_process
.file
) != -1)
69 if ((handle
= duplicate_handle( thread
->process
, handle
, debugger
->process
,
70 GENERIC_READ
, FALSE
, 0 )) == -1)
72 event
->data
.create_process
.file
= handle
;
74 if ((event
->data
.create_process
.process
= alloc_handle( debugger
->process
, thread
->process
,
75 PROCESS_VM_READ
| PROCESS_VM_WRITE
, FALSE
)) == -1)
77 if (handle
!= -1) close_handle( debugger
->process
, handle
);
80 if ((event
->data
.create_process
.thread
= alloc_handle( debugger
->process
, thread
,
81 THREAD_GET_CONTEXT
| THREAD_SET_CONTEXT
| THREAD_SUSPEND_RESUME
, FALSE
)) == -1)
83 if (handle
!= -1) close_handle( debugger
->process
, handle
);
84 close_handle( debugger
->process
, event
->data
.create_process
.process
);
88 case LOAD_DLL_DEBUG_EVENT
:
89 if ((handle
= event
->data
.load_dll
.handle
) != -1)
91 if ((handle
= duplicate_handle( thread
->process
, handle
, debugger
->process
,
92 GENERIC_READ
, FALSE
, 0 )) == -1)
94 event
->data
.load_dll
.handle
= handle
;
101 /* free a debug event structure */
102 static void free_event( struct debug_event
*event
)
106 case CREATE_THREAD_DEBUG_EVENT
:
107 close_handle( event
->thread
->process
, event
->data
.create_thread
.handle
);
109 case CREATE_PROCESS_DEBUG_EVENT
:
110 if (event
->data
.create_process
.file
!= -1)
111 close_handle( event
->thread
->process
, event
->data
.create_process
.file
);
112 close_handle( event
->thread
->process
, event
->data
.create_process
.thread
);
113 close_handle( event
->thread
->process
, event
->data
.create_process
.process
);
115 case LOAD_DLL_DEBUG_EVENT
:
116 if (event
->data
.load_dll
.handle
!= -1)
117 close_handle( event
->thread
->process
, event
->data
.load_dll
.handle
);
120 event
->thread
->debug_event
= NULL
;
121 release_object( event
->thread
);
125 /* unlink the first event from the queue */
126 static void unlink_event( struct debug_ctx
*debug_ctx
, struct debug_event
*event
)
128 if (event
->prev
) event
->prev
->next
= event
->next
;
129 else debug_ctx
->event_head
= event
->next
;
130 if (event
->next
) event
->next
->prev
= event
->prev
;
131 else debug_ctx
->event_tail
= event
->prev
;
132 event
->next
= event
->prev
= NULL
;
135 /* link an event at the end of the queue */
136 static void link_event( struct debug_ctx
*debug_ctx
, struct debug_event
*event
)
139 event
->prev
= debug_ctx
->event_tail
;
140 if (event
->prev
) event
->prev
->next
= event
;
141 else debug_ctx
->event_head
= event
;
142 debug_ctx
->event_tail
= event
;
145 /* send the first queue event as a reply */
146 static void send_event_reply( struct debug_ctx
*debug_ctx
)
148 struct wait_debug_event_reply reply
;
149 struct debug_event
*event
= debug_ctx
->event_head
;
150 struct thread
*thread
= event
->thread
;
153 assert( debug_ctx
->waiting
);
155 unlink_event( debug_ctx
, event
);
157 reply
.code
= event
->code
;
158 reply
.pid
= thread
->process
;
160 debug_ctx
->waiting
= 0;
161 if (debug_ctx
->timeout
)
163 remove_timeout_user( debug_ctx
->timeout
);
164 debug_ctx
->timeout
= NULL
;
166 debug_ctx
->owner
->error
= 0;
167 send_reply( debug_ctx
->owner
, -1, 2, &reply
, sizeof(reply
),
168 &event
->data
, event_sizes
[event
->code
] );
171 /* timeout callback while waiting for a debug event */
172 static void wait_event_timeout( void *ctx
)
174 struct debug_ctx
*debug_ctx
= (struct debug_ctx
*)ctx
;
175 struct wait_debug_event_reply reply
;
177 assert( debug_ctx
->waiting
);
182 debug_ctx
->waiting
= 0;
183 debug_ctx
->timeout
= NULL
;
184 debug_ctx
->owner
->error
= WAIT_TIMEOUT
;
185 send_reply( debug_ctx
->owner
, -1, 1, &reply
, sizeof(reply
) );
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
)
191 struct debug_ctx
*debug_ctx
= current
->debug_ctx
;
194 if (!debug_ctx
) /* current thread is not a debugger */
196 SET_ERROR( ERROR_ACCESS_DENIED
); /* FIXME */
199 assert( !debug_ctx
->waiting
);
200 if (debug_ctx
->event_head
) /* already have a pending event */
202 debug_ctx
->waiting
= 1;
203 send_event_reply( debug_ctx
);
206 if (!timeout
) /* no event and we don't want to wait */
208 SET_ERROR( WAIT_TIMEOUT
);
211 if (timeout
!= -1) /* start the timeout */
213 make_timeout( &when
, timeout
);
214 if (!(debug_ctx
->timeout
= add_timeout_user( &when
, wait_event_timeout
, debug_ctx
)))
217 debug_ctx
->waiting
= 1;
221 /* continue a debug event */
222 static int continue_debug_event( struct process
*process
, struct thread
*thread
, int status
)
224 struct debug_event
*event
= thread
->debug_event
;
226 if (process
->debugger
!= current
|| !event
|| !event
->sent
)
228 /* not debugging this process, or no event pending */
229 SET_ERROR( ERROR_ACCESS_DENIED
); /* FIXME */
232 if (thread
->state
!= TERMINATED
)
234 /* only send a reply if the thread is still there */
235 /* (we can get a continue on an exit thread/process event) */
236 struct send_debug_event_reply reply
;
237 reply
.status
= status
;
238 send_reply( thread
, -1, 1, &reply
, sizeof(reply
) );
241 resume_process( process
);
245 /* queue a debug event for a debugger */
246 static struct debug_event
*queue_debug_event( struct thread
*debugger
, struct thread
*thread
,
247 int code
, void *data
)
249 struct debug_ctx
*debug_ctx
= debugger
->debug_ctx
;
250 struct debug_event
*event
;
253 /* cannot queue a debug event for myself */
254 assert( debugger
->process
!= thread
->process
);
256 /* build the event */
257 if (!(event
= mem_alloc( sizeof(*event
) - sizeof(event
->data
) + event_sizes
[code
] )))
261 event
->thread
= (struct thread
*)grab_object( thread
);
262 memcpy( &event
->data
, data
, event_sizes
[code
] );
264 if (!fill_debug_event( debugger
, thread
, event
))
266 release_object( event
->thread
);
271 if (thread
->debug_event
)
273 /* only exit events can replace others */
274 assert( code
== EXIT_THREAD_DEBUG_EVENT
|| code
== EXIT_PROCESS_DEBUG_EVENT
);
275 if (!thread
->debug_event
->sent
) unlink_event( debug_ctx
, thread
->debug_event
);
276 free_event( thread
->debug_event
);
279 link_event( debug_ctx
, event
);
280 thread
->debug_event
= event
;
281 suspend_process( thread
->process
);
282 if (debug_ctx
->waiting
) send_event_reply( debug_ctx
);
286 /* attach a process to a debugger thread */
287 int debugger_attach( struct process
*process
, struct thread
*debugger
)
289 struct debug_ctx
*debug_ctx
;
290 struct thread
*thread
;
292 if (process
->debugger
) /* already being debugged */
294 SET_ERROR( ERROR_ACCESS_DENIED
);
297 /* make sure we don't create a debugging loop */
298 for (thread
= debugger
; thread
; thread
= thread
->process
->debugger
)
299 if (thread
->process
== process
)
301 SET_ERROR( ERROR_ACCESS_DENIED
);
305 if (!debugger
->debug_ctx
) /* need to allocate a context */
307 assert( !debugger
->debug_first
);
308 if (!(debug_ctx
= mem_alloc( sizeof(*debug_ctx
) ))) return 0;
309 debug_ctx
->owner
= current
;
310 debug_ctx
->waiting
= 0;
311 debug_ctx
->timeout
= NULL
;
312 debug_ctx
->event_head
= NULL
;
313 debug_ctx
->event_tail
= NULL
;
314 debugger
->debug_ctx
= debug_ctx
;
316 process
->debugger
= debugger
;
317 process
->debug_prev
= NULL
;
318 process
->debug_next
= debugger
->debug_first
;
319 debugger
->debug_first
= process
;
323 /* detach a process from its debugger thread */
324 static void debugger_detach( struct process
*process
)
326 struct thread
*debugger
= process
->debugger
;
330 if (process
->debug_next
) process
->debug_next
->debug_prev
= process
->debug_prev
;
331 if (process
->debug_prev
) process
->debug_prev
->debug_next
= process
->debug_next
;
332 else debugger
->debug_first
= process
;
333 process
->debugger
= NULL
;
336 /* a thread is exiting */
337 void debug_exit_thread( struct thread
*thread
, int exit_code
)
339 struct thread
*debugger
= current
->process
->debugger
;
340 struct debug_ctx
*debug_ctx
= thread
->debug_ctx
;
342 if (debugger
) /* being debugged -> send an event to the debugger */
344 struct debug_event_exit event
;
345 event
.exit_code
= exit_code
;
346 if (!thread
->proc_next
&& !thread
->proc_prev
)
348 assert( thread
->process
->thread_list
== thread
);
349 /* this is the last thread, send an exit process event and cleanup */
350 queue_debug_event( debugger
, current
, EXIT_PROCESS_DEBUG_EVENT
, &event
);
351 debugger_detach( thread
->process
);
353 else queue_debug_event( debugger
, current
, EXIT_THREAD_DEBUG_EVENT
, &event
);
356 if (debug_ctx
) /* this thread is a debugger */
358 struct debug_event
*event
;
360 /* kill all debugged processes */
361 while (thread
->debug_first
) kill_process( thread
->debug_first
, exit_code
);
362 /* free all pending events */
363 while ((event
= debug_ctx
->event_head
) != NULL
)
365 unlink_event( debug_ctx
, event
);
368 /* remove the timeout */
369 if (debug_ctx
->timeout
) remove_timeout_user( debug_ctx
->timeout
);
370 thread
->debug_ctx
= NULL
;
375 /* Wait for a debug event */
376 DECL_HANDLER(wait_debug_event
)
378 struct wait_debug_event_reply reply
;
380 if (!wait_for_debug_event( req
->timeout
))
385 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
389 /* Continue a debug event */
390 DECL_HANDLER(continue_debug_event
)
392 struct process
*process
= get_process_from_id( req
->pid
);
395 struct thread
*thread
= get_thread_from_id( req
->tid
);
398 continue_debug_event( process
, thread
, req
->status
);
399 release_object( thread
);
401 release_object( process
);
403 send_reply( current
, -1, 0 );
406 /* Start debugging an existing process */
407 DECL_HANDLER(debug_process
)
409 struct process
*process
= get_process_from_id( req
->pid
);
412 debugger_attach( process
, current
);
413 /* FIXME: should notice the debugged process somehow */
414 release_object( process
);
416 send_reply( current
, -1, 0 );
419 /* Send a debug event */
420 DECL_HANDLER(send_debug_event
)
422 struct thread
*debugger
= current
->process
->debugger
;
423 struct send_debug_event_reply reply
;
425 if ((req
->code
<= 0) || (req
->code
> RIP_EVENT
))
426 fatal_protocol_error( "send_debug_event: bad event code %d\n", req
->code
);
427 if (len
!= event_sizes
[req
->code
])
428 fatal_protocol_error( "send_debug_event: bad event length %d/%d\n",
429 len
, event_sizes
[req
->code
] );
430 assert( !current
->debug_event
);
434 if (queue_debug_event( debugger
, current
, req
->code
, data
))
435 return; /* don't reply now, wait for continue_debug_event */
437 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );