ReactOS 0.4.15-dev-7924-g5949c20
kdpacket.c
Go to the documentation of this file.
1/*
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.
6 */
7
8#include "kdgdb.h"
9
10/* LOCALS *********************************************************************/
11static
14 _In_ ULONG PacketType,
15 _In_ PSTRING MessageHeader,
16 _In_ PSTRING MessageData);
18
19/* GLOBALS ********************************************************************/
24/* Callbacks used to communicate with KD aside from GDB */
27/* Data describing the current exception */
32
33/* PRIVATE FUNCTIONS **********************************************************/
34
35static
38 _In_ ULONG PacketType,
39 _In_ PSTRING MessageHeader,
40 _In_ PSTRING MessageData
41)
42{
44 const CONTEXT* Context = (const CONTEXT*)MessageData->Buffer;
45
46 if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
47 || (State->ApiNumber != DbgKdGetContextApi)
48 || (MessageData->Length < sizeof(*Context)))
49 {
50 KDDBGPRINT("ERROR: Received wrong packet from KD.\n");
51 return FALSE;
52 }
53
54 /* Just copy it */
57 return TRUE;
58}
59
60static
64 _Out_ PSTRING MessageData,
65 _Out_ PULONG MessageLength,
66 _Inout_ PKD_CONTEXT KdContext
67)
68{
69 State->ApiNumber = DbgKdGetContextApi;
71 State->ReturnStatus = STATUS_SUCCESS;
72 State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
73 MessageData->Length = 0;
74
75 /* Update the send <-> receive loop handler */
78
79 return KdPacketReceived;
80}
81
82static
85 _In_ ULONG PacketType,
86 _In_ PSTRING MessageHeader,
87 _In_ PSTRING MessageData
88)
89{
91
92 /* We just confirm that all went well */
93 if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
94 || (State->ApiNumber != DbgKdSetContextApi)
95 || (State->ReturnStatus != STATUS_SUCCESS))
96 {
97 /* Should we bugcheck ? */
98 KDDBGPRINT("BAD BAD BAD not manipulating state for sending context.\n");
99 return FALSE;
100 }
101
103 return TRUE;
104}
105
109 _Out_ PSTRING MessageData,
110 _Out_ PULONG MessageLength,
111 _Inout_ PKD_CONTEXT KdContext
112)
113{
114 State->ApiNumber = DbgKdSetContextApi;
116 State->ReturnStatus = STATUS_SUCCESS;
117 State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
118 MessageData->Length = sizeof(CurrentContext);
119
120 if (MessageData->MaximumLength < sizeof(CurrentContext))
121 {
122 KDDBGPRINT("Wrong message length %u.\n", MessageData->MaximumLength);
123 while (1);
124 }
125
126 RtlCopyMemory(MessageData->Buffer, &CurrentContext, sizeof(CurrentContext));
127
128 /* Update the send <-> receive loop handlers */
131
132 return KdPacketReceived;
133}
134
135static
136void
138{
140
141 switch (StateChange->NewState)
142 {
145 {
146 PETHREAD Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread;
147 /* Save current state for later GDB queries */
148 CurrentStateChange = *StateChange;
149 KDDBGPRINT("Exception 0x%08x in thread p%p.%p.\n",
153 /* Set the current debugged process/thread accordingly */
155#if MONOPROCESS
156 gdb_dbg_pid = 0;
157#else
159#endif
161 /* Next receive call will ask for the context */
163 break;
164 }
165 default:
166 KDDBGPRINT("Unknown StateChange %u.\n", StateChange->NewState);
167 while (1);
168 }
169}
170
171static
172void
174 _In_ DBGKD_DEBUG_IO* DebugIO,
176{
177 if (InException)
178 return;
179
180 switch (DebugIO->ApiNumber)
181 {
185 break;
186 default:
187 KDDBGPRINT("Unknown ApiNumber %u.\n", DebugIO->ApiNumber);
188 while (1);
189 }
190}
191
192static
193void
196 _In_ PSTRING MessageData)
197{
198 switch (State->ApiNumber)
199 {
200#if 0
202 /* This is an answer to a 'g' GDB request */
203 gdb_send_registers((CONTEXT*)MessageData->Buffer);
204 return;
205#endif
206 default:
207 KDDBGPRINT("Unknown ApiNumber %u.\n", State->ApiNumber);
208 while (1);
209 }
210}
211
215 _Out_ PSTRING MessageData,
216 _Out_ PULONG MessageLength,
217 _Inout_ PKD_CONTEXT KdContext
218)
219{
220 /* Let's go on */
221 State->ApiNumber = DbgKdContinueApi;
222 State->ReturnStatus = STATUS_SUCCESS; /* ? */
224 State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
225 if (MessageData)
226 MessageData->Length = 0;
227 *MessageLength = 0;
228 State->u.Continue.ContinueStatus = STATUS_SUCCESS;
229
230 /* We definitely are at the end of the send <-> receive loop, if any */
233 /* We're not handling an exception anymore */
235
236 return KdPacketReceived;
237}
238
239static
242 _In_ ULONG PacketType,
243 _In_ PSTRING MessageHeader,
244 _In_ PSTRING MessageData)
245{
247 PLIST_ENTRY DebuggerDataList;
248
249 /* Confirm that all went well */
250 if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
251 || (State->ApiNumber != DbgKdGetVersionApi)
252 || !NT_SUCCESS(State->ReturnStatus))
253 {
254 KDDBGPRINT("Wrong packet received after asking for data.\n");
255 return FALSE;
256 }
257
258 /* Copy the relevant data */
259 RtlCopyMemory(&KdVersion, &State->u.GetVersion64, sizeof(KdVersion));
260 DebuggerDataList = *(PLIST_ENTRY*)&KdVersion.DebuggerDataList;
261 KdDebuggerDataBlock = CONTAINING_RECORD(DebuggerDataList->Flink, KDDEBUGGER_DATA64, Header.List);
264
265 /* Now we can get the context for the current state */
268 return TRUE;
269}
270
271static
275 _Out_ PSTRING MessageData,
276 _Out_ PULONG MessageLength,
277 _Inout_ PKD_CONTEXT KdContext)
278{
279 /* Ask for the version data */
280 State->ApiNumber = DbgKdGetVersionApi;
282 State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
283
284 /* The next send call will serve this query */
287
288 return KdPacketReceived;
289}
290
291static
294 _In_ ULONG PacketType,
295 _In_ PSTRING MessageHeader,
296 _In_ PSTRING MessageData)
297{
298 DBGKD_ANY_WAIT_STATE_CHANGE* StateChange = (DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer;
300
301 if (PacketType != PACKET_TYPE_KD_STATE_CHANGE64)
302 {
303 KDDBGPRINT("First KD packet is not a state change!\n");
304 return FALSE;
305 }
306
307 KDDBGPRINT("KDGDB: START!\n");
308
309 Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread;
310
311 /* Set up the current state */
312 CurrentStateChange = *StateChange;
314#if MONOPROCESS
315 gdb_dbg_pid = 0;
316#else
318#endif
319 /* This is the idle process. Save it! */
322
323 KDDBGPRINT("Pid Tid of the first message: %" PRIxPTR", %" PRIxPTR ".\n", gdb_dbg_pid, gdb_dbg_tid);
324
325 /* The next receive call will be asking for the version data */
328 return TRUE;
329}
330
331/* PUBLIC FUNCTIONS ***********************************************************/
332
333/******************************************************************************
334 * \name KdReceivePacket
335 * \brief Receive a packet from the KD port.
336 * \param [in] PacketType Describes the type of the packet to receive.
337 * This can be one of the PACKET_TYPE_ constants.
338 * \param [out] MessageHeader Pointer to a STRING structure for the header.
339 * \param [out] MessageData Pointer to a STRING structure for the data.
340 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
341 * timed out, KdPacketNeedsResend to signal that the last packet needs
342 * to be sent again.
343 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
344 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
345 * packet byte is received.
346 * \sa http://www.nynaeve.net/?p=169
347 */
349NTAPI
351 _In_ ULONG PacketType,
352 _Out_ PSTRING MessageHeader,
353 _Out_ PSTRING MessageData,
355 _Inout_ PKD_CONTEXT KdContext)
356{
357 KDDBGPRINT("KdReceivePacket --> ");
358
359 if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN)
360 {
361 static BOOLEAN firstTime = TRUE;
362 KDDBGPRINT("Polling break in.\n");
363 if (firstTime)
364 {
365 /* Force debug break on init */
366 firstTime = FALSE;
367 return KdPacketReceived;
368 }
369
370 return KdpPollBreakIn();
371 }
372
373 if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
374 {
375 static BOOLEAN ignore = 0;
376 KDDBGPRINT("Debug prompt.\n");
377 /* HACK ! Debug prompt asks for break or ignore. First break, then ignore. */
378 MessageData->Length = 1;
379 MessageData->Buffer[0] = ignore ? 'i' : 'b';
380 ignore = !ignore;
381 return KdPacketReceived;
382 }
383
384 if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE)
385 {
387
388 KDDBGPRINT("State manipulation: ");
389
390 /* Maybe we are in a send<->receive loop that GDB doesn't need to know about */
392 {
393 KDDBGPRINT("We have a manipulate state handler.\n");
394 return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext);
395 }
396
397 /* Receive data from GDB and interpret it */
398 KDDBGPRINT("Receiving data from GDB.\n");
399 return gdb_receive_and_interpret_packet(State, MessageData, DataLength, KdContext);
400 }
401
402 /* What should we do ? */
403 while (1);
404 return KdPacketNeedsResend;
405}
406
407VOID
408NTAPI
410 IN ULONG PacketType,
411 IN PSTRING MessageHeader,
412 IN PSTRING MessageData,
413 IN OUT PKD_CONTEXT KdContext)
414{
415 /* Override if we have some debug print from KD. */
416 if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
417 {
418 send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData);
419 return;
420 }
421
422 /* Maybe we are in a send <-> receive loop that GDB doesn't need to know about */
424 && KdpSendPacketHandler(PacketType, MessageHeader, MessageData))
425 {
426 return;
427 }
428
429 switch (PacketType)
430 {
432 send_kd_state_change((DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer);
433 return;
435 send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData);
436 break;
438 send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer, MessageData);
439 break;
440 default:
441 KDDBGPRINT("Unknown packet type %u.\n", PacketType);
442 while (1);
443 }
444}
445
446/* EOF */
unsigned char BOOLEAN
KDSTATUS gdb_send_registers(void)
Definition: amd64_sup.c:144
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
Definition: Header.h:9
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define KDDBGPRINT(...)
Definition: kddll.h:19
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
KDSTATUS gdb_receive_and_interpret_packet(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:994
UINT_PTR gdb_dbg_tid
Definition: gdb_input.c:21
UINT_PTR gdb_dbg_pid
Definition: gdb_input.c:20
KDSTATUS gdb_send_debug_io(_In_ PSTRING String, _In_ BOOLEAN WithPrefix)
Definition: gdb_send.c:168
KDSTATUS gdb_send_exception()
Definition: gdb_send.c:197
#define PRIxPTR
Definition: inttypes.h:236
KDP_STATUS NTAPI KdpPollBreakIn(VOID)
Definition: kdcom.c:343
BOOLEAN(* KDP_SEND_HANDLER)(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdgdb.h:60
#define handle_to_gdb_pid
Definition: kdgdb.h:45
FORCEINLINE UINT_PTR handle_to_gdb_tid(HANDLE Handle)
Definition: kdgdb.h:41
KDSTATUS(* KDP_MANIPULATESTATE_HANDLER)(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdgdb.h:65
CONTEXT CurrentContext
Definition: kdpacket.c:29
static BOOLEAN GetContextSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:37
static void send_kd_debug_io(_In_ DBGKD_DEBUG_IO *DebugIO, _In_ PSTRING String)
Definition: kdpacket.c:173
KDP_SEND_HANDLER KdpSendPacketHandler
Definition: kdpacket.c:25
static BOOLEAN GetVersionSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:241
KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler
Definition: kdpacket.c:26
KDSTATUS SetContextManipulateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:107
VOID NTAPI KdSendPacket(IN ULONG PacketType, IN PSTRING MessageHeader, IN PSTRING MessageData, IN OUT PKD_CONTEXT KdContext)
Definition: kdpacket.c:409
DBGKD_GET_VERSION64 KdVersion
Definition: kdpacket.c:20
PEPROCESS TheIdleProcess
Definition: kdpacket.c:30
static void send_kd_state_manipulate(_In_ DBGKD_MANIPULATE_STATE64 *State, _In_ PSTRING MessageData)
Definition: kdpacket.c:194
PETHREAD TheIdleThread
Definition: kdpacket.c:31
DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange
Definition: kdpacket.c:28
KDDEBUGGER_DATA64 * KdDebuggerDataBlock
Definition: kdpacket.c:21
static void send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE *StateChange)
Definition: kdpacket.c:137
static BOOLEAN FirstSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:293
static KDSTATUS GetContextManipulateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:62
KDSTATUS ContinueManipulateStateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:213
LIST_ENTRY * ModuleListHead
Definition: kdpacket.c:23
static BOOLEAN InException
Definition: kdpacket.c:17
KDSTATUS NTAPI KdReceivePacket(_In_ ULONG PacketType, _Out_ PSTRING MessageHeader, _Out_ PSTRING MessageData, _Out_ PULONG DataLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:350
LIST_ENTRY * ProcessListHead
Definition: kdpacket.c:22
static KDSTATUS GetVersionManipulateStateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:273
static BOOLEAN SetContextSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:84
if(dx< 0)
Definition: linetemp.h:194
#define _Inout_
Definition: ms_sal.h:378
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
struct _ETHREAD * PETHREAD
Definition: nt_native.h:29
HANDLE NTAPI PsGetThreadId(IN PETHREAD Thread)
Definition: thread.c:705
HANDLE NTAPI PsGetThreadProcessId(IN PETHREAD Thread)
Definition: thread.c:745
#define KdPacketReceived
Definition: kddll.h:5
#define KdPacketNeedsResend
Definition: kddll.h:7
ULONG KDSTATUS
Definition: kddll.h:4
#define STATUS_SUCCESS
Definition: shellext.h:65
DBGKM_EXCEPTION64 Exception
Definition: windbgkd.h:508
union _DBGKD_ANY_WAIT_STATE_CHANGE::@3549 u
ULONG64 DebuggerDataList
Definition: wdbgexts.h:167
EXCEPTION_RECORD64 ExceptionRecord
Definition: windbgkd.h:312
KTHREAD Tcb
Definition: pstypes.h:1103
NTSTATUS ExceptionCode
Definition: rtltypes.h:190
ULPTR64 PsActiveProcessHead
Definition: wdbgexts.h:203
ULPTR64 PsLoadedModuleList
Definition: wdbgexts.h:202
KAPC_STATE ApcState
Definition: ketypes.h:1778
Definition: typedefs.h:120
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433
#define DbgKdGetVersionApi
Definition: windbgkd.h:96
#define DbgKdGetContextApi
Definition: windbgkd.h:76
#define DbgKdLoadSymbolsStateChange
Definition: windbgkd.h:60
#define DbgKdPrintStringApi
Definition: windbgkd.h:122
#define DbgKdSetContextApi
Definition: windbgkd.h:77
#define PACKET_TYPE_KD_STATE_MANIPULATE
Definition: windbgkd.h:43
#define DbgKdGetStringApi
Definition: windbgkd.h:123
#define DbgKdExceptionStateChange
Definition: windbgkd.h:59
#define PACKET_TYPE_KD_STATE_CHANGE64
Definition: windbgkd.h:48
#define DbgKdContinueApi
Definition: windbgkd.h:80
#define PACKET_TYPE_KD_POLL_BREAKIN
Definition: windbgkd.h:49
#define PACKET_TYPE_KD_DEBUG_IO
Definition: windbgkd.h:44