update for HEAD-2003050101
[reactos.git] / ntoskrnl / kd / gdbstub.c
index 89c2112..2c8e461 100644 (file)
@@ -129,6 +129,8 @@ typedef struct _CPU_REGISTER
 {
   DWORD Size;
   DWORD OffsetInTF;
+  DWORD OffsetInContext;
+  BOOLEAN SetInContext;
 } CPU_REGISTER, *PCPU_REGISTER;
 
 #define KTRAP_FRAME_X86 KTRAP_FRAME
@@ -137,22 +139,22 @@ typedef struct _CPU_REGISTER
 
 static CPU_REGISTER GspRegisters[NUMREGS] =
 {
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eax) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ecx) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Edx) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ebx) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Esp) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ebp) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Esi) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Edi) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eip) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eflags) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Cs) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ss) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ds) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Es) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Fs) },
-  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Gs) }
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eax), FIELD_OFFSET (CONTEXT, Eax), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ecx), FIELD_OFFSET (CONTEXT, Ecx), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Edx), FIELD_OFFSET (CONTEXT, Edx), FALSE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ebx), FIELD_OFFSET (CONTEXT, Ebx), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Esp), FIELD_OFFSET (CONTEXT, Esp), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ebp), FIELD_OFFSET (CONTEXT, Ebp), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Esi), FIELD_OFFSET (CONTEXT, Esi), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Edi), FIELD_OFFSET (CONTEXT, Edi), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eip), FIELD_OFFSET (CONTEXT, Eip), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eflags), FIELD_OFFSET (CONTEXT, EFlags), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Cs), FIELD_OFFSET (CONTEXT, SegCs), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ss), FIELD_OFFSET (CONTEXT, SegSs), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ds), FIELD_OFFSET (CONTEXT, SegDs), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Es), FIELD_OFFSET (CONTEXT, SegEs), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Fs), FIELD_OFFSET (CONTEXT, SegFs), TRUE },
+  { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Gs), FIELD_OFFSET (CONTEXT, SegGs), TRUE }
 };
 
 static PCHAR GspThreadStates[THREAD_STATE_MAX] =
@@ -349,46 +351,10 @@ GspPutPacketNoWait (PCHAR Buffer)
   KdPutChar (HexChars[Checksum & 0xf]);
 }
 
-
-VOID
-GspDebugError(LPSTR Message)
-{
-  DbgPrint ("%s\n", Message);
-}
-
-/* Address of a routine to RTE to if we get a memory fault.  */
-static VOID (*volatile MemoryFaultRoutine) () = NULL;
-
 /* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an
    error.  */
 static volatile BOOLEAN GspMemoryError = FALSE;
-
-
-/* Currently not used */
-VOID
-GspSetMemoryError()
-{
-  GspMemoryError = TRUE;
-}
-
-
-/* These are separate functions so that they are so short and sweet
-   that the compiler won't save any Registers (if there is a fault
-   to MemoryFaultRoutine, they won't get restored, so there better
-   not be any saved).  */
-CHAR
-GspGetChar (PCHAR Address)
-{
-  return *Address;
-}
-
-
-VOID
-GspSetChar (PCHAR Address,
-  CHAR Value)
-{
-  *Address = Value;
-}
+static volatile void *GspAccessLocation = NULL;
 
 
 /* Convert the memory pointed to by Address into hex, placing result in Buffer */
@@ -404,19 +370,25 @@ GspMem2Hex (PCHAR Address,
   ULONG i;
   CHAR ch;
 
-  if (MayFault)
-    MemoryFaultRoutine = GspSetMemoryError;
+  if (NULL == Address && MayFault)
+    {
+      GspMemoryError = TRUE;
+      return Buffer;
+    }
+
   for (i = 0; i < (ULONG) Count; i++)
     {
-      ch = GspGetChar (Address++);
+      if (MayFault)
+        GspAccessLocation = Address;
+      ch = *Address;
+      GspAccessLocation = NULL;
       if (MayFault && GspMemoryError)
         return (Buffer);
       *Buffer++ = HexChars[(ch >> 4) & 0xf];
       *Buffer++ = HexChars[ch & 0xf];
+      Address++;
     }
   *Buffer = 0;
-  if (MayFault)
-    MemoryFaultRoutine = NULL;
   return (Buffer);
 }
 
@@ -429,21 +401,51 @@ GspHex2Mem (PCHAR Buffer,
   ULONG Count,
   BOOLEAN MayFault)
 {
+  PCHAR current;
+  PCHAR page;
+  ULONG countinpage;
   ULONG i;
   CHAR ch;
+  ULONG oldprot = 0;
 
-  if (MayFault)
-    MemoryFaultRoutine = GspSetMemoryError;
-  for (i = 0; i < Count; i++)
+  current = Address;
+  while ( current < Address + Count )
     {
-      ch = HexValue (*Buffer++) << 4;
-      ch = ch + HexValue (*Buffer++);
-      GspSetChar (Address++, ch);
-      if (MayFault && GspMemoryError)
-        return (Buffer);
+      page = (PCHAR)PAGE_ROUND_DOWN (current);
+      if (Address + Count <= page + PAGE_SIZE)
+        {
+          /* Fits in this page */
+          countinpage = Count;
+        }
+      else
+        {
+          /* Flows into next page, handle only current page in this iteration */
+          countinpage = PAGE_SIZE - (Address - page);
+        }
+      if (MayFault)
+        {
+          oldprot = MmGetPageProtect (NULL, Address);
+          MmSetPageProtect (NULL, Address, PAGE_EXECUTE_READWRITE);
+        }
+
+      for (i = 0; i < countinpage && ! GspMemoryError; i++)
+        {
+          ch = HexValue (*Buffer++) << 4;
+          ch = ch + HexValue (*Buffer++);
+
+          GspAccessLocation = Address;
+          *current = ch;
+          GspAccessLocation = NULL;
+          current++;
+        }
+      if (MayFault)
+        {
+          MmSetPageProtect (NULL, page, oldprot);
+          if (GspMemoryError)
+            return (Buffer);
+        }
     }
-  if (MayFault)
-    MemoryFaultRoutine = NULL;
+
   return (Buffer);
 }
 
@@ -461,14 +463,12 @@ GspComputeSignal (NTSTATUS ExceptionCode)
       SigVal = 8;
       break;                   /* divide by zero */
     case STATUS_SINGLE_STEP:
-      SigVal = 5;
-      break;                   /* debug exception */
+                               /* debug exception */
     case STATUS_BREAKPOINT:
       SigVal = 5;
       break;                   /* breakpoint */
     case STATUS_INTEGER_OVERFLOW:
-      SigVal = 16;
-      break;                   /* into instruction (overflow) */
+                               /* into instruction (overflow) */
     case STATUS_ARRAY_BOUNDS_EXCEEDED:
       SigVal = 16;
       break;                   /* bound instruction */
@@ -481,11 +481,12 @@ GspComputeSignal (NTSTATUS ExceptionCode)
       break;                   /* coprocessor not available */
 #endif
     case STATUS_STACK_OVERFLOW:
-      SigVal = 11;
-      break;                   /* stack exception */
+                               /* stack exception */
     case STATUS_DATATYPE_MISALIGNMENT:
-      SigVal = 11;
-      break;                   /* page fault */
+                               /* page fault */
+    case STATUS_ACCESS_VIOLATION:
+      SigVal = 11;             /* access violation */
+      break;
     default:
       SigVal = 7;              /* "software generated" */
     }
@@ -530,55 +531,73 @@ GspLong2Hex (PCHAR *Address,
 {
   LONG Save;
 
-  Save = (((Value >> 0) & 0xf) << 24) |
-         (((Value >> 8) & 0xf) << 16) |
-         (((Value >> 16) & 0xf) << 8) |
-         (((Value >> 24) & 0xf) << 0);
+  Save = (((Value >> 0) & 0xff) << 24) |
+         (((Value >> 8) & 0xff) << 16) |
+         (((Value >> 16) & 0xff) << 8) |
+         (((Value >> 24) & 0xff) << 0);
   *Address = GspMem2Hex ((PCHAR) &Save, *Address, 4, FALSE);
 }
 
 
+/*
+ * Esp is not stored in the trap frame, although there is a member with it's name.
+ * Instead, it was pointing to the location of the TrapFrame Esp member when the
+ * exception occured.
+ */
+static LONG
+GspGetEspFromTrapFrame(PKTRAP_FRAME TrapFrame)
+{
+  return (LONG) &TrapFrame->Esp;
+}
+
+
 VOID
 GspGetRegistersFromTrapFrame(PCHAR Address,
+  PCONTEXT Context,
   PKTRAP_FRAME TrapFrame)
 {
-  PCPU_REGISTER Regs;
   ULONG Value;
   PCHAR Buffer;
   PULONG p;
   DWORD i;
 
   Buffer = Address;
-  Regs = &GspRegisters[0];
-  for (i = 0; i < NUMREGS; i++)
+  for (i = 0; i < sizeof (GspRegisters) / sizeof (GspRegisters[0]); i++)
   {
     if (TrapFrame)
     {
-      p = (PULONG) ((ULONG_PTR) TrapFrame + Regs[i].OffsetInTF);
-      Value = *p;
+      if (ESP == i)
+      {
+        Value = GspGetEspFromTrapFrame (TrapFrame);
+      }
+      else
+      {
+        p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[i].OffsetInTF);
+        Value = *p;
+      }
     }
     else if (i == EIP_REGNO)
-               {
+    {
       /*
        * This thread has not been sheduled yet so assume it
        * is still in PsBeginThreadWithContextInternal().
        */
       Value = (ULONG) PsBeginThreadWithContextInternal;
-               }
+    }
     else
-               {
+    {
       Value = 0;
     }
-    Buffer = GspMem2Hex ((PCHAR) &Value, Buffer, Regs[i].Size, FALSE);
+    Buffer = GspMem2Hex ((PCHAR) &Value, Buffer, GspRegisters[i].Size, FALSE);
   }
 }
 
 
 VOID
 GspSetRegistersInTrapFrame(PCHAR Address,
+  PCONTEXT Context,
   PKTRAP_FRAME TrapFrame)
 {
-  PCPU_REGISTER Regs;
   ULONG Value;
   PCHAR Buffer;
   PULONG p;
@@ -588,12 +607,14 @@ GspSetRegistersInTrapFrame(PCHAR Address,
     return;
 
   Buffer = Address;
-  Regs = &GspRegisters[0];
   for (i = 0; i < NUMREGS; i++)
   {
-    p = (PULONG) ((ULONG_PTR) TrapFrame + Regs[i].OffsetInTF);
+    if (GspRegisters[i].SetInContext)
+      p = (PULONG) ((ULONG_PTR) Context + GspRegisters[i].OffsetInContext);
+    else
+      p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[i].OffsetInTF);
     Value = 0;
-    Buffer = GspHex2Mem (Buffer, (PCHAR) &Value, Regs[i].Size, FALSE);
+    Buffer = GspHex2Mem (Buffer, (PCHAR) &Value, GspRegisters[i].Size, FALSE);
     *p = Value;
   }
 }
@@ -602,6 +623,7 @@ GspSetRegistersInTrapFrame(PCHAR Address,
 VOID
 GspSetSingleRegisterInTrapFrame(PCHAR Address,
   LONG Number,
+  PCONTEXT Context,
   PKTRAP_FRAME TrapFrame)
 {
   ULONG Value;
@@ -610,7 +632,10 @@ GspSetSingleRegisterInTrapFrame(PCHAR Address,
   if (!TrapFrame)
     return;
 
-  p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[Number].OffsetInTF);
+  if (GspRegisters[Number].SetInContext)
+    p = (PULONG) ((ULONG_PTR) Context + GspRegisters[Number].OffsetInContext);
+  else
+    p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[Number].OffsetInTF);
   Value = 0;
   GspHex2Mem (Address, (PCHAR) &Value, GspRegisters[Number].Size, FALSE);
   *p = Value;
@@ -667,7 +692,10 @@ GspSetThread(PCHAR Request)
                          {
                            GspOutBuffer[0] = 'O';
                            GspOutBuffer[1] = 'K';
-               GspRunThread = ThreadInfo;
+
+                            if(GspRunThread) ObDereferenceObject(GspRunThread);
+
+                           GspRunThread = ThreadInfo;
                          }
                          else
                          {
@@ -679,7 +707,10 @@ GspSetThread(PCHAR Request)
                          {
                            GspOutBuffer[0] = 'O';
                            GspOutBuffer[1] = 'K';
-               GspDbgThread = ThreadInfo;
+
+                            if(GspDbgThread) ObDereferenceObject(GspDbgThread);
+
+                            GspDbgThread = ThreadInfo;
                          }
                          else
                          {
@@ -706,7 +737,14 @@ GspQuery(PCHAR Request)
     /* Get current thread id */
     GspOutBuffer[0] = 'Q';
     GspOutBuffer[1] = 'C';
-    Value = (ULONG) GspDbgThread->Cid.UniqueThread;
+    if (NULL != GspDbgThread)
+    {
+      Value = (ULONG) GspDbgThread->Cid.UniqueThread;
+    }
+    else
+    {
+      Value = (ULONG) PsGetCurrentThread()->Cid.UniqueThread;
+    }
     GspLong2Hex (&ptr, Value);
   }
   else if (strncmp (Command, "fThreadInfo", 11) == 0)
@@ -735,7 +773,7 @@ GspQuery(PCHAR Request)
     }
                else
                {
-           GspOutBuffer[0] = '1';
+           GspOutBuffer[0] = 'l';
                }
   }
   else if (strncmp (Command, "ThreadExtraInfo", 15) == 0)
@@ -746,8 +784,11 @@ GspQuery(PCHAR Request)
     /* Get thread information */
     if (GspFindThread (ptr, &ThreadInfo))
          {
-      PCHAR String = GspThreadStates[ThreadInfo->Tcb.State];
-      GspMem2Hex (String, &GspOutBuffer[0], strlen (String), FALSE);
+             PCHAR String = GspThreadStates[ThreadInfo->Tcb.State];
+           
+             ObDereferenceObject(ThreadInfo);
+           
+             GspMem2Hex (String, &GspOutBuffer[0], strlen (String), FALSE);
          }
   }
 #if 0
@@ -808,6 +849,8 @@ GspQueryThreadStatus(PCHAR Request)
 
   if (GspFindThread (ptr, &ThreadInfo))
   {
+    ObDereferenceObject(ThreadInfo);
+
     GspOutBuffer[0] = 'O';
     GspOutBuffer[1] = 'K';
     GspOutBuffer[2] = '\0';
@@ -947,248 +990,269 @@ KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
   LONG SigVal;
   LONG NewPC;
   PCHAR ptr;
+  LONG Esp;
 
   /* FIXME: Stop on other CPUs too */
   /* Disable hardware debugging while we are inside the stub */
   __asm__("movl %0,%%db7" : /* no output */ : "r" (0));
 
-  /* reply to host that an exception has occurred */
-  SigVal = GspComputeSignal (ExceptionRecord->ExceptionCode);
-
-  ptr = &GspOutBuffer[0];
-
-  *ptr++ = 'T';                        /* notify gdb with signo, PC, FP and SP */
-  *ptr++ = HexChars[(SigVal >> 4) & 0xf];
-  *ptr++ = HexChars[SigVal & 0xf];
-
-  *ptr++ = HexChars[ESP];
-  *ptr++ = ':';
-  ptr = GspMem2Hex ((PCHAR) &TrapFrame->Esp, ptr, 4, 0);       /* SP */
-  *ptr++ = ';';
-
-  *ptr++ = HexChars[EBP];
-  *ptr++ = ':';
-  ptr = GspMem2Hex ((PCHAR) &TrapFrame->Ebp, ptr, 4, 0);       /* FP */
-  *ptr++ = ';';
-
-  *ptr++ = HexChars[PC];
-  *ptr++ = ':';
-  ptr = GspMem2Hex((PCHAR) &TrapFrame->Eip, ptr, 4, 0);        /* PC */
-  *ptr++ = ';';
-
-  *ptr = '\0';
-
-  GspPutPacket (&GspOutBuffer[0]);
-
-  Stepping = FALSE;
-
-  while (TRUE)
+  if (STATUS_ACCESS_VIOLATION == (NTSTATUS) ExceptionRecord->ExceptionCode &&
+      NULL != GspAccessLocation &&
+      (ULONG_PTR) GspAccessLocation ==
+      (ULONG_PTR) ExceptionRecord->ExceptionInformation[1])
     {
-      /* Zero the buffer now so we don't have to worry about the terminating zero character */
-      memset (GspOutBuffer, 0, sizeof (GspInBuffer));
-      ptr = GspGetPacket ();
-
-      switch (*ptr++)
-       {
-       case '?':
-         GspOutBuffer[0] = 'S';
-         GspOutBuffer[1] = HexChars[SigVal >> 4];
-         GspOutBuffer[2] = HexChars[SigVal % 16];
-         GspOutBuffer[3] = 0;
-         break;
-       case 'd':
-         GspRemoteDebug = !GspRemoteDebug; /* toggle debug flag */
-         break;
-       case 'g':               /* return the value of the CPU Registers */
-    if (GspDbgThread)
-      GspGetRegistersFromTrapFrame (&GspOutBuffer[0], GspDbgThread->Tcb.TrapFrame);
-    else
-      GspGetRegistersFromTrapFrame (&GspOutBuffer[0], TrapFrame);
-         break;
-       case 'G':               /* set the value of the CPU Registers - return OK */
-    if (GspDbgThread)
-      GspSetRegistersInTrapFrame (ptr, GspDbgThread->Tcb.TrapFrame);
-    else
-      GspSetRegistersInTrapFrame (ptr, TrapFrame);
-         strcpy (GspOutBuffer, "OK");
-         break;
-       case 'P':               /* set the value of a single CPU register - return OK */
-         {
-           LONG Register;
-
-           if ((GspHex2Long (&ptr, &Register)) && (*ptr++ == '='))
-             if ((Register >= 0) && (Register < NUMREGS))
-                                       {
-                                   if (GspDbgThread)
-                                     GspSetSingleRegisterInTrapFrame (ptr, Register,
-                GspDbgThread->Tcb.TrapFrame);
-                                   else
-                                      GspSetSingleRegisterInTrapFrame (ptr, Register, TrapFrame);
-                                         strcpy (GspOutBuffer, "OK");
-                                         break;
-                                       }
-
-           strcpy (GspOutBuffer, "E01");
-           break;
-         }
-
-         /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
-       case 'm':
-         /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
-         if (GspHex2Long (&ptr, &Address))
-           if (*(ptr++) == ',')
-             if (GspHex2Long (&ptr, &Length))
-               {
-                 ptr = 0;
-                 GspMemoryError = FALSE;
-                 GspMem2Hex ((PCHAR) Address, GspOutBuffer, Length, 1);
-                 if (GspMemoryError)
-                   {
-                     strcpy (GspOutBuffer, "E03");
-                     GspDebugError ("memory fault");
-                   }
-               }
-
-         if (ptr)
-           {
-             strcpy (GspOutBuffer, "E01");
-           }
-         break;
-
-         /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
-       case 'M':
-         /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
-         if (GspHex2Long (&ptr, &Address))
-           if (*(ptr++) == ',')
-             if (GspHex2Long (&ptr, &Length))
-               if (*(ptr++) == ':')
-                 {
-        GspMemoryError = FALSE;
-                   GspHex2Mem (ptr, (PCHAR) Address, Length, TRUE);
-
-                   if (GspMemoryError)
-                     {
-                                               strcpy (GspOutBuffer, "E03");
-                                               GspDebugError ("memory fault");
-                     }
-                   else
-                     {
-                             strcpy (GspOutBuffer, "OK");
-                     }
-
-                   ptr = NULL;
-                 }
-         if (ptr)
-           {
-             strcpy (GspOutBuffer, "E02");
-           }
-         break;
-
-         /* cAA..AA   Continue at address AA..AA(optional) */
-         /* sAA..AA   Step one instruction from AA..AA(optional) */
-       case 's':
-         Stepping = TRUE;
-       case 'c':
-  {
-    ULONG BreakpointNumber;
-    ULONG dr6;
+      GspAccessLocation = NULL;
+      GspMemoryError = TRUE;
+      TrapFrame->Eip += 2;
+      ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NONCONTINUABLE;
+    }
+  else
+    {
+      /* reply to host that an exception has occurred */
+      SigVal = GspComputeSignal (ExceptionRecord->ExceptionCode);
 
-         /* try to read optional parameter, pc unchanged if no parm */
-         if (GspHex2Long (&ptr, &Address))
-           Context->Eip = Address;
+      ptr = &GspOutBuffer[0];
 
-         NewPC = Context->Eip;
+      *ptr++ = 'T';                    /* notify gdb with signo, PC, FP and SP */
+      *ptr++ = HexChars[(SigVal >> 4) & 0xf];
+      *ptr++ = HexChars[SigVal & 0xf];
 
-         /* clear the trace bit */
-         Context->EFlags &= 0xfffffeff;
+      *ptr++ = HexChars[ESP];
+      *ptr++ = ':';
 
-         /* set the trace bit if we're Stepping */
-         if (Stepping)
-           Context->EFlags |= 0x100;
+      Esp = GspGetEspFromTrapFrame (TrapFrame);                        /* SP */
+      ptr = GspMem2Hex ((PCHAR) &Esp, ptr, 4, 0);
+      *ptr++ = ';';
 
-    asm volatile ("movl %%db6, %0\n" : "=r" (dr6) : );
-    if (!(dr6 & 0x4000))
-           {
-             for (BreakpointNumber = 0; BreakpointNumber < 4; ++BreakpointNumber)
-               {
-                 if (dr6 & (1 << BreakpointNumber))
-                   {
-                     if (GspBreakpoints[BreakpointNumber].Type == 0)
-                       {
-                         /* Set restore flag */
-                         Context->EFlags |= 0x10000;
-                         break;
-                       }
-                   }
-               }
-      }
-    GspCorrectHwBreakpoint();
-    asm volatile ("movl %0, %%db6\n" : : "r" (0));
+      *ptr++ = HexChars[EBP];
+      *ptr++ = ':';
+      ptr = GspMem2Hex ((PCHAR) &TrapFrame->Ebp, ptr, 4, 0);   /* FP */
+      *ptr++ = ';';
 
-         return kdHandleException;
-         break;
-  }
-       case 'k':       /* kill the program */
-    strcpy (GspOutBuffer, "OK");
-         break;
-         /* kill the program */
-       case 'H':               /* Set thread */
-    GspSetThread (ptr);
-         break;
-  case 'q': /* Query */
-    GspQuery (ptr);
-    break;
-  case 'T': /* Query thread status */
-    GspQueryThreadStatus (ptr);
-    break;
-  case 'Y':
-  {
-    ULONG Number;
-    ULONG Length;
-    ULONG Type;
-    ULONG Address;
-
-    ptr = &GspOutBuffer[1];
-    GspHex2Long (&ptr, &Number);
-    ptr++;
-    GspHex2Long (&ptr, &Type);
-    ptr++;
-    GspHex2Long (&ptr, &Length);
-    ptr++;
-    GspHex2Long (&ptr, &Address);
-    if (GspSetHwBreakpoint (Number & 0x3, Type & 0x3 , Length & 0x3, Address) == 0)
-      {
-        strcpy (GspOutBuffer, "OK");
-      }
-    else
-      {
-        strcpy (GspOutBuffer, "E");
-      }
-    break;
-    /* Remove hardware breakpoint */
-  }
-  case 'y':
-  {
-    ULONG Number;
+      *ptr++ = HexChars[PC];
+      *ptr++ = ':';
+      ptr = GspMem2Hex((PCHAR) &TrapFrame->Eip, ptr, 4, 0);    /* PC */
+      *ptr++ = ';';
 
-    ptr = &GspOutBuffer[1];
-    GspHex2Long(&ptr, &Number);
-    if (GspRemoveHwBreakpoint (Number & 0x3) == 0)
-      {
-        strcpy (GspOutBuffer, "OK");
-      }
-    else
-      {
-        strcpy (GspOutBuffer, "E");
-      }
-    break;
-  }
-  default:
-    break;
-       }                       /* switch */
+      *ptr = '\0';
 
-      /* reply to the request */
       GspPutPacket (&GspOutBuffer[0]);
+
+      Stepping = FALSE;
+
+      while (TRUE)
+        {
+          /* Zero the buffer now so we don't have to worry about the terminating zero character */
+          memset (GspOutBuffer, 0, sizeof (GspInBuffer));
+          ptr = GspGetPacket ();
+
+          switch (*ptr++)
+            {
+            case '?':
+              GspOutBuffer[0] = 'S';
+              GspOutBuffer[1] = HexChars[SigVal >> 4];
+              GspOutBuffer[2] = HexChars[SigVal % 16];
+              GspOutBuffer[3] = 0;
+              break;
+            case 'd':
+              GspRemoteDebug = !GspRemoteDebug; /* toggle debug flag */
+              break;
+            case 'g':          /* return the value of the CPU Registers */
+              if (GspDbgThread)
+                GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, GspDbgThread->Tcb.TrapFrame);
+              else
+                GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame);
+              break;
+            case 'G':          /* set the value of the CPU Registers - return OK */
+              if (GspDbgThread)
+/*                GspSetRegistersInTrapFrame (ptr, Context, GspDbgThread->Tcb.TrapFrame);*/
+GspSetRegistersInTrapFrame (ptr, Context, TrapFrame);
+              else
+                GspSetRegistersInTrapFrame (ptr, Context, TrapFrame);
+              strcpy (GspOutBuffer, "OK");
+              break;
+            case 'P':          /* set the value of a single CPU register - return OK */
+              {
+                LONG Register;
+
+                if ((GspHex2Long (&ptr, &Register)) && (*ptr++ == '='))
+                  if ((Register >= 0) && (Register < NUMREGS))
+                    {
+                      if (GspDbgThread)
+/*                        GspSetSingleRegisterInTrapFrame (ptr, Register,
+                                                         Context, GspDbgThread->Tcb.TrapFrame);*/
+GspSetSingleRegisterInTrapFrame (ptr, Register, Context, TrapFrame);
+                      else
+                        GspSetSingleRegisterInTrapFrame (ptr, Register, Context, TrapFrame);
+                      strcpy (GspOutBuffer, "OK");
+                      break;
+                    }
+
+                strcpy (GspOutBuffer, "E01");
+                break;
+              }
+
+            /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
+            case 'm':
+              /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
+              if (GspHex2Long (&ptr, &Address))
+                if (*(ptr++) == ',')
+                  if (GspHex2Long (&ptr, &Length))
+                    {
+                      ptr = 0;
+                      GspMemoryError = FALSE;
+                      GspMem2Hex ((PCHAR) Address, GspOutBuffer, Length, 1);
+                      if (GspMemoryError)
+                        {
+                          strcpy (GspOutBuffer, "E03");
+                          DPRINT ("Fault during memory read\n");
+                        }
+                    }
+
+              if (ptr)
+                strcpy (GspOutBuffer, "E01");
+              break;
+
+            /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+            case 'M':
+              /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
+              if (GspHex2Long (&ptr, &Address))
+                if (*(ptr++) == ',')
+                  if (GspHex2Long (&ptr, &Length))
+                    if (*(ptr++) == ':')
+                      {
+                        GspMemoryError = FALSE;
+                        GspHex2Mem (ptr, (PCHAR) Address, Length, TRUE);
+
+                        if (GspMemoryError)
+                          {
+                            strcpy (GspOutBuffer, "E03");
+                            DPRINT ("Fault during memory write\n");
+                          }
+                        else
+                          {
+                            strcpy (GspOutBuffer, "OK");
+                          }
+
+                        ptr = NULL;
+                      }
+              if (ptr)
+                strcpy (GspOutBuffer, "E02");
+              break;
+
+            /* cAA..AA   Continue at address AA..AA(optional) */
+            /* sAA..AA   Step one instruction from AA..AA(optional) */
+            case 's':
+              Stepping = TRUE;
+            case 'c':
+              {
+                ULONG BreakpointNumber;
+                ULONG dr6;
+
+                /* try to read optional parameter, pc unchanged if no parm */
+                if (GspHex2Long (&ptr, &Address))
+                Context->Eip = Address;
+
+                NewPC = Context->Eip;
+
+                /* clear the trace bit */
+                Context->EFlags &= 0xfffffeff;
+
+                /* set the trace bit if we're Stepping */
+                if (Stepping)
+                  Context->EFlags |= 0x100;
+
+                asm volatile ("movl %%db6, %0\n" : "=r" (dr6) : );
+                if (!(dr6 & 0x4000))
+                  {
+                    for (BreakpointNumber = 0; BreakpointNumber < 4; ++BreakpointNumber)
+                      {
+                        if (dr6 & (1 << BreakpointNumber))
+                          {
+                            if (GspBreakpoints[BreakpointNumber].Type == 0)
+                              {
+                                /* Set restore flag */
+                                Context->EFlags |= 0x10000;
+                                break;
+                              }
+                          }
+                      }
+                  }
+                GspCorrectHwBreakpoint();
+                asm volatile ("movl %0, %%db6\n" : : "r" (0));
+
+                return kdHandleException;
+                break;
+              }
+
+            case 'k':  /* kill the program */
+              strcpy (GspOutBuffer, "OK");
+              break;
+              /* kill the program */
+
+            case 'H':          /* Set thread */
+              GspSetThread (ptr);
+              break;
+
+            case 'q': /* Query */
+              GspQuery (ptr);
+              break;
+
+            case 'T': /* Query thread status */
+              GspQueryThreadStatus (ptr);
+              break;
+
+            case 'Y':
+              {
+                LONG Number;
+                LONG Length;
+                LONG Type;
+                LONG Address;
+
+                ptr = &GspOutBuffer[1];
+                GspHex2Long (&ptr, &Number);
+                ptr++;
+                GspHex2Long (&ptr, &Type);
+                ptr++;
+                GspHex2Long (&ptr, &Length);
+                ptr++;
+                GspHex2Long (&ptr, &Address);
+                if (GspSetHwBreakpoint (Number & 0x3, Type & 0x3 , Length & 0x3, Address) == 0)
+                  {
+                    strcpy (GspOutBuffer, "OK");
+                  }
+                else
+                  {
+                    strcpy (GspOutBuffer, "E");
+                  }
+                break;
+              }
+
+            /* Remove hardware breakpoint */
+            case 'y':
+              {
+                LONG Number;
+
+                ptr = &GspOutBuffer[1];
+                GspHex2Long(&ptr, &Number);
+                if (GspRemoveHwBreakpoint (Number & 0x3) == 0)
+                  {
+                    strcpy (GspOutBuffer, "OK");
+                  }
+                else
+                  {
+                    strcpy (GspOutBuffer, "E");
+                  }
+                break;
+              }
+
+            default:
+              break;
+            }                  /* switch */
+
+          /* reply to the request */
+          GspPutPacket (&GspOutBuffer[0]);
+        }
     }
 
   return kdDoNotHandleException;
@@ -1253,7 +1317,11 @@ KdGdbStubInit(ULONG Phase)
 
                  GspInitialized = TRUE;
                  GspRunThread = PsGetCurrentThread();
-                 GspDbgThread = PsGetCurrentThread();
+     
+                  ObReferenceObject(GspRunThread);
+
+/*               GspDbgThread = PsGetCurrentThread(); */
+                  GspDbgThread = NULL;
                  GspEnumThread = NULL;
 
       DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);