2 * COPYRIGHT: GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/base/kddll/gdb_input.c
5 * PURPOSE: Base functions for the kernel debugger.
10 /* LOCALS *********************************************************************/
11 static HANDLE gdb_run_thread
;
12 static HANDLE gdb_dbg_process
;
13 HANDLE gdb_dbg_thread
;
14 CONTEXT CurrentContext
;
16 /* PRIVATE FUNCTIONS **********************************************************/
19 hex_to_thread(char* buffer
)
25 hex
= hex_value(*buffer
++);
36 hex_to_address(char* buffer
)
42 hex
= hex_value(*buffer
++);
54 handle_gdb_set_thread(void)
59 if (strcmp(&gdb_input
[2], "-1") == 0)
60 gdb_run_thread
= (HANDLE
)-1;
62 gdb_run_thread
= hex_to_thread(&gdb_input
[2]);
63 send_gdb_packet("OK");
66 if (strncmp(&gdb_input
[2], "p-1", 3) == 0)
68 gdb_dbg_process
= (HANDLE
)-1;
69 gdb_dbg_thread
= (HANDLE
)-1;
73 char* ptr
= strstr(gdb_input
, ".") + 1;
74 gdb_dbg_process
= hex_to_thread(&gdb_input
[3]);
75 if (strncmp(ptr
, "-1", 2) == 0)
76 gdb_dbg_thread
= (HANDLE
)-1;
78 gdb_dbg_thread
= hex_to_thread(ptr
);
80 send_gdb_packet("OK");
83 KDDBGPRINT("KDGBD: Unknown 'H' command: %s\n", gdb_input
);
90 handle_gdb_thread_alive(void)
92 char* ptr
= strstr(gdb_input
, ".") + 1;
97 ClientId
.UniqueProcess
= hex_to_thread(&gdb_input
[2]);
98 ClientId
.UniqueThread
= hex_to_thread(ptr
);
100 Status
= PsLookupProcessThreadByCid(&ClientId
, NULL
, &Thread
);
102 if (!NT_SUCCESS(Status
))
104 /* Thread doesn't exist */
105 send_gdb_packet("E03");
110 ObDereferenceObject(Thread
);
111 send_gdb_packet("OK");
117 handle_gdb_query(void)
119 if (strncmp(gdb_input
, "qSupported:", 11) == 0)
121 send_gdb_packet("PacketSize=4096;multiprocess+;");
125 if (strncmp(gdb_input
, "qAttached", 9) == 0)
127 /* Say yes: the remote server didn't create the process, ReactOS did! */
128 send_gdb_packet("0");
132 if (strncmp(gdb_input
, "qRcmd,", 6) == 0)
134 send_gdb_packet("OK");
138 if (strcmp(gdb_input
, "qC") == 0)
141 sprintf(gdb_out
, "QC:p%p.%p;",
142 PsGetThreadProcessId((PETHREAD
)(ULONG_PTR
)CurrentStateChange
.Thread
),
143 PsGetThreadId((PETHREAD
)(ULONG_PTR
)CurrentStateChange
.Thread
));
144 send_gdb_packet(gdb_out
);
148 if (strncmp(gdb_input
, "qTStatus", 8) == 0)
150 /* We don't support tracepoints. */
151 send_gdb_packet("T0");
155 KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input
);
162 handle_gdb_registers(
163 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
164 _Out_ PSTRING MessageData
,
165 _Out_ PULONG MessageLength
)
169 KDDBGPRINT("Should get registers from other thread!\n");
172 State
->ApiNumber
= DbgKdGetContextApi
;
173 State
->ReturnStatus
= STATUS_SUCCESS
; /* ? */
174 State
->Processor
= CurrentStateChange
.Processor
;
175 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
177 MessageData
->Length
= 0;
179 return KdPacketReceived
;
186 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
187 _Out_ PSTRING MessageData
,
188 _Out_ PULONG MessageLength
)
190 State
->ApiNumber
= DbgKdReadVirtualMemoryApi
;
191 State
->ReturnStatus
= STATUS_SUCCESS
; /* ? */
192 State
->Processor
= CurrentStateChange
.Processor
;
193 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
195 MessageData
->Length
= 0;
198 State
->u
.ReadMemory
.TargetBaseAddress
= hex_to_address(&gdb_input
[1]);
199 State
->u
.ReadMemory
.TransferCount
= hex_to_address(strstr(&gdb_input
[1], ",") + 1);
200 return KdPacketReceived
;
205 GetCurrentContextSendHandler(
206 _In_ ULONG PacketType
,
207 _In_ PSTRING MessageHeader
,
208 _In_ PSTRING MessageData
211 DBGKD_MANIPULATE_STATE64
* State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
212 const CONTEXT
* Context
= (const CONTEXT
*)MessageData
->Buffer
;
214 if ((PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
215 || (State
->ApiNumber
!= DbgKdGetContextApi
)
216 || (MessageData
->Length
< sizeof(*Context
)))
218 /* Should we bugcheck ? */
223 RtlCopyMemory(&CurrentContext
, Context
, sizeof(*Context
));
229 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
230 _Out_ PSTRING MessageData
,
231 _Out_ PULONG MessageLength
,
232 _Inout_ PKD_CONTEXT KdContext
,
233 _In_opt_ KDP_MANIPULATESTATE_HANDLER ManipulateStateHandler
236 State
->ApiNumber
= DbgKdGetContextApi
;
237 State
->Processor
= CurrentStateChange
.Processor
;
238 State
->ReturnStatus
= STATUS_SUCCESS
;
239 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
240 MessageData
->Length
= 0;
242 /* Update the send <-> receive loop handler */
243 KdpSendPacketHandler
= GetCurrentContextSendHandler
;
244 KdpManipulateStateHandler
= ManipulateStateHandler
;
249 SetContextSendHandler(
250 _In_ ULONG PacketType
,
251 _In_ PSTRING MessageHeader
,
252 _In_ PSTRING MessageData
255 DBGKD_MANIPULATE_STATE64
* State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
257 /* We just confirm that all went well */
258 if ((PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
259 || (State
->ApiNumber
!= DbgKdSetContextApi
)
260 || (State
->ReturnStatus
!= STATUS_SUCCESS
))
262 /* Should we bugcheck ? */
270 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
271 _Out_ PSTRING MessageData
,
272 _Out_ PULONG MessageLength
,
273 _Inout_ PKD_CONTEXT KdContext
,
274 _In_opt_ KDP_MANIPULATESTATE_HANDLER ManipulateStateHandler
277 State
->ApiNumber
= DbgKdSetContextApi
;
278 State
->Processor
= CurrentStateChange
.Processor
;
279 State
->ReturnStatus
= STATUS_SUCCESS
;
280 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
281 MessageData
->Length
= sizeof(CurrentContext
);
283 if (MessageData
->MaximumLength
< sizeof(CurrentContext
))
288 RtlCopyMemory(MessageData
->Buffer
, &CurrentContext
, sizeof(CurrentContext
));
290 /* Update the send <-> receive loop handlers */
291 KdpSendPacketHandler
= SetContextSendHandler
;
292 KdpManipulateStateHandler
= ManipulateStateHandler
;
294 return KdPacketReceived
;
300 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
301 _Out_ PSTRING MessageData
,
302 _Out_ PULONG MessageLength
,
303 _Inout_ PKD_CONTEXT KdContext
307 State
->ApiNumber
= DbgKdContinueApi
;
308 State
->ReturnStatus
= STATUS_SUCCESS
; /* ? */
309 State
->Processor
= CurrentStateChange
.Processor
;
310 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
312 MessageData
->Length
= 0;
314 State
->u
.Continue
.ContinueStatus
= STATUS_SUCCESS
;
316 /* We definitely are at the end of the send <-> receive loop, if any */
317 KdpSendPacketHandler
= NULL
;
318 KdpManipulateStateHandler
= NULL
;
320 /* Tell GDB we are fine */
321 send_gdb_packet("OK");
322 return KdPacketReceived
;
327 UpdateProgramCounterSendContinue(
328 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
329 _Out_ PSTRING MessageData
,
330 _Out_ PULONG MessageLength
,
331 _Inout_ PKD_CONTEXT KdContext
)
333 ULONG_PTR ProgramCounter
;
335 /* So we must get past the breakpoint instruction */
336 ProgramCounter
= KdpGetContextPc(&CurrentContext
);
337 KdpSetContextPc(&CurrentContext
, ProgramCounter
+ KD_BREAKPOINT_SIZE
);
339 /* Set the context and continue */
340 SetContext(State
, MessageData
, MessageLength
, KdContext
, SendContinue
);
341 return KdPacketReceived
;
347 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
348 _Out_ PSTRING MessageData
,
349 _Out_ PULONG MessageLength
,
350 _Inout_ PKD_CONTEXT KdContext
)
352 if (strncmp(gdb_input
, "vCont", 5) == 0)
354 if (gdb_input
[5] == '?')
357 /* Report what we support */
358 send_gdb_packet("vCont;c;C;s;S");
359 Status
= gdb_receive_packet(KdContext
);
360 if (Status
!= KdPacketReceived
)
362 return gdb_interpret_input(State
, MessageData
, MessageLength
, KdContext
);
365 if (strcmp(gdb_input
, "vCont;c") == 0)
367 DBGKM_EXCEPTION64
* Exception
= NULL
;
369 if (CurrentStateChange
.NewState
== DbgKdExceptionStateChange
)
370 Exception
= &CurrentStateChange
.u
.Exception
;
372 /* See if we should update the program counter (unlike windbg, gdb doesn't do it for us) */
373 if (Exception
&& (Exception
->ExceptionRecord
.ExceptionCode
== STATUS_BREAKPOINT
)
374 && (Exception
->ExceptionRecord
.ExceptionInformation
[0] == 0))
376 /* So we get the context, update it and send it back */
377 GetCurrentContext(State
, MessageData
, MessageLength
, KdContext
, UpdateProgramCounterSendContinue
);
378 return KdPacketReceived
;
381 return SendContinue(State
, MessageData
, MessageLength
, KdContext
);
385 return KdPacketReceived
;
388 /* GLOBAL FUNCTIONS ***********************************************************/
391 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
392 _Out_ PSTRING MessageData
,
393 _Out_ PULONG MessageLength
,
394 _Inout_ PKD_CONTEXT KdContext
)
397 switch (gdb_input
[0])
400 /* Send the Status */
401 gdb_send_exception();
404 gdb_send_registers();
407 handle_gdb_set_thread();
410 return handle_gdb_read_mem(State
, MessageData
, MessageLength
);
415 handle_gdb_thread_alive();
418 return handle_gdb_v(State
, MessageData
, MessageLength
, KdContext
);
420 /* We don't know how to handle this request. Maybe this is something for KD */
421 State
->ReturnStatus
= STATUS_NOT_SUPPORTED
;
422 return KdPacketReceived
;
424 /* Get the answer from GDB */
425 Status
= gdb_receive_packet(KdContext
);
426 if (Status
!= KdPacketReceived
)
428 /* Try interpreting this new packet */
429 return gdb_interpret_input(State
, MessageData
, MessageLength
, KdContext
);