ReactOS  0.4.14-dev-552-g2fad488
gdb_input.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/gdb_input.c
5  * PURPOSE: Base functions for the kernel debugger.
6  */
7 
8 #include "kdgdb.h"
9 
10 /* LOCALS *********************************************************************/
12 static struct
13 {
16 } BreakPointHandles[32];
17 
18 
19 /* GLOBALS ********************************************************************/
22 
23 static inline
26 {
27  return (x == KdPacketReceived) ? (KDSTATUS)-1 : x;
28 }
29 
30 /* PRIVATE FUNCTIONS **********************************************************/
31 static
34 {
35  ULONG_PTR ret = 0;
36  char hex;
37  while (*buffer)
38  {
39  hex = hex_value(*buffer++);
40  if (hex < 0)
41  return ret;
42  ret <<= 4;
43  ret += hex;
44  }
45  return ret;
46 }
47 #define hex_to_pid hex_to_tid
48 
49 static
50 ULONG64
52 {
53  ULONG64 ret = 0;
54  char hex;
55  while (*buffer)
56  {
57  hex = hex_value(*buffer++);
58  if (hex < 0)
59  return ret;
60  ret <<= 4;
61  ret += hex;
62  }
63  return ret;
64 }
65 
66 /* H* packets */
67 static
70 {
72 
73  switch (gdb_input[1])
74  {
75  case 'c':
76  if (strcmp(&gdb_input[2], "-1") == 0)
77  gdb_run_tid = (ULONG_PTR)-1;
78  else
80  Status = send_gdb_packet("OK");
81  break;
82  case 'g':
83  KDDBGPRINT("Setting debug thread: %s.\n", gdb_input);
84 #if MONOPROCESS
85  gdb_dbg_pid = 0;
86  if (strncmp(&gdb_input[2], "-1", 2) == 0)
87  {
88  gdb_dbg_tid = (UINT_PTR)-1;
89  }
90  else
91  {
93  }
94 #else
95  if (strncmp(&gdb_input[2], "p-1", 3) == 0)
96  {
97  gdb_dbg_pid = (UINT_PTR)-1;
98  gdb_dbg_tid = (UINT_PTR)-1;
99  }
100  else
101  {
102  char* ptr = strstr(gdb_input, ".") + 1;
104  if (strncmp(ptr, "-1", 2) == 0)
105  gdb_dbg_tid = (UINT_PTR)-1;
106  else
108  }
109 #endif
110  Status = send_gdb_packet("OK");
111  break;
112  default:
113  KDDBGPRINT("KDGBD: Unknown 'H' command: %s\n", gdb_input);
114  Status = send_gdb_packet("");
115  }
116 
117  return Status;
118 }
119 
120 static
121 KDSTATUS
123 {
124  ULONG_PTR Pid, Tid;
127 
128 #if MONOPROCESS
129  Pid = 0;
130  Tid = hex_to_tid(&gdb_input[1]);
131 
132  KDDBGPRINT("Checking if %p is alive.\n", Tid);
133 
134 #else
135  Pid = hex_to_pid(&gdb_input[2]);
136  Tid = hex_to_tid(strstr(gdb_input, ".") + 1);
137 
138  /* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL.
139  * So loop. */
140  KDDBGPRINT("Checking if p%p.%p is alive.\n", Pid, Tid);
141 #endif
142 
143  Thread = find_thread(Pid, Tid);
144 
145  if (Thread != NULL)
146  Status = send_gdb_packet("OK");
147  else
148  Status = send_gdb_packet("E03");
149 
150  return Status;
151 }
152 
153 /* q* packets */
154 static
155 KDSTATUS
157 {
158  if (strncmp(gdb_input, "qSupported:", 11) == 0)
159  {
160 #if MONOPROCESS
161  return send_gdb_packet("PacketSize=1000;qXfer:libraries:read+;");
162 #else
163  return send_gdb_packet("PacketSize=1000;multiprocess+;qXfer:libraries:read+;");
164 #endif
165  }
166 
167  if (strncmp(gdb_input, "qAttached", 9) == 0)
168  {
169 #if MONOPROCESS
170  return send_gdb_packet("1");
171 #else
172  UINT_PTR queried_pid = hex_to_pid(&gdb_input[10]);
173  /* Let's say we created system process */
174  if (gdb_pid_to_handle(queried_pid) == NULL)
175  return send_gdb_packet("0");
176  else
177  return send_gdb_packet("1");
178 #endif
179  }
180 
181  if (strncmp(gdb_input, "qRcmd,", 6) == 0)
182  {
183  return send_gdb_packet("OK");
184  }
185 
186  if (strcmp(gdb_input, "qC") == 0)
187  {
188  char gdb_out[64];
189 #if MONOPROCESS
190  sprintf(gdb_out, "QC:%"PRIxPTR";",
192 #else
193  sprintf(gdb_out, "QC:p%"PRIxPTR".%"PRIxPTR";",
196 #endif
197  return send_gdb_packet(gdb_out);
198  }
199 
200  if (strncmp(gdb_input, "qfThreadInfo", 12) == 0)
201  {
203  char gdb_out[40];
204  LIST_ENTRY* CurrentProcessEntry;
205 
206  CurrentProcessEntry = ProcessListHead->Flink;
207  if (CurrentProcessEntry == NULL) /* Ps is not initialized */
208  {
209 #if MONOPROCESS
210  return send_gdb_packet("m1");
211 #else
212  return send_gdb_packet("mp1.1");
213 #endif
214  }
215 
216  /* We will push threads as we find them */
218 
219  /* Start with the system thread */
220 #if MONOPROCESS
222 #else
223  send_gdb_partial_packet("mp1.1");
224 #endif
225 
226  /* List all the processes */
227  for ( ;
228  CurrentProcessEntry != ProcessListHead;
229  CurrentProcessEntry = CurrentProcessEntry->Flink)
230  {
231  LIST_ENTRY* CurrentThreadEntry;
232 
233  Process = CONTAINING_RECORD(CurrentProcessEntry, EPROCESS, ActiveProcessLinks);
234 
235  /* List threads from this process */
236  for ( CurrentThreadEntry = Process->ThreadListHead.Flink;
237  CurrentThreadEntry != &Process->ThreadListHead;
238  CurrentThreadEntry = CurrentThreadEntry->Flink)
239  {
240  PETHREAD Thread = CONTAINING_RECORD(CurrentThreadEntry, ETHREAD, ThreadListEntry);
241 
242 #if MONOPROCESS
243  _snprintf(gdb_out, 40, ",%p", handle_to_gdb_tid(Thread->Cid.UniqueThread));
244 #else
245  _snprintf(gdb_out, 40, ",p%p.%p",
246  handle_to_gdb_pid(Process->UniqueProcessId),
248 #endif
249  send_gdb_partial_packet(gdb_out);
250  }
251  }
252 
253  return finish_gdb_packet();
254  }
255 
256  if (strncmp(gdb_input, "qsThreadInfo", 12) == 0)
257  {
258  /* We sent the whole thread list on first qfThreadInfo call */
259  return send_gdb_packet("l");
260  }
261 
262  if (strncmp(gdb_input, "qThreadExtraInfo,", 17) == 0)
263  {
264  ULONG_PTR Pid, Tid;
267  char out_string[64];
268  STRING String = {0, 64, out_string};
269 
270  KDDBGPRINT("Giving extra info for");
271 
272 #if MONOPROCESS
273  Pid = 0;
274  Tid = hex_to_tid(&gdb_input[17]);
275 
276  KDDBGPRINT(" %p.\n", Tid);
277 
278  Thread = find_thread(Pid, Tid);
280 #else
281  Pid = hex_to_pid(&gdb_input[18]);
282  Tid = hex_to_tid(strstr(&gdb_input[18], ".") + 1);
283 
284  /* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL.
285  * So loop. */
286  KDDBGPRINT(" p%p.%p.\n", Pid, Tid);
287 
288  Process = find_process(Pid);
289  Thread = find_thread(Pid, Tid);
290 #endif
291 
292  if (PsGetThreadProcessId(Thread) == 0)
293  {
294  String.Length = sprintf(out_string, "SYSTEM");
295  }
296  else
297  {
298  String.Length = sprintf(out_string, "%.*s", 16, Process->ImageFileName);
299  }
300 
301  return gdb_send_debug_io(&String, FALSE);
302  }
303 
304  if (strncmp(gdb_input, "qOffsets", 8) == 0)
305  {
306  /* We load ntoskrnl at 0x80800000 while compiling it at 0x00800000 base address */
307  return send_gdb_packet("TextSeg=80000000");
308  }
309 
310  if (strcmp(gdb_input, "qTStatus") == 0)
311  {
312  /* No tracepoint support */
313  return send_gdb_packet("T0");
314  }
315 
316  if (strcmp(gdb_input, "qSymbol::") == 0)
317  {
318  /* No need */
319  return send_gdb_packet("OK");
320  }
321 
322  if (strncmp(gdb_input, "qXfer:libraries:read::", 22) == 0)
323  {
324  static LIST_ENTRY* CurrentEntry = NULL;
325  char str_helper[256];
326  char name_helper[64];
328  ULONG_PTR ToSend = hex_to_address(strstr(&gdb_input[22], ",") + 1);
329  ULONG Sent = 0;
330  static BOOLEAN allDone = FALSE;
331 
332  KDDBGPRINT("KDGDB: qXfer:libraries:read !\n");
333 
334  /* Start the packet */
336 
337  if (allDone)
338  {
340  allDone = FALSE;
341  return finish_gdb_packet();
342  }
343 
345  Sent++;
346 
347  /* Are we starting ? */
348  if (Offset == 0)
349  {
350  Sent += send_gdb_partial_binary("<?xml version=\"1.0\"?>", 21);
351  Sent += send_gdb_partial_binary("<library-list>", 14);
352 
353  CurrentEntry = ModuleListHead->Flink;
354 
355  if (!CurrentEntry)
356  {
357  /* Ps is not initialized. Send end of XML data or mark that we are finished. */
358  Sent += send_gdb_partial_binary("</library-list>", 15);
359  allDone = TRUE;
360  return finish_gdb_packet();
361  }
362  }
363 
364  for ( ;
365  CurrentEntry != ModuleListHead;
366  CurrentEntry = CurrentEntry->Flink)
367  {
368  PLDR_DATA_TABLE_ENTRY TableEntry = CONTAINING_RECORD(CurrentEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
369  PVOID DllBase = (PVOID)((ULONG_PTR)TableEntry->DllBase + 0x1000);
370  LONG mem_length;
371  char* ptr;
372 
373  /* Convert names to lower case. Yes this _is_ ugly */
374  _snprintf(name_helper, 64, "%wZ", &TableEntry->BaseDllName);
375  for (ptr = name_helper; *ptr; ptr++)
376  {
377  if (*ptr >= 'A' && *ptr <= 'Z')
378  *ptr += 'a' - 'A';
379  }
380 
381  /* GDB doesn't load the file if you don't prefix it with a drive letter... */
382  mem_length = _snprintf(str_helper, 256, "<library name=\"C:\\%s\"><segment address=\"0x%p\"/></library>", &name_helper, DllBase);
383 
384  /* DLL name must be too long. */
385  if (mem_length < 0)
386  {
387  KDDBGPRINT("Failed to report %wZ\n", &TableEntry->BaseDllName);
388  continue;
389  }
390 
391  if ((Sent + mem_length) > ToSend)
392  {
393  /* We're done for this pass */
394  return finish_gdb_packet();
395  }
396 
397  Sent += send_gdb_partial_binary(str_helper, mem_length);
398  }
399 
400  if ((ToSend - Sent) > 15)
401  {
402  Sent += send_gdb_partial_binary("</library-list>", 15);
403  allDone = TRUE;
404  }
405 
406  return finish_gdb_packet();
407 
408  }
409 
410  KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input);
411  return send_gdb_packet("");
412 }
413 
414 #if 0
415 static
416 KDSTATUS
417 handle_gdb_registers(
419  _Out_ PSTRING MessageData,
420  _Out_ PULONG MessageLength)
421 {
422  /*
423  if (gdb_dbg_thread)
424  KDDBGPRINT("Should get registers from other thread!\n");
425  */
426 
427  State->ApiNumber = DbgKdGetContextApi;
428  State->ReturnStatus = STATUS_SUCCESS; /* ? */
429  State->Processor = CurrentStateChange.Processor;
430  State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
431  if (MessageData)
432  MessageData->Length = 0;
433  *MessageLength = 0;
434  return KdPacketReceived;
435 }
436 #endif
437 
438 static
439 void
441  _In_ ULONG PacketType,
442  _In_ PSTRING MessageHeader,
443  _In_ PSTRING MessageData)
444 {
445  DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
446 
447  if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
448  {
449  // KdAssert
450  KDDBGPRINT("Wrong packet type (%lu) received after DbgKdReadVirtualMemoryApi request.\n", PacketType);
451  while (1);
452  }
453 
454  if (State->ApiNumber != DbgKdReadVirtualMemoryApi)
455  {
456  KDDBGPRINT("Wrong API number (%lu) after DbgKdReadVirtualMemoryApi request.\n", State->ApiNumber);
457  }
458 
459  /* Check status. Allow to send partial data. */
460  if (!MessageData->Length && !NT_SUCCESS(State->ReturnStatus))
461  send_gdb_ntstatus(State->ReturnStatus);
462  else
463  send_gdb_memory(MessageData->Buffer, MessageData->Length);
466 
467 #if MONOPROCESS
468  if (gdb_dbg_tid != 0)
469  /* Reset the TLB */
470 #else
472 #endif
473  {
474  /* Only do this if Ps is initialized */
475  if (ProcessListHead->Flink)
476  __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
477  }
478 }
479 
480 static
481 KDSTATUS
484  _Out_ PSTRING MessageData,
485  _Out_ PULONG MessageLength,
486  _Inout_ PKD_CONTEXT KdContext)
487 {
488  State->ApiNumber = DbgKdReadVirtualMemoryApi;
489  State->ReturnStatus = STATUS_SUCCESS; /* ? */
490  State->Processor = CurrentStateChange.Processor;
491  State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
492  if (MessageData)
493  MessageData->Length = 0;
494  *MessageLength = 0;
495 
496  /* Set the TLB according to the process being read. Pid 0 means any process. */
497 #if MONOPROCESS
499  {
500  PETHREAD AttachedThread = find_thread(0, gdb_dbg_tid);
501  PKPROCESS AttachedProcess;
502  if (AttachedThread == NULL)
503  {
504  KDDBGPRINT("The current GDB debug thread is invalid!");
505  return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
506  }
507 
508  AttachedProcess = AttachedThread->Tcb.Process;
509  if (AttachedProcess == NULL)
510  {
511  KDDBGPRINT("The current GDB debug thread is invalid!");
512  return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
513  }
514  __writecr3(AttachedProcess->DirectoryTableBase[0]);
515  }
516 #else
518  {
519  PEPROCESS AttachedProcess = find_process(gdb_dbg_pid);
520  if (AttachedProcess == NULL)
521  {
522  KDDBGPRINT("The current GDB debug thread is invalid!");
523  return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
524  }
525  /* Only do this if Ps is initialized */
526  if (ProcessListHead->Flink)
527  __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]);
528  }
529 #endif
530 
531  State->u.ReadMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]);
532  State->u.ReadMemory.TransferCount = hex_to_address(strstr(&gdb_input[1], ",") + 1);
533 
534  /* KD will reply with KdSendPacket. Catch it */
536  return KdPacketReceived;
537 }
538 
539 static
540 void
542  _In_ ULONG PacketType,
543  _In_ PSTRING MessageHeader,
544  _In_ PSTRING MessageData)
545 {
546  DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
547 
548  if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
549  {
550  // KdAssert
551  KDDBGPRINT("Wrong packet type (%lu) received after DbgKdWriteVirtualMemoryApi request.\n", PacketType);
552  while (1);
553  }
554 
555  if (State->ApiNumber != DbgKdWriteVirtualMemoryApi)
556  {
557  KDDBGPRINT("Wrong API number (%lu) after DbgKdWriteVirtualMemoryApi request.\n", State->ApiNumber);
558  }
559 
560  /* Check status */
561  if (!NT_SUCCESS(State->ReturnStatus))
562  send_gdb_ntstatus(State->ReturnStatus);
563  else
564  send_gdb_packet("OK");
567 
568 #if MONOPROCESS
569  if (gdb_dbg_tid != 0)
570  /* Reset the TLB */
571 #else
573 #endif
574  {
575  /* Only do this if Ps is initialized */
576  if (ProcessListHead->Flink)
577  __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
578  }
579 }
580 
581 static
582 KDSTATUS
585  _Out_ PSTRING MessageData,
586  _Out_ PULONG MessageLength,
587  _Inout_ PKD_CONTEXT KdContext)
588 {
589  /* Maximal input buffer is 0x1000. Each byte is encoded on two bytes by GDB */
590  static UCHAR OutBuffer[0x800];
592  char* blob_ptr;
593  UCHAR* OutPtr;
594 
595  State->ApiNumber = DbgKdWriteVirtualMemoryApi;
596  State->ReturnStatus = STATUS_SUCCESS; /* ? */
597  State->Processor = CurrentStateChange.Processor;
598  State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
599 
600  /* Set the TLB according to the process being read. Pid 0 means any process. */
601 #if MONOPROCESS
603  {
604  PETHREAD AttachedThread = find_thread(0, gdb_dbg_tid);
605  PKPROCESS AttachedProcess;
606  if (AttachedThread == NULL)
607  {
608  KDDBGPRINT("The current GDB debug thread is invalid!");
609  return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
610  }
611 
612  AttachedProcess = AttachedThread->Tcb.Process;
613  if (AttachedProcess == NULL)
614  {
615  KDDBGPRINT("The current GDB debug thread is invalid!");
616  return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
617  }
618  __writecr3(AttachedProcess->DirectoryTableBase[0]);
619  }
620 #else
622  {
623  PEPROCESS AttachedProcess = find_process(gdb_dbg_pid);
624  if (AttachedProcess == NULL)
625  {
626  KDDBGPRINT("The current GDB debug thread is invalid!");
627  return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
628  }
629  /* Only do this if Ps is initialized */
630  if (ProcessListHead->Flink)
631  __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]);
632  }
633 #endif
634 
635  State->u.WriteMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]);
636  BufferLength = hex_to_address(strstr(&gdb_input[1], ",") + 1);
637  if (BufferLength == 0)
638  {
639  /* Nothing to do */
640  return LOOP_IF_SUCCESS(send_gdb_packet("OK"));
641  }
642 
643  State->u.WriteMemory.TransferCount = BufferLength;
644  MessageData->Length = BufferLength;
645  MessageData->Buffer = (CHAR*)OutBuffer;
646 
647  OutPtr = OutBuffer;
648  blob_ptr = strstr(strstr(&gdb_input[1], ",") + 1, ":") + 1;
649  while (BufferLength)
650  {
651  if (BufferLength >= 4)
652  {
653  *((ULONG*)OutPtr) = *((ULONG*)blob_ptr);
654  OutPtr += 4;
655  blob_ptr += 4;
656  BufferLength -= 4;
657  }
658  else if (BufferLength >= 2)
659  {
660  *((USHORT*)OutPtr) = *((USHORT*)blob_ptr);
661  OutPtr += 2;
662  blob_ptr += 2;
663  BufferLength -= 2;
664  }
665  else
666  {
667  *OutPtr++ = *blob_ptr++;
668  BufferLength--;
669  }
670  }
671 
672  /* KD will reply with KdSendPacket. Catch it */
674  return KdPacketReceived;
675 }
676 
677 static
678 void
680  _In_ ULONG PacketType,
681  _In_ PSTRING MessageHeader,
682  _In_ PSTRING MessageData)
683 {
684  DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
685 
686  if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
687  {
688  // KdAssert
689  KDDBGPRINT("Wrong packet type (%lu) received after DbgKdWriteBreakPointApi request.\n", PacketType);
690  while (1);
691  }
692 
693  if (State->ApiNumber != DbgKdWriteBreakPointApi)
694  {
695  KDDBGPRINT("Wrong API number (%lu) after DbgKdWriteBreakPointApi request.\n", State->ApiNumber);
696  }
697 
698  /* Check status */
699  if (!NT_SUCCESS(State->ReturnStatus))
700  {
701  KDDBGPRINT("Inserting breakpoint failed!\n");
702  send_gdb_ntstatus(State->ReturnStatus);
703  }
704  else
705  {
706  /* Keep track of the address+handle couple */
707  ULONG i;
708  for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++)
709  {
710  if (BreakPointHandles[i].Address == 0)
711  {
712  BreakPointHandles[i].Address = (ULONG_PTR)State->u.WriteBreakPoint.BreakPointAddress;
713  BreakPointHandles[i].Handle = State->u.WriteBreakPoint.BreakPointHandle;
714  break;
715  }
716  }
717  send_gdb_packet("OK");
718  }
721 }
722 
723 static
724 KDSTATUS
727  _Out_ PSTRING MessageData,
728  _Out_ PULONG MessageLength,
729  _Inout_ PKD_CONTEXT KdContext)
730 {
731  State->ReturnStatus = STATUS_SUCCESS; /* ? */
732  State->Processor = CurrentStateChange.Processor;
733  State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
734  if (MessageData)
735  MessageData->Length = 0;
736  *MessageLength = 0;
737 
738  switch (gdb_input[1])
739  {
740  case '0':
741  {
743  ULONG i;
744  BOOLEAN HasFreeSlot = FALSE;
745 
746  KDDBGPRINT("Inserting breakpoint at %p.\n", (void*)Address);
747 
748  for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++)
749  {
750  if (BreakPointHandles[i].Address == 0)
751  HasFreeSlot = TRUE;
752  }
753 
754  if (!HasFreeSlot)
755  {
756  /* We don't have a way to keep track of this break point. Fail. */
757  KDDBGPRINT("No breakpoint slot available!\n");
758  return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
759  }
760 
761  State->ApiNumber = DbgKdWriteBreakPointApi;
762  State->u.WriteBreakPoint.BreakPointAddress = Address;
763  /* FIXME : ignoring all other Z0 arguments */
764 
765  /* KD will reply with KdSendPacket. Catch it */
767  return KdPacketReceived;
768  }
769  }
770 
771  KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input);
772  return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
773 }
774 
775 static
776 void
778  _In_ ULONG PacketType,
779  _In_ PSTRING MessageHeader,
780  _In_ PSTRING MessageData)
781 {
782  DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
783  ULONG i;
784 
785  if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
786  {
787  // KdAssert
788  KDDBGPRINT("Wrong packet type (%lu) received after DbgKdRestoreBreakPointApi request.\n", PacketType);
789  while (1);
790  }
791 
792  if (State->ApiNumber != DbgKdRestoreBreakPointApi)
793  {
794  KDDBGPRINT("Wrong API number (%lu) after DbgKdRestoreBreakPointApi request.\n", State->ApiNumber);
795  }
796 
797  /* We ignore failure here. If DbgKdRestoreBreakPointApi fails,
798  * this means that the breakpoint was already invalid for KD. So clean it up on our side. */
799  for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++)
800  {
801  if (BreakPointHandles[i].Handle == State->u.RestoreBreakPoint.BreakPointHandle)
802  {
803  BreakPointHandles[i].Address = 0;
804  BreakPointHandles[i].Handle = 0;
805  break;
806  }
807  }
808 
809  send_gdb_packet("OK");
810 
813 }
814 
815 static
816 KDSTATUS
819  _Out_ PSTRING MessageData,
820  _Out_ PULONG MessageLength,
821  _Inout_ PKD_CONTEXT KdContext)
822 {
823  State->ReturnStatus = STATUS_SUCCESS; /* ? */
824  State->Processor = CurrentStateChange.Processor;
825  State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
826  if (MessageData)
827  MessageData->Length = 0;
828  *MessageLength = 0;
829 
830  switch (gdb_input[1])
831  {
832  case '0':
833  {
835  ULONG i, Handle = 0;
836 
837  KDDBGPRINT("Removing breakpoint on %p.\n", (void*)Address);
838 
839  for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++)
840  {
842  {
843  Handle = BreakPointHandles[i].Handle;
844  break;
845  }
846  }
847 
848  if (Handle == 0)
849  {
850  KDDBGPRINT("Received %s, but breakpoint was never inserted ?!\n", gdb_input);
851  return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
852  }
853 
854  State->ApiNumber = DbgKdRestoreBreakPointApi;
855  State->u.RestoreBreakPoint.BreakPointHandle = Handle;
856  /* FIXME : ignoring all other z0 arguments */
857 
858  /* KD will reply with KdSendPacket. Catch it */
860  return KdPacketReceived;
861  }
862  }
863 
864  KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input);
865  return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
866 }
867 
868 static
869 KDSTATUS
872  _Out_ PSTRING MessageData,
873  _Out_ PULONG MessageLength,
874  _Inout_ PKD_CONTEXT KdContext)
875 {
877 
878  /* Tell GDB everything is fine, we will handle it */
879  Status = send_gdb_packet("OK");
880  if (Status != KdPacketReceived)
881  return Status;
882 
883 
885  {
887  ULONG_PTR ProgramCounter = KdpGetContextPc(&CurrentContext);
888 
889  /* See if we should update the program counter */
890  if (Exception && (Exception->ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT)
891  && ((*(KD_BREAKPOINT_TYPE*)ProgramCounter) == KD_BREAKPOINT_VALUE))
892  {
893  /* We must get past the breakpoint instruction */
894  KdpSetContextPc(&CurrentContext, ProgramCounter + KD_BREAKPOINT_SIZE);
895 
896  SetContextManipulateHandler(State, MessageData, MessageLength, KdContext);
898  return KdPacketReceived;
899  }
900  }
901 
902  return ContinueManipulateStateHandler(State, MessageData, MessageLength, KdContext);
903 }
904 
905 static
906 KDSTATUS
909  _Out_ PSTRING MessageData,
910  _Out_ PULONG MessageLength,
911  _Inout_ PKD_CONTEXT KdContext)
912 {
913  KDDBGPRINT("Single stepping.\n");
914  /* Set CPU single step mode and continue */
915  KdpSetSingleStep(&CurrentContext);
916  SetContextManipulateHandler(State, MessageData, MessageLength, KdContext);
918  return KdPacketReceived;
919 }
920 
921 static
922 KDSTATUS
925  _Out_ PSTRING MessageData,
926  _Out_ PULONG MessageLength,
927  _Inout_ PKD_CONTEXT KdContext)
928 {
929  if (strncmp(gdb_input, "vCont", 5) == 0)
930  {
931  if (gdb_input[5] == '?')
932  {
933  /* Report what we support */
934  return LOOP_IF_SUCCESS(send_gdb_packet("vCont;c;s"));
935  }
936 
937  if (strncmp(gdb_input, "vCont;c", 7) == 0)
938  {
939  return handle_gdb_c(State, MessageData, MessageLength, KdContext);
940  }
941 
942  if (strncmp(gdb_input, "vCont;s", 7) == 0)
943  {
944 
945  return handle_gdb_s(State, MessageData, MessageLength, KdContext);
946  }
947  }
948 
949  KDDBGPRINT("Unhandled 'v' packet: %s\n", gdb_input);
950  return LOOP_IF_SUCCESS(send_gdb_packet(""));
951 }
952 
953 KDSTATUS
956  _Out_ PSTRING MessageData,
957  _Out_ PULONG MessageLength,
958  _Inout_ PKD_CONTEXT KdContext)
959 {
961 
962  do
963  {
964  KDDBGPRINT("KDGBD: Receiving packet.\n");
965  Status = gdb_receive_packet(KdContext);
966  KDDBGPRINT("KDGBD: Packet \"%s\" received with status %u\n", gdb_input, Status);
967 
968  if (Status != KdPacketReceived)
969  return Status;
970 
971  Status = (KDSTATUS)-1;
972 
973  switch (gdb_input[0])
974  {
975  case '?':
976  /* Send the Status */
978  break;
979  case '!':
981  break;
982  case 'c':
983  Status = handle_gdb_c(State, MessageData, MessageLength, KdContext);
984  break;
985  case 'g':
987  break;
988  case 'H':
990  break;
991  case 'm':
992  Status = handle_gdb_read_mem(State, MessageData, MessageLength, KdContext);
993  break;
994  case 'p':
996  break;
997  case 'q':
999  break;
1000  case 's':
1001  Status = handle_gdb_s(State, MessageData, MessageLength, KdContext);
1002  break;
1003  case 'T':
1005  break;
1006  case 'v':
1007  Status = handle_gdb_v(State, MessageData, MessageLength, KdContext);
1008  break;
1009  case 'X':
1010  Status = handle_gdb_write_mem(State, MessageData, MessageLength, KdContext);
1011  break;
1012  case 'z':
1013  Status = handle_gdb_remove_breakpoint(State, MessageData, MessageLength, KdContext);
1014  break;
1015  case 'Z':
1016  Status = handle_gdb_insert_breakpoint(State, MessageData, MessageLength, KdContext);
1017  break;
1018  default:
1019  /* We don't know how to handle this request. */
1020  KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input);
1022  }
1023  } while (Status == (KDSTATUS)-1);
1024 
1025  return Status;
1026 }
1027 
void send_gdb_partial_packet(_In_ const CHAR *Buffer)
Definition: gdb_send.c:60
#define KdPacketReceived
Definition: kddll.h:5
unsigned __int3264 UINT_PTR
Definition: activex.cpp:275
#define DbgKdWriteVirtualMemoryApi
Definition: windbgkd.h:75
#define TRUE
Definition: types.h:120
FORCEINLINE HANDLE gdb_tid_to_handle(UINT_PTR Tid)
Definition: kdgdb.h:35
void send_gdb_ntstatus(_In_ NTSTATUS Status)
Definition: gdb_send.c:231
ULONG_PTR DirectoryTableBase
Definition: ketypes.h:1977
union _DBGKD_ANY_WAIT_STATE_CHANGE::@3422 u
CONTEXT CurrentContext
Definition: kdpacket.c:29
#define KDDBGPRINT(...)
Definition: kddll.h:19
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
KDSTATUS gdb_send_registers(void)
Definition: i386_sup.c:150
#define DbgKdReadVirtualMemoryApi
Definition: windbgkd.h:74
char CHAR
Definition: xmlstorage.h:175
static void WriteMemorySendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: gdb_input.c:541
#define handle_to_gdb_pid
Definition: kdgdb.h:45
KTHREAD Tcb
Definition: pstypes.h:1034
NTSTATUS ExceptionCode
Definition: rtltypes.h:186
GLuint buffer
Definition: glext.h:5915
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
static ULONG64 hex_to_address(char *buffer)
Definition: gdb_input.c:51
KDSTATUS ContinueManipulateStateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:212
static WCHAR String[]
Definition: stringtable.c:55
KDSTATUS gdb_send_register(void)
Definition: i386_sup.c:221
#define DbgKdExceptionStateChange
Definition: windbgkd.h:59
static KDSTATUS handle_gdb_thread_alive(void)
Definition: gdb_input.c:122
KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler
Definition: kdpacket.c:26
PKPROCESS Process
Definition: ketypes.h:1798
static const char hex[16]
Definition: profile.c:123
#define DbgKdRestoreBreakPointApi
Definition: windbgkd.h:79
KDSTATUS send_gdb_memory(_In_ const VOID *Buffer, _In_ size_t Length)
Definition: gdb_send.c:158
DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange
Definition: kdpacket.c:28
KDSTATUS send_gdb_packet(_In_ const CHAR *Buffer)
Definition: gdb_send.c:100
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define KD_BREAKPOINT_VALUE
Definition: ke.h:119
KDSTATUS gdb_send_exception()
Definition: gdb_send.c:197
#define sprintf(buf, format,...)
Definition: sprintf.c:55
ULONG Handle
Definition: gdb_input.c:15
#define _snprintf
Definition: xmlstorage.h:200
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1675
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static void ReadMemorySendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: gdb_input.c:440
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
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
long LONG
Definition: pedump.c:60
_In_ ULONG BufferLength
Definition: usbdlib.h:225
static PVOID ptr
Definition: dispmode.c:27
#define PsGetCurrentProcess
Definition: psfuncs.h:17
KDP_SEND_HANDLER KdpSendPacketHandler
Definition: kdpacket.c:25
unsigned char BOOLEAN
static KDSTATUS handle_gdb_remove_breakpoint(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:817
smooth NULL
Definition: ftsmooth.c:416
#define STATUS_BREAKPOINT
Definition: ntstatus.h:172
#define _Out_
Definition: no_sal2.h:323
PETHREAD find_thread(_In_ UINT_PTR Pid, _In_ UINT_PTR Tid)
Definition: utils.c:41
PsGetCurrentThreadId
Definition: CrNtStubs.h:7
void * PVOID
Definition: retypes.h:9
static KDSTATUS handle_gdb_read_mem(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:482
static KDSTATUS handle_gdb_insert_breakpoint(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:725
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
char hex_value(char ch)
Definition: gdb_receive.c:15
KDSTATUS gdb_send_debug_io(_In_ PSTRING String, _In_ BOOLEAN WithPrefix)
Definition: gdb_send.c:168
static struct @591 BreakPointHandles[32]
KDSTATUS NTAPI gdb_receive_packet(_Inout_ PKD_CONTEXT KdContext)
Definition: gdb_receive.c:31
UINT_PTR gdb_dbg_tid
Definition: gdb_input.c:21
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE Handle
Definition: extypes.h:390
void start_gdb_packet(void)
Definition: gdb_send.c:52
UINT_PTR gdb_dbg_pid
Definition: gdb_input.c:20
static KDSTATUS handle_gdb_write_mem(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:583
ULONG send_gdb_partial_binary(_In_ const VOID *Buffer, _In_ size_t Length)
Definition: gdb_send.c:108
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
CLIENT_ID Cid
Definition: pstypes.h:1059
HANDLE NTAPI PsGetThreadProcessId(IN PETHREAD Thread)
Definition: thread.c:745
#define DbgKdGetContextApi
Definition: windbgkd.h:76
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define _Inout_
Definition: no_sal2.h:244
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
static UINT_PTR hex_to_tid(char *buffer)
Definition: gdb_input.c:33
HANDLE UniqueThread
Definition: compat.h:483
std::wstring STRING
Definition: fontsub.cpp:33
#define PACKET_TYPE_KD_STATE_MANIPULATE
Definition: windbgkd.h:43
unsigned __int64 ULONG64
Definition: imports.h:198
EXCEPTION_RECORD64 ExceptionRecord
Definition: windbgkd.h:303
unsigned char UCHAR
Definition: xmlstorage.h:181
static KDSTATUS handle_gdb_c(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:870
int ret
#define PRIxPTR
Definition: inttypes.h:236
#define hex_to_pid
Definition: gdb_input.c:47
PEPROCESS find_process(_In_ UINT_PTR Pid)
Definition: utils.c:16
Definition: btrfs_drv.h:1853
Definition: typedefs.h:117
KPROCESS Pcb
Definition: pstypes.h:1193
HANDLE NTAPI PsGetThreadId(IN PETHREAD Thread)
Definition: thread.c:705
static KDSTATUS handle_gdb_set_thread(void)
Definition: gdb_input.c:69
Status
Definition: gdiplustypes.h:24
KDSTATUS SetContextManipulateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:106
#define KD_BREAKPOINT_TYPE
Definition: ke.h:117
#define _In_
Definition: no_sal2.h:204
LIST_ENTRY * ProcessListHead
Definition: kdpacket.c:22
#define DbgKdWriteBreakPointApi
Definition: windbgkd.h:78
static void RestoreBreakPointSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: gdb_input.c:777
unsigned short USHORT
Definition: pedump.c:61
ULONG KDSTATUS
Definition: kddll.h:4
unsigned int * PULONG
Definition: retypes.h:1
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
UINT Sent
Definition: arping.c:39
static ULONG_PTR gdb_run_tid
Definition: gdb_input.c:11
DBGKM_EXCEPTION64 Exception
Definition: windbgkd.h:488
static KDSTATUS handle_gdb_v(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:923
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:3947
static KDSTATUS handle_gdb_s(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:907
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
FORCEINLINE UINT_PTR handle_to_gdb_tid(HANDLE Handle)
Definition: kdgdb.h:41
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ULONG_PTR Address
Definition: gdb_input.c:14
#define ULONG_PTR
Definition: config.h:101
CHAR gdb_input[0x1000]
Definition: gdb_receive.c:11
#define KD_BREAKPOINT_SIZE
Definition: ke.h:118
#define gdb_pid_to_handle
Definition: kdgdb.h:39
static KDSTATUS handle_gdb_query(void)
Definition: gdb_input.c:156
return STATUS_SUCCESS
Definition: btrfs.c:2938
static KDSTATUS LOOP_IF_SUCCESS(x)
Definition: gdb_input.c:25
static void WriteBreakPointSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: gdb_input.c:679
LIST_ENTRY * ModuleListHead
Definition: kdpacket.c:23
KDSTATUS finish_gdb_packet(void)
Definition: gdb_send.c:74