ReactOS  0.4.15-dev-2947-g59e1b78
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 *********************************************************************/
11 static
12 BOOLEAN
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 
35 static
36 BOOLEAN
38  _In_ ULONG PacketType,
39  _In_ PSTRING MessageHeader,
40  _In_ PSTRING MessageData
41 )
42 {
43  DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
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 
60 static
64  _Out_ PSTRING MessageData,
65  _Out_ PULONG MessageLength,
66  _Inout_ PKD_CONTEXT KdContext
67 )
68 {
69  State->ApiNumber = DbgKdGetContextApi;
70  State->Processor = CurrentStateChange.Processor;
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 
82 static
83 BOOLEAN
85  _In_ ULONG PacketType,
86  _In_ PSTRING MessageHeader,
87  _In_ PSTRING MessageData
88 )
89 {
90  DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
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 
106 KDSTATUS
109  _Out_ PSTRING MessageData,
110  _Out_ PULONG MessageLength,
111  _Inout_ PKD_CONTEXT KdContext
112 )
113 {
114  State->ApiNumber = DbgKdSetContextApi;
115  State->Processor = CurrentStateChange.Processor;
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 
135 static
136 void
138 {
139  InException = TRUE;
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 
171 static
172 void
174  _In_ DBGKD_DEBUG_IO* DebugIO,
176 {
177  if (InException)
178  return;
179 
180  switch (DebugIO->ApiNumber)
181  {
182  case DbgKdPrintStringApi:
183  case DbgKdGetStringApi:
185  break;
186  default:
187  KDDBGPRINT("Unknown ApiNumber %u.\n", DebugIO->ApiNumber);
188  while (1);
189  }
190 }
191 
192 static
193 void
196  _In_ PSTRING MessageData)
197 {
198  switch (State->ApiNumber)
199  {
200 #if 0
201  case DbgKdGetContextApi:
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 
212 KDSTATUS
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; /* ? */
223  State->Processor = CurrentStateChange.Processor;
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 */
234  InException = FALSE;
235 
236  return KdPacketReceived;
237 }
238 
239 static
240 BOOLEAN
242  _In_ ULONG PacketType,
243  _In_ PSTRING MessageHeader,
244  _In_ PSTRING MessageData)
245 {
246  DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
247  LIST_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 = (LIST_ENTRY*)(ULONG_PTR)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 
271 static
272 KDSTATUS
275  _Out_ PSTRING MessageData,
276  _Out_ PULONG MessageLength,
277  _Inout_ PKD_CONTEXT KdContext)
278 {
279  /* Ask for the version data */
280  State->ApiNumber = DbgKdGetVersionApi;
281  State->Processor = CurrentStateChange.Processor;
282  State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
283 
284  /* The next send call will serve this query */
287 
288  return KdPacketReceived;
289 }
290 
291 static
292 BOOLEAN
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  */
348 KDSTATUS
349 NTAPI
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  {
386  DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
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 
407 VOID
408 NTAPI
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 */
ULONG_PTR Pointer
Definition: wdbgexts.h:173
#define KdPacketReceived
Definition: kddll.h:5
#define IN
Definition: typedefs.h:39
DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange
Definition: kdpacket.c:28
KDSTATUS(* KDP_MANIPULATESTATE_HANDLER)(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdgdb.h:65
static KDSTATUS GetContextManipulateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:62
#define _Inout_
Definition: ms_sal.h:378
GCC_ULONG64 PsLoadedModuleList
Definition: wdbgexts.h:189
#define DbgKdGetVersionApi
Definition: windbgkd.h:96
PETHREAD TheIdleThread
Definition: kdpacket.c:31
#define _Out_
Definition: ms_sal.h:345
#define KDDBGPRINT(...)
Definition: kddll.h:19
#define TRUE
Definition: types.h:120
static BOOLEAN GetContextSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:37
static BOOLEAN InException
Definition: kdpacket.c:17
static BOOLEAN SetContextSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:84
int ignore(int trapCode, ppc_trap_frame_t *trap)
Definition: mmuobject.c:296
#define handle_to_gdb_pid
Definition: kdgdb.h:45
KTHREAD Tcb
Definition: pstypes.h:1103
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
NTSTATUS ExceptionCode
Definition: rtltypes.h:190
static void send_kd_debug_io(_In_ DBGKD_DEBUG_IO *DebugIO, _In_ PSTRING String)
Definition: kdpacket.c:173
#define DbgKdExceptionStateChange
Definition: windbgkd.h:59
#define DbgKdContinueApi
Definition: windbgkd.h:80
if(dx==0 &&dy==0)
Definition: linetemp.h:174
static BOOLEAN FirstSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:293
GCC_ULONG64 PsActiveProcessHead
Definition: wdbgexts.h:190
VOID NTAPI KdSendPacket(IN ULONG PacketType, IN PSTRING MessageHeader, IN PSTRING MessageData, IN OUT PKD_CONTEXT KdContext)
Definition: kdpacket.c:409
CONTEXT CurrentContext
Definition: kdpacket.c:29
uint32_t ULONG_PTR
Definition: typedefs.h:65
KDSTATUS gdb_send_exception()
Definition: gdb_send.c:197
#define DbgKdGetStringApi
Definition: windbgkd.h:123
#define KdPacketNeedsResend
Definition: kddll.h:7
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2430
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
Definition: Header.h:8
#define DbgKdPrintStringApi
Definition: windbgkd.h:122
KDP_STATUS NTAPI KdpPollBreakIn(VOID)
Definition: kdcom.c:343
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
static BOOLEAN GetVersionSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:241
KAPC_STATE ApcState
Definition: ketypes.h:1710
unsigned char BOOLEAN
#define _In_
Definition: ms_sal.h:308
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1437
KDSTATUS gdb_send_registers(void)
Definition: amd64_sup.c:144
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
KDSTATUS gdb_send_debug_io(_In_ PSTRING String, _In_ BOOLEAN WithPrefix)
Definition: gdb_send.c:168
DBGKD_GET_VERSION64 KdVersion
Definition: kdpacket.c:20
UINT_PTR gdb_dbg_tid
Definition: gdb_input.c:21
UINT_PTR gdb_dbg_pid
Definition: gdb_input.c:20
KDDEBUGGER_DATA64 * KdDebuggerDataBlock
Definition: kdpacket.c:21
#define DbgKdLoadSymbolsStateChange
Definition: windbgkd.h:60
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
HANDLE NTAPI PsGetThreadProcessId(IN PETHREAD Thread)
Definition: thread.c:745
#define DbgKdGetContextApi
Definition: windbgkd.h:76
KDP_SEND_HANDLER KdpSendPacketHandler
Definition: kdpacket.c:25
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2652
#define PACKET_TYPE_KD_STATE_MANIPULATE
Definition: windbgkd.h:43
static void send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE *StateChange)
Definition: kdpacket.c:137
EXCEPTION_RECORD64 ExceptionRecord
Definition: windbgkd.h:303
#define PACKET_TYPE_KD_STATE_CHANGE64
Definition: windbgkd.h:48
#define PRIxPTR
Definition: inttypes.h:236
#define DbgKdSetContextApi
Definition: windbgkd.h:77
LIST_ENTRY * ProcessListHead
Definition: kdpacket.c:22
Definition: typedefs.h:119
HANDLE NTAPI PsGetThreadId(IN PETHREAD Thread)
Definition: thread.c:705
PEPROCESS TheIdleProcess
Definition: kdpacket.c:30
KDSTATUS SetContextManipulateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:107
static KDSTATUS GetVersionManipulateStateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:273
#define PACKET_TYPE_KD_DEBUG_IO
Definition: windbgkd.h:44
ULONG KDSTATUS
Definition: kddll.h:4
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
DBGKM_EXCEPTION64 Exception
Definition: windbgkd.h:488
LIST_ENTRY * ModuleListHead
Definition: kdpacket.c:23
BOOLEAN(* KDP_SEND_HANDLER)(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdgdb.h:60
KDSTATUS ContinueManipulateStateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:213
#define OUT
Definition: typedefs.h:40
static void send_kd_state_manipulate(_In_ DBGKD_MANIPULATE_STATE64 *State, _In_ PSTRING MessageData)
Definition: kdpacket.c:194
FORCEINLINE UINT_PTR handle_to_gdb_tid(HANDLE Handle)
Definition: kdgdb.h:41
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
struct _ETHREAD * PETHREAD
Definition: nt_native.h:29
#define STATUS_SUCCESS
Definition: shellext.h:65
union _DBGKD_ANY_WAIT_STATE_CHANGE::@3498 u
KDSTATUS NTAPI KdReceivePacket(_In_ ULONG PacketType, _Out_ PSTRING MessageHeader, _Out_ PSTRING MessageData, _Out_ PULONG DataLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:350
KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler
Definition: kdpacket.c:26
ULONG64 DebuggerDataList
Definition: wdbgexts.h:161
#define PACKET_TYPE_KD_POLL_BREAKIN
Definition: windbgkd.h:49