ReactOS  r76032
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 VOID
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 VOID
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  /* Should we bugcheck ? */
51  KDDBGPRINT("ERROR: Received wrong packet from KD.\n");
52  while (1);
53  }
54 
55  /* Just copy it */
56  RtlCopyMemory(&CurrentContext, Context, sizeof(*Context));
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 VOID
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  while (1);
100  }
101 
103 }
104 
105 KDSTATUS
108  _Out_ PSTRING MessageData,
109  _Out_ PULONG MessageLength,
110  _Inout_ PKD_CONTEXT KdContext
111 )
112 {
113  State->ApiNumber = DbgKdSetContextApi;
114  State->Processor = CurrentStateChange.Processor;
115  State->ReturnStatus = STATUS_SUCCESS;
116  State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
117  MessageData->Length = sizeof(CurrentContext);
118 
119  if (MessageData->MaximumLength < sizeof(CurrentContext))
120  {
121  KDDBGPRINT("Wrong message length %u.\n", MessageData->MaximumLength);
122  while (1);
123  }
124 
125  RtlCopyMemory(MessageData->Buffer, &CurrentContext, sizeof(CurrentContext));
126 
127  /* Update the send <-> receive loop handlers */
130 
131  return KdPacketReceived;
132 }
133 
134 static
135 void
137 {
138  InException = TRUE;
139 
140  switch (StateChange->NewState)
141  {
144  {
145  PETHREAD Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread;
146  /* Save current state for later GDB queries */
147  CurrentStateChange = *StateChange;
148  KDDBGPRINT("Exception 0x%08x in thread p%p.%p.\n",
150  PsGetThreadProcessId(Thread),
151  PsGetThreadId(Thread));
152  /* Set the current debugged process/thread accordingly */
154 #if MONOPROCESS
155  gdb_dbg_pid = 0;
156 #else
158 #endif
160  /* Next receive call will ask for the context */
162  break;
163  }
164  default:
165  KDDBGPRINT("Unknown StateChange %u.\n", StateChange->NewState);
166  while (1);
167  }
168 }
169 
170 static
171 void
173  _In_ DBGKD_DEBUG_IO* DebugIO,
175 {
176  if (InException)
177  return;
178 
179  switch (DebugIO->ApiNumber)
180  {
181  case DbgKdPrintStringApi:
182  case DbgKdGetStringApi:
183  gdb_send_debug_io(String, TRUE);
184  break;
185  default:
186  KDDBGPRINT("Unknown ApiNumber %u.\n", DebugIO->ApiNumber);
187  while (1);
188  }
189 }
190 
191 static
192 void
195  _In_ PSTRING MessageData)
196 {
197  switch (State->ApiNumber)
198  {
199 #if 0
200  case DbgKdGetContextApi:
201  /* This is an answer to a 'g' GDB request */
202  gdb_send_registers((CONTEXT*)MessageData->Buffer);
203  return;
204 #endif
205  default:
206  KDDBGPRINT("Unknown ApiNumber %u.\n", State->ApiNumber);
207  while (1);
208  }
209 }
210 
211 KDSTATUS
214  _Out_ PSTRING MessageData,
215  _Out_ PULONG MessageLength,
216  _Inout_ PKD_CONTEXT KdContext
217 )
218 {
219  /* Let's go on */
220  State->ApiNumber = DbgKdContinueApi;
221  State->ReturnStatus = STATUS_SUCCESS; /* ? */
222  State->Processor = CurrentStateChange.Processor;
223  State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
224  if (MessageData)
225  MessageData->Length = 0;
226  *MessageLength = 0;
227  State->u.Continue.ContinueStatus = STATUS_SUCCESS;
228 
229  /* We definitely are at the end of the send <-> receive loop, if any */
232  /* We're not handling an exception anymore */
233  InException = FALSE;
234 
235  return KdPacketReceived;
236 }
237 
238 static
239 VOID
241  _In_ ULONG PacketType,
242  _In_ PSTRING MessageHeader,
243  _In_ PSTRING MessageData)
244 {
245  DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
246  LIST_ENTRY* DebuggerDataList;
247 
248  /* Confirm that all went well */
249  if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
250  || (State->ApiNumber != DbgKdGetVersionApi)
251  || !NT_SUCCESS(State->ReturnStatus))
252  {
253  /* FIXME: should detach from KD and go along without debugging */
254  KDDBGPRINT("Wrong packet received after asking for data.\n");
255  while(1);
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);
262  ProcessListHead = (LIST_ENTRY*)KdDebuggerDataBlock->PsActiveProcessHead.Pointer;
263  ModuleListHead = (LIST_ENTRY*)KdDebuggerDataBlock->PsLoadedModuleList.Pointer;
264 
265  /* Now we can get the context for the current state */
268 }
269 
270 static
271 KDSTATUS
274  _Out_ PSTRING MessageData,
275  _Out_ PULONG MessageLength,
276  _Inout_ PKD_CONTEXT KdContext)
277 {
278  /* Ask for the version data */
279  State->ApiNumber = DbgKdGetVersionApi;
280  State->Processor = CurrentStateChange.Processor;
281  State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
282 
283  /* The next send call will serve this query */
286 
287  return KdPacketReceived;
288 }
289 
290 static
291 VOID
293  _In_ ULONG PacketType,
294  _In_ PSTRING MessageHeader,
295  _In_ PSTRING MessageData)
296 {
297  DBGKD_ANY_WAIT_STATE_CHANGE* StateChange = (DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer;
299 
300  if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
301  {
302  /* This is not the packet we are waiting for */
303  send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData);
304  return;
305  }
306 
307  if (PacketType != PACKET_TYPE_KD_STATE_CHANGE64)
308  {
309  KDDBGPRINT("First KD packet is not a state change!\n");
310  /* FIXME: What should we send back to KD ? */
311  while(1);
312  }
313 
314  KDDBGPRINT("KDGDB: START!\n");
315 
316  Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread;
317 
318  /* Set up the current state */
319  CurrentStateChange = *StateChange;
321 #if MONOPROCESS
322  gdb_dbg_pid = 0;
323 #else
325 #endif
326  /* This is the idle process. Save it! */
327  TheIdleThread = Thread;
328  TheIdleProcess = (PEPROCESS)Thread->Tcb.ApcState.Process;
329 
330  KDDBGPRINT("Pid Tid of the first message: %" PRIxPTR", %" PRIxPTR ".\n", gdb_dbg_pid, gdb_dbg_tid);
331 
332  /* The next receive call will be asking for the version data */
335 }
336 
337 /* PUBLIC FUNCTIONS ***********************************************************/
338 
339 /******************************************************************************
340  * \name KdReceivePacket
341  * \brief Receive a packet from the KD port.
342  * \param [in] PacketType Describes the type of the packet to receive.
343  * This can be one of the PACKET_TYPE_ constants.
344  * \param [out] MessageHeader Pointer to a STRING structure for the header.
345  * \param [out] MessageData Pointer to a STRING structure for the data.
346  * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
347  * timed out, KdPacketNeedsResend to signal that the last packet needs
348  * to be sent again.
349  * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
350  * wait for any data, but returns KdPacketTimedOut instantly if no breakin
351  * packet byte is received.
352  * \sa http://www.nynaeve.net/?p=169
353  */
354 KDSTATUS
355 NTAPI
357  _In_ ULONG PacketType,
358  _Out_ PSTRING MessageHeader,
359  _Out_ PSTRING MessageData,
361  _Inout_ PKD_CONTEXT KdContext)
362 {
363  KDDBGPRINT("KdReceivePacket.\n");
364 
365  if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN)
366  {
367  return KdpPollBreakIn();
368  }
369 
370  if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
371  {
372  /* HACK ! RtlAssert asks for (boipt), always say "o" --> break once. */
373  MessageData->Length = 1;
374  MessageData->Buffer[0] = 'o';
375  return KdPacketReceived;
376  }
377 
378  if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE)
379  {
380  DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
381 
382  /* Maybe we are in a send<->receive loop that GDB doesn't need to know about */
384  {
385  KDDBGPRINT("KDGBD: We have a manipulate state handler.\n");
386  return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext);
387  }
388 
389  /* Receive data from GDB and interpret it */
390  return gdb_receive_and_interpret_packet(State, MessageData, DataLength, KdContext);
391  }
392 
393  /* What should we do ? */
394  while (1);
395  return KdPacketNeedsResend;
396 }
397 
398 VOID
399 NTAPI
401  IN ULONG PacketType,
402  IN PSTRING MessageHeader,
403  IN PSTRING MessageData,
404  IN OUT PKD_CONTEXT KdContext)
405 {
406  /* Override if we have some debug print from KD. */
407  if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
408  {
409  send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData);
410  return;
411  }
412 
413  /* Maybe we are in a send <-> receive loop that GDB doesn't need to know about */
415  {
416  KdpSendPacketHandler(PacketType, MessageHeader, MessageData);
417  return;
418  }
419 
420  switch (PacketType)
421  {
423  send_kd_state_change((DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer);
424  return;
426  send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData);
427  break;
429  send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer, MessageData);
430  break;
431  default:
432  KDDBGPRINT("Unknown packet type %u.\n", PacketType);
433  while (1);
434  }
435 }
436 
437 /* EOF */
ULONG_PTR Pointer
Definition: wdbgexts.h:173
#define KdPacketReceived
Definition: kddll.h:5
union _DBGKD_MANIPULATE_STATE64::@3215 u
#define IN
Definition: typedefs.h:38
DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange
Definition: kdpacket.c:28
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static KDSTATUS GetContextManipulateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:62
GCC_ULONG64 PsLoadedModuleList
Definition: wdbgexts.h:189
#define DbgKdGetVersionApi
Definition: windbgkd.h:96
PETHREAD TheIdleThread
Definition: kdpacket.c:31
#define KDDBGPRINT(...)
Definition: kddll.h:19
return STATUS_SUCCESS
Definition: btrfs.c:2664
KDSTATUS gdb_send_registers(void)
Definition: i386_sup.c:150
static BOOLEAN InException
Definition: kdpacket.c:17
VOID(* 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
KTHREAD Tcb
Definition: pstypes.h:1035
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
NTSTATUS ExceptionCode
Definition: rtltypes.h:186
static void send_kd_debug_io(_In_ DBGKD_DEBUG_IO *DebugIO, _In_ PSTRING String)
Definition: kdpacket.c:172
#define DbgKdExceptionStateChange
Definition: windbgkd.h:59
#define DbgKdContinueApi
Definition: windbgkd.h:80
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:400
CONTEXT CurrentContext
Definition: kdpacket.c:29
uint32_t ULONG_PTR
Definition: typedefs.h:63
KDSTATUS gdb_send_exception()
Definition: gdb_send.c:197
#define DbgKdGetStringApi
Definition: windbgkd.h:123
#define KdPacketNeedsResend
Definition: kddll.h:7
CHAR16 * String
Definition: acefiex.h:201
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:332
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:954
KAPC_STATE ApcState
Definition: ketypes.h:969
smooth NULL
Definition: ftsmooth.c:557
#define _Out_
Definition: no_sal2.h:323
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
unsigned char BOOLEAN
UINT_PTR gdb_dbg_pid
Definition: gdb_input.c:20
KDDEBUGGER_DATA64 * KdDebuggerDataBlock
Definition: kdpacket.c:21
#define DbgKdLoadSymbolsStateChange
Definition: windbgkd.h:60
if(!(yy_init))
Definition: macro.lex.yy.c:704
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
static VOID GetContextSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:37
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:2653
#define _Inout_
Definition: no_sal2.h:244
#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:136
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:117
HANDLE NTAPI PsGetThreadId(IN PETHREAD Thread)
Definition: thread.c:705
#define _In_
Definition: no_sal2.h:204
DBGKD_GET_VERSION64 GetVersion64
Definition: windbgkd.h:787
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:106
static VOID GetVersionSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:240
static KDSTATUS GetVersionManipulateStateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:272
static VOID FirstSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:292
#define PACKET_TYPE_KD_DEBUG_IO
Definition: windbgkd.h:44
ULONG KDSTATUS
Definition: kddll.h:4
unsigned int * PULONG
Definition: retypes.h:1
DBGKM_EXCEPTION64 Exception
Definition: windbgkd.h:488
LIST_ENTRY * ModuleListHead
Definition: kdpacket.c:23
static VOID SetContextSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: kdpacket.c:84
KDSTATUS ContinueManipulateStateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:212
#define OUT
Definition: typedefs.h:39
static void send_kd_state_manipulate(_In_ DBGKD_MANIPULATE_STATE64 *State, _In_ PSTRING MessageData)
Definition: kdpacket.c:193
FORCEINLINE UINT_PTR handle_to_gdb_tid(HANDLE Handle)
Definition: kdgdb.h:41
unsigned int ULONG
Definition: retypes.h:1
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:259
struct _ETHREAD * PETHREAD
Definition: nt_native.h:29
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333
union _DBGKD_ANY_WAIT_STATE_CHANGE::@3207 u
KDSTATUS NTAPI KdReceivePacket(_In_ ULONG PacketType, _Out_ PSTRING MessageHeader, _Out_ PSTRING MessageData, _Out_ PULONG DataLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:356
KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler
Definition: kdpacket.c:26
ULONG64 DebuggerDataList
Definition: wdbgexts.h:161
KDSTATUS(* KDP_MANIPULATESTATE_HANDLER)(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdgdb.h:65
#define PACKET_TYPE_KD_POLL_BREAKIN
Definition: windbgkd.h:49