2 * COPYRIGHT: GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/base/kddll/kdpacket.c
5 * PURPOSE: Base functions for the kernel debugger.
10 /* LOCALS *********************************************************************/
14 _In_ ULONG PacketType
,
15 _In_ PSTRING MessageHeader
,
16 _In_ PSTRING MessageData
);
18 /* GLOBALS ********************************************************************/
19 DBGKD_GET_VERSION64 KdVersion
;
20 KDDEBUGGER_DATA64
* KdDebuggerDataBlock
;
21 BOOLEAN InException
= FALSE
;
22 /* Callbacks used to communicate with KD aside from GDB */
23 KDP_SEND_HANDLER KdpSendPacketHandler
= FirstSendHandler
;
24 KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler
= NULL
;
25 /* Data describing the current exception */
26 DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange
;
27 CONTEXT CurrentContext
;
29 /* PRIVATE FUNCTIONS **********************************************************/
33 GetContextSendHandler(
34 _In_ ULONG PacketType
,
35 _In_ PSTRING MessageHeader
,
36 _In_ PSTRING MessageData
39 DBGKD_MANIPULATE_STATE64
* State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
40 const CONTEXT
* Context
= (const CONTEXT
*)MessageData
->Buffer
;
42 if ((PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
43 || (State
->ApiNumber
!= DbgKdGetContextApi
)
44 || (MessageData
->Length
< sizeof(*Context
)))
46 /* Should we bugcheck ? */
47 KDDBGPRINT("ERROR: Received wrong packet from KD.\n");
52 RtlCopyMemory(&CurrentContext
, Context
, sizeof(*Context
));
53 KdpSendPacketHandler
= NULL
;
58 GetContextManipulateHandler(
59 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
60 _Out_ PSTRING MessageData
,
61 _Out_ PULONG MessageLength
,
62 _Inout_ PKD_CONTEXT KdContext
65 State
->ApiNumber
= DbgKdGetContextApi
;
66 State
->Processor
= CurrentStateChange
.Processor
;
67 State
->ReturnStatus
= STATUS_SUCCESS
;
68 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
69 MessageData
->Length
= 0;
71 /* Update the send <-> receive loop handler */
72 KdpSendPacketHandler
= GetContextSendHandler
;
73 KdpManipulateStateHandler
= NULL
;
75 return KdPacketReceived
;
80 SetContextSendHandler(
81 _In_ ULONG PacketType
,
82 _In_ PSTRING MessageHeader
,
83 _In_ PSTRING MessageData
86 DBGKD_MANIPULATE_STATE64
* State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
88 /* We just confirm that all went well */
89 if ((PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
90 || (State
->ApiNumber
!= DbgKdSetContextApi
)
91 || (State
->ReturnStatus
!= STATUS_SUCCESS
))
93 /* Should we bugcheck ? */
97 KdpSendPacketHandler
= NULL
;
101 SetContextManipulateHandler(
102 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
103 _Out_ PSTRING MessageData
,
104 _Out_ PULONG MessageLength
,
105 _Inout_ PKD_CONTEXT KdContext
108 State
->ApiNumber
= DbgKdSetContextApi
;
109 State
->Processor
= CurrentStateChange
.Processor
;
110 State
->ReturnStatus
= STATUS_SUCCESS
;
111 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
112 MessageData
->Length
= sizeof(CurrentContext
);
114 if (MessageData
->MaximumLength
< sizeof(CurrentContext
))
119 RtlCopyMemory(MessageData
->Buffer
, &CurrentContext
, sizeof(CurrentContext
));
121 /* Update the send <-> receive loop handlers */
122 KdpSendPacketHandler
= SetContextSendHandler
;
123 KdpManipulateStateHandler
= NULL
;
125 return KdPacketReceived
;
130 send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE
* StateChange
)
132 switch (StateChange
->NewState
)
134 case DbgKdLoadSymbolsStateChange
:
136 /* We don't care about symbols loading */
137 KdpManipulateStateHandler
= ContinueManipulateStateHandler
;
140 case DbgKdExceptionStateChange
:
141 /* Save current state for later GDB queries */
142 CurrentStateChange
= *StateChange
;
143 /* Unless GDB tells us otherwise, those are what we should have */
144 gdb_dbg_thread
= PsGetThreadId((PETHREAD
)StateChange
->Thread
);
145 gdb_dbg_process
= PsGetThreadProcessId((PETHREAD
)StateChange
->Thread
);
146 gdb_send_exception();
147 /* Next receive call will ask for the context */
148 KdpManipulateStateHandler
= GetContextManipulateHandler
;
159 _In_ DBGKD_DEBUG_IO
* DebugIO
,
162 switch (DebugIO
->ApiNumber
)
164 case DbgKdPrintStringApi
:
165 gdb_send_debug_io(String
);
175 send_kd_state_manipulate(
176 _In_ DBGKD_MANIPULATE_STATE64
* State
,
177 _In_ PSTRING MessageData
)
179 switch (State
->ApiNumber
)
182 case DbgKdGetContextApi
:
183 /* This is an answer to a 'g' GDB request */
184 gdb_send_registers((CONTEXT
*)MessageData
->Buffer
);
194 ContinueManipulateStateHandler(
195 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
196 _Out_ PSTRING MessageData
,
197 _Out_ PULONG MessageLength
,
198 _Inout_ PKD_CONTEXT KdContext
202 State
->ApiNumber
= DbgKdContinueApi
;
203 State
->ReturnStatus
= STATUS_SUCCESS
; /* ? */
204 State
->Processor
= CurrentStateChange
.Processor
;
205 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
207 MessageData
->Length
= 0;
209 State
->u
.Continue
.ContinueStatus
= STATUS_SUCCESS
;
211 /* We definitely are at the end of the send <-> receive loop, if any */
212 KdpSendPacketHandler
= NULL
;
213 KdpManipulateStateHandler
= NULL
;
214 return KdPacketReceived
;
219 GetVersionSendHandler(
220 _In_ ULONG PacketType
,
221 _In_ PSTRING MessageHeader
,
222 _In_ PSTRING MessageData
)
224 DBGKD_MANIPULATE_STATE64
* State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
225 LIST_ENTRY
* DebuggerDataList
;
227 /* Confirm that all went well */
228 if ((PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
229 || (State
->ApiNumber
!= DbgKdGetVersionApi
)
230 || !NT_SUCCESS(State
->ReturnStatus
))
232 /* FIXME: should detach from KD and go along without debugging */
233 KDDBGPRINT("Wrong packet received after asking for data.\n");
237 /* Copy the relevant data */
238 RtlCopyMemory(&KdVersion
, &State
->u
.GetVersion64
, sizeof(KdVersion
));
239 DebuggerDataList
= (LIST_ENTRY
*)(ULONG_PTR
)KdVersion
.DebuggerDataList
;
240 KdDebuggerDataBlock
= CONTAINING_RECORD(DebuggerDataList
->Flink
, KDDEBUGGER_DATA64
, Header
.List
);
242 /* We can tell KD to continue */
243 KdpSendPacketHandler
= NULL
;
244 KdpManipulateStateHandler
= ContinueManipulateStateHandler
;
249 GetVersionManipulateStateHandler(
250 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
251 _Out_ PSTRING MessageData
,
252 _Out_ PULONG MessageLength
,
253 _Inout_ PKD_CONTEXT KdContext
)
255 /* Ask for the version data */
256 State
->ApiNumber
= DbgKdGetVersionApi
;
257 State
->Processor
= CurrentStateChange
.Processor
;
258 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
260 /* The next send call will serve this query */
261 KdpSendPacketHandler
= GetVersionSendHandler
;
262 KdpManipulateStateHandler
= NULL
;
264 /* This will make KD breakin and we will be able to properly attach to GDB */
265 KdContext
->KdpControlCPending
= TRUE
;
267 return KdPacketReceived
;
273 _In_ ULONG PacketType
,
274 _In_ PSTRING MessageHeader
,
275 _In_ PSTRING MessageData
)
277 DBGKD_ANY_WAIT_STATE_CHANGE
* StateChange
= (DBGKD_ANY_WAIT_STATE_CHANGE
*)MessageHeader
->Buffer
;
279 if (PacketType
== PACKET_TYPE_KD_DEBUG_IO
)
281 /* This is not the packet we are waiting for */
282 send_kd_debug_io((DBGKD_DEBUG_IO
*)MessageHeader
->Buffer
, MessageData
);
286 if (PacketType
!= PACKET_TYPE_KD_STATE_CHANGE64
)
288 KDDBGPRINT("First KD packet is not a state change!\n");
289 /* FIXME: What should we send back to KD ? */
293 CurrentStateChange
= *StateChange
;
295 /* The next receive call will be asking for the version data */
296 KdpSendPacketHandler
= NULL
;
297 KdpManipulateStateHandler
= GetVersionManipulateStateHandler
;
300 /* PUBLIC FUNCTIONS ***********************************************************/
302 /******************************************************************************
303 * \name KdReceivePacket
304 * \brief Receive a packet from the KD port.
305 * \param [in] PacketType Describes the type of the packet to receive.
306 * This can be one of the PACKET_TYPE_ constants.
307 * \param [out] MessageHeader Pointer to a STRING structure for the header.
308 * \param [out] MessageData Pointer to a STRING structure for the data.
309 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
310 * timed out, KdPacketNeedsResend to signal that the last packet needs
312 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
313 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
314 * packet byte is received.
315 * \sa http://www.nynaeve.net/?p=169
320 _In_ ULONG PacketType
,
321 _Out_ PSTRING MessageHeader
,
322 _Out_ PSTRING MessageData
,
323 _Out_ PULONG DataLength
,
324 _Inout_ PKD_CONTEXT KdContext
)
327 DBGKD_MANIPULATE_STATE64
* State
;
329 /* Special handling for breakin packet */
330 if (PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
332 return KdpPollBreakIn();
335 if (PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
337 /* What should we do ? */
341 State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
343 /* Maybe we are in a send<->receive loop that GDB doesn't need to know about */
344 if (KdpManipulateStateHandler
!= NULL
)
345 return KdpManipulateStateHandler(State
, MessageData
, DataLength
, KdContext
);
347 /* Receive data from GDB */
348 Status
= gdb_receive_packet(KdContext
);
349 if (Status
!= KdPacketReceived
)
353 return gdb_interpret_input(State
, MessageData
, DataLength
, KdContext
);
360 IN PSTRING MessageHeader
,
361 IN PSTRING MessageData
,
362 IN OUT PKD_CONTEXT KdContext
)
364 /* Maybe we are in a send <-> receive loop that GDB doesn't need to know about */
365 if (KdpSendPacketHandler
)
367 KdpSendPacketHandler(PacketType
, MessageHeader
, MessageData
);
373 case PACKET_TYPE_KD_STATE_CHANGE64
:
374 send_kd_state_change((DBGKD_ANY_WAIT_STATE_CHANGE
*)MessageHeader
->Buffer
);
376 case PACKET_TYPE_KD_DEBUG_IO
:
377 send_kd_debug_io((DBGKD_DEBUG_IO
*)MessageHeader
->Buffer
, MessageData
);
379 case PACKET_TYPE_KD_STATE_MANIPULATE
:
380 send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
, MessageData
);