ReactOS  0.4.15-dev-448-gd6c4411
gdbstub.c
Go to the documentation of this file.
1 /****************************************************************************
2 
3  THIS SOFTWARE IS NOT COPYRIGHTED
4 
5  HP offers the following for use in the public domain. HP makes no
6  warranty with regard to the software or it's performance and the
7  user accepts the software "AS IS" with all faults.
8 
9  HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10  TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12 
13 ****************************************************************************/
14 /****************************************************************************
15  * Contributor: Lake Stevens Instrument Division$
16  *
17  * Description: low level support for gdb debugger. $
18  *
19  * Written by: Glenn Engel $
20  * ModuleState: Experimental $
21  *
22  * Modified for 386 by Jim Kingdon, Cygnus Support.
23  * Modified for ReactOS by Casper S. Hornstrup <chorns@users.sourceforge.net>
24  *
25  ****************************************************************************/
26 
27 #include <ntoskrnl.h>
28 #define NDEBUG
29 #include <debug.h>
30 
31 /************************************************************************/
32 
35 
36 static CONST CHAR HexChars[] = "0123456789abcdef";
37 
38 static PETHREAD GspRunThread; /* NULL means run all threads */
41 
43 
45 
46 /* FIXME hardcoded for COM2, 115200 baud */
49 
50 static CHAR GspInBuffer[1000];
51 static CHAR GspOutBuffer[1000];
52 
53 /* Number of Registers. */
54 #define NUMREGS 16
55 
57 {
58  EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
59  PC /* also known as eip */ ,
60  PS /* also known as eflags */ ,
61  CS, SS, DS, ES, FS, GS
62 };
63 
64 typedef struct _CPU_REGISTER
65 {
71 
73 {
74  { 4, FIELD_OFFSET(KTRAP_FRAME, Eax), FIELD_OFFSET(CONTEXT, Eax), TRUE },
75  { 4, FIELD_OFFSET(KTRAP_FRAME, Ecx), FIELD_OFFSET(CONTEXT, Ecx), TRUE },
76  { 4, FIELD_OFFSET(KTRAP_FRAME, Edx), FIELD_OFFSET(CONTEXT, Edx), FALSE },
77  { 4, FIELD_OFFSET(KTRAP_FRAME, Ebx), FIELD_OFFSET(CONTEXT, Ebx), TRUE },
78  { 4, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp), FIELD_OFFSET(CONTEXT, Esp), TRUE },
79  { 4, FIELD_OFFSET(KTRAP_FRAME, DbgEbp), FIELD_OFFSET(CONTEXT, Ebp), TRUE },
80  { 4, FIELD_OFFSET(KTRAP_FRAME, Esi), FIELD_OFFSET(CONTEXT, Esi), TRUE },
81  { 4, FIELD_OFFSET(KTRAP_FRAME, Edi), FIELD_OFFSET(CONTEXT, Edi), TRUE },
82  { 4, FIELD_OFFSET(KTRAP_FRAME, DbgEip), FIELD_OFFSET(CONTEXT, Eip), TRUE },
83  { 4, FIELD_OFFSET(KTRAP_FRAME, EFlags), FIELD_OFFSET(CONTEXT, EFlags), TRUE },
84  { 4, FIELD_OFFSET(KTRAP_FRAME, SegCs), FIELD_OFFSET(CONTEXT, SegCs), TRUE },
85  { 4, FIELD_OFFSET(KTRAP_FRAME, HardwareSegSs), FIELD_OFFSET(CONTEXT, SegSs), TRUE },
86  { 4, FIELD_OFFSET(KTRAP_FRAME, SegDs), FIELD_OFFSET(CONTEXT, SegDs), TRUE },
87  { 4, FIELD_OFFSET(KTRAP_FRAME, SegEs), FIELD_OFFSET(CONTEXT, SegEs), TRUE },
88  { 4, FIELD_OFFSET(KTRAP_FRAME, SegFs), FIELD_OFFSET(CONTEXT, SegFs), TRUE },
89  { 4, FIELD_OFFSET(KTRAP_FRAME, SegGs), FIELD_OFFSET(CONTEXT, SegGs), TRUE }
90 };
91 
93 {
94  "Initialized",
95  "Ready",
96  "Running",
97  "Standby",
98  "Terminated",
99  "Waiting",
100  "Transition",
101  "DeferredReady"
102 };
103 
104 LONG
106 {
107  if ((ch >= '0') && (ch <= '9'))
108  return (ch - '0');
109 
110  if ((ch >= 'a') && (ch <= 'f'))
111  return (ch - 'a' + 10);
112 
113  if ((ch >= 'A') && (ch <= 'F'))
114  return (ch - 'A' + 10);
115 
116  return -1;
117 }
118 
119 VOID
121 {
123 }
124 
125 UCHAR
127 {
128  UCHAR Value;
129 
130  while (!KdPortGetByteEx(&GdbPortInfo, &Value)) ;
131  return Value;
132 }
133 
134 /* scan for the sequence $<data>#<Checksum> */
135 PCHAR
137 {
138  PCHAR Buffer = &GspInBuffer[0];
139  CHAR Checksum;
140  CHAR XmitChecksum;
141  ULONG Count;
142  CHAR ch;
143 
144  while (TRUE)
145  {
146  /* wait around for the start character, ignore all other characters */
147  while ((ch = GdbGetChar()) != '$') ;
148 
149 retry:
150  Checksum = 0;
151  XmitChecksum = -1;
152  Count = 0;
153 
154  /* now, read until a # or end of Buffer is found */
155  while (Count < sizeof(GspInBuffer) - 1)
156  {
157  ch = GdbGetChar();
158  if (ch == '$')
159  goto retry;
160 
161  if (ch == '#')
162  break;
163 
164  Checksum = Checksum + ch;
165  Buffer[Count] = ch;
166  Count = Count + 1;
167  }
168  Buffer[Count] = 0;
169 
170  if (ch == '#')
171  {
172  ch = GdbGetChar();
173  XmitChecksum = (CHAR)(HexValue(ch) << 4);
174  ch = GdbGetChar();
175  XmitChecksum += (CHAR)(HexValue(ch));
176 
177  if (Checksum != XmitChecksum)
178  {
179  GdbPutChar('-'); /* failed checksum */
180  }
181  else
182  {
183  GdbPutChar('+'); /* successful transfer */
184  return &Buffer[0];
185  }
186  }
187  }
188 }
189 
190 /* send the packet in Buffer. */
191 VOID
193 {
194  CHAR Checksum;
195  LONG Count;
196  CHAR ch;
197 
198  /* $<packet info>#<Checksum>. */
199  do
200  {
201  GdbPutChar('$');
202  Checksum = 0;
203  Count = 0;
204 
205  while ((ch = Buffer[Count]))
206  {
207  GdbPutChar(ch);
208  Checksum += ch;
209  Count += 1;
210  }
211 
212  GdbPutChar('#');
213  GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
214  GdbPutChar(HexChars[Checksum & 0xf]);
215  }
216  while (GdbGetChar() != '+');
217 }
218 
219 VOID
221 {
222  CHAR Checksum;
223  LONG Count;
224  CHAR ch;
225 
226  /* $<packet info>#<Checksum>. */
227  GdbPutChar('$');
228  Checksum = 0;
229  Count = 0;
230 
231  while ((ch = Buffer[Count]))
232  {
233  GdbPutChar(ch);
234  Checksum += ch;
235  Count += 1;
236  }
237 
238  GdbPutChar('#');
239  GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
240  GdbPutChar(HexChars[Checksum & 0xf]);
241 }
242 
243 /* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an error. */
244 static volatile BOOLEAN GspMemoryError = FALSE;
245 
246 static CHAR
248 {
249  CHAR Ch = 0;
250 
251 #if 0
253  0, MMDBG_COPY_UNSAFE, NULL)))
254 #else
257 #endif
258  {
260  }
261 
262  return Ch;
263 }
264 
265 static void
267 {
268 #if 0
271 #else
274 #endif
275  {
277  }
278 }
279 
280 /* Convert the memory pointed to by Address into hex, placing result in Buffer
281  * Return a pointer to the last char put in Buffer (null)
282  * If MayFault is TRUE, then we should set GspMemoryError in response to
283  * a fault; if FALSE treat a fault like any other fault in the stub.
284  */
285 static PCHAR
287 {
288  ULONG i;
289  CHAR ch;
290 
291  for (i = 0; i < (ULONG)Count; i++)
292  {
293  if (MayFault)
294  {
295  ch = GspReadMemSafe(Address);
296  if (GspMemoryError)
297  return Buffer;
298  }
299  else
300  {
301  ch = *Address;
302  }
303  *Buffer++ = HexChars[(ch >> 4) & 0xf];
304  *Buffer++ = HexChars[ch & 0xf];
305  Address++;
306  }
307 
308  *Buffer = 0;
309  return Buffer;
310 }
311 
312 static ULONG
314  CHAR (*GetContent)(PVOID Context, ULONG Offset), PVOID Context)
315 {
316  PCHAR Current;
317  PCHAR Page;
318  ULONG CountInPage;
319  ULONG i;
320  CHAR ch;
321 
322  Current = Address;
323  while (Current < Address + Count)
324  {
325  Page = (PCHAR)PAGE_ROUND_DOWN(Current);
326  if (Address + Count <= Page + PAGE_SIZE)
327  {
328  /* Fits in this page */
329  CountInPage = Count;
330  }
331  else
332  {
333  /* Flows into next page, handle only current page in this iteration */
334  CountInPage = PAGE_SIZE - (Address - Page);
335  }
336 
337  for (i = 0; i < CountInPage && !GspMemoryError; i++)
338  {
339  ch = (*GetContent)(Context, Current - Address);
340 
341  if (MayFault)
342  GspWriteMemSafe(Current, ch);
343  else
344  *Current = ch;
345 
346  Current++;
347  }
348  if (MayFault)
349  {
350  if (GspMemoryError)
351  return Current - Address;
352  }
353  }
354 
355  return Current - Address;
356 }
357 
358 static CHAR
360 {
361  return (CHAR)((HexValue(*((PCHAR)Context + 2 * Offset)) << 4) +
362  HexValue(*((PCHAR)Context + 2 * Offset + 1)));
363 }
364 
365 /* Convert the hex array pointed to by Buffer into binary to be placed at Address
366  * Return a pointer to the character AFTER the last byte read from Buffer */
367 static PCHAR
369 {
371  return Buffer + 2 * Count;
372 }
373 
374 /**********************************************/
375 /* WHILE WE FIND NICE HEX CHARS, BUILD A LONG */
376 /* RETURN NUMBER OF CHARS PROCESSED */
377 /**********************************************/
378 LONG
380 {
381  LONG NumChars = 0;
382  LONG Hex;
383 
384  *Value = 0;
385 
386  while (**Address)
387  {
388  Hex = HexValue(**Address);
389  if (Hex >= 0)
390  {
391  *Value = (*Value << 4) | Hex;
392  NumChars++;
393  }
394  else
395  {
396  break;
397  }
398 
399  (*Address)++;
400  }
401 
402  return NumChars;
403 }
404 
405 VOID
407 {
408  LONG Save;
409 
410  Save = (((Value >> 0) & 0xff) << 24) | (((Value >> 8) & 0xff) << 16) |
411  (((Value >> 16) & 0xff) << 8) | (((Value >> 24) & 0xff) << 0);
412 
414 }
415 
416 /*
417  * When coming from kernel mode, Esp is not stored in the trap frame.
418  * Instead, it was pointing to the location of the TrapFrame Esp member
419  * when the exception occured. When coming from user mode, Esp is just
420  * stored in the TrapFrame Esp member.
421  */
422 static LONG
424 {
425  return KeGetPreviousMode() == KernelMode ?
426  (LONG)&TrapFrame->HardwareEsp : (LONG)TrapFrame->HardwareEsp;
427 }
428 
429 static VOID
431 {
433  PULONG p;
434  ULONG i;
436  ULONG_PTR *KernelStack;
437 
438  if (NULL == GspDbgThread)
439  {
441  }
442  else
443  {
444  TrapFrame = GspDbgThread->Tcb.TrapFrame;
446  }
447 
448  if (Waiting == Thread->Tcb.State)
449  {
450  KernelStack = Thread->Tcb.KernelStack;
451  for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
452  {
453  switch (i)
454  {
455  case EBP:
456  Value = KernelStack[3];
457  break;
458  case EDI:
459  Value = KernelStack[4];
460  break;
461  case ESI:
462  Value = KernelStack[5];
463  break;
464  case EBX:
465  Value = KernelStack[6];
466  break;
467  case PC:
468  Value = KernelStack[7];
469  break;
470  case ESP:
471  Value = (ULONG_PTR)(KernelStack + 8);
472  break;
473  case CS:
475  break;
476  case DS:
478  break;
479  default:
480  Value = 0;
481  break;
482  }
483 
485  }
486  }
487  else
488  {
489  for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
490  {
491  if (TrapFrame)
492  {
493  if (ESP == i)
494  {
495  Value = GspGetEspFromTrapFrame(TrapFrame);
496  }
497  else
498  {
499  p = (PULONG)((ULONG_PTR)TrapFrame + GspRegisters[i].OffsetInTF);
500  Value = *p;
501  }
502  }
503  else if (i == PC)
504  {
505  /*
506  * This thread has not been sheduled yet so assume it
507  * is still in PsBeginThreadWithContextInternal().
508  */
510  }
511  else
512  {
513  Value = 0;
514  }
515 
517  }
518  }
519 }
520 
521 VOID
523 {
524  ULONG Value;
525  PCHAR Buffer;
526  PULONG p;
527  ULONG i;
528 
529  if (!TrapFrame)
530  return;
531 
532  Buffer = Address;
533  for (i = 0; i < NUMREGS; i++)
534  {
535  if (GspRegisters[i].SetInContext)
536  {
538  }
539  else
540  {
541  p = (PULONG)((ULONG_PTR)TrapFrame + GspRegisters[i].OffsetInTF);
542  }
543 
544  Value = 0;
546  *p = Value;
547  }
548 }
549 
550 VOID
552 {
553  ULONG Value;
554  PULONG p;
555 
556  if (!TrapFrame)
557  return;
558 
559  if (GspRegisters[Number].SetInContext)
560  {
562  }
563  else
564  {
565  p = (PULONG)((ULONG_PTR)TrapFrame + GspRegisters[Number].OffsetInTF);
566  }
567 
568  Value = 0;
570  *p = Value;
571 }
572 
573 BOOLEAN
575 {
577 
578  if (strcmp(Data, "-1") == 0)
579  {
580  /* All threads */
581  ThreadInfo = NULL;
582  }
583  else
584  {
585  ULONG uThreadId;
586  HANDLE ThreadId;
587  PCHAR ptr = &Data[0];
588 
589  GspHex2Long(&ptr, (PLONG)&uThreadId);
590  ThreadId = (HANDLE)uThreadId;
591 
593  {
594  *Thread = NULL;
595  return FALSE;
596  }
597  }
598 
599  *Thread = ThreadInfo;
600  return TRUE;
601 }
602 
603 VOID
605 {
607  PCHAR ptr = &Request[1];
608 
609  switch (Request[0])
610  {
611  case 'c': /* Run thread */
613  {
614  GspOutBuffer[0] = 'O';
615  GspOutBuffer[1] = 'K';
616 
617  if (NULL != GspRunThread)
619 
621 
622  if (NULL != GspRunThread)
624  }
625  else
626  {
627  GspOutBuffer[0] = 'E';
628  }
629  break;
630 
631  case 'g': /* Debug thread */
633  {
634  GspOutBuffer[0] = 'O';
635  GspOutBuffer[1] = 'K';
636 
637  if (NULL != GspDbgThread)
639 
641  {
642  GspDbgThread = NULL;
644  }
645  else
646  {
648  }
649  }
650  else
651  {
652  GspOutBuffer[0] = 'E';
653  }
654  break;
655 
656  default:
657  break;
658  }
659 }
660 
661 VOID
663 {
664  ULONG Value;
665 
666  if (strncmp(Request, "C", 1) == 0)
667  {
668  PCHAR ptr = &GspOutBuffer[2];
669 
670  /* Get current thread id */
671  GspOutBuffer[0] = 'Q';
672  GspOutBuffer[1] = 'C';
673 
674  if (NULL != GspDbgThread)
676  else
677  Value = (ULONG)PsGetCurrentThread()->Cid.UniqueThread;
678 
679  GspLong2Hex(&ptr, Value);
680  }
681  else if (strncmp(Request, "fThreadInfo", 11) == 0)
682  {
684  PLIST_ENTRY AThread, AProcess;
685  PCHAR ptr = &GspOutBuffer[1];
686 
687  /* Get first thread id */
689  AProcess = PsActiveProcessHead.Flink;
690  while (AProcess != &PsActiveProcessHead)
691  {
692  Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
693  AThread = Process->ThreadListHead.Flink;
694  if (AThread != &Process->ThreadListHead)
695  {
696  GspEnumThread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
697  ETHREAD, ThreadListEntry);
698  break;
699  }
700  AProcess = AProcess->Flink;
701  }
702  if (GspEnumThread != NULL)
703  {
704  GspOutBuffer[0] = 'm';
706  GspLong2Hex(&ptr, Value);
707  }
708  else
709  {
710  /* FIXME - what to do here? This case should never happen though, there
711  should always be at least one thread on the system... */
712  /* GspOutBuffer[0] = 'l'; */
713  }
714  }
715  else if (strncmp(Request, "sThreadInfo", 11) == 0)
716  {
718  PLIST_ENTRY AThread, AProcess;
719  PCHAR ptr = &GspOutBuffer[1];
720 
721  /* Get next thread id */
722  if (GspEnumThread != NULL)
723  {
724  /* find the next thread */
725  Process = GspEnumThread->ThreadsProcess;
726  if (GspEnumThread->ThreadListEntry.Flink != &Process->ThreadListHead)
727  {
729  ETHREAD, ThreadListEntry);
730  }
731  else
732  {
733  PETHREAD Thread = NULL;
734  AProcess = Process->ActiveProcessLinks.Flink;
735  while (AProcess != &PsActiveProcessHead)
736  {
737  Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
738  AThread = Process->ThreadListHead.Flink;
739  if (AThread != &Process->ThreadListHead)
740  {
741  Thread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
742  ETHREAD, ThreadListEntry);
743  break;
744  }
745  AProcess = AProcess->Flink;
746  }
748  }
749 
750  if (GspEnumThread != NULL)
751  {
752  /* return the ID */
753  GspOutBuffer[0] = 'm';
755  GspLong2Hex(&ptr, Value);
756  }
757  else
758  {
759  GspOutBuffer[0] = 'l';
760  }
761  }
762  else
763  {
764  GspOutBuffer[0] = 'l';
765  }
766  }
767  else if (strncmp(Request, "ThreadExtraInfo", 15) == 0)
768  {
770 
771  /* Get thread information */
772  if (GspFindThread(Request + 16, &ThreadInfo))
773  {
774  char Buffer[64];
775  PEPROCESS Proc;
776 
777  Proc = (PEPROCESS)ThreadInfo->ThreadsProcess;
778 
779  Buffer[0] = '\0';
780 
781  if (NULL != Proc)
782  sprintf(Buffer, "%s [%d:0x%x], ",
783  Proc->ImageFileName,
784  (int)Proc->UniqueProcessId,
785  (int)ThreadInfo->Cid.UniqueThread);
786 
788 
790 
792  }
793  }
794  else if (strncmp(Request, "Supported", 9) == 0)
795  {
796  /* tell maximum incoming packet size */
797  sprintf(GspOutBuffer, "PacketSize=%u", sizeof(GspInBuffer) - 1);
798  }
799  else if (strncmp(Request, "Rcmd,", 5) == 0)
800  {
801  }
802 }
803 
804 VOID
806 {
808  PCHAR ptr = &Request[0];
809 
811  {
813 
814  GspOutBuffer[0] = 'O';
815  GspOutBuffer[1] = 'K';
816  GspOutBuffer[2] = '\0';
817  }
818  else
819  {
820  GspOutBuffer[0] = 'E';
821  GspOutBuffer[1] = '\0';
822  }
823 }
824 
825 #define DR6_BS 0x00004000 /* Single step */
826 
827 #define DR7_L0 0x00000001 /* Local breakpoint 0 enable */
828 #define DR7_G0 0x00000002 /* Global breakpoint 0 enable */
829 #define DR7_L1 0x00000004 /* Local breakpoint 1 enable */
830 #define DR7_G1 0x00000008 /* Global breakpoint 1 enable */
831 #define DR7_L2 0x00000010 /* Local breakpoint 2 enable */
832 #define DR7_G2 0x00000020 /* Global breakpoint 2 enable */
833 #define DR7_L3 0x00000040 /* Local breakpoint 3 enable */
834 #define DR7_G3 0x00000080 /* Global breakpoint 3 enable */
835 #define DR7_LE 0x00000100 /* Local exact breakpoint enable (old) */
836 #define DR7_GE 0x00000200 /* Global exact breakpoint enable (old) */
837 #define DR7_GD 0x00002000 /* General detect enable */
838 #define DR7_TYPE0_MASK 0x00030000 /* Breakpoint 0 condition */
839 #define DR7_LEN0_MASK 0x000c0000 /* Breakpoint 0 length */
840 #define DR7_TYPE1_MASK 0x00300000 /* Breakpoint 1 condition */
841 #define DR7_LEN1_MASK 0x00c00000 /* Breakpoint 1 length */
842 #define DR7_TYPE2_MASK 0x03000000 /* Breakpoint 2 condition */
843 #define DR7_LEN2_MASK 0x0c000000 /* Breakpoint 2 length */
844 #define DR7_TYPE3_MASK 0x30000000 /* Breakpoint 3 condition */
845 #define DR7_LEN3_MASK 0xc0000000 /* Breakpoint 3 length */
846 #define DR7_GLOBAL_ENABLE(Bp) (2 << (2 * (Bp)))
847 #define DR7_TYPE(Bp, Type) ((Type) << (16 + 4 * (Bp)))
848 #define DR7_LEN(Bp, Len) ((Len) << (18 + 4 * (Bp)))
849 
850 #define I386_BP_TYPE_EXECUTE 0
851 #define I386_BP_TYPE_DATA_WRITE 1
852 #define I386_BP_TYPE_DATA_READWRITE 3
853 
854 #define I386_OPCODE_INT3 0xcc
855 
856 #define GDB_ZTYPE_MEMORY_BREAKPOINT 0
857 #define GDB_ZTYPE_HARDWARE_BREAKPOINT 1
858 #define GDB_ZTYPE_WRITE_WATCHPOINT 2
859 #define GDB_ZTYPE_READ_WATCHPOINT 3
860 #define GDB_ZTYPE_ACCESS_WATCHPOINT 4
861 
862 typedef struct _GSPHWBREAKPOINT
863 {
868 
869 #define MAX_HW_BREAKPOINTS 4
870 static unsigned GspHwBreakpointCount = 0;
872 
873 typedef struct _GSPSWBREAKPOINT
874 {
879 
880 #define MAX_SW_BREAKPOINTS 64
881 static unsigned GspSwBreakpointCount = 0;
883 
884 static void
886 {
887  DPRINT("GspSetHwBreakpoint(%lu, 0x%p, %lu)\n", Type, Address, Length);
888 
890  {
891  DPRINT1("Read watchpoint not supported\n");
892  strcpy(GspOutBuffer, "E22");
893  }
894  else if (GDB_ZTYPE_HARDWARE_BREAKPOINT == Type && 1 != Length)
895  {
896  DPRINT1("Invalid length %lu for hardware breakpoint\n", Length);
897  strcpy(GspOutBuffer, "E22");
898  }
899  else if (1 != Length && 2 != Length && 4 != Length)
900  {
901  DPRINT1("Invalid length %lu for GDB Z type %lu\n", Length, Type);
902  strcpy(GspOutBuffer, "E22");
903  }
904  else if (0 != (Address & (Length - 1)))
905  {
906  DPRINT1("Invalid alignment for address 0x%p and length %d\n", Address, Length);
907  strcpy(GspOutBuffer, "E22");
908  }
910  {
911  DPRINT1("Trying to set too many hardware breakpoints\n");
912  strcpy(GspOutBuffer, "E22");
913  }
914  else
915  {
916  DPRINT("Stored at index %u\n", GspHwBreakpointCount);
921  strcpy(GspOutBuffer, "OK");
922  }
923 }
924 
925 static void
927 {
928  unsigned Index;
929 
930  DPRINT("GspRemoveHwBreakpoint(%lu, 0x%p, %lu)\n", Type, Address, Length);
931  for (Index = 0; Index < GspHwBreakpointCount; Index++)
932  {
933  if (GspHwBreakpoints[Index].Type == Type &&
936  {
937  DPRINT("Found match at index %u\n", Index);
938  if (Index + 1 < GspHwBreakpointCount)
940  GspHwBreakpoints + (Index + 1),
941  (GspHwBreakpointCount - Index - 1) * sizeof(GSPHWBREAKPOINT));
942 
944  strcpy(GspOutBuffer, "OK");
945  return;
946  }
947  }
948 
949  DPRINT1("Not found\n");
950  strcpy(GspOutBuffer, "E22");
951 }
952 
953 static BOOLEAN
955 {
956  ULONG Index;
957 
958  for (Index = 0; Index < GspSwBreakpointCount; Index++)
959  {
961  {
962  if (PIndex)
963  *PIndex = Index;
964  return TRUE;
965  }
966  }
967 
968  return FALSE;
969 }
970 
971 static void
973 {
974  DPRINT("GspSetSwBreakpoint(0x%p)\n", Address);
975 
977  {
978  DPRINT1("Trying to set too many software breakpoints\n");
979  strcpy(GspOutBuffer, "E22");
980  return;
981  }
982 
984  {
985  strcpy(GspOutBuffer, "E22");
986  return;
987  }
988 
989  DPRINT("Stored at index %u\n", GspSwBreakpointCount);
993  strcpy(GspOutBuffer, "OK");
994 }
995 
996 static void
998 {
999  ULONG Index;
1000 
1001  DPRINT("GspRemoveSwBreakpoint(0x%p)\n", Address);
1002 
1004  {
1005  DPRINT("Found match at index %u\n", Index);
1007 
1008  if (Index + 1 < GspSwBreakpointCount)
1010  GspSwBreakpoints + (Index + 1),
1011  (GspSwBreakpointCount - Index - 1) * sizeof(GSPSWBREAKPOINT));
1012 
1014  strcpy(GspOutBuffer, "OK");
1015  return;
1016  }
1017 
1018  DPRINT1("Not found\n");
1019  strcpy(GspOutBuffer, "E22");
1020 }
1021 
1022 static void
1023 GspLoadHwBreakpoint(PKTRAP_FRAME TrapFrame, unsigned BpIndex,
1025 {
1026  DPRINT("GspLoadHwBreakpoint(0x%p, %d, 0x%p, %d)\n",
1027  TrapFrame, BpIndex, Address, Type);
1028 
1029  /* Set the DR7_Gx bit to globally enable the breakpoint */
1030  TrapFrame->Dr7 |= DR7_GLOBAL_ENABLE(BpIndex) |
1031  DR7_LEN(BpIndex, Length) |
1032  DR7_TYPE(BpIndex, Type);
1033 
1034  switch (BpIndex)
1035  {
1036  case 0:
1037  DPRINT("Setting DR0 to 0x%p\n", Address);
1038  TrapFrame->Dr0 = Address;
1039  break;
1040 
1041  case 1:
1042  DPRINT("Setting DR1 to 0x%p\n", Address);
1043  TrapFrame->Dr1 = Address;
1044  break;
1045 
1046  case 2:
1047  DPRINT("Setting DR2 to 0x%p\n", Address);
1048  TrapFrame->Dr2 = Address;
1049  break;
1050 
1051  case 3:
1052  DPRINT("Setting DR3 to 0x%p\n", Address);
1053  TrapFrame->Dr3 = Address;
1054  break;
1055  }
1056 }
1057 
1058 static void
1060 {
1062 
1064 
1065  if (!GspMemoryError)
1067 
1069 
1070  if (GspMemoryError)
1071  DPRINT1("Failed to set software breakpoint at 0x%p\n", GspSwBreakpoints[Index].Address);
1072  else
1073  DPRINT("Successfully set software breakpoint at 0x%p\n", GspSwBreakpoints[Index].Address);
1074 }
1075 
1076 static void
1078 {
1079  unsigned Index;
1080  ULONG i386Type;
1081 
1082  DPRINT("GspLoadBreakpoints\n");
1083  DPRINT("DR7 on entry: 0x%08x\n", TrapFrame->Dr7);
1084 
1085  /* Remove all breakpoints */
1086  TrapFrame->Dr7 &= ~(DR7_L0 | DR7_L1 | DR7_L2 | DR7_L3 |
1087  DR7_G0 | DR7_G1 | DR7_G2 | DR7_G3 |
1092 
1093  for (Index = 0; Index < GspHwBreakpointCount; Index++)
1094  {
1095  switch (GspHwBreakpoints[Index].Type)
1096  {
1098  i386Type = I386_BP_TYPE_EXECUTE;
1099  break;
1101  i386Type = I386_BP_TYPE_DATA_WRITE;
1102  break;
1104  i386Type = I386_BP_TYPE_DATA_READWRITE;
1105  break;
1106  default:
1107  ASSERT(FALSE);
1108  i386Type = I386_BP_TYPE_EXECUTE;
1109  break;
1110  }
1111 
1113  GspHwBreakpoints[Index].Length - 1, i386Type);
1114  }
1115 
1116  for (Index = 0; Index < GspSwBreakpointCount; Index++)
1117  {
1118  DPRINT("Using real software breakpoint\n");
1120  }
1121 
1122  DPRINT("Final DR7 value 0x%08x\n", TrapFrame->Dr7);
1123 }
1124 
1125 static void
1127 {
1128  unsigned Index;
1129 
1130  DPRINT("GspUnloadBreakpoints\n");
1131 
1132  /* Disable hardware debugging while we are inside the stub */
1133  __writedr(7, 0);
1134 
1135  for (Index = 0; Index < GspSwBreakpointCount; Index++)
1136  {
1138  {
1141  GspSwBreakpoints[Index].PrevContent);
1143  if (GspMemoryError)
1144  {
1145  DPRINT1("Failed to remove software breakpoint from 0x%p\n",
1147  }
1148  else
1149  {
1150  DPRINT("Successfully removed software breakpoint from 0x%p\n",
1152  }
1153  }
1154  }
1155 }
1156 
1157 static void
1159 {
1161  ULONG SigVal;
1162  LONG Esp;
1163 
1164  switch (ExceptionCode)
1165  {
1167  SigVal = 8; /* divide by zero */
1168  break;
1169  case STATUS_SINGLE_STEP:
1170  case STATUS_BREAKPOINT:
1171  SigVal = 5; /* breakpoint */
1172  break;
1175  SigVal = 16; /* bound instruction */
1176  break;
1178  SigVal = 4; /* Invalid opcode */
1179  break;
1180  case STATUS_STACK_OVERFLOW:
1183  SigVal = 11; /* access violation */
1184  break;
1185  default:
1186  SigVal = 7; /* "software generated" */
1187  }
1188 
1189  ptr = GspOutBuffer;
1190 
1191  *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */
1192  *ptr++ = HexChars[(SigVal >> 4) & 0xf];
1193  *ptr++ = HexChars[SigVal & 0xf];
1194 
1195  *ptr++ = HexChars[ESP];
1196  *ptr++ = ':';
1197 
1198  Esp = GspGetEspFromTrapFrame(TrapFrame); /* SP */
1199  ptr = GspMem2Hex((PCHAR)&Esp, ptr, 4, 0);
1200  *ptr++ = ';';
1201 
1202  *ptr++ = HexChars[EBP];
1203  *ptr++ = ':';
1204  ptr = GspMem2Hex((PCHAR)&TrapFrame->Ebp, ptr, 4, 0); /* FP */
1205  *ptr++ = ';';
1206 
1207  *ptr++ = HexChars[PC];
1208  *ptr++ = ':';
1209  ptr = GspMem2Hex((PCHAR)&TrapFrame->Eip, ptr, 4, 0); /* PC */
1210  *ptr++ = ';';
1211 
1212  *ptr = '\0';
1213 }
1214 
1215 /*
1216  * This function does all command procesing for interfacing to GDB.
1217  */
1218 KD_CONTINUE_TYPE
1219 NTAPI
1221  PCONTEXT Context,
1222  PKTRAP_FRAME TrapFrame)
1223 {
1224  static BOOLEAN GdbAttached = FALSE;
1225  BOOLEAN Stepping = FALSE;
1227  LONG Address;
1228  LONG Length;
1229  PCHAR ptr;
1230 
1231  /* FIXME: Stop on other CPUs too */
1232 
1233  DPRINT("Thread %p entering stub\n", PsGetCurrentThread());
1234  ExceptionCode = (NTSTATUS)ExceptionRecord->ExceptionCode;
1235 
1236  /* Can only debug 1 thread at a time... */
1238  DPRINT("Thread %p acquired mutex\n", PsGetCurrentThread());
1239 
1241 
1242  /* Make sure we're debugging the current thread. */
1243  if (NULL != GspDbgThread)
1244  {
1245  DPRINT1("Internal error: entering stub with non-NULL GspDbgThread\n");
1247  GspDbgThread = NULL;
1248  }
1249 
1250  if (GdbAttached)
1251  {
1252  GspStopReply(ExceptionCode, TrapFrame);
1254  // DbgPrint(">>> (%s) >>>\n", GspOutBuffer);
1255  }
1256  else
1257  {
1258  GdbAttached = TRUE;
1259  }
1260 
1261  while (TRUE)
1262  {
1263  /* Zero the buffer now so we don't have to worry about the terminating zero character */
1264  memset(GspOutBuffer, 0, sizeof(GspOutBuffer));
1265  ptr = GspGetPacket();
1266  // DbgPrint("<<< (%s) <<<\n", ptr);
1267 
1268  switch (*ptr++)
1269  {
1270  case '?':
1271  /* a little hack to send more complete status information */
1272  GspStopReply(ExceptionCode, TrapFrame);
1273  break;
1274 
1275  case 'd':
1276  GspRemoteDebug = !GspRemoteDebug; /* toggle debug flag */
1277  break;
1278 
1279  case 'g': /* return the value of the CPU Registers */
1280  GspGetRegisters(GspOutBuffer, TrapFrame);
1281  break;
1282 
1283  case 'G': /* set the value of the CPU Registers - return OK */
1284  if (NULL != GspDbgThread)
1286  else
1287  GspSetRegistersInTrapFrame(ptr, Context, TrapFrame);
1288 
1289  strcpy(GspOutBuffer, "OK");
1290  break;
1291 
1292  case 'P': /* set the value of a single CPU register - return OK */
1293  {
1294  LONG Register;
1295 
1296  if ((GspHex2Long(&ptr, &Register)) && (*ptr++ == '='))
1297  {
1298  if ((Register >= 0) && (Register < NUMREGS))
1299  {
1300  if (GspDbgThread)
1301  {
1304  }
1305  else
1306  {
1307  GspSetSingleRegisterInTrapFrame(ptr, Register, Context, TrapFrame);
1308  }
1309  strcpy(GspOutBuffer, "OK");
1310  break;
1311  }
1312  }
1313 
1314  strcpy(GspOutBuffer, "E01");
1315  break;
1316  }
1317 
1318  /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
1319  case 'm':
1320  {
1321  /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
1322  if (GspHex2Long(&ptr, &Address) && *(ptr++) == ',' && GspHex2Long(&ptr, &Length))
1323  {
1324  PEPROCESS DbgProcess = NULL;
1325 
1326  ptr = NULL;
1327  if (NULL != GspDbgThread &&
1328  PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
1329  {
1330  DbgProcess = GspDbgThread->ThreadsProcess;
1331  KeAttachProcess(&DbgProcess->Pcb);
1332  }
1333 
1336 
1337  if (NULL != DbgProcess)
1338  KeDetachProcess();
1339 
1340  if (GspMemoryError)
1341  {
1342  strcpy(GspOutBuffer, "E03");
1343  DPRINT1("Fault during memory read\n");
1344  }
1345  ptr = NULL;
1346  }
1347 
1348  if (NULL != ptr)
1349  strcpy(GspOutBuffer, "E01");
1350 
1351  break;
1352  }
1353 
1354  /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
1355  case 'M':
1356  {
1357  /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
1358  if (GspHex2Long(&ptr, &Address))
1359  {
1360  if (*(ptr++) == ',' && GspHex2Long(&ptr, &Length) && *(ptr++) == ':')
1361  {
1362  PEPROCESS DbgProcess = NULL;
1363 
1364  if (NULL != GspDbgThread &&
1365  PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
1366  {
1367  DbgProcess = GspDbgThread->ThreadsProcess;
1368  KeAttachProcess(&DbgProcess->Pcb);
1369  }
1372  if (NULL != DbgProcess)
1373  KeDetachProcess();
1374 
1375  if (GspMemoryError)
1376  {
1377  strcpy(GspOutBuffer, "E03");
1378  DPRINT1("Fault during memory write\n");
1379  }
1380  else
1381  {
1382  strcpy(GspOutBuffer, "OK");
1383  }
1384  ptr = NULL;
1385  }
1386  }
1387 
1388  if (NULL != ptr)
1389  strcpy(GspOutBuffer, "E02");
1390 
1391  break;
1392  }
1393 
1394  /* cAA..AA Continue at address AA..AA */
1395  /* sAA..AA Step one instruction from AA..AA */
1396  case 's':
1397  Stepping = TRUE;
1398  case 'c':
1399  {
1400  ULONG BreakpointNumber;
1401  ULONG Dr6;
1402 
1403  /* try to read optional parameter, pc changed if param */
1404  if (GspHex2Long(&ptr, &Address))
1405  {
1406  Context->Eip = Address;
1407  }
1408  else if (ExceptionCode == STATUS_BREAKPOINT)
1409  {
1411  Context->Eip++;
1412  }
1413 
1414  /* clear the trace bit */
1415  Context->EFlags &= ~EFLAGS_TF;
1416 
1417  /* set the trace bit if we're Stepping */
1418  if (Stepping)
1419  Context->EFlags |= EFLAGS_TF;
1420 
1421  Dr6 = __readdr(6);
1422  if (!(Dr6 & DR6_BS))
1423  {
1424  for (BreakpointNumber = 0;
1425  BreakpointNumber < MAX_HW_BREAKPOINTS;
1426  BreakpointNumber++)
1427  {
1428  if (Dr6 & (1 << BreakpointNumber))
1429  {
1430  if (GspHwBreakpoints[BreakpointNumber].Type == I386_BP_TYPE_EXECUTE)
1431  {
1432  /* Set restore flag */
1433  Context->EFlags |= EFLAGS_RF;
1434  break;
1435  }
1436  }
1437  }
1438  }
1439 
1440  GspLoadBreakpoints(TrapFrame);
1441  __writedr(6, 0);
1442 
1443  if (NULL != GspDbgThread)
1444  {
1446  GspDbgThread = NULL;
1447  }
1448 
1449  DPRINT("Thread %p releasing mutex\n", PsGetCurrentThread());
1451  DPRINT("Thread %p leaving stub\n", PsGetCurrentThread());
1452 
1455  return kdContinue;
1456 
1457  return kdHandleException;
1458  }
1459 
1460  case 'k': /* kill the program */
1461  strcpy(GspOutBuffer, "OK");
1462  break;
1463 
1464  case 'H': /* Set thread */
1465  GspSetThread(ptr);
1466  break;
1467 
1468  case 'q': /* Query */
1469  GspQuery(ptr);
1470  break;
1471 
1472  case 'T': /* Query thread status */
1474  break;
1475 
1476  case 'Z':
1477  {
1478  LONG Type;
1479  LONG Address;
1480  LONG Length;
1481 
1482  GspHex2Long(&ptr, &Type);
1483  ptr++;
1484  GspHex2Long(&ptr, &Address);
1485  ptr++;
1486  GspHex2Long(&ptr, &Length);
1487 
1488  if (0 == Type)
1490  else
1492 
1493  break;
1494  }
1495 
1496  case 'z':
1497  {
1498  LONG Type;
1499  LONG Address;
1500  LONG Length;
1501 
1502  GspHex2Long(&ptr, &Type);
1503  ptr++;
1504  GspHex2Long(&ptr, &Address);
1505  ptr++;
1506  GspHex2Long(&ptr, &Length);
1507 
1508  if (0 == Type)
1510  else
1512 
1513  break;
1514  }
1515 
1516  default:
1517  break;
1518  }
1519 
1520  /* reply to the request */
1522  // DbgPrint(">>> (%s) >>>\n", GspOutBuffer);
1523  }
1524 }
1525 
1526 BOOLEAN
1527 NTAPI
1529 {
1530  PKTRAP_FRAME TrapFrame;
1531  BOOLEAN DoBreakIn;
1532  CONTEXT Context;
1533  KIRQL OldIrql;
1534  UCHAR Value;
1535 
1536  DPRINT("Break In\n");
1537 
1538  DoBreakIn = FALSE;
1539  while (KdPortGetByteEx(&GdbPortInfo, &Value))
1540  {
1541  if (Value == 0x03)
1542  DoBreakIn = TRUE;
1543  }
1544 
1545  if (!DoBreakIn)
1546  return TRUE;
1547 
1549 
1550  TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
1551 
1552  KeTrapFrameToContext(TrapFrame, NULL, &Context);
1553 
1555 
1556  KeContextToTrapFrame(&Context, NULL, TrapFrame, Context.ContextFlags, KernelMode);
1557 
1559 
1560  return TRUE;
1561 }
1562 
1563 VOID
1564 NTAPI
1566 {
1567 }
1568 
1569 /* Initialize the GDB stub */
1570 VOID
1571 NTAPI
1572 KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable, ULONG BootPhase)
1573 {
1574  if (!KdDebuggerEnabled || !KdpDebugMode.Gdb)
1575  return;
1576 
1577  if (BootPhase == 0)
1578  {
1580 
1581  /* Write out the functions that we support for now */
1582  WrapperTable->KdpInitRoutine = KdpGdbStubInit;
1583  WrapperTable->KdpPrintRoutine = KdpGdbDebugPrint;
1584  WrapperTable->KdpExceptionRoutine = KdpGdbEnterDebuggerException;
1585 
1586  /* Initialize the Port */
1588  }
1589  else if (BootPhase == 1)
1590  {
1591  GspInitialized = TRUE;
1592 
1593  GspRunThread = NULL;
1594  GspDbgThread = NULL;
1595  GspEnumThread = NULL;
1596 
1597  HalDisplayString("Waiting for GDB to attach\r\n");
1599  }
1600  else if (BootPhase == 2)
1601  {
1602  HalDisplayString("\r\n GDB debugging enabled\r\n\r\n");
1603  }
1604 }
1605 
1606 /* EOF */
VOID NTAPI KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, ULONG ContextFlags, KPROCESSOR_MODE PreviousMode)
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2373
signed char * PCHAR
Definition: retypes.h:7
CPPORT GdbPortInfo
Definition: gdbstub.c:48
Definition: gdbstub.c:61
BOOLEAN GspFindThread(PCHAR Data, PETHREAD *Thread)
Definition: gdbstub.c:574
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1782
static void GspRemoveHwBreakpoint(ULONG Type, ULONG_PTR Address, ULONG Length)
Definition: gdbstub.c:926
static PCHAR GspThreadStates[DeferredReady+1]
Definition: gdbstub.c:92
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
__INTRIN_INLINE void __writedr(unsigned reg, unsigned int value)
Definition: intrin_x86.h:1832
#define GDB_ZTYPE_ACCESS_WATCHPOINT
Definition: gdbstub.c:860
#define DR7_L1
Definition: gdbstub.c:829
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define MAX_SW_BREAKPOINTS
Definition: gdbstub.c:880
#define TRUE
Definition: types.h:120
#define DR7_L3
Definition: gdbstub.c:833
LIST_ENTRY ThreadListEntry
Definition: pstypes.h:1097
#define STATUS_ILLEGAL_INSTRUCTION
Definition: ntstatus.h:252
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
KDP_DEBUG_MODE KdpDebugMode
Definition: kdinit.c:25
#define I386_OPCODE_INT3
Definition: gdbstub.c:854
Type
Definition: Type.h:6
#define DR6_BS
Definition: gdbstub.c:825
VOID GdbPutChar(UCHAR Value)
Definition: gdbstub.c:120
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
struct _CPU_REGISTER * PCPU_REGISTER
KD_CONTINUE_TYPE NTAPI KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT Context, PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:1220
static void GspStopReply(NTSTATUS ExceptionCode, PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:1158
static CHAR GspOutBuffer[1000]
Definition: gdbstub.c:51
Definition: gdbstub.c:61
NTSTATUS NTAPI KdpCopyMemoryChunks(_In_ ULONG64 Address, _In_ PVOID Buffer, _In_ ULONG TotalSize, _In_ ULONG ChunkSize, _In_ ULONG Flags, _Out_opt_ PULONG ActualSize)
Definition: kdapi.c:50
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
Definition: gdbstub.c:58
#define GDB_ZTYPE_HARDWARE_BREAKPOINT
Definition: gdbstub.c:857
#define GDB_ZTYPE_READ_WATCHPOINT
Definition: gdbstub.c:859
#define DR7_TYPE2_MASK
Definition: gdbstub.c:842
static ULONG GspWriteMem(PCHAR Address, ULONG Count, BOOLEAN MayFault, CHAR(*GetContent)(PVOID Context, ULONG Offset), PVOID Context)
Definition: gdbstub.c:313
NTSTATUS NTAPI PsLookupThreadByThreadId(IN HANDLE ThreadId, OUT PETHREAD *Thread)
Definition: thread.c:643
char CHAR
Definition: xmlstorage.h:175
#define MAX_HW_BREAKPOINTS
Definition: gdbstub.c:869
#define KeGetPreviousMode()
Definition: ketypes.h:1107
LONG NTSTATUS
Definition: precomp.h:26
VOID GspSetThread(PCHAR Request)
Definition: gdbstub.c:604
#define STATUS_SINGLE_STEP
Definition: ntstatus.h:173
KTHREAD Tcb
Definition: pstypes.h:1042
static void GspRemoveSwBreakpoint(ULONG_PTR Address)
Definition: gdbstub.c:997
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
static PCHAR GspHex2Mem(PCHAR Buffer, PCHAR Address, ULONG Count, BOOLEAN MayFault)
Definition: gdbstub.c:368
#define DR7_G0
Definition: gdbstub.c:828
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
static CONST CHAR HexChars[]
Definition: gdbstub.c:36
static BOOLEAN GspRemoteDebug
Definition: gdbstub.c:34
#define KGDT_R0_CODE
Definition: ketypes.h:75
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
PKTRAP_FRAME TrapFrame
Definition: ketypes.h:1664
#define DR7_TYPE(Bp, Type)
Definition: gdbstub.c:847
struct _ThreadInfo ThreadInfo
ULONG GdbPortNumber
Definition: gdbstub.c:47
static void GspLoadSwBreakpoint(ULONG Index)
Definition: gdbstub.c:1059
VOID GspLong2Hex(PCHAR *Address, LONG Value)
Definition: gdbstub.c:406
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define DR7_GLOBAL_ENABLE(Bp)
Definition: gdbstub.c:846
#define Ch(x, y, z)
Definition: sha2.c:141
Definition: gdbstub.c:61
Definition: gdbstub.c:58
static GSPHWBREAKPOINT GspHwBreakpoints[MAX_HW_BREAKPOINTS]
Definition: gdbstub.c:871
static CHAR GspReadMemSafe(PCHAR Address)
Definition: gdbstub.c:247
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
static unsigned GspHwBreakpointCount
Definition: gdbstub.c:870
HANDLE UniqueProcessId
Definition: pstypes.h:1206
Definition: gdbstub.c:61
static const CHAR Hex[]
Definition: hwdisk.c:40
VOID GspPutPacketNoWait(PCHAR Buffer)
Definition: gdbstub.c:220
uint32_t ULONG_PTR
Definition: typedefs.h:64
_In_ NDIS_HANDLE _In_ PNDIS_REQUEST Request
Definition: ndis.h:5173
#define sprintf(buf, format,...)
Definition: sprintf.c:55
DWORD ExceptionCode
Definition: compat.h:197
BOOLEAN NTAPI KdPortInitializeEx(PCPPORT PortInformation, ULONG ComPortNumber)
UCHAR KIRQL
Definition: env_spec_w32.h:591
struct _GSPSWBREAKPOINT GSPSWBREAKPOINT
ULONG Size
Definition: gdbstub.c:66
static PETHREAD GspDbgThread
Definition: gdbstub.c:39
Definition: gdbstub.c:58
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 GspUnloadBreakpoints(void)
Definition: gdbstub.c:1126
UINT64 Dr2
Definition: ketypes.h:344
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
ULONG OffsetInTF
Definition: gdbstub.c:67
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
static CHAR GspInBuffer[1000]
Definition: gdbstub.c:50
#define DR7_TYPE1_MASK
Definition: gdbstub.c:840
#define STATUS_INTEGER_OVERFLOW
Definition: ntstatus.h:371
long LONG
Definition: pedump.c:60
struct _CPU_REGISTER CPU_REGISTER
static BOOLEAN GspInitialized
Definition: gdbstub.c:33
#define DR7_LEN2_MASK
Definition: gdbstub.c:843
#define DR7_G1
Definition: gdbstub.c:830
#define STATUS_INTEGER_DIVIDE_BY_ZERO
Definition: ntstatus.h:370
static PVOID ptr
Definition: dispmode.c:27
#define DEFAULT_DEBUG_PORT
Definition: kdcom.c:25
CHAR * PCH
Definition: ntbasedef.h:398
#define PsGetCurrentProcess
Definition: psfuncs.h:17
static int Save(const char **args)
Definition: vfdcmd.c:1851
unsigned char BOOLEAN
#define DR7_TYPE3_MASK
Definition: gdbstub.c:844
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
#define STATUS_BREAKPOINT
Definition: ntstatus.h:172
BOOLEAN KdDebuggerEnabled
Definition: kdmain.c:48
static PETHREAD GspRunThread
Definition: gdbstub.c:38
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
VOID NTAPI KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN OUT PCONTEXT Context)
Definition: context.c:147
PVOID KernelStack
Definition: ketypes.h:1565
Definition: gdbstub.c:58
VOID NTAPI KdPortPutByteEx(PCPPORT PortInformation, UCHAR ByteToSend)
#define MMDBG_COPY_WRITE
Definition: mm.h:53
#define DR7_LEN0_MASK
Definition: gdbstub.c:839
Definition: sacdrv.h:287
static unsigned GspSwBreakpointCount
Definition: gdbstub.c:881
static GSPSWBREAKPOINT GspSwBreakpoints[MAX_SW_BREAKPOINTS]
Definition: gdbstub.c:882
static CPU_REGISTER GspRegisters[NUMREGS]
Definition: gdbstub.c:72
static volatile BOOLEAN GspMemoryError
Definition: gdbstub.c:244
Definition: gdbstub.c:58
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
#define PCHAR
Definition: match.c:90
FAST_MUTEX
Definition: extypes.h:17
VOID GspSetSingleRegisterInTrapFrame(PCHAR Address, LONG Number, PCONTEXT Context, PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:551
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
#define DEFAULT_DEBUG_BAUD_RATE
Definition: kdcom.c:28
static FAST_MUTEX GspLock
Definition: gdbstub.c:42
VOID NTAPI KdpGdbDebugPrint(PCH Message, ULONG Length)
Definition: gdbstub.c:1565
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define KGDT_R0_DATA
Definition: ketypes.h:76
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: gdbstub.c:61
CLIENT_ID Cid
Definition: pstypes.h:1067
static void GspSetHwBreakpoint(ULONG Type, ULONG_PTR Address, ULONG Length)
Definition: gdbstub.c:885
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
ULONG HardwareEsp
Definition: ketypes.h:270
static const UCHAR Index[8]
Definition: usbohci.c:18
PVOID HANDLE
Definition: typedefs.h:72
Definition: gdbstub.c:58
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID ServiceContext
Definition: iofuncs.h:798
UINT64 Dr3
Definition: ketypes.h:345
HANDLE UniqueThread
Definition: compat.h:484
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
LONG GspHex2Long(PCHAR *Address, PLONG Value)
Definition: gdbstub.c:379
CHAR Message[80]
Definition: alive.c:5
unsigned __int64 ULONG64
Definition: imports.h:198
#define DR7_G2
Definition: gdbstub.c:832
VOID NTAPI KeDetachProcess(VOID)
Definition: procobj.c:618
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOLEAN NTAPI KdPortGetByteEx(PCPPORT PortInformation, PUCHAR ByteReceived)
UINT64 Dr1
Definition: ketypes.h:343
UCHAR GdbGetChar(VOID)
Definition: gdbstub.c:126
CHAR PrevContent
Definition: gdbstub.c:876
static PETHREAD GspEnumThread
Definition: gdbstub.c:40
#define DR7_L0
Definition: gdbstub.c:827
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define DR7_LEN1_MASK
Definition: gdbstub.c:841
#define NTSTATUS
Definition: precomp.h:20
#define EFLAGS_RF
Definition: cpu.c:19
LONG HexValue(CHAR ch)
Definition: gdbstub.c:105
#define DR7_TYPE0_MASK
Definition: gdbstub.c:838
BOOLEAN Active
Definition: gdbstub.c:877
#define PAGE_SIZE
Definition: env_spec_w32.h:49
static void GspWriteMemSafe(PCHAR Address, CHAR Ch)
Definition: gdbstub.c:266
__INTRIN_INLINE unsigned int __readdr(unsigned int reg)
Definition: intrin_x86.h:1799
Definition: typedefs.h:118
#define EFLAGS_TF
Definition: ketypes.h:125
KPROCESS Pcb
Definition: pstypes.h:1201
static PCHAR GspMem2Hex(PCHAR Address, PCHAR Buffer, LONG Count, BOOLEAN MayFault)
Definition: gdbstub.c:286
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
ULONG Eip
Definition: ketypes.h:267
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
REGISTER_NAMES
Definition: gdbstub.c:56
UINT64 Dr0
Definition: ketypes.h:342
Definition: gdbstub.c:58
static BOOLEAN GspFindSwBreakpoint(ULONG_PTR Address, PULONG PIndex)
Definition: gdbstub.c:954
Definition: gdbstub.c:60
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
#define NUMREGS
Definition: gdbstub.c:54
static VOID GspGetRegisters(PCHAR Address, PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:430
NTSTATUS NTAPI MmDbgCopyMemory(IN ULONG64 Address, IN PVOID Buffer, IN ULONG Size, IN ULONG Flags)
Definition: mmdbg.c:126
Definition: gdbstub.c:59
BOOLEAN NTAPI GspBreakIn(PKINTERRUPT Interrupt, PVOID ServiceContext)
Definition: gdbstub.c:1528
#define DR7_LEN(Bp, Len)
Definition: gdbstub.c:848
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
Definition: gdbstub.c:61
VOID NTAPI KeAttachProcess(IN PKPROCESS Process)
Definition: procobj.c:579
#define MMDBG_COPY_UNSAFE
Definition: mm.h:55
VOID GspQuery(PCHAR Request)
Definition: gdbstub.c:662
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
static CHAR GspHex2MemGetContent(PVOID Context, ULONG Offset)
Definition: gdbstub.c:359
unsigned int * PULONG
Definition: retypes.h:1
#define STATUS_STACK_OVERFLOW
Definition: ntstatus.h:475
NTHALAPI VOID NTAPI HalDisplayString(PUCHAR String)
PCHAR GspGetPacket(VOID)
Definition: gdbstub.c:136
#define I386_BP_TYPE_DATA_READWRITE
Definition: gdbstub.c:852
#define I386_BP_TYPE_DATA_WRITE
Definition: gdbstub.c:851
ULONG_PTR Address
Definition: gdbstub.c:865
Definition: gdbstub.c:58
VOID NTAPI KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable, ULONG BootPhase)
Definition: gdbstub.c:1572
#define DPRINT1
Definition: precomp.h:8
#define DBG_STATUS_CONTROL_C
Definition: kdtypes.h:39
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define DR7_G3
Definition: gdbstub.c:834
#define ObReferenceObject
Definition: obfuncs.h:204
#define STATUS_DATATYPE_MISALIGNMENT
Definition: ntstatus.h:171
volatile UCHAR State
Definition: ketypes.h:1679
VOID NTAPI KiThreadStartup(VOID)
Definition: thrdini.c:63
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define DR7_L2
Definition: gdbstub.c:831
KD_DISPATCH_TABLE WrapperTable
Definition: kdinit.c:28
struct tagContext Context
Definition: acpixf.h:1034
CHAR ImageFileName[16]
Definition: pstypes.h:1265
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
static void GspLoadHwBreakpoint(PKTRAP_FRAME TrapFrame, unsigned BpIndex, ULONG_PTR Address, ULONG Length, ULONG Type)
Definition: gdbstub.c:1023
#define ULONG_PTR
Definition: config.h:101
VOID GspQueryThreadStatus(PCHAR Request)
Definition: gdbstub.c:805
static void GspLoadBreakpoints(PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:1077
ULONG_PTR Address
Definition: gdbstub.c:875
__analysis_noreturn NTSYSAPI VOID NTAPI DbgBreakPointWithStatus(_In_ ULONG Status)
UINT64 Dr7
Definition: ketypes.h:347
LIST_ENTRY PsActiveProcessHead
Definition: process.c:22
struct _GSPHWBREAKPOINT GSPHWBREAKPOINT
GLfloat GLfloat p
Definition: glext.h:8902
#define I386_BP_TYPE_EXECUTE
Definition: gdbstub.c:850
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define memset(x, y, z)
Definition: compat.h:39
signed int * PLONG
Definition: retypes.h:5
BOOLEAN SetInContext
Definition: gdbstub.c:69
#define CHAR(Char)
#define DR7_LEN3_MASK
Definition: gdbstub.c:845
#define STATUS_ARRAY_BOUNDS_EXCEEDED
Definition: ntstatus.h:362
#define GDB_ZTYPE_WRITE_WATCHPOINT
Definition: gdbstub.c:858
ULONG OffsetInContext
Definition: gdbstub.c:68
#define CONST
Definition: pedump.c:81
static void GspSetSwBreakpoint(ULONG_PTR Address)
Definition: gdbstub.c:972
ULONG Ebp
Definition: ketypes.h:265
VOID GspSetRegistersInTrapFrame(PCHAR Address, PCONTEXT Context, PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:522
static LONG GspGetEspFromTrapFrame(PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:423
VOID GspPutPacket(PCHAR Buffer)
Definition: gdbstub.c:192