ReactOS  0.4.15-dev-1203-g0e5a4d5
gdbstub_powerpc.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 /****************************************************************************
16  * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17  *
18  * Module name: remcom.c $
19  * Revision: 1.34 $
20  * Date: 91/03/09 12:29:49 $
21  * Contributor: Lake Stevens Instrument Division$
22  *
23  * Description: low level support for gdb debugger. $
24  *
25  * Considerations: only works on target hardware $
26  *
27  * Written by: Glenn Engel $
28  * ModuleState: Experimental $
29  *
30  * NOTES: See Below $
31  *
32  * Modified for 386 by Jim Kingdon, Cygnus Support.
33  * Modified for ReactOS by Casper S. Hornstrup <chorns@users.sourceforge.net>
34  *
35  * To enable debugger support, two things need to happen. One, setting
36  * up a routine so that it is in the exception path, is necessary in order
37  * to allow any breakpoints or error conditions to be properly intercepted
38  * and reported to gdb.
39  * Two, a breakpoint needs to be generated to begin communication.
40  *
41  * Because gdb will sometimes write to the stack area to execute function
42  * calls, this program cannot rely on using the supervisor stack so it
43  * uses it's own stack area.
44  *
45  *************
46  *
47  * The following gdb commands are supported:
48  *
49  * command function Return value
50  *
51  * g return the value of the CPU Registers hex data or ENN
52  * G set the value of the CPU Registers OK or ENN
53  *
54  * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
55  * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
56  *
57  * c Resume at current address SNN ( signal NN)
58  * cAA..AA Continue at address AA..AA SNN
59  *
60  * s Step one instruction SNN
61  * sAA..AA Step one instruction from AA..AA SNN
62  *
63  * k kill
64  *
65  * ? What was the last sigval ? SNN (signal NN)
66  *
67  * All commands and responses are sent with a packet which includes a
68  * Checksum. A packet consists of
69  *
70  * $<packet info>#<Checksum>.
71  *
72  * where
73  * <packet info> :: <characters representing the command or response>
74  * <Checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
75  *
76  * When a packet is received, it is first acknowledged with either '+' or '-'.
77  * '+' indicates a successful transfer. '-' indicates a failed transfer.
78  *
79  * Example:
80  *
81  * Host: Reply:
82  * $m0,10#2a +$00010203040506070809101112131415#42
83  *
84  ****************************************************************************/
85 
86 #include <ntoskrnl.h>
87 #define NDEBUG
88 #include <debug.h>
89 
90 /************************************************************************/
91 
94 
95 static CONST CHAR HexChars[]="0123456789abcdef";
96 
97 static PETHREAD GspRunThread; /* NULL means run all threads */
100 
102 
104 
105 /* FIXME hardcoded for COM2, 115200 baud */
108 
109 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
110 /* at least NUMREGBYTES*2 are needed for register packets */
111 #define BUFMAX 1000
114 
115 /* Number of Registers. */
116 #define NUMREGS 16
117 
119 {
121  PC /* also known as eip */,
122  PS /* also known as eflags */,
123  CS, SS, DS, ES, FS, GS
124 };
125 
126 typedef struct _CPU_REGISTER
127 {
128  ULONG Size;
133 
135 {
136 };
137 
139 {
140  "Initialized",
141  "Ready",
142  "Running",
143  "Standby",
144  "Terminated",
145  "Waiting",
146  "Transition",
147  "DeferredReady"
148 };
149 
150 
151 LONG
153 {
154  if ((ch >= '0') && (ch <= '9'))
155  return (ch - '0');
156 
157  if ((ch >= 'a') && (ch <= 'f'))
158  return (ch - 'a' + 10);
159 
160  if ((ch >= 'A') && (ch <= 'F'))
161  return (ch - 'A' + 10);
162 
163  return -1;
164 }
165 
166 VOID
168 {
170 }
171 
172 UCHAR
174 {
175  UCHAR Value;
176 
177  while (!KdPortGetByteEx(&GdbPortInfo, &Value)) ;
178  return Value;
179 }
180 
181 /* scan for the sequence $<data>#<Checksum> */
182 
183 PCHAR
185 {
186  PCHAR Buffer = &GspInBuffer[0];
187  CHAR Checksum;
188  CHAR XmitChecksum;
189  ULONG Count;
190  CHAR ch;
191 
192  while (TRUE)
193  {
194  /* wait around for the start character, ignore all other characters */
195  while ((ch = GdbGetChar ()) != '$') ;
196 
197 retry:
198  Checksum = 0;
199  XmitChecksum = -1;
200  Count = 0;
201 
202  /* now, read until a # or end of Buffer is found */
203  while (Count < BUFMAX)
204  {
205  ch = GdbGetChar();
206  if (ch == '$')
207  goto retry;
208 
209  if (ch == '#')
210  break;
211 
212  Checksum = Checksum + ch;
213  Buffer[Count] = ch;
214  Count = Count + 1;
215  }
216  Buffer[Count] = 0;
217 
218  if (ch == '#')
219  {
220  ch = GdbGetChar();
221  XmitChecksum = (CHAR)(HexValue(ch) << 4);
222  ch = GdbGetChar();
223  XmitChecksum += (CHAR)(HexValue(ch));
224 
225  if (Checksum != XmitChecksum)
226  {
227  GdbPutChar('-'); /* failed checksum */
228  }
229  else
230  {
231  GdbPutChar('+'); /* successful transfer */
232  return &Buffer[0];
233  }
234  }
235  }
236 }
237 
238 /* send the packet in Buffer. */
239 
240 VOID
242 {
243  CHAR Checksum;
244  LONG Count;
245  CHAR ch;
246 
247  /* $<packet info>#<Checksum>. */
248  do
249  {
250  GdbPutChar('$');
251  Checksum = 0;
252  Count = 0;
253 
254  while ((ch = Buffer[Count]))
255  {
256  GdbPutChar(ch);
257  Checksum += ch;
258  Count += 1;
259  }
260 
261  GdbPutChar('#');
262  GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
263  GdbPutChar(HexChars[Checksum & 0xf]);
264  }
265  while (GdbGetChar() != '+');
266 }
267 
268 
269 VOID
271 {
272  CHAR Checksum;
273  LONG Count;
274  CHAR ch;
275 
276  /* $<packet info>#<Checksum>. */
277  GdbPutChar('$');
278  Checksum = 0;
279  Count = 0;
280 
281  while ((ch = Buffer[Count]))
282  {
283  GdbPutChar(ch);
284  Checksum += ch;
285  Count += 1;
286  }
287 
288  GdbPutChar('#');
289  GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
290  GdbPutChar(HexChars[Checksum & 0xf]);
291 }
292 
293 /* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an
294  error. */
295 static volatile BOOLEAN GspMemoryError = FALSE;
296 static volatile void *GspAccessLocation = NULL;
297 
298 static CHAR
300 {
301  CHAR ch;
302 
303  if (NULL == Address)
304  {
306  return '\0';
307  }
308 
310  ch = *Address;
312 
313  return ch;
314 }
315 
316 static CHAR
318 {
319  ASSERT(0 == Offset);
320  return *((PCHAR) Context);
321 }
322 
323 static void
325  CHAR Ch)
326 {
328 }
329 
330 /* Convert the memory pointed to by Address into hex, placing result in Buffer */
331 /* Return a pointer to the last char put in Buffer (null) */
332 /* If MayFault is TRUE, then we should set GspMemoryError in response to
333  a fault; if FALSE treat a fault like any other fault in the stub. */
334 static PCHAR
336  PCHAR Buffer,
337  LONG Count,
338  BOOLEAN MayFault)
339 {
340  ULONG i;
341  CHAR ch;
342 
343  for (i = 0; i < (ULONG) Count; i++)
344  {
345  if (MayFault)
346  {
347  ch = GspReadMemSafe(Address);
348  if (GspMemoryError)
349  return Buffer;
350  }
351  else
352  {
353  ch = *Address;
354  }
355  *Buffer++ = HexChars[(ch >> 4) & 0xf];
356  *Buffer++ = HexChars[ch & 0xf];
357  Address++;
358  }
359 
360  *Buffer = 0;
361  return Buffer;
362 }
363 
364 static ULONG
366  ULONG Count,
367  BOOLEAN MayFault,
368  CHAR (*GetContent)(PVOID Context, ULONG Offset),
369  PVOID Context)
370 {
371  PCHAR Current;
372  PCHAR Page;
373  ULONG CountInPage;
374  ULONG i;
375  CHAR ch;
376  ULONG OldProt = 0;
377 
378  Current = Address;
379  while (Current < Address + Count)
380  {
381  Page = (PCHAR)PAGE_ROUND_DOWN(Current);
382  if (Address + Count <= Page + PAGE_SIZE)
383  {
384  /* Fits in this page */
385  CountInPage = Count;
386  }
387  else
388  {
389  /* Flows into next page, handle only current page in this iteration */
390  CountInPage = PAGE_SIZE - (Address - Page);
391  }
392  if (MayFault)
393  {
394  OldProt = MmGetPageProtect(NULL, Address);
396  }
397 
398  for (i = 0; i < CountInPage && ! GspMemoryError; i++)
399  {
400  ch = (*GetContent)(Context, Current - Address);
401 
402  if (MayFault)
403  GspAccessLocation = Current;
404 
405  *Current = ch;
406 
407  if (MayFault)
409 
410  Current++;
411  }
412  if (MayFault)
413  {
414  MmSetPageProtect(NULL, Page, OldProt);
415  if (GspMemoryError)
416  return Current - Address;
417  }
418  }
419 
420  return Current - Address;
421 }
422 
423 static CHAR
425 {
426  return (CHAR)((HexValue(*((PCHAR) Context + 2 * Offset)) << 4) +
427  HexValue(*((PCHAR) Context + 2 * Offset + 1)));
428 }
429 
430 /* Convert the hex array pointed to by Buffer into binary to be placed at Address */
431 /* Return a pointer to the character AFTER the last byte read from Buffer */
432 static PCHAR
434  PCHAR Address,
435  ULONG Count,
436  BOOLEAN MayFault)
437 {
439  return Buffer + 2 * Count;
440 }
441 
442 
443 /* This function takes the 386 exception vector and attempts to
444  translate this number into a unix compatible signal value */
445 ULONG
447 {
448  ULONG SigVal;
449 
450  switch (ExceptionCode)
451  {
453  SigVal = 8; /* divide by zero */
454  break;
455 
456  case STATUS_SINGLE_STEP:
457  case STATUS_BREAKPOINT:
458  SigVal = 5; /* breakpoint */
459  break;
460 
463  SigVal = 16; /* bound instruction */
464  break;
465 
467  SigVal = 4; /* Invalid opcode */
468  break;
469 
473  SigVal = 11; /* access violation */
474  break;
475 
476  default:
477  SigVal = 7; /* "software generated" */
478  }
479  return SigVal;
480 }
481 
482 
483 /**********************************************/
484 /* WHILE WE FIND NICE HEX CHARS, BUILD A LONG */
485 /* RETURN NUMBER OF CHARS PROCESSED */
486 /**********************************************/
487 LONG
489  PLONG Value)
490 {
491  LONG NumChars = 0;
492  LONG Hex;
493 
494  *Value = 0;
495 
496  while (**Address)
497  {
498  Hex = HexValue(**Address);
499  if (Hex >= 0)
500  {
501  *Value = (*Value << 4) | Hex;
502  NumChars++;
503  }
504  else
505  {
506  break;
507  }
508 
509  (*Address)++;
510  }
511 
512  return NumChars;
513 }
514 
515 
516 VOID
518  LONG Value)
519 {
520  LONG Save;
521 
522  Save = (((Value >> 0) & 0xff) << 24) |
523  (((Value >> 8) & 0xff) << 16) |
524  (((Value >> 16) & 0xff) << 8) |
525  (((Value >> 24) & 0xff) << 0);
526  *Address = GspMem2Hex((PCHAR) &Save, *Address, 4, FALSE);
527 }
528 
529 
530 /*
531  * When coming from kernel mode, Esp is not stored in the trap frame.
532  * Instead, it was pointing to the location of the TrapFrame Esp member
533  * when the exception occured. When coming from user mode, Esp is just
534  * stored in the TrapFrame Esp member.
535  */
536 static LONG
538 {
539  return KeGetPreviousMode() == KernelMode
540  ? (LONG) &TrapFrame->Gpr1 : (LONG)TrapFrame->Gpr1;
541 }
542 
543 
544 static VOID
546  PKTRAP_FRAME TrapFrame)
547 {
549  PULONG p;
550  ULONG i;
552  ULONG_PTR *KernelStack;
553 
554  if (NULL == GspDbgThread)
555  {
557  }
558  else
559  {
560  TrapFrame = GspDbgThread->Tcb.TrapFrame;
562  }
563 
564  if (Waiting == Thread->Tcb.State)
565  {
566  KernelStack = Thread->Tcb.KernelStack;
567  for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
568  {
569  switch(i)
570  {
571  }
573  FALSE);
574  }
575  }
576  else
577  {
578  for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
579  {
580  if (TrapFrame)
581  {
582  if (ESP == i)
583  {
584  Value = GspGetEspFromTrapFrame(TrapFrame);
585  }
586  else
587  {
588  p = (PULONG)((ULONG_PTR) TrapFrame +
590  Value = *p;
591  }
592  }
593  else if (i == PC)
594  {
595  /*
596  * This thread has not been sheduled yet so assume it
597  * is still in PsBeginThreadWithContextInternal().
598  */
600  }
601  else
602  {
603  Value = 0;
604  }
607  }
608  }
609 }
610 
611 
612 VOID
615  PKTRAP_FRAME TrapFrame)
616 {
617  ULONG Value;
618  PCHAR Buffer;
619  PULONG p;
620  ULONG i;
621 
622  if (!TrapFrame)
623  {
624  return;
625  }
626 
627  Buffer = Address;
628  for (i = 0; i < NUMREGS; i++)
629  {
630  if (GspRegisters[i].SetInContext)
631  {
633  }
634  else
635  {
636  p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[i].OffsetInTF);
637  }
638  Value = 0;
640  *p = Value;
641  }
642 }
643 
644 
645 VOID
647  LONG Number,
649  PKTRAP_FRAME TrapFrame)
650 {
651  ULONG Value;
652  PULONG p;
653 
654  if (!TrapFrame)
655  {
656  return;
657  }
658 
659  if (GspRegisters[Number].SetInContext)
660  {
662  }
663  else
664  {
665  p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[Number].OffsetInTF);
666  }
667  Value = 0;
669  *p = Value;
670 }
671 
672 
673 BOOLEAN
675  PETHREAD *Thread)
676 {
678 
679  if (strcmp (Data, "-1") == 0)
680  {
681  /* All threads */
682  ThreadInfo = NULL;
683  }
684  else
685  {
686  ULONG uThreadId;
687  HANDLE ThreadId;
688  PCHAR ptr = &Data[0];
689 
690  GspHex2Long(&ptr, (PLONG) &uThreadId);
691  ThreadId = (HANDLE)uThreadId;
692 
694  {
695  *Thread = NULL;
696  return FALSE;
697  }
698  }
699  *Thread = ThreadInfo;
700  return TRUE;
701 }
702 
703 
704 VOID
706 {
708  PCHAR ptr = &Request[1];
709 
710  switch (Request[0])
711  {
712  case 'c': /* Run thread */
714  {
715  GspOutBuffer[0] = 'O';
716  GspOutBuffer[1] = 'K';
717 
718  if (NULL != GspRunThread)
719  {
721  }
723  if (NULL != GspRunThread)
724  {
726  }
727  }
728  else
729  {
730  GspOutBuffer[0] = 'E';
731  }
732  break;
733  case 'g': /* Debug thread */
735  {
736  GspOutBuffer[0] = 'O';
737  GspOutBuffer[1] = 'K';
738 
739  if (NULL != GspDbgThread)
740  {
742  }
743 
745  {
746  GspDbgThread = NULL;
748  }
749  else
750  {
752  }
753  }
754  else
755  {
756  GspOutBuffer[0] = 'E';
757  }
758  break;
759  default:
760  break;
761  }
762 }
763 
764 
765 VOID
767 {
768  ULONG Value;
769 
770  if (strncmp(Request, "C", 1) == 0)
771  {
772  PCHAR ptr = &GspOutBuffer[2];
773 
774  /* Get current thread id */
775  GspOutBuffer[0] = 'Q';
776  GspOutBuffer[1] = 'C';
777  if (NULL != GspDbgThread)
778  {
780  }
781  else
782  {
783  Value = (ULONG) PsGetCurrentThread()->Cid.UniqueThread;
784  }
785  GspLong2Hex(&ptr, Value);
786  }
787  else if (strncmp(Request, "fThreadInfo", 11) == 0)
788  {
790  PLIST_ENTRY AThread, AProcess;
791  PCHAR ptr = &GspOutBuffer[1];
792 
793  /* Get first thread id */
795  AProcess = PsActiveProcessHead.Flink;
796  while(AProcess != &PsActiveProcessHead)
797  {
798  Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
799  AThread = Process->ThreadListHead.Flink;
800  if (AThread != &Process->ThreadListHead)
801  {
802  GspEnumThread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
803  ETHREAD, ThreadListEntry);
804  break;
805  }
806  AProcess = AProcess->Flink;
807  }
808  if(GspEnumThread != NULL)
809  {
810  GspOutBuffer[0] = 'm';
812  GspLong2Hex(&ptr, Value);
813  }
814  else
815  {
816  /* FIXME - what to do here? This case should never happen though, there
817  should always be at least one thread on the system... */
818  /* GspOutBuffer[0] = 'l'; */
819  }
820  }
821  else if (strncmp(Request, "sThreadInfo", 11) == 0)
822  {
824  PLIST_ENTRY AThread, AProcess;
825  PCHAR ptr = &GspOutBuffer[1];
826 
827  /* Get next thread id */
828  if (GspEnumThread != NULL)
829  {
830  /* find the next thread */
831  Process = GspEnumThread->ThreadsProcess;
832  if(GspEnumThread->ThreadListEntry.Flink != &Process->ThreadListHead)
833  {
835  ETHREAD, ThreadListEntry);
836  }
837  else
838  {
839  PETHREAD Thread = NULL;
840  AProcess = Process->ActiveProcessLinks.Flink;
841  while(AProcess != &PsActiveProcessHead)
842  {
843  Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
844  AThread = Process->ThreadListHead.Flink;
845  if (AThread != &Process->ThreadListHead)
846  {
847  Thread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
848  ETHREAD, ThreadListEntry);
849  break;
850  }
851  AProcess = AProcess->Flink;
852  }
854  }
855 
856  if (GspEnumThread != NULL)
857  {
858  /* return the ID */
859  GspOutBuffer[0] = 'm';
861  GspLong2Hex(&ptr, Value);
862  }
863  else
864  {
865  GspOutBuffer[0] = 'l';
866  }
867  }
868  else
869  {
870  GspOutBuffer[0] = 'l';
871  }
872  }
873  else if (strncmp(Request, "ThreadExtraInfo", 15) == 0)
874  {
876 
877  /* Get thread information */
878  if (GspFindThread(Request + 16, &ThreadInfo))
879  {
880  char Buffer[64];
881  PEPROCESS Proc;
882 
883  Proc = (PEPROCESS) ThreadInfo->ThreadsProcess;
884 
885  Buffer[0] = '\0';
886  if (NULL != Proc )
887  {
888  sprintf(Buffer, "%s [%d:0x%x], ", Proc->ImageFileName,
889  (int) Proc->UniqueProcessId,
890  (int) ThreadInfo->Cid.UniqueThread);
891  }
893  GspThreadStates[ThreadInfo->Tcb.State]);
894 
896 
898  }
899  }
900 }
901 
902 VOID
904 {
906  PCHAR ptr = &Request[0];
907 
909  {
911 
912  GspOutBuffer[0] = 'O';
913  GspOutBuffer[1] = 'K';
914  GspOutBuffer[2] = '\0';
915  }
916  else
917  {
918  GspOutBuffer[0] = 'E';
919  GspOutBuffer[1] = '\0';
920  }
921 }
922 
923 #define DR7_L0 0x00000001 /* Local breakpoint 0 enable */
924 #define DR7_G0 0x00000002 /* Global breakpoint 0 enable */
925 #define DR7_L1 0x00000004 /* Local breakpoint 1 enable */
926 #define DR7_G1 0x00000008 /* Global breakpoint 1 enable */
927 #define DR7_L2 0x00000010 /* Local breakpoint 2 enable */
928 #define DR7_G2 0x00000020 /* Global breakpoint 2 enable */
929 #define DR7_L3 0x00000040 /* Local breakpoint 3 enable */
930 #define DR7_G3 0x00000080 /* Global breakpoint 3 enable */
931 #define DR7_LE 0x00000100 /* Local exact breakpoint enable (old) */
932 #define DR7_GE 0x00000200 /* Global exact breakpoint enable (old) */
933 #define DR7_GD 0x00002000 /* General detect enable */
934 #define DR7_TYPE0_MASK 0x00030000 /* Breakpoint 0 condition */
935 #define DR7_LEN0_MASK 0x000c0000 /* Breakpoint 0 length */
936 #define DR7_TYPE1_MASK 0x00300000 /* Breakpoint 1 condition */
937 #define DR7_LEN1_MASK 0x00c00000 /* Breakpoint 1 length */
938 #define DR7_TYPE2_MASK 0x03000000 /* Breakpoint 2 condition */
939 #define DR7_LEN2_MASK 0x0c000000 /* Breakpoint 2 length */
940 #define DR7_TYPE3_MASK 0x30000000 /* Breakpoint 3 condition */
941 #define DR7_LEN3_MASK 0xc0000000 /* Breakpoint 3 length */
942 #define DR7_GLOBAL_ENABLE(Bp) (2 << (2 * (Bp)))
943 #define DR7_TYPE(Bp, Type) ((Type) << (16 + 4 * (Bp)))
944 #define DR7_LEN(Bp, Len) ((Len) << (18 + 4 * (Bp)))
945 
946 #define I386_BP_TYPE_EXECUTE 0
947 #define I386_BP_TYPE_DATA_WRITE 1
948 #define I386_BP_TYPE_DATA_READWRITE 3
949 
950 #define I386_OPCODE_INT3 0xcc
951 
952 #define GDB_ZTYPE_MEMORY_BREAKPOINT 0
953 #define GDB_ZTYPE_HARDWARE_BREAKPOINT 1
954 #define GDB_ZTYPE_WRITE_WATCHPOINT 2
955 #define GDB_ZTYPE_READ_WATCHPOINT 3
956 #define GDB_ZTYPE_ACCESS_WATCHPOINT 4
957 
958 typedef struct _GSPHWBREAKPOINT
959 {
960  ULONG Type;
962  ULONG Length;
964 
965 #define MAX_HW_BREAKPOINTS 4
966 static unsigned GspHwBreakpointCount = 0;
968 
969 typedef struct _GSPSWBREAKPOINT
970 {
973  BOOLEAN Active;
975 
976 #define MAX_SW_BREAKPOINTS 64
977 static unsigned GspSwBreakpointCount = 0;
979 
980 static void
982 {
983  DPRINT("GspSetHwBreakpoint(%lu, 0x%p, %lu)\n", Type, Address, Length);
984 
986  {
987  DPRINT1("Read watchpoint not supported\n");
988  strcpy(GspOutBuffer, "E22");
989  }
990  else if (GDB_ZTYPE_HARDWARE_BREAKPOINT == Type && 1 != Length)
991  {
992  DPRINT1("Invalid length %lu for hardware breakpoint\n", Length);
993  strcpy(GspOutBuffer, "E22");
994  }
995  else if (1 != Length && 2 != Length && 4 != Length)
996  {
997  DPRINT1("Invalid length %lu for GDB Z type %lu\n", Length, Type);
998  strcpy(GspOutBuffer, "E22");
999  }
1000  else if (0 != (Address & (Length - 1)))
1001  {
1002  DPRINT1("Invalid alignment for address 0x%p and length %d\n",
1003  Address, Length);
1004  strcpy(GspOutBuffer, "E22");
1005  }
1007  {
1008  DPRINT1("Trying to set too many hardware breakpoints\n");
1009  strcpy(GspOutBuffer, "E22");
1010  }
1011  else
1012  {
1013  DPRINT("Stored at index %u\n", GspHwBreakpointCount);
1018  strcpy(GspOutBuffer, "OK");
1019  }
1020 }
1021 
1022 static void
1024 {
1025  unsigned Index;
1026 
1027  DPRINT("GspRemoveHwBreakpoint(%lu, 0x%p, %lu)\n", Type, Address, Length);
1028  for (Index = 0; Index < GspHwBreakpointCount; Index++)
1029  {
1030  if (GspHwBreakpoints[Index].Type == Type &&
1033  {
1034  DPRINT("Found match at index %u\n", Index);
1035  if (Index + 1 < GspHwBreakpointCount)
1036  {
1038  GspHwBreakpoints + (Index + 1),
1039  (GspHwBreakpointCount - Index - 1) *
1040  sizeof(GSPHWBREAKPOINT));
1041  }
1043  strcpy(GspOutBuffer, "OK");
1044  return;
1045  }
1046  }
1047 
1048  DPRINT1("Not found\n");
1049  strcpy(GspOutBuffer, "E22");
1050 }
1051 
1052 static void
1054 {
1055  DPRINT("GspSetSwBreakpoint(0x%p)\n", Address);
1056 
1058  {
1059  DPRINT1("Trying to set too many software breakpoints\n");
1060  strcpy(GspOutBuffer, "E22");
1061  }
1062  else
1063  {
1064  DPRINT("Stored at index %u\n", GspSwBreakpointCount);
1068  strcpy(GspOutBuffer, "OK");
1069  }
1070 }
1071 
1072 static void
1074 {
1075  unsigned Index;
1076 
1077  DPRINT("GspRemoveSwBreakpoint(0x%p)\n", Address);
1078  for (Index = 0; Index < GspSwBreakpointCount; Index++)
1079  {
1081  {
1082  DPRINT("Found match at index %u\n", Index);
1084  if (Index + 1 < GspSwBreakpointCount)
1085  {
1087  GspSwBreakpoints + (Index + 1),
1088  (GspSwBreakpointCount - Index - 1) *
1089  sizeof(GSPSWBREAKPOINT));
1090  }
1092  strcpy(GspOutBuffer, "OK");
1093  return;
1094  }
1095  }
1096 
1097  DPRINT1("Not found\n");
1098  strcpy(GspOutBuffer, "E22");
1099 }
1100 
1101 static void
1103  unsigned BpIndex,
1105  ULONG Length,
1106  ULONG Type)
1107 {
1108  DPRINT("GspLoadHwBreakpoint(0x%p, %d, 0x%p, %d)\n", TrapFrame, BpIndex,
1109  Address, Type);
1110 
1111  /* Set the DR7_Gx bit to globally enable the breakpoint */
1112  TrapFrame->Dr7 |= DR7_GLOBAL_ENABLE(BpIndex) |
1113  DR7_LEN(BpIndex, Length) |
1114  DR7_TYPE(BpIndex, Type);
1115 
1116  switch (BpIndex)
1117  {
1118  case 0:
1119  DPRINT("Setting DR0 to 0x%p\n", Address);
1120  TrapFrame->Dr0 = Address;
1121  break;
1122 
1123  case 1:
1124  DPRINT("Setting DR1 to 0x%p\n", Address);
1125  TrapFrame->Dr1 = Address;
1126  break;
1127 
1128  case 2:
1129  DPRINT("Setting DR2 to 0x%p\n", Address);
1130  TrapFrame->Dr2 = Address;
1131  break;
1132 
1133  case 3:
1134  DPRINT("Setting DR3 to 0x%p\n", Address);
1135  TrapFrame->Dr3 = Address;
1136  break;
1137  }
1138 }
1139 
1140 static void
1142 {
1143  unsigned Index;
1144  ULONG i386Type;
1145 
1146  DPRINT("GspLoadBreakpoints\n");
1147  DPRINT("DR7 on entry: 0x%08x\n", TrapFrame->Dr7);
1148  /* Remove all breakpoints */
1149  TrapFrame->Dr7 &= ~(DR7_L0 | DR7_L1 | DR7_L2 | DR7_L3 |
1150  DR7_G0 | DR7_G1 | DR7_G2 | DR7_G3 |
1155 
1156  for (Index = 0; Index < GspHwBreakpointCount; Index++)
1157  {
1158  switch(GspHwBreakpoints[Index].Type)
1159  {
1161  i386Type = I386_BP_TYPE_EXECUTE;
1162  break;
1164  i386Type = I386_BP_TYPE_DATA_WRITE;
1165  break;
1167  i386Type = I386_BP_TYPE_DATA_READWRITE;
1168  break;
1169  default:
1170  ASSERT(FALSE);
1171  i386Type = I386_BP_TYPE_EXECUTE;
1172  break;
1173  }
1174 
1176  GspHwBreakpoints[Index].Length - 1, i386Type);
1177  }
1178 
1179  for (Index = 0; Index < GspSwBreakpointCount; Index++)
1180  {
1182  {
1183  DPRINT("Implementing software interrupt using hardware register\n");
1188  }
1189  else
1190  {
1191  DPRINT("Using real software breakpoint\n");
1194  if (! GspMemoryError)
1195  {
1197  }
1199  if (GspMemoryError)
1200  {
1201  DPRINT1("Failed to set software breakpoint at 0x%p\n",
1203  }
1204  else
1205  {
1206  DPRINT("Successfully set software breakpoint at 0x%p\n",
1208  DPRINT1("Successfully set software breakpoint at 0x%p\n", GspSwBreakpoints[Index].Address);
1209  }
1210  }
1211  }
1212 
1213  DPRINT("Final DR7 value 0x%08x\n", TrapFrame->Dr7);
1214 }
1215 
1216 static void
1218 {
1219  unsigned Index;
1220 
1221  DPRINT("GspUnloadHwBreakpoints\n");
1222 
1223  for (Index = 0; Index < GspSwBreakpointCount; Index++)
1224  {
1226  {
1229  GspSwBreakpoints[Index].PrevContent);
1231  if (GspMemoryError)
1232  {
1233  DPRINT1("Failed to remove software breakpoint from 0x%p\n",
1235  }
1236  else
1237  {
1238  DPRINT("Successfully removed software breakpoint from 0x%p\n",
1240  }
1241  }
1242  }
1243 }
1244 
1246 /*
1247  * This function does all command processing for interfacing to gdb.
1248  */
1249 KD_CONTINUE_TYPE
1250 NTAPI
1252  PCONTEXT Context,
1253  PKTRAP_FRAME TrapFrame)
1254 {
1255  BOOLEAN Stepping;
1256  LONG Address;
1257  LONG Length;
1258  LONG SigVal = 0;
1259  //LONG NewPC;
1260  PCHAR ptr;
1261 
1262  /* FIXME: Stop on other CPUs too */
1263 
1264  if (STATUS_ACCESS_VIOLATION == (NTSTATUS) ExceptionRecord->ExceptionCode &&
1265  NULL != GspAccessLocation &&
1267  (ULONG_PTR) ExceptionRecord->ExceptionInformation[1])
1268  {
1270  GspMemoryError = TRUE;
1271  //Context->Eip += 3;
1272  }
1273  else
1274  {
1275  DPRINT("Thread %p entering stub\n", PsGetCurrentThread());
1276  /* Can only debug 1 thread at a time... */
1278  DPRINT("Thread %p acquired mutex\n", PsGetCurrentThread());
1279 
1280  /* Disable hardware debugging while we are inside the stub */
1281  //Ke386SetDr7(0);
1282  GspUnloadBreakpoints(TrapFrame);
1283 
1284  /* Make sure we're debugging the current thread. */
1285  if (NULL != GspDbgThread)
1286  {
1287  DPRINT1("Internal error: entering stub with non-NULL GspDbgThread\n");
1289  GspDbgThread = NULL;
1290  }
1291 
1292  /* ugly hack to avoid attempting to send status at the very
1293  * beginning, right when GDB is trying to query the stub */
1294  if (gdb_attached_yet)
1295  {
1296  LONG Esp;
1297 
1298 stop_reply:
1299  /* reply to host that an exception has occurred */
1300  SigVal = GspComputeSignal(ExceptionRecord->ExceptionCode);
1301 
1302  ptr = GspOutBuffer;
1303 
1304  *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */
1305  *ptr++ = HexChars[(SigVal >> 4) & 0xf];
1306  *ptr++ = HexChars[SigVal & 0xf];
1307 
1308  *ptr++ = HexChars[ESP];
1309  *ptr++ = ':';
1310 
1311  Esp = GspGetEspFromTrapFrame(TrapFrame); /* SP */
1312  ptr = GspMem2Hex((PCHAR) &Esp, ptr, 4, 0);
1313  *ptr++ = ';';
1314 
1315  *ptr++ = HexChars[EBP];
1316  *ptr++ = ':';
1317  //ptr = GspMem2Hex((PCHAR) &TrapFrame->Ebp, ptr, 4, 0); /* FP */
1318  *ptr++ = ';';
1319 
1320  *ptr++ = HexChars[PC];
1321  *ptr++ = ':';
1322  //ptr = GspMem2Hex((PCHAR) &TrapFrame->Eip, ptr, 4, 0); /* PC */
1323  *ptr++ = ';';
1324 
1325  *ptr = '\0';
1326 
1328  }
1329  else
1330  {
1331  gdb_attached_yet = 1;
1332  }
1333 
1334  Stepping = FALSE;
1335 
1336  while (TRUE)
1337  {
1338  /* Zero the buffer now so we don't have to worry about the terminating zero character */
1339  memset(GspOutBuffer, 0, sizeof(GspInBuffer));
1340  ptr = GspGetPacket();
1341 
1342  switch(*ptr++)
1343  {
1344  case '?':
1345 #if 1
1346  /* a little hack to send more complete status information */
1347  goto stop_reply;
1348 #else
1349  GspOutBuffer[0] = 'S';
1350  GspOutBuffer[1] = HexChars[SigVal >> 4];
1351  GspOutBuffer[2] = HexChars[SigVal % 16];
1352  GspOutBuffer[3] = 0;
1353  break;
1354 #endif
1355  case 'd':
1356  GspRemoteDebug = !GspRemoteDebug; /* toggle debug flag */
1357  break;
1358  case 'g': /* return the value of the CPU Registers */
1359  GspGetRegisters(GspOutBuffer, TrapFrame);
1360  break;
1361  case 'G': /* set the value of the CPU Registers - return OK */
1362  if (NULL != GspDbgThread)
1363  {
1365  }
1366  else
1367  {
1368  GspSetRegistersInTrapFrame(ptr, Context, TrapFrame);
1369  }
1370  strcpy(GspOutBuffer, "OK");
1371  break;
1372  case 'P': /* set the value of a single CPU register - return OK */
1373  {
1374  LONG Register;
1375 
1376  if ((GspHex2Long(&ptr, &Register)) && (*ptr++ == '='))
1377  {
1378  if ((Register >= 0) && (Register < NUMREGS))
1379  {
1380  if (GspDbgThread)
1381  {
1383  Context,
1385  }
1386  else
1387  {
1389  Context, TrapFrame);
1390  }
1391  strcpy(GspOutBuffer, "OK");
1392  break;
1393  }
1394  }
1395 
1396  strcpy(GspOutBuffer, "E01");
1397  break;
1398  }
1399 
1400  /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
1401  case 'm':
1402  /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
1403  if (GspHex2Long(&ptr, &Address) &&
1404  *(ptr++) == ',' &&
1405  GspHex2Long(&ptr, &Length))
1406  {
1407  PEPROCESS DbgProcess = NULL;
1408 
1409  ptr = NULL;
1410  if (NULL != GspDbgThread &&
1411  PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
1412  {
1413  DbgProcess = GspDbgThread->ThreadsProcess;
1414  KeAttachProcess(&DbgProcess->Pcb);
1415  }
1418  if (NULL != DbgProcess)
1419  {
1420  KeDetachProcess();
1421  }
1422  if (GspMemoryError)
1423  {
1424  strcpy(GspOutBuffer, "E03");
1425  DPRINT("Fault during memory read\n");
1426  }
1427  }
1428 
1429  if (NULL != ptr)
1430  {
1431  strcpy(GspOutBuffer, "E01");
1432  }
1433  break;
1434 
1435  /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
1436  case 'M':
1437  /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
1438  if (GspHex2Long(&ptr, &Address))
1439  {
1440  if (*(ptr++) == ',' &&
1441  GspHex2Long(&ptr, &Length) &&
1442  *(ptr++) == ':')
1443  {
1444  PEPROCESS DbgProcess = NULL;
1445 
1446  if (NULL != GspDbgThread &&
1447  PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
1448  {
1449  DbgProcess = GspDbgThread->ThreadsProcess;
1450  KeAttachProcess(&DbgProcess->Pcb);
1451  }
1454  if (NULL != DbgProcess)
1455  {
1456  KeDetachProcess();
1457  }
1458  if (GspMemoryError)
1459  {
1460  strcpy(GspOutBuffer, "E03");
1461  DPRINT("Fault during memory write\n");
1462  }
1463  else
1464  {
1465  strcpy(GspOutBuffer, "OK");
1466  }
1467  ptr = NULL;
1468  }
1469  }
1470 
1471  if (NULL != ptr)
1472  {
1473  strcpy(GspOutBuffer, "E02");
1474  }
1475  break;
1476 
1477  /* cAA..AA Continue at address AA..AA(optional) */
1478  /* sAA..AA Step one instruction from AA..AA(optional) */
1479  case 's':
1480  Stepping = TRUE;
1481  case 'c':
1482  {
1483  ULONG BreakpointNumber;
1484  ULONG dr6_ = 0;
1485 
1486  /* try to read optional parameter, pc unchanged if no parm */
1487  if (GspHex2Long (&ptr, &Address))
1488  {
1489  //Context->Eip = Address;
1490  }
1491 
1492  //NewPC = Context->Eip;
1493 
1494  /* clear the trace bit */
1495  //Context->EFlags &= 0xfffffeff;
1496 
1497  /* set the trace bit if we're Stepping */
1498  if (Stepping)
1499  {
1500  //Context->EFlags |= 0x100;
1501  }
1502 
1503  // XXX arty load dr6
1504  if (!(dr6_ & 0x4000))
1505  {
1506  for (BreakpointNumber = 0; BreakpointNumber < 4; ++BreakpointNumber)
1507  {
1508  if (dr6_ & (1 << BreakpointNumber))
1509  {
1510  if (GspHwBreakpoints[BreakpointNumber].Type == 0)
1511  {
1512  /* Set restore flag */
1513  //Context->EFlags |= 0x10000;
1514  break;
1515  }
1516  }
1517  }
1518  }
1519  GspLoadBreakpoints(TrapFrame);
1520  // XXX load dr6
1521  if (NULL != GspDbgThread)
1522  {
1524  GspDbgThread = NULL;
1525  }
1526 
1527  DPRINT("Thread %p releasing mutex\n", PsGetCurrentThread());
1529  DPRINT("Thread %p leaving stub\n", PsGetCurrentThread());
1530  return kdContinue;
1531  }
1532 
1533  case 'k': /* kill the program */
1534  strcpy(GspOutBuffer, "OK");
1535  break;
1536 
1537  case 'H': /* Set thread */
1538  GspSetThread(ptr);
1539  break;
1540 
1541  case 'q': /* Query */
1542  GspQuery(ptr);
1543  break;
1544 
1545  case 'T': /* Query thread status */
1547  break;
1548 
1549  case 'Z':
1550  {
1551  LONG Type;
1552  LONG Address;
1553  LONG Length;
1554 
1555  GspHex2Long(&ptr, &Type);
1556  ptr++;
1557  GspHex2Long(&ptr, &Address);
1558  ptr++;
1559  GspHex2Long(&ptr, &Length);
1560  if (0 == Type)
1561  {
1563  }
1564  else
1565  {
1567  }
1568  break;
1569  }
1570 
1571  case 'z':
1572  {
1573  LONG Type;
1574  LONG Address;
1575  LONG Length;
1576 
1577  GspHex2Long(&ptr, &Type);
1578  ptr++;
1579  GspHex2Long(&ptr, &Address);
1580  ptr++;
1581  GspHex2Long(&ptr, &Length);
1582  if (0 == Type)
1583  {
1585  }
1586  else
1587  {
1589  }
1590  break;
1591  }
1592 
1593  default:
1594  break;
1595  }
1596 
1597  /* reply to the request */
1599  }
1600 
1601  /* not reached */
1602  ASSERT(0);
1603  }
1604 
1605  if (NULL != GspDbgThread)
1606  {
1608  GspDbgThread = NULL;
1609  }
1610 
1611  return kdContinue;
1612 }
1613 
1614 
1615 BOOLEAN
1616 NTAPI
1619 {
1620  PKTRAP_FRAME TrapFrame;
1621  BOOLEAN DoBreakIn;
1622  CONTEXT Context;
1623  KIRQL OldIrql;
1624  UCHAR Value;
1625 
1626  DPRINT("Break In\n");
1627 
1628  DoBreakIn = FALSE;
1629  while (KdPortGetByteEx(&GdbPortInfo, &Value))
1630  {
1631  if (Value == 0x03)
1632  DoBreakIn = TRUE;
1633  }
1634 
1635  if (!DoBreakIn)
1636  return TRUE;
1637 
1639 
1640  TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
1641 
1642  KeTrapFrameToContext(TrapFrame, NULL, &Context);
1643 
1645 
1646  KeContextToTrapFrame(&Context, NULL, TrapFrame, Context.ContextFlags, KernelMode);
1647 
1649 
1650  return TRUE;
1651 }
1652 
1653 VOID
1654 NTAPI
1656 {
1657 }
1658 
1659 /* Initialize the GDB stub */
1660 VOID
1661 NTAPI
1662 KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable,
1663  ULONG BootPhase)
1664 {
1665  if (!KdDebuggerEnabled || !KdpDebugMode.Gdb)
1666  return;
1667 
1668  if (BootPhase == 0)
1669  {
1671 
1672  /* Write out the functions that we support for now */
1673  WrapperTable->KdpInitRoutine = KdpGdbStubInit;
1674  WrapperTable->KdpPrintRoutine = KdpGdbDebugPrint;
1675  WrapperTable->KdpExceptionRoutine = KdpGdbEnterDebuggerException;
1676 
1677  /* Initialize the Port */
1679  // KdpPort = GdbPortInfo.ComPort;
1680  }
1681  else if (BootPhase == 1)
1682  {
1683  GspInitialized = TRUE;
1684 
1685  GspRunThread = NULL;
1686  GspDbgThread = NULL;
1687  GspEnumThread = NULL;
1688 
1689  HalDisplayString("Waiting for GDB to attach\r\n");
1691  }
1692  else if (BootPhase == 2)
1693  {
1694  HalDisplayString("\r\n GDB debugging enabled\r\n\r\n");
1695  }
1696 }
1697 
1698 /* EOF */
VOID GdbPutChar(UCHAR Value)
VOID NTAPI KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, ULONG ContextFlags, KPROCESSOR_MODE PreviousMode)
signed char * PCHAR
Definition: retypes.h:7
CPPORT GdbPortInfo
VOID GspQueryThreadStatus(PCHAR Request)
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1772
#define MAX_SW_BREAKPOINTS
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
BOOLEAN GspFindThread(PCHAR Data, PETHREAD *Thread)
static CHAR GspReadMemSafe(PCHAR Address)
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
LIST_ENTRY ThreadListEntry
Definition: pstypes.h:1100
_In_ WDFREQUEST Request
Definition: cdrom.h:1234
#define STATUS_ILLEGAL_INSTRUCTION
Definition: ntstatus.h:266
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
KDP_DEBUG_MODE KdpDebugMode
Definition: kdinit.c:25
#define GDB_ZTYPE_READ_WATCHPOINT
Type
Definition: Type.h:6
#define DR7_TYPE1_MASK
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
VOID GspPutPacket(PCHAR Buffer)
static unsigned GspHwBreakpointCount
static void GspLoadHwBreakpoint(PKTRAP_FRAME TrapFrame, unsigned BpIndex, ULONG_PTR Address, ULONG Length, ULONG Type)
#define DR7_LEN1_MASK
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static GSPSWBREAKPOINT GspSwBreakpoints[MAX_SW_BREAKPOINTS]
struct _GSPSWBREAKPOINT GSPSWBREAKPOINT
ULONG NTAPI MmGetPageProtect(struct _EPROCESS *Process, PVOID Address)
#define TRUE
Definition: types.h:120
static PCHAR GspThreadStates[DeferredReady+1]
NTSTATUS NTAPI PsLookupThreadByThreadId(IN HANDLE ThreadId, OUT PETHREAD *Thread)
Definition: thread.c:643
char CHAR
Definition: xmlstorage.h:175
#define GDB_ZTYPE_WRITE_WATCHPOINT
#define KeGetPreviousMode()
Definition: ketypes.h:1107
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_SINGLE_STEP
Definition: ntstatus.h:185
KTHREAD Tcb
Definition: pstypes.h:1045
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
static CONST CHAR HexChars[]
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1223
#define DR7_TYPE0_MASK
PKTRAP_FRAME TrapFrame
Definition: ketypes.h:1664
struct _ThreadInfo ThreadInfo
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define Ch(x, y, z)
Definition: sha2.c:141
#define DR7_L0
#define DR7_TYPE3_MASK
#define DR7_LEN(Bp, Len)
VOID GspQuery(PCHAR Request)
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
HANDLE UniqueProcessId
Definition: pstypes.h:1209
static GSPHWBREAKPOINT GspHwBreakpoints[MAX_HW_BREAKPOINTS]
static const CHAR Hex[]
Definition: hwdisk.c:40
IN UCHAR Value
Definition: halp.h:394
static BOOLEAN GspRemoteDebug
#define DR7_TYPE(Bp, Type)
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define GDB_ZTYPE_ACCESS_WATCHPOINT
#define DR7_LEN3_MASK
#define DR7_TYPE2_MASK
#define sprintf(buf, format,...)
Definition: sprintf.c:55
DWORD ExceptionCode
Definition: compat.h:208
#define MAX_HW_BREAKPOINTS
BOOLEAN NTAPI KdPortInitializeEx(PCPPORT PortInformation, ULONG ComPortNumber)
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG Size
Definition: gdbstub.c:66
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
#define DR7_G3
static CPU_REGISTER GspRegisters[NUMREGS]
UINT64 Dr2
Definition: ketypes.h:344
static BOOLEAN gdb_attached_yet
static PETHREAD GspEnumThread
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
#define FALSE
Definition: types.h:117
#define STATUS_INTEGER_OVERFLOW
Definition: ntstatus.h:385
long LONG
Definition: pedump.c:60
LIST_ENTRY PsActiveProcessHead
Definition: process.c:22
#define I386_BP_TYPE_DATA_WRITE
#define STATUS_INTEGER_DIVIDE_BY_ZERO
Definition: ntstatus.h:384
#define BUFMAX
static PVOID ptr
Definition: dispmode.c:27
#define DEFAULT_DEBUG_PORT
Definition: kdcom.c:25
CHAR * PCH
Definition: ntbasedef.h:392
#define PsGetCurrentProcess
Definition: psfuncs.h:17
static int Save(const char **args)
Definition: vfdcmd.c:1851
#define DR7_L3
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
#define STATUS_BREAKPOINT
Definition: ntstatus.h:184
ULONG Gpr1
Definition: ketypes.h:103
BOOLEAN KdDebuggerEnabled
Definition: kdmain.c:48
#define I386_BP_TYPE_EXECUTE
void DPRINT(...)
Definition: polytest.cpp:61
static void GspSetHwBreakpoint(ULONG Type, ULONG_PTR Address, ULONG Length)
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
VOID NTAPI KdPortPutByteEx(PCPPORT PortInformation, UCHAR ByteToSend)
#define GDB_ZTYPE_HARDWARE_BREAKPOINT
static LONG GspGetEspFromTrapFrame(PKTRAP_FRAME TrapFrame)
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
struct _CPU_REGISTER CPU_REGISTER
#define PCHAR
Definition: match.c:90
FAST_MUTEX
Definition: extypes.h:17
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
static void GspWriteMemSafe(PCHAR Address, CHAR Ch)
static VOID GspGetRegisters(PCHAR Address, PKTRAP_FRAME TrapFrame)
#define DEFAULT_DEBUG_BAUD_RATE
Definition: kdcom.c:28
UCHAR GdbGetChar(VOID)
VOID NTAPI KdpGdbDebugPrint(PCH Message, ULONG Length)
static CHAR GspInBuffer[BUFMAX]
static CHAR GspWriteMemSafeGetContent(PVOID Context, ULONG Offset)
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
VOID GspPutPacketNoWait(PCHAR Buffer)
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define DR7_LEN0_MASK
VOID GspSetSingleRegisterInTrapFrame(PCHAR Address, LONG Number, PCONTEXT Context, PKTRAP_FRAME TrapFrame)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static void GspLoadBreakpoints(PKTRAP_FRAME TrapFrame)
static BOOLEAN GspInitialized
CLIENT_ID Cid
Definition: pstypes.h:1070
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
BOOLEAN NTAPI GspBreakIn(PKINTERRUPT Interrupt, PVOID ServiceContext)
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
ULONG GspComputeSignal(NTSTATUS ExceptionCode)
static const UCHAR Index[8]
Definition: usbohci.c:18
ULONG GdbPortNumber
PVOID HANDLE
Definition: typedefs.h:73
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
static ULONG GspWriteMem(PCHAR Address, ULONG Count, BOOLEAN MayFault, CHAR(*GetContent)(PVOID Context, ULONG Offset), PVOID Context)
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
VOID NTAPI KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable, ULONG BootPhase)
LONG GspHex2Long(PCHAR *Address, PLONG Value)
static unsigned GspSwBreakpointCount
KD_CONTINUE_TYPE NTAPI KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT Context, PKTRAP_FRAME TrapFrame)
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID ServiceContext
Definition: iofuncs.h:798
UINT64 Dr3
Definition: ketypes.h:345
HANDLE UniqueThread
Definition: compat.h:685
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
CHAR Message[80]
Definition: alive.c:5
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
CHAR PrevContent
Definition: gdbstub.c:876
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
static PCHAR GspMem2Hex(PCHAR Address, PCHAR Buffer, LONG Count, BOOLEAN MayFault)
#define NUMREGS
BOOLEAN Active
Definition: gdbstub.c:877
static PETHREAD GspRunThread
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
KPROCESS Pcb
Definition: pstypes.h:1204
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
static volatile BOOLEAN GspMemoryError
#define DR7_LEN2_MASK
_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
static FAST_MUTEX GspLock
static void GspRemoveSwBreakpoint(ULONG_PTR Address)
#define DR7_GLOBAL_ENABLE(Bp)
#define I386_OPCODE_INT3
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
struct _GSPHWBREAKPOINT GSPHWBREAKPOINT
PCHAR GspGetPacket(VOID)
static CHAR GspOutBuffer[BUFMAX]
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
VOID NTAPI KeAttachProcess(IN PKPROCESS Process)
Definition: procobj.c:579
VOID GspLong2Hex(PCHAR *Address, LONG Value)
#define DR7_L2
#define DR7_G2
unsigned int * PULONG
Definition: retypes.h:1
static PCHAR GspHex2Mem(PCHAR Buffer, PCHAR Address, ULONG Count, BOOLEAN MayFault)
#define STATUS_STACK_OVERFLOW
Definition: ntstatus.h:489
NTHALAPI VOID NTAPI HalDisplayString(PUCHAR String)
static PETHREAD GspDbgThread
ULONG_PTR Address
Definition: gdbstub.c:865
#define DPRINT1
Definition: precomp.h:8
static void GspRemoveHwBreakpoint(ULONG Type, ULONG_PTR Address, ULONG Length)
static void GspSetSwBreakpoint(ULONG_PTR Address)
#define DR7_G0
LONG HexValue(CHAR ch)
#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
VOID GspSetThread(PCHAR Request)
#define ObReferenceObject
Definition: obfuncs.h:204
#define STATUS_DATATYPE_MISALIGNMENT
Definition: ntstatus.h:183
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
KD_DISPATCH_TABLE WrapperTable
Definition: kdinit.c:28
struct tagContext Context
Definition: acpixf.h:1034
CHAR ImageFileName[16]
Definition: pstypes.h:1268
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
struct _CPU_REGISTER * PCPU_REGISTER
ULONG_PTR Address
Definition: gdbstub.c:875
_In_ ULONG _In_ BOOLEAN Active
Definition: potypes.h:560
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
__analysis_noreturn NTSYSAPI VOID NTAPI DbgBreakPointWithStatus(_In_ ULONG Status)
UINT64 Dr7
Definition: ketypes.h:347
GLfloat GLfloat p
Definition: glext.h:8902
#define DR7_G1
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 STATUS_ARRAY_BOUNDS_EXCEEDED
Definition: ntstatus.h:376
#define DR7_L1
ULONG OffsetInContext
Definition: gdbstub.c:68
#define CONST
Definition: pedump.c:81
#define I386_BP_TYPE_DATA_READWRITE
static void GspUnloadBreakpoints(PKTRAP_FRAME TrapFrame)
VOID GspSetRegistersInTrapFrame(PCHAR Address, PCONTEXT Context, PKTRAP_FRAME TrapFrame)
static volatile void * GspAccessLocation
static CHAR GspHex2MemGetContent(PVOID Context, ULONG Offset)