ReactOS  0.4.13-dev-79-gcd489d8
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 (!KdpSafeReadMemory((ULONG_PTR)Address, 1, &ch))
253 
254  return ch;
255 }
256 
257 static void
259 {
262 }
263 
264 /* Convert the memory pointed to by Address into hex, placing result in Buffer
265  * Return a pointer to the last char put in Buffer (null)
266  * If MayFault is TRUE, then we should set GspMemoryError in response to
267  * a fault; if FALSE treat a fault like any other fault in the stub.
268  */
269 static PCHAR
271 {
272  ULONG i;
273  CHAR ch;
274 
275  for (i = 0; i < (ULONG)Count; i++)
276  {
277  if (MayFault)
278  {
279  ch = GspReadMemSafe(Address);
280  if (GspMemoryError)
281  return Buffer;
282  }
283  else
284  {
285  ch = *Address;
286  }
287  *Buffer++ = HexChars[(ch >> 4) & 0xf];
288  *Buffer++ = HexChars[ch & 0xf];
289  Address++;
290  }
291 
292  *Buffer = 0;
293  return Buffer;
294 }
295 
296 static ULONG
298  CHAR (*GetContent)(PVOID Context, ULONG Offset), PVOID Context)
299 {
300  PCHAR Current;
301  PCHAR Page;
302  ULONG CountInPage;
303  ULONG i;
304  CHAR ch;
305 
306  Current = Address;
307  while (Current < Address + Count)
308  {
309  Page = (PCHAR)PAGE_ROUND_DOWN(Current);
310  if (Address + Count <= Page + PAGE_SIZE)
311  {
312  /* Fits in this page */
313  CountInPage = Count;
314  }
315  else
316  {
317  /* Flows into next page, handle only current page in this iteration */
318  CountInPage = PAGE_SIZE - (Address - Page);
319  }
320 
321  for (i = 0; i < CountInPage && !GspMemoryError; i++)
322  {
323  ch = (*GetContent)(Context, Current - Address);
324 
325  if (MayFault)
326  GspWriteMemSafe(Current, ch);
327  else
328  *Current = ch;
329 
330  Current++;
331  }
332  if (MayFault)
333  {
334  if (GspMemoryError)
335  return Current - Address;
336  }
337  }
338 
339  return Current - Address;
340 }
341 
342 static CHAR
344 {
345  return (CHAR)((HexValue(*((PCHAR)Context + 2 * Offset)) << 4) +
346  HexValue(*((PCHAR)Context + 2 * Offset + 1)));
347 }
348 
349 /* Convert the hex array pointed to by Buffer into binary to be placed at Address
350  * Return a pointer to the character AFTER the last byte read from Buffer */
351 static PCHAR
353 {
355  return Buffer + 2 * Count;
356 }
357 
358 /**********************************************/
359 /* WHILE WE FIND NICE HEX CHARS, BUILD A LONG */
360 /* RETURN NUMBER OF CHARS PROCESSED */
361 /**********************************************/
362 LONG
364 {
365  LONG NumChars = 0;
366  LONG Hex;
367 
368  *Value = 0;
369 
370  while (**Address)
371  {
372  Hex = HexValue(**Address);
373  if (Hex >= 0)
374  {
375  *Value = (*Value << 4) | Hex;
376  NumChars++;
377  }
378  else
379  {
380  break;
381  }
382 
383  (*Address)++;
384  }
385 
386  return NumChars;
387 }
388 
389 VOID
391 {
392  LONG Save;
393 
394  Save = (((Value >> 0) & 0xff) << 24) | (((Value >> 8) & 0xff) << 16) |
395  (((Value >> 16) & 0xff) << 8) | (((Value >> 24) & 0xff) << 0);
396 
398 }
399 
400 /*
401  * When coming from kernel mode, Esp is not stored in the trap frame.
402  * Instead, it was pointing to the location of the TrapFrame Esp member
403  * when the exception occured. When coming from user mode, Esp is just
404  * stored in the TrapFrame Esp member.
405  */
406 static LONG
408 {
409  return KeGetPreviousMode() == KernelMode ?
410  (LONG)&TrapFrame->HardwareEsp : (LONG)TrapFrame->HardwareEsp;
411 }
412 
413 static VOID
415 {
417  PULONG p;
418  ULONG i;
420  ULONG_PTR *KernelStack;
421 
422  if (NULL == GspDbgThread)
423  {
425  }
426  else
427  {
428  TrapFrame = GspDbgThread->Tcb.TrapFrame;
430  }
431 
432  if (Waiting == Thread->Tcb.State)
433  {
434  KernelStack = Thread->Tcb.KernelStack;
435  for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
436  {
437  switch (i)
438  {
439  case EBP:
440  Value = KernelStack[3];
441  break;
442  case EDI:
443  Value = KernelStack[4];
444  break;
445  case ESI:
446  Value = KernelStack[5];
447  break;
448  case EBX:
449  Value = KernelStack[6];
450  break;
451  case PC:
452  Value = KernelStack[7];
453  break;
454  case ESP:
455  Value = (ULONG_PTR)(KernelStack + 8);
456  break;
457  case CS:
459  break;
460  case DS:
462  break;
463  default:
464  Value = 0;
465  break;
466  }
467 
469  }
470  }
471  else
472  {
473  for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
474  {
475  if (TrapFrame)
476  {
477  if (ESP == i)
478  {
479  Value = GspGetEspFromTrapFrame(TrapFrame);
480  }
481  else
482  {
483  p = (PULONG)((ULONG_PTR)TrapFrame + GspRegisters[i].OffsetInTF);
484  Value = *p;
485  }
486  }
487  else if (i == PC)
488  {
489  /*
490  * This thread has not been sheduled yet so assume it
491  * is still in PsBeginThreadWithContextInternal().
492  */
494  }
495  else
496  {
497  Value = 0;
498  }
499 
501  }
502  }
503 }
504 
505 VOID
507 {
508  ULONG Value;
509  PCHAR Buffer;
510  PULONG p;
511  ULONG i;
512 
513  if (!TrapFrame)
514  return;
515 
516  Buffer = Address;
517  for (i = 0; i < NUMREGS; i++)
518  {
519  if (GspRegisters[i].SetInContext)
520  {
522  }
523  else
524  {
525  p = (PULONG)((ULONG_PTR)TrapFrame + GspRegisters[i].OffsetInTF);
526  }
527 
528  Value = 0;
530  *p = Value;
531  }
532 }
533 
534 VOID
536 {
537  ULONG Value;
538  PULONG p;
539 
540  if (!TrapFrame)
541  return;
542 
543  if (GspRegisters[Number].SetInContext)
544  {
546  }
547  else
548  {
549  p = (PULONG)((ULONG_PTR)TrapFrame + GspRegisters[Number].OffsetInTF);
550  }
551 
552  Value = 0;
554  *p = Value;
555 }
556 
557 BOOLEAN
559 {
561 
562  if (strcmp(Data, "-1") == 0)
563  {
564  /* All threads */
565  ThreadInfo = NULL;
566  }
567  else
568  {
569  ULONG uThreadId;
570  HANDLE ThreadId;
571  PCHAR ptr = &Data[0];
572 
573  GspHex2Long(&ptr, (PLONG)&uThreadId);
574  ThreadId = (HANDLE)uThreadId;
575 
577  {
578  *Thread = NULL;
579  return FALSE;
580  }
581  }
582 
583  *Thread = ThreadInfo;
584  return TRUE;
585 }
586 
587 VOID
589 {
591  PCHAR ptr = &Request[1];
592 
593  switch (Request[0])
594  {
595  case 'c': /* Run thread */
597  {
598  GspOutBuffer[0] = 'O';
599  GspOutBuffer[1] = 'K';
600 
601  if (NULL != GspRunThread)
603 
605 
606  if (NULL != GspRunThread)
608  }
609  else
610  {
611  GspOutBuffer[0] = 'E';
612  }
613  break;
614 
615  case 'g': /* Debug thread */
617  {
618  GspOutBuffer[0] = 'O';
619  GspOutBuffer[1] = 'K';
620 
621  if (NULL != GspDbgThread)
623 
625  {
626  GspDbgThread = NULL;
628  }
629  else
630  {
632  }
633  }
634  else
635  {
636  GspOutBuffer[0] = 'E';
637  }
638  break;
639 
640  default:
641  break;
642  }
643 }
644 
645 VOID
647 {
648  ULONG Value;
649 
650  if (strncmp(Request, "C", 1) == 0)
651  {
652  PCHAR ptr = &GspOutBuffer[2];
653 
654  /* Get current thread id */
655  GspOutBuffer[0] = 'Q';
656  GspOutBuffer[1] = 'C';
657 
658  if (NULL != GspDbgThread)
660  else
661  Value = (ULONG)PsGetCurrentThread()->Cid.UniqueThread;
662 
663  GspLong2Hex(&ptr, Value);
664  }
665  else if (strncmp(Request, "fThreadInfo", 11) == 0)
666  {
668  PLIST_ENTRY AThread, AProcess;
669  PCHAR ptr = &GspOutBuffer[1];
670 
671  /* Get first thread id */
673  AProcess = PsActiveProcessHead.Flink;
674  while (AProcess != &PsActiveProcessHead)
675  {
676  Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
677  AThread = Process->ThreadListHead.Flink;
678  if (AThread != &Process->ThreadListHead)
679  {
680  GspEnumThread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
681  ETHREAD, ThreadListEntry);
682  break;
683  }
684  AProcess = AProcess->Flink;
685  }
686  if (GspEnumThread != NULL)
687  {
688  GspOutBuffer[0] = 'm';
690  GspLong2Hex(&ptr, Value);
691  }
692  else
693  {
694  /* FIXME - what to do here? This case should never happen though, there
695  should always be at least one thread on the system... */
696  /* GspOutBuffer[0] = 'l'; */
697  }
698  }
699  else if (strncmp(Request, "sThreadInfo", 11) == 0)
700  {
702  PLIST_ENTRY AThread, AProcess;
703  PCHAR ptr = &GspOutBuffer[1];
704 
705  /* Get next thread id */
706  if (GspEnumThread != NULL)
707  {
708  /* find the next thread */
709  Process = GspEnumThread->ThreadsProcess;
710  if (GspEnumThread->ThreadListEntry.Flink != &Process->ThreadListHead)
711  {
713  ETHREAD, ThreadListEntry);
714  }
715  else
716  {
717  PETHREAD Thread = NULL;
718  AProcess = Process->ActiveProcessLinks.Flink;
719  while (AProcess != &PsActiveProcessHead)
720  {
721  Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
722  AThread = Process->ThreadListHead.Flink;
723  if (AThread != &Process->ThreadListHead)
724  {
725  Thread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
726  ETHREAD, ThreadListEntry);
727  break;
728  }
729  AProcess = AProcess->Flink;
730  }
732  }
733 
734  if (GspEnumThread != NULL)
735  {
736  /* return the ID */
737  GspOutBuffer[0] = 'm';
739  GspLong2Hex(&ptr, Value);
740  }
741  else
742  {
743  GspOutBuffer[0] = 'l';
744  }
745  }
746  else
747  {
748  GspOutBuffer[0] = 'l';
749  }
750  }
751  else if (strncmp(Request, "ThreadExtraInfo", 15) == 0)
752  {
754 
755  /* Get thread information */
756  if (GspFindThread(Request + 16, &ThreadInfo))
757  {
758  char Buffer[64];
759  PEPROCESS Proc;
760 
761  Proc = (PEPROCESS)ThreadInfo->ThreadsProcess;
762 
763  Buffer[0] = '\0';
764 
765  if (NULL != Proc)
766  sprintf(Buffer, "%s [%d:0x%x], ",
767  Proc->ImageFileName,
768  (int)Proc->UniqueProcessId,
769  (int)ThreadInfo->Cid.UniqueThread);
770 
772 
774 
776  }
777  }
778  else if (strncmp(Request, "Supported", 9) == 0)
779  {
780  /* tell maximum incoming packet size */
781  sprintf(GspOutBuffer, "PacketSize=%u", sizeof(GspInBuffer) - 1);
782  }
783  else if (strncmp(Request, "Rcmd,", 5) == 0)
784  {
785  }
786 }
787 
788 VOID
790 {
792  PCHAR ptr = &Request[0];
793 
795  {
797 
798  GspOutBuffer[0] = 'O';
799  GspOutBuffer[1] = 'K';
800  GspOutBuffer[2] = '\0';
801  }
802  else
803  {
804  GspOutBuffer[0] = 'E';
805  GspOutBuffer[1] = '\0';
806  }
807 }
808 
809 #define DR6_BS 0x00004000 /* Single step */
810 
811 #define DR7_L0 0x00000001 /* Local breakpoint 0 enable */
812 #define DR7_G0 0x00000002 /* Global breakpoint 0 enable */
813 #define DR7_L1 0x00000004 /* Local breakpoint 1 enable */
814 #define DR7_G1 0x00000008 /* Global breakpoint 1 enable */
815 #define DR7_L2 0x00000010 /* Local breakpoint 2 enable */
816 #define DR7_G2 0x00000020 /* Global breakpoint 2 enable */
817 #define DR7_L3 0x00000040 /* Local breakpoint 3 enable */
818 #define DR7_G3 0x00000080 /* Global breakpoint 3 enable */
819 #define DR7_LE 0x00000100 /* Local exact breakpoint enable (old) */
820 #define DR7_GE 0x00000200 /* Global exact breakpoint enable (old) */
821 #define DR7_GD 0x00002000 /* General detect enable */
822 #define DR7_TYPE0_MASK 0x00030000 /* Breakpoint 0 condition */
823 #define DR7_LEN0_MASK 0x000c0000 /* Breakpoint 0 length */
824 #define DR7_TYPE1_MASK 0x00300000 /* Breakpoint 1 condition */
825 #define DR7_LEN1_MASK 0x00c00000 /* Breakpoint 1 length */
826 #define DR7_TYPE2_MASK 0x03000000 /* Breakpoint 2 condition */
827 #define DR7_LEN2_MASK 0x0c000000 /* Breakpoint 2 length */
828 #define DR7_TYPE3_MASK 0x30000000 /* Breakpoint 3 condition */
829 #define DR7_LEN3_MASK 0xc0000000 /* Breakpoint 3 length */
830 #define DR7_GLOBAL_ENABLE(Bp) (2 << (2 * (Bp)))
831 #define DR7_TYPE(Bp, Type) ((Type) << (16 + 4 * (Bp)))
832 #define DR7_LEN(Bp, Len) ((Len) << (18 + 4 * (Bp)))
833 
834 #define I386_BP_TYPE_EXECUTE 0
835 #define I386_BP_TYPE_DATA_WRITE 1
836 #define I386_BP_TYPE_DATA_READWRITE 3
837 
838 #define I386_OPCODE_INT3 0xcc
839 
840 #define GDB_ZTYPE_MEMORY_BREAKPOINT 0
841 #define GDB_ZTYPE_HARDWARE_BREAKPOINT 1
842 #define GDB_ZTYPE_WRITE_WATCHPOINT 2
843 #define GDB_ZTYPE_READ_WATCHPOINT 3
844 #define GDB_ZTYPE_ACCESS_WATCHPOINT 4
845 
846 typedef struct _GSPHWBREAKPOINT
847 {
852 
853 #define MAX_HW_BREAKPOINTS 4
854 static unsigned GspHwBreakpointCount = 0;
856 
857 typedef struct _GSPSWBREAKPOINT
858 {
863 
864 #define MAX_SW_BREAKPOINTS 64
865 static unsigned GspSwBreakpointCount = 0;
867 
868 static void
870 {
871  DPRINT("GspSetHwBreakpoint(%lu, 0x%p, %lu)\n", Type, Address, Length);
872 
874  {
875  DPRINT1("Read watchpoint not supported\n");
876  strcpy(GspOutBuffer, "E22");
877  }
878  else if (GDB_ZTYPE_HARDWARE_BREAKPOINT == Type && 1 != Length)
879  {
880  DPRINT1("Invalid length %lu for hardware breakpoint\n", Length);
881  strcpy(GspOutBuffer, "E22");
882  }
883  else if (1 != Length && 2 != Length && 4 != Length)
884  {
885  DPRINT1("Invalid length %lu for GDB Z type %lu\n", Length, Type);
886  strcpy(GspOutBuffer, "E22");
887  }
888  else if (0 != (Address & (Length - 1)))
889  {
890  DPRINT1("Invalid alignment for address 0x%p and length %d\n", Address, Length);
891  strcpy(GspOutBuffer, "E22");
892  }
894  {
895  DPRINT1("Trying to set too many hardware breakpoints\n");
896  strcpy(GspOutBuffer, "E22");
897  }
898  else
899  {
900  DPRINT("Stored at index %u\n", GspHwBreakpointCount);
905  strcpy(GspOutBuffer, "OK");
906  }
907 }
908 
909 static void
911 {
912  unsigned Index;
913 
914  DPRINT("GspRemoveHwBreakpoint(%lu, 0x%p, %lu)\n", Type, Address, Length);
915  for (Index = 0; Index < GspHwBreakpointCount; Index++)
916  {
917  if (GspHwBreakpoints[Index].Type == Type &&
920  {
921  DPRINT("Found match at index %u\n", Index);
922  if (Index + 1 < GspHwBreakpointCount)
924  GspHwBreakpoints + (Index + 1),
925  (GspHwBreakpointCount - Index - 1) * sizeof(GSPHWBREAKPOINT));
926 
928  strcpy(GspOutBuffer, "OK");
929  return;
930  }
931  }
932 
933  DPRINT1("Not found\n");
934  strcpy(GspOutBuffer, "E22");
935 }
936 
937 static BOOLEAN
939 {
940  ULONG Index;
941 
942  for (Index = 0; Index < GspSwBreakpointCount; Index++)
943  {
945  {
946  if (PIndex)
947  *PIndex = Index;
948  return TRUE;
949  }
950  }
951 
952  return FALSE;
953 }
954 
955 static void
957 {
958  DPRINT("GspSetSwBreakpoint(0x%p)\n", Address);
959 
961  {
962  DPRINT1("Trying to set too many software breakpoints\n");
963  strcpy(GspOutBuffer, "E22");
964  return;
965  }
966 
968  {
969  strcpy(GspOutBuffer, "E22");
970  return;
971  }
972 
973  DPRINT("Stored at index %u\n", GspSwBreakpointCount);
977  strcpy(GspOutBuffer, "OK");
978 }
979 
980 static void
982 {
983  ULONG Index;
984 
985  DPRINT("GspRemoveSwBreakpoint(0x%p)\n", Address);
986 
988  {
989  DPRINT("Found match at index %u\n", Index);
991 
992  if (Index + 1 < GspSwBreakpointCount)
994  GspSwBreakpoints + (Index + 1),
995  (GspSwBreakpointCount - Index - 1) * sizeof(GSPSWBREAKPOINT));
996 
998  strcpy(GspOutBuffer, "OK");
999  return;
1000  }
1001 
1002  DPRINT1("Not found\n");
1003  strcpy(GspOutBuffer, "E22");
1004 }
1005 
1006 static void
1007 GspLoadHwBreakpoint(PKTRAP_FRAME TrapFrame, unsigned BpIndex,
1009 {
1010  DPRINT("GspLoadHwBreakpoint(0x%p, %d, 0x%p, %d)\n",
1011  TrapFrame, BpIndex, Address, Type);
1012 
1013  /* Set the DR7_Gx bit to globally enable the breakpoint */
1014  TrapFrame->Dr7 |= DR7_GLOBAL_ENABLE(BpIndex) |
1015  DR7_LEN(BpIndex, Length) |
1016  DR7_TYPE(BpIndex, Type);
1017 
1018  switch (BpIndex)
1019  {
1020  case 0:
1021  DPRINT("Setting DR0 to 0x%p\n", Address);
1022  TrapFrame->Dr0 = Address;
1023  break;
1024 
1025  case 1:
1026  DPRINT("Setting DR1 to 0x%p\n", Address);
1027  TrapFrame->Dr1 = Address;
1028  break;
1029 
1030  case 2:
1031  DPRINT("Setting DR2 to 0x%p\n", Address);
1032  TrapFrame->Dr2 = Address;
1033  break;
1034 
1035  case 3:
1036  DPRINT("Setting DR3 to 0x%p\n", Address);
1037  TrapFrame->Dr3 = Address;
1038  break;
1039  }
1040 }
1041 
1042 static void
1044 {
1046 
1048 
1049  if (!GspMemoryError)
1051 
1053 
1054  if (GspMemoryError)
1055  DPRINT1("Failed to set software breakpoint at 0x%p\n", GspSwBreakpoints[Index].Address);
1056  else
1057  DPRINT("Successfully set software breakpoint at 0x%p\n", GspSwBreakpoints[Index].Address);
1058 }
1059 
1060 static void
1062 {
1063  unsigned Index;
1064  ULONG i386Type;
1065 
1066  DPRINT("GspLoadBreakpoints\n");
1067  DPRINT("DR7 on entry: 0x%08x\n", TrapFrame->Dr7);
1068 
1069  /* Remove all breakpoints */
1070  TrapFrame->Dr7 &= ~(DR7_L0 | DR7_L1 | DR7_L2 | DR7_L3 |
1071  DR7_G0 | DR7_G1 | DR7_G2 | DR7_G3 |
1076 
1077  for (Index = 0; Index < GspHwBreakpointCount; Index++)
1078  {
1079  switch (GspHwBreakpoints[Index].Type)
1080  {
1082  i386Type = I386_BP_TYPE_EXECUTE;
1083  break;
1085  i386Type = I386_BP_TYPE_DATA_WRITE;
1086  break;
1088  i386Type = I386_BP_TYPE_DATA_READWRITE;
1089  break;
1090  default:
1091  ASSERT(FALSE);
1092  i386Type = I386_BP_TYPE_EXECUTE;
1093  break;
1094  }
1095 
1097  GspHwBreakpoints[Index].Length - 1, i386Type);
1098  }
1099 
1100  for (Index = 0; Index < GspSwBreakpointCount; Index++)
1101  {
1102  DPRINT("Using real software breakpoint\n");
1104  }
1105 
1106  DPRINT("Final DR7 value 0x%08x\n", TrapFrame->Dr7);
1107 }
1108 
1109 static void
1111 {
1112  unsigned Index;
1113 
1114  DPRINT("GspUnloadBreakpoints\n");
1115 
1116  /* Disable hardware debugging while we are inside the stub */
1117  __writedr(7, 0);
1118 
1119  for (Index = 0; Index < GspSwBreakpointCount; Index++)
1120  {
1122  {
1125  GspSwBreakpoints[Index].PrevContent);
1127  if (GspMemoryError)
1128  {
1129  DPRINT1("Failed to remove software breakpoint from 0x%p\n",
1131  }
1132  else
1133  {
1134  DPRINT("Successfully removed software breakpoint from 0x%p\n",
1136  }
1137  }
1138  }
1139 }
1140 
1141 static void
1143 {
1145  ULONG SigVal;
1146  LONG Esp;
1147 
1148  switch (ExceptionCode)
1149  {
1151  SigVal = 8; /* divide by zero */
1152  break;
1153  case STATUS_SINGLE_STEP:
1154  case STATUS_BREAKPOINT:
1155  SigVal = 5; /* breakpoint */
1156  break;
1159  SigVal = 16; /* bound instruction */
1160  break;
1162  SigVal = 4; /* Invalid opcode */
1163  break;
1164  case STATUS_STACK_OVERFLOW:
1167  SigVal = 11; /* access violation */
1168  break;
1169  default:
1170  SigVal = 7; /* "software generated" */
1171  }
1172 
1173  ptr = GspOutBuffer;
1174 
1175  *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */
1176  *ptr++ = HexChars[(SigVal >> 4) & 0xf];
1177  *ptr++ = HexChars[SigVal & 0xf];
1178 
1179  *ptr++ = HexChars[ESP];
1180  *ptr++ = ':';
1181 
1182  Esp = GspGetEspFromTrapFrame(TrapFrame); /* SP */
1183  ptr = GspMem2Hex((PCHAR)&Esp, ptr, 4, 0);
1184  *ptr++ = ';';
1185 
1186  *ptr++ = HexChars[EBP];
1187  *ptr++ = ':';
1188  ptr = GspMem2Hex((PCHAR)&TrapFrame->Ebp, ptr, 4, 0); /* FP */
1189  *ptr++ = ';';
1190 
1191  *ptr++ = HexChars[PC];
1192  *ptr++ = ':';
1193  ptr = GspMem2Hex((PCHAR)&TrapFrame->Eip, ptr, 4, 0); /* PC */
1194  *ptr++ = ';';
1195 
1196  *ptr = '\0';
1197 }
1198 
1199 /*
1200  * This function does all command procesing for interfacing to GDB.
1201  */
1202 KD_CONTINUE_TYPE
1203 NTAPI
1205  PCONTEXT Context,
1206  PKTRAP_FRAME TrapFrame)
1207 {
1208  static BOOLEAN GdbAttached = FALSE;
1209  BOOLEAN Stepping = FALSE;
1211  LONG Address;
1212  LONG Length;
1213  PCHAR ptr;
1214 
1215  /* FIXME: Stop on other CPUs too */
1216 
1217  DPRINT("Thread %p entering stub\n", PsGetCurrentThread());
1218  ExceptionCode = (NTSTATUS)ExceptionRecord->ExceptionCode;
1219 
1220  /* Can only debug 1 thread at a time... */
1222  DPRINT("Thread %p acquired mutex\n", PsGetCurrentThread());
1223 
1225 
1226  /* Make sure we're debugging the current thread. */
1227  if (NULL != GspDbgThread)
1228  {
1229  DPRINT1("Internal error: entering stub with non-NULL GspDbgThread\n");
1231  GspDbgThread = NULL;
1232  }
1233 
1234  if (GdbAttached)
1235  {
1236  GspStopReply(ExceptionCode, TrapFrame);
1238  // DbgPrint(">>> (%s) >>>\n", GspOutBuffer);
1239  }
1240  else
1241  {
1242  GdbAttached = TRUE;
1243  }
1244 
1245  while (TRUE)
1246  {
1247  /* Zero the buffer now so we don't have to worry about the terminating zero character */
1248  memset(GspOutBuffer, 0, sizeof(GspOutBuffer));
1249  ptr = GspGetPacket();
1250  // DbgPrint("<<< (%s) <<<\n", ptr);
1251 
1252  switch (*ptr++)
1253  {
1254  case '?':
1255  /* a little hack to send more complete status information */
1256  GspStopReply(ExceptionCode, TrapFrame);
1257  break;
1258 
1259  case 'd':
1260  GspRemoteDebug = !GspRemoteDebug; /* toggle debug flag */
1261  break;
1262 
1263  case 'g': /* return the value of the CPU Registers */
1264  GspGetRegisters(GspOutBuffer, TrapFrame);
1265  break;
1266 
1267  case 'G': /* set the value of the CPU Registers - return OK */
1268  if (NULL != GspDbgThread)
1270  else
1271  GspSetRegistersInTrapFrame(ptr, Context, TrapFrame);
1272 
1273  strcpy(GspOutBuffer, "OK");
1274  break;
1275 
1276  case 'P': /* set the value of a single CPU register - return OK */
1277  {
1278  LONG Register;
1279 
1280  if ((GspHex2Long(&ptr, &Register)) && (*ptr++ == '='))
1281  {
1282  if ((Register >= 0) && (Register < NUMREGS))
1283  {
1284  if (GspDbgThread)
1285  {
1288  }
1289  else
1290  {
1291  GspSetSingleRegisterInTrapFrame(ptr, Register, Context, TrapFrame);
1292  }
1293  strcpy(GspOutBuffer, "OK");
1294  break;
1295  }
1296  }
1297 
1298  strcpy(GspOutBuffer, "E01");
1299  break;
1300  }
1301 
1302  /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
1303  case 'm':
1304  {
1305  /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
1306  if (GspHex2Long(&ptr, &Address) && *(ptr++) == ',' && GspHex2Long(&ptr, &Length))
1307  {
1308  PEPROCESS DbgProcess = NULL;
1309 
1310  ptr = NULL;
1311  if (NULL != GspDbgThread &&
1312  PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
1313  {
1314  DbgProcess = GspDbgThread->ThreadsProcess;
1315  KeAttachProcess(&DbgProcess->Pcb);
1316  }
1317 
1320 
1321  if (NULL != DbgProcess)
1322  KeDetachProcess();
1323 
1324  if (GspMemoryError)
1325  {
1326  strcpy(GspOutBuffer, "E03");
1327  DPRINT1("Fault during memory read\n");
1328  }
1329  ptr = NULL;
1330  }
1331 
1332  if (NULL != ptr)
1333  strcpy(GspOutBuffer, "E01");
1334 
1335  break;
1336  }
1337 
1338  /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
1339  case 'M':
1340  {
1341  /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
1342  if (GspHex2Long(&ptr, &Address))
1343  {
1344  if (*(ptr++) == ',' && GspHex2Long(&ptr, &Length) && *(ptr++) == ':')
1345  {
1346  PEPROCESS DbgProcess = NULL;
1347 
1348  if (NULL != GspDbgThread &&
1349  PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
1350  {
1351  DbgProcess = GspDbgThread->ThreadsProcess;
1352  KeAttachProcess(&DbgProcess->Pcb);
1353  }
1356  if (NULL != DbgProcess)
1357  KeDetachProcess();
1358 
1359  if (GspMemoryError)
1360  {
1361  strcpy(GspOutBuffer, "E03");
1362  DPRINT1("Fault during memory write\n");
1363  }
1364  else
1365  {
1366  strcpy(GspOutBuffer, "OK");
1367  }
1368  ptr = NULL;
1369  }
1370  }
1371 
1372  if (NULL != ptr)
1373  strcpy(GspOutBuffer, "E02");
1374 
1375  break;
1376  }
1377 
1378  /* cAA..AA Continue at address AA..AA */
1379  /* sAA..AA Step one instruction from AA..AA */
1380  case 's':
1381  Stepping = TRUE;
1382  case 'c':
1383  {
1384  ULONG BreakpointNumber;
1385  ULONG Dr6;
1386 
1387  /* try to read optional parameter, pc changed if param */
1388  if (GspHex2Long(&ptr, &Address))
1389  {
1390  Context->Eip = Address;
1391  }
1392  else if (ExceptionCode == STATUS_BREAKPOINT)
1393  {
1395  Context->Eip++;
1396  }
1397 
1398  /* clear the trace bit */
1399  Context->EFlags &= ~EFLAGS_TF;
1400 
1401  /* set the trace bit if we're Stepping */
1402  if (Stepping)
1403  Context->EFlags |= EFLAGS_TF;
1404 
1405  Dr6 = __readdr(6);
1406  if (!(Dr6 & DR6_BS))
1407  {
1408  for (BreakpointNumber = 0;
1409  BreakpointNumber < MAX_HW_BREAKPOINTS;
1410  BreakpointNumber++)
1411  {
1412  if (Dr6 & (1 << BreakpointNumber))
1413  {
1414  if (GspHwBreakpoints[BreakpointNumber].Type == I386_BP_TYPE_EXECUTE)
1415  {
1416  /* Set restore flag */
1417  Context->EFlags |= EFLAGS_RF;
1418  break;
1419  }
1420  }
1421  }
1422  }
1423 
1424  GspLoadBreakpoints(TrapFrame);
1425  __writedr(6, 0);
1426 
1427  if (NULL != GspDbgThread)
1428  {
1430  GspDbgThread = NULL;
1431  }
1432 
1433  DPRINT("Thread %p releasing mutex\n", PsGetCurrentThread());
1435  DPRINT("Thread %p leaving stub\n", PsGetCurrentThread());
1436 
1439  return kdContinue;
1440 
1441  return kdHandleException;
1442  }
1443 
1444  case 'k': /* kill the program */
1445  strcpy(GspOutBuffer, "OK");
1446  break;
1447 
1448  case 'H': /* Set thread */
1449  GspSetThread(ptr);
1450  break;
1451 
1452  case 'q': /* Query */
1453  GspQuery(ptr);
1454  break;
1455 
1456  case 'T': /* Query thread status */
1458  break;
1459 
1460  case 'Z':
1461  {
1462  LONG Type;
1463  LONG Address;
1464  LONG Length;
1465 
1466  GspHex2Long(&ptr, &Type);
1467  ptr++;
1468  GspHex2Long(&ptr, &Address);
1469  ptr++;
1470  GspHex2Long(&ptr, &Length);
1471 
1472  if (0 == Type)
1474  else
1476 
1477  break;
1478  }
1479 
1480  case 'z':
1481  {
1482  LONG Type;
1483  LONG Address;
1484  LONG Length;
1485 
1486  GspHex2Long(&ptr, &Type);
1487  ptr++;
1488  GspHex2Long(&ptr, &Address);
1489  ptr++;
1490  GspHex2Long(&ptr, &Length);
1491 
1492  if (0 == Type)
1494  else
1496 
1497  break;
1498  }
1499 
1500  default:
1501  break;
1502  }
1503 
1504  /* reply to the request */
1506  // DbgPrint(">>> (%s) >>>\n", GspOutBuffer);
1507  }
1508 }
1509 
1510 BOOLEAN
1511 NTAPI
1513 {
1514  PKTRAP_FRAME TrapFrame;
1515  BOOLEAN DoBreakIn;
1516  CONTEXT Context;
1517  KIRQL OldIrql;
1518  UCHAR Value;
1519 
1520  DPRINT("Break In\n");
1521 
1522  DoBreakIn = FALSE;
1523  while (KdPortGetByteEx(&GdbPortInfo, &Value))
1524  {
1525  if (Value == 0x03)
1526  DoBreakIn = TRUE;
1527  }
1528 
1529  if (!DoBreakIn)
1530  return TRUE;
1531 
1533 
1534  TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
1535 
1536  KeTrapFrameToContext(TrapFrame, NULL, &Context);
1537 
1539 
1540  KeContextToTrapFrame(&Context, NULL, TrapFrame, Context.ContextFlags, KernelMode);
1541 
1543 
1544  return TRUE;
1545 }
1546 
1547 VOID
1548 NTAPI
1550 {
1551 }
1552 
1553 /* Initialize the GDB stub */
1554 VOID
1555 NTAPI
1556 KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable, ULONG BootPhase)
1557 {
1558  if (!KdDebuggerEnabled || !KdpDebugMode.Gdb)
1559  return;
1560 
1561  if (BootPhase == 0)
1562  {
1564 
1565  /* Write out the functions that we support for now */
1566  WrapperTable->KdpInitRoutine = KdpGdbStubInit;
1567  WrapperTable->KdpPrintRoutine = KdpGdbDebugPrint;
1568  WrapperTable->KdpExceptionRoutine = KdpGdbEnterDebuggerException;
1569 
1570  /* Initialize the Port */
1572  }
1573  else if (BootPhase == 1)
1574  {
1575  GspInitialized = TRUE;
1576 
1577  GspRunThread = NULL;
1578  GspDbgThread = NULL;
1579  GspEnumThread = NULL;
1580 
1581  HalDisplayString("Waiting for GDB to attach\r\n");
1583  }
1584  else if (BootPhase == 2)
1585  {
1586  HalDisplayString("\r\n GDB debugging enabled\r\n\r\n");
1587  }
1588 }
1589 
1590 /* 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:2327
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:558
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1782
static void GspRemoveHwBreakpoint(ULONG Type, ULONG_PTR Address, ULONG Length)
Definition: gdbstub.c:910
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:844
#define DR7_L1
Definition: gdbstub.c:813
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define MAX_SW_BREAKPOINTS
Definition: gdbstub.c:864
#define TRUE
Definition: types.h:120
#define DR7_L3
Definition: gdbstub.c:817
LIST_ENTRY ThreadListEntry
Definition: pstypes.h:1089
#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:838
Type
Definition: Type.h:6
#define DR6_BS
Definition: gdbstub.c:809
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:1204
static void GspStopReply(NTSTATUS ExceptionCode, PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:1142
static CHAR GspOutBuffer[1000]
Definition: gdbstub.c:51
Definition: gdbstub.c:61
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
Definition: gdbstub.c:58
#define GDB_ZTYPE_HARDWARE_BREAKPOINT
Definition: gdbstub.c:841
#define GDB_ZTYPE_READ_WATCHPOINT
Definition: gdbstub.c:843
#define DR7_TYPE2_MASK
Definition: gdbstub.c:826
static ULONG GspWriteMem(PCHAR Address, ULONG Count, BOOLEAN MayFault, CHAR(*GetContent)(PVOID Context, ULONG Offset), PVOID Context)
Definition: gdbstub.c:297
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:853
#define KeGetPreviousMode()
Definition: ketypes.h:1081
LONG NTSTATUS
Definition: precomp.h:26
VOID GspSetThread(PCHAR Request)
Definition: gdbstub.c:588
#define STATUS_SINGLE_STEP
Definition: ntstatus.h:173
KTHREAD Tcb
Definition: pstypes.h:1034
static void GspRemoveSwBreakpoint(ULONG_PTR Address)
Definition: gdbstub.c:981
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
static PCHAR GspHex2Mem(PCHAR Buffer, PCHAR Address, ULONG Count, BOOLEAN MayFault)
Definition: gdbstub.c:352
#define DR7_G0
Definition: gdbstub.c:812
#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:74
BOOLEAN NTAPI KdpSafeWriteMemory(ULONG_PTR Addr, LONG Len, ULONGLONG Value)
Definition: kdmemsup.c:193
_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:831
struct _ThreadInfo ThreadInfo
ULONG GdbPortNumber
Definition: gdbstub.c:47
static void GspLoadSwBreakpoint(ULONG Index)
Definition: gdbstub.c:1043
VOID GspLong2Hex(PCHAR *Address, LONG Value)
Definition: gdbstub.c:390
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define DR7_GLOBAL_ENABLE(Bp)
Definition: gdbstub.c:830
#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:855
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:854
HANDLE UniqueProcessId
Definition: pstypes.h:1198
Definition: gdbstub.c:61
static const CHAR Hex[]
Definition: hwdisk.c:41
VOID GspPutPacketNoWait(PCHAR Buffer)
Definition: gdbstub.c:220
uint32_t ULONG_PTR
Definition: typedefs.h:63
_In_ NDIS_HANDLE _In_ PNDIS_REQUEST Request
Definition: ndis.h:5155
#define sprintf(buf, format,...)
Definition: sprintf.c:55
DWORD ExceptionCode
Definition: compat.h:196
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
BOOLEAN NTAPI KdpSafeReadMemory(ULONG_PTR Addr, LONG Len, PVOID Value)
Definition: kdmemsup.c:157
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:1110
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:824
#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:827
#define DR7_G1
Definition: gdbstub.c:814
#define STATUS_INTEGER_DIVIDE_BY_ZERO
Definition: ntstatus.h:370
static PVOID ptr
Definition: dispmode.c:27
#define DEFAULT_DEBUG_PORT
Definition: kdcom.c:18
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:828
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:16
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 DR7_LEN0_MASK
Definition: gdbstub.c:823
Definition: sacdrv.h:287
static unsigned GspSwBreakpointCount
Definition: gdbstub.c:865
static GSPSWBREAKPOINT GspSwBreakpoints[MAX_SW_BREAKPOINTS]
Definition: gdbstub.c:866
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:535
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define DEFAULT_DEBUG_BAUD_RATE
Definition: kdcom.c:21
static FAST_MUTEX GspLock
Definition: gdbstub.c:42
VOID NTAPI KdpGdbDebugPrint(PCH Message, ULONG Length)
Definition: gdbstub.c:1549
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define KGDT_R0_DATA
Definition: ketypes.h:75
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: gdbstub.c:61
CLIENT_ID Cid
Definition: pstypes.h:1059
static void GspSetHwBreakpoint(ULONG Type, ULONG_PTR Address, ULONG Length)
Definition: gdbstub.c:869
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:268
static const UCHAR Index[8]
Definition: usbohci.c:18
PVOID HANDLE
Definition: typedefs.h:71
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:475
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
LONG GspHex2Long(PCHAR *Address, PLONG Value)
Definition: gdbstub.c:363
CHAR Message[80]
Definition: alive.c:5
#define DR7_G2
Definition: gdbstub.c:816
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:860
static PETHREAD GspEnumThread
Definition: gdbstub.c:40
#define DR7_L0
Definition: gdbstub.c:811
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define DR7_LEN1_MASK
Definition: gdbstub.c:825
#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:822
BOOLEAN Active
Definition: gdbstub.c:861
#define PAGE_SIZE
Definition: env_spec_w32.h:49
static void GspWriteMemSafe(PCHAR Address, CHAR Ch)
Definition: gdbstub.c:258
__INTRIN_INLINE unsigned int __readdr(unsigned int reg)
Definition: intrin_x86.h:1799
Definition: typedefs.h:117
#define EFLAGS_TF
Definition: ketypes.h:125
KPROCESS Pcb
Definition: pstypes.h:1193
static PCHAR GspMem2Hex(PCHAR Address, PCHAR Buffer, LONG Count, BOOLEAN MayFault)
Definition: gdbstub.c:270
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
ULONG Eip
Definition: ketypes.h:265
_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:938
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:414
Definition: gdbstub.c:59
BOOLEAN NTAPI GspBreakIn(PKINTERRUPT Interrupt, PVOID ServiceContext)
Definition: gdbstub.c:1512
#define DR7_LEN(Bp, Len)
Definition: gdbstub.c:832
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
VOID GspQuery(PCHAR Request)
Definition: gdbstub.c:646
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
static CHAR GspHex2MemGetContent(PVOID Context, ULONG Offset)
Definition: gdbstub.c:343
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:836
#define I386_BP_TYPE_DATA_WRITE
Definition: gdbstub.c:835
ULONG_PTR Address
Definition: gdbstub.c:849
Definition: gdbstub.c:58
VOID NTAPI KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable, ULONG BootPhase)
Definition: gdbstub.c:1556
#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:818
#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:815
KD_DISPATCH_TABLE WrapperTable
Definition: kdinit.c:28
struct tagContext Context
Definition: acpixf.h:1012
CHAR ImageFileName[16]
Definition: pstypes.h:1257
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:1007
#define ULONG_PTR
Definition: config.h:101
VOID GspQueryThreadStatus(PCHAR Request)
Definition: gdbstub.c:789
static void GspLoadBreakpoints(PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:1061
ULONG_PTR Address
Definition: gdbstub.c:859
__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:834
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:829
#define STATUS_ARRAY_BOUNDS_EXCEEDED
Definition: ntstatus.h:362
#define GDB_ZTYPE_WRITE_WATCHPOINT
Definition: gdbstub.c:842
ULONG OffsetInContext
Definition: gdbstub.c:68
#define CONST
Definition: pedump.c:81
static void GspSetSwBreakpoint(ULONG_PTR Address)
Definition: gdbstub.c:956
ULONG Ebp
Definition: ketypes.h:263
VOID GspSetRegistersInTrapFrame(PCHAR Address, PCONTEXT Context, PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:506
static LONG GspGetEspFromTrapFrame(PKTRAP_FRAME TrapFrame)
Definition: gdbstub.c:407
VOID GspPutPacket(PCHAR Buffer)
Definition: gdbstub.c:192