Only debug 1 thread at a time
[reactos.git] / reactos / ntoskrnl / kd / wrappers / gdbstub.c
index 5574b23..fb307df 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 
-               THIS SOFTWARE IS NOT COPYRIGHTED
+   THIS SOFTWARE IS NOT COPYRIGHTED
 
    HP offers the following for use in the public domain.  HP makes no
    warranty with regard to the software or it's performance and the
@@ -94,9 +94,6 @@
 #define BUFMAX 1000
 
 static BOOLEAN GspInitialized;
-#if 0
-static PKINTERRUPT GspInterrupt;
-#endif
 
 static BOOLEAN GspRemoteDebug;
 
@@ -106,18 +103,20 @@ static PETHREAD GspRunThread; /* NULL means run all threads */
 static PETHREAD GspDbgThread;
 static PETHREAD GspEnumThread;
 
+static FAST_MUTEX GspLock;
+
 extern LIST_ENTRY PsActiveProcessHead;
 KD_PORT_INFORMATION GdbPortInfo = { 2, 115200, 0 }; /* FIXME hardcoded for COM2, 115200 baud */
 
 /* Number of Registers.  */
-#define NUMREGS        16
+#define NUMREGS 16
 
 enum REGISTER_NAMES
 {
   EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
-       PC /* also known as eip */,
-       PS /* also known as eflags */,
-       CS, SS, DS, ES, FS, GS
+  PC /* also known as eip */,
+  PS /* also known as eflags */,
+  CS, SS, DS, ES, FS, GS
 };
 
 typedef struct _CPU_REGISTER
@@ -128,46 +127,29 @@ typedef struct _CPU_REGISTER
   BOOLEAN SetInContext;
 } CPU_REGISTER, *PCPU_REGISTER;
 
-#define KTRAP_FRAME_X86 KTRAP_FRAME
-
-#define EIP_REGNO 8
-
-typedef
-VOID
-STDCALL_FUNC
-(*PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine,
-                    PVOID StartContext);
-
-VOID
-STDCALL
-KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
-                PKSTART_ROUTINE StartRoutine,
-                PVOID StartContext,
-                BOOLEAN UserThread,
-                KTRAP_FRAME TrapFrame);
-
 static CPU_REGISTER GspRegisters[NUMREGS] =
 {
-  { 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 }
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Eax), FIELD_OFFSET(CONTEXT, Eax), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Ecx), FIELD_OFFSET(CONTEXT, Ecx), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Edx), FIELD_OFFSET(CONTEXT, Edx), FALSE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Ebx), FIELD_OFFSET(CONTEXT, Ebx), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Esp), FIELD_OFFSET(CONTEXT, Esp), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, DebugEbp), FIELD_OFFSET(CONTEXT, Ebp), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Esi), FIELD_OFFSET(CONTEXT, Esi), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Edi), FIELD_OFFSET(CONTEXT, Edi), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, DebugEip), FIELD_OFFSET(CONTEXT, Eip), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Eflags), FIELD_OFFSET(CONTEXT, EFlags), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Cs), FIELD_OFFSET(CONTEXT, SegCs), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Ss), FIELD_OFFSET(CONTEXT, SegSs), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Ds), FIELD_OFFSET(CONTEXT, SegDs), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Es), FIELD_OFFSET(CONTEXT, SegEs), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Fs), FIELD_OFFSET(CONTEXT, SegFs), TRUE },
+  { 4, FIELD_OFFSET(KTRAP_FRAME, Gs), FIELD_OFFSET(CONTEXT, SegGs), TRUE }
 };
 
 static PCHAR GspThreadStates[DeferredReady+1] =
-{ "Initialized",
+{
+  "Initialized",
   "Ready",
   "Running",
   "Standby",
@@ -179,12 +161,22 @@ static PCHAR GspThreadStates[DeferredReady+1] =
 
 
 LONG
-HexValue (CHAR ch)
+HexValue(CHAR ch)
 {
-  if ((ch >= '0') && (ch <= '9')) return (ch - '0');
-  if ((ch >= 'a') && (ch <= 'f')) return (ch - 'a' + 10);
-  if ((ch >= 'A') && (ch <= 'F')) return (ch - 'A' + 10);
-  return (-1);
+  if ((ch >= '0') && (ch <= '9'))
+    {
+      return (ch - '0');
+    }
+  if ((ch >= 'a') && (ch <= 'f'))
+    {
+      return (ch - 'a' + 10);
+    }
+  if ((ch >= 'A') && (ch <= 'F'))
+    {
+      return (ch - 'A' + 10);
+    }
+
+  return -1;
 }
 
 static CHAR GspInBuffer[BUFMAX];
@@ -193,7 +185,7 @@ static CHAR GspOutBuffer[BUFMAX];
 VOID
 GdbPutChar(UCHAR Value)
 {
-  KdPortPutByteEx (&GdbPortInfo, Value);
+  KdPortPutByteEx(&GdbPortInfo, Value);
 }
 
 UCHAR
@@ -201,7 +193,8 @@ GdbGetChar(VOID)
 {
   UCHAR Value;
 
-  while (!KdPortGetByteEx (&GdbPortInfo, &Value));
+  while (!KdPortGetByteEx(&GdbPortInfo, &Value))
+    ;
 
   return Value;
 }
@@ -220,7 +213,8 @@ GspGetPacket()
   while (TRUE)
     {
       /* wait around for the start character, ignore all other characters */
-      while ((ch = GdbGetChar ()) != '$');
+      while ((ch = GdbGetChar ()) != '$')
+        ;
 
     retry:
       Checksum = 0;
@@ -229,52 +223,47 @@ GspGetPacket()
 
       /* now, read until a # or end of Buffer is found */
       while (Count < BUFMAX)
-       {
-         ch = GdbGetChar ();
-         if (ch == '$')
-           goto retry;
-         if (ch == '#')
-           break;
-         Checksum = Checksum + ch;
-         Buffer[Count] = ch;
-         Count = Count + 1;
-       }
+        {
+          ch = GdbGetChar();
+          if (ch == '$')
+            {
+              goto retry;
+            }
+          if (ch == '#')
+            {
+              break;
+            }
+          Checksum = Checksum + ch;
+          Buffer[Count] = ch;
+          Count = Count + 1;
+        }
       Buffer[Count] = 0;
 
       if (ch == '#')
-       {
-         ch = GdbGetChar ();
-         XmitChecksum = (CHAR)(HexValue (ch) << 4);
-         ch = GdbGetChar ();
-         XmitChecksum += (CHAR)(HexValue (ch));
-
-         if (Checksum != XmitChecksum)
-           {
-             GdbPutChar ('-'); /* failed checksum */
-           }
-         else
-           {
-             GdbPutChar ('+'); /* successful transfer */
-
-             /* if a sequence char is present, reply the sequence ID */
-             if (Buffer[2] == ':')
-               {
-                 GdbPutChar (Buffer[0]);
-                 GdbPutChar (Buffer[1]);
-
-                 return &Buffer[3];
-               }
-
-             return &Buffer[0];
-           }
-       }
+        {
+          ch = GdbGetChar();
+          XmitChecksum = (CHAR)(HexValue(ch) << 4);
+          ch = GdbGetChar();
+          XmitChecksum += (CHAR)(HexValue(ch));
+
+          if (Checksum != XmitChecksum)
+            {
+              GdbPutChar('-'); /* failed checksum */
+            }
+          else
+            {
+              GdbPutChar('+'); /* successful transfer */
+
+              return &Buffer[0];
+            }
+        }
     }
 }
 
 /* send the packet in Buffer.  */
 
 VOID
-GspPutPacket (PCHAR Buffer)
+GspPutPacket(PCHAR Buffer)
 {
   CHAR Checksum;
   LONG Count;
@@ -283,47 +272,47 @@ GspPutPacket (PCHAR Buffer)
   /*  $<packet info>#<Checksum>. */
   do
     {
-      GdbPutChar ('$');
+      GdbPutChar('$');
       Checksum = 0;
       Count = 0;
 
       while ((ch = Buffer[Count]))
-                               {
-                                 GdbPutChar (ch);
-                                 Checksum += ch;
-                                 Count += 1;
-                               }
-
-      GdbPutChar ('#');
-      GdbPutChar (HexChars[(Checksum >> 4) & 0xf]);
-      GdbPutChar (HexChars[Checksum & 0xf]);
+        {
+          GdbPutChar(ch);
+          Checksum += ch;
+          Count += 1;
+        }
+
+      GdbPutChar('#');
+      GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
+      GdbPutChar(HexChars[Checksum & 0xf]);
     }
-  while (GdbGetChar () != '+');
+  while (GdbGetChar() != '+');
 }
 
 
 VOID
-GspPutPacketNoWait (PCHAR Buffer)
+GspPutPacketNoWait(PCHAR Buffer)
 {
   CHAR Checksum;
   LONG Count;
   CHAR ch;
 
   /*  $<packet info>#<Checksum>. */
-  GdbPutChar ('$');
+  GdbPutChar('$');
   Checksum = 0;
   Count = 0;
 
   while ((ch = Buffer[Count]))
-               {
-                 GdbPutChar (ch);
-                 Checksum += ch;
-                 Count += 1;
-               }
-
-  GdbPutChar ('#');
-  GdbPutChar (HexChars[(Checksum >> 4) & 0xf]);
-  GdbPutChar (HexChars[Checksum & 0xf]);
+    {
+      GdbPutChar(ch);
+      Checksum += ch;
+      Count += 1;
+    }
+
+  GdbPutChar('#');
+  GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
+  GdbPutChar(HexChars[Checksum & 0xf]);
 }
 
 /* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an
@@ -337,7 +326,7 @@ static volatile void *GspAccessLocation = NULL;
 /* If MayFault is TRUE, then we should set GspMemoryError in response to
    a fault; if FALSE treat a fault like any other fault in the stub.  */
 PCHAR
-GspMem2Hex (PCHAR Address,
+GspMem2Hex(PCHAR Address,
   PCHAR Buffer,
   LONG Count,
   BOOLEAN MayFault)
@@ -354,26 +343,28 @@ GspMem2Hex (PCHAR Address,
   for (i = 0; i < (ULONG) Count; i++)
     {
       if (MayFault)
-        GspAccessLocation = Address;
+        {
+          GspAccessLocation = Address;
+        }
       ch = *Address;
       GspAccessLocation = NULL;
       if (MayFault && GspMemoryError)
         {
-          return (Buffer);
+          return Buffer;
         }
       *Buffer++ = HexChars[(ch >> 4) & 0xf];
       *Buffer++ = HexChars[ch & 0xf];
       Address++;
     }
   *Buffer = 0;
-  return (Buffer);
+  return Buffer;
 }
 
 
 /* Convert the hex array pointed to by Buffer into binary to be placed at Address */
 /* Return a pointer to the character AFTER the last byte read from Buffer */
 PCHAR
-GspHex2Mem (PCHAR Buffer,
+GspHex2Mem(PCHAR Buffer,
   PCHAR Address,
   ULONG Count,
   BOOLEAN MayFault)
@@ -388,7 +379,7 @@ GspHex2Mem (PCHAR Buffer,
   current = Address;
   while ( current < Address + Count )
     {
-      page = (PCHAR)PAGE_ROUND_DOWN (current);
+      page = (PCHAR)PAGE_ROUND_DOWN(current);
       if (Address + Count <= page + PAGE_SIZE)
         {
           /* Fits in this page */
@@ -401,14 +392,14 @@ GspHex2Mem (PCHAR Buffer,
         }
       if (MayFault)
         {
-          oldprot = MmGetPageProtect (NULL, Address);
-          MmSetPageProtect (NULL, Address, PAGE_EXECUTE_READWRITE);
+          oldprot = MmGetPageProtect(NULL, Address);
+          MmSetPageProtect(NULL, Address, PAGE_EXECUTE_READWRITE);
         }
 
       for (i = 0; i < countinpage && ! GspMemoryError; i++)
         {
-          ch = (CHAR)(HexValue (*Buffer++) << 4);
-          ch = (CHAR)(ch + HexValue (*Buffer++));
+          ch = (CHAR)(HexValue(*Buffer++) << 4);
+          ch = (CHAR)(ch + HexValue(*Buffer++));
 
           GspAccessLocation = current;
           *current = ch;
@@ -417,59 +408,50 @@ GspHex2Mem (PCHAR Buffer,
         }
       if (MayFault)
         {
-          MmSetPageProtect (NULL, page, oldprot);
+          MmSetPageProtect(NULL, page, oldprot);
           if (GspMemoryError)
             {
-              return (Buffer);
+              return Buffer;
             }
         }
     }
 
-  return (Buffer);
+  return Buffer;
 }
 
 
 /* This function takes the 386 exception vector and attempts to
    translate this number into a unix compatible signal value */
 ULONG
-GspComputeSignal (NTSTATUS ExceptionCode)
+GspComputeSignal(NTSTATUS ExceptionCode)
 {
   ULONG SigVal;
 
   switch (ExceptionCode)
     {
     case STATUS_INTEGER_DIVIDE_BY_ZERO:
-      SigVal = 8;
-      break;                   /* divide by zero */
+      SigVal = 8; /* divide by zero */
+      break;
     case STATUS_SINGLE_STEP:
-                               /* debug exception */
     case STATUS_BREAKPOINT:
-      SigVal = 5;
-      break;                   /* breakpoint */
+      SigVal = 5; /* breakpoint */
+      break;
     case STATUS_INTEGER_OVERFLOW:
-                               /* into instruction (overflow) */
     case STATUS_ARRAY_BOUNDS_EXCEEDED:
-      SigVal = 16;
-      break;                   /* bound instruction */
+      SigVal = 16; /* bound instruction */
+      break;
     case STATUS_ILLEGAL_INSTRUCTION:
-      SigVal = 4;
-      break;                   /* Invalid opcode */
-#if 0
-    case STATUS_FLT_INVALID_OPERATION:
-      SigVal = 8;
-      break;                   /* coprocessor not available */
-#endif
+      SigVal = 4; /* Invalid opcode */
+      break;
     case STATUS_STACK_OVERFLOW:
-                               /* stack exception */
     case STATUS_DATATYPE_MISALIGNMENT:
-                               /* page fault */
     case STATUS_ACCESS_VIOLATION:
-      SigVal = 11;             /* access violation */
+      SigVal = 11; /* access violation */
       break;
     default:
-      SigVal = 7;              /* "software generated" */
+      SigVal = 7; /* "software generated" */
     }
-  return (SigVal);
+  return SigVal;
 }
 
 
@@ -478,7 +460,7 @@ GspComputeSignal (NTSTATUS ExceptionCode)
 /* RETURN NUMBER OF CHARS PROCESSED           */
 /**********************************************/
 LONG
-GspHex2Long (PCHAR *Address,
+GspHex2Long(PCHAR *Address,
   PLONG Value)
 {
   LONG NumChars = 0;
@@ -488,24 +470,26 @@ GspHex2Long (PCHAR *Address,
 
   while (**Address)
     {
-      Hex = HexValue (**Address);
+      Hex = HexValue(**Address);
       if (Hex >= 0)
-                               {
-                                 *Value = (*Value << 4) | Hex;
-                                 NumChars++;
-                               }
-        else
-               break;
+        {
+          *Value = (*Value << 4) | Hex;
+          NumChars++;
+        }
+      else
+        {
+          break;
+        }
 
       (*Address)++;
     }
 
-  return (NumChars);
+  return NumChars;
 }
 
 
 VOID
-GspLong2Hex (PCHAR *Address,
+GspLong2Hex(PCHAR *Address,
   LONG Value)
 {
   LONG Save;
@@ -514,7 +498,7 @@ GspLong2Hex (PCHAR *Address,
          (((Value >> 8) & 0xff) << 16) |
          (((Value >> 16) & 0xff) << 8) |
          (((Value >> 24) & 0xff) << 0);
-  *Address = GspMem2Hex ((PCHAR) &Save, *Address, 4, FALSE);
+  *Address = GspMem2Hex((PCHAR) &Save, *Address, 4, FALSE);
 }
 
 
@@ -527,51 +511,103 @@ GspLong2Hex (PCHAR *Address,
 static LONG
 GspGetEspFromTrapFrame(PKTRAP_FRAME TrapFrame)
 {
-
   return KeGetPreviousMode() == KernelMode
-         ? (LONG) &TrapFrame->Esp : TrapFrame->Esp;
+         ? (LONG) &TrapFrame->Esp : (LONG)TrapFrame->Esp;
 }
 
 
-VOID
-GspGetRegistersFromTrapFrame(PCHAR Address,
-  PCONTEXT Context,
+static VOID
+GspGetRegisters(PCHAR Address,
   PKTRAP_FRAME TrapFrame)
 {
-  ULONG Value;
-  PCHAR Buffer;
+  ULONG_PTR Value;
   PULONG p;
   DWORD i;
+  PETHREAD Thread;
+  ULONG_PTR *KernelStack;
 
-  Buffer = Address;
-  for (i = 0; i < sizeof (GspRegisters) / sizeof (GspRegisters[0]); i++)
-  {
-    if (TrapFrame)
+  if (NULL == GspDbgThread)
     {
-      if (ESP == i)
-      {
-        Value = GspGetEspFromTrapFrame (TrapFrame);
-      }
-      else
-      {
-        p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[i].OffsetInTF);
-        Value = *p;
-      }
+      Thread = PsGetCurrentThread();
     }
-    else if (i == EIP_REGNO)
+  else
     {
-      /*
-       * This thread has not been sheduled yet so assume it
-       * is still in PsBeginThreadWithContextInternal().
-       */
-      Value = (ULONG)KiThreadStartup;
+      TrapFrame = GspDbgThread->Tcb.TrapFrame;
+      Thread = GspDbgThread;
     }
-    else
+
+  if (Waiting == Thread->Tcb.State)
     {
-      Value = 0;
+      KernelStack = Thread->Tcb.KernelStack;
+      for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
+        {
+          switch(i)
+            {
+              case EBP:
+                Value = KernelStack[3];
+                break;
+              case EDI:
+                Value = KernelStack[4];
+                break;
+              case ESI:
+                Value = KernelStack[5];
+                break;
+              case EBX:
+                Value = KernelStack[6];
+                break;
+              case PC:
+                Value = KernelStack[7];
+                break;
+              case ESP:
+                Value = (ULONG_PTR) (KernelStack + 8);
+                break;
+              case CS:
+                Value = KERNEL_CS;
+                break;
+              case DS:
+                Value = KERNEL_DS;
+                break;
+              default:
+                Value = 0;
+                break;
+            }
+          Address = GspMem2Hex((PCHAR) &Value, Address, GspRegisters[i].Size,
+                               FALSE);
+        }
+    }
+  else
+    {
+      for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
+        {
+          if (TrapFrame)
+            {
+              if (ESP == i)
+                {
+                  Value = GspGetEspFromTrapFrame(TrapFrame);
+                }
+              else
+                {
+                  p = (PULONG)((ULONG_PTR) TrapFrame +
+                               GspRegisters[i].OffsetInTF);
+                  Value = *p;
+                }
+            }
+          else if (i == PC)
+            {
+              /*
+               * This thread has not been sheduled yet so assume it
+               * is still in PsBeginThreadWithContextInternal().
+               */
+              Value = (ULONG)KiThreadStartup;
+            }
+          else
+            {
+              Value = 0;
+            }
+          Address = GspMem2Hex((PCHAR) &Value, Address,
+                               GspRegisters[i].Size, FALSE);
+        }
     }
-    Buffer = GspMem2Hex ((PCHAR) &Value, Buffer, GspRegisters[i].Size, FALSE);
-  }
 }
 
 
@@ -586,19 +622,25 @@ GspSetRegistersInTrapFrame(PCHAR Address,
   DWORD i;
 
   if (!TrapFrame)
-    return;
+    {
+      return;
+    }
 
   Buffer = Address;
   for (i = 0; i < NUMREGS; i++)
-  {
-    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, GspRegisters[i].Size, FALSE);
-    *p = Value;
-  }
+    {
+      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, GspRegisters[i].Size, FALSE);
+      *p = Value;
+    }
 }
 
 
@@ -612,14 +654,20 @@ GspSetSingleRegisterInTrapFrame(PCHAR Address,
   PULONG p;
 
   if (!TrapFrame)
-    return;
+    {
+      return;
+    }
 
   if (GspRegisters[Number].SetInContext)
-    p = (PULONG) ((ULONG_PTR) Context + GspRegisters[Number].OffsetInContext);
+    {
+      p = (PULONG) ((ULONG_PTR) Context + GspRegisters[Number].OffsetInContext);
+    }
   else
-    p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[Number].OffsetInTF);
+    {
+      p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[Number].OffsetInTF);
+    }
   Value = 0;
-  GspHex2Mem (Address, (PCHAR) &Value, GspRegisters[Number].Size, FALSE);
+  GspHex2Mem(Address, (PCHAR) &Value, GspRegisters[Number].Size, FALSE);
   *p = Value;
 }
 
@@ -635,17 +683,17 @@ GspFindThread(PCHAR Data,
       /* All threads */
       ThreadInfo = NULL;
     }
-    else
+  else
     {
       ULONG uThreadId;
       HANDLE ThreadId;
       PCHAR ptr = &Data[0];
 
-      GspHex2Long (&ptr, (PLONG) &uThreadId);
+      GspHex2Long(&ptr, (PLONG) &uThreadId);
       ThreadId = (HANDLE)uThreadId;
 
-      if (!NT_SUCCESS (PsLookupThreadByThreadId (ThreadId, &ThreadInfo)))
-                         {
+      if (!NT_SUCCESS(PsLookupThreadByThreadId(ThreadId, &ThreadInfo)))
+        {
           *Thread = NULL;
           return FALSE;
         }
@@ -664,7 +712,7 @@ GspSetThread(PCHAR Request)
   switch (Request[0])
   {
     case 'c': /* Run thread */
-      if (GspFindThread (ptr, &ThreadInfo))
+      if (GspFindThread(ptr, &ThreadInfo))
         {
           GspOutBuffer[0] = 'O';
           GspOutBuffer[1] = 'K';
@@ -685,19 +733,30 @@ GspSetThread(PCHAR Request)
         }
       break;
     case 'g': /* Debug thread */
-      if (GspFindThread (ptr, &ThreadInfo))
-                         {
-                           GspOutBuffer[0] = 'O';
-                           GspOutBuffer[1] = 'K';
-
-                            if(GspDbgThread) ObDereferenceObject(GspDbgThread);
-
-                            GspDbgThread = ThreadInfo;
-                         }
-                         else
-                         {
-                           GspOutBuffer[0] = 'E';
-                         }
+      if (GspFindThread(ptr, &ThreadInfo))
+        {
+          GspOutBuffer[0] = 'O';
+          GspOutBuffer[1] = 'K';
+
+          if (NULL != GspDbgThread)
+            {
+              ObDereferenceObject(GspDbgThread);
+            }
+
+          if (ThreadInfo == PsGetCurrentThread())
+            {
+              GspDbgThread = NULL;
+              ObDereferenceObject(ThreadInfo);
+            }
+          else
+            {
+              GspDbgThread = ThreadInfo;
+            }
+        }
+      else
+        {
+          GspOutBuffer[0] = 'E';
+        }
       break;
     default:
       break;
@@ -708,176 +767,138 @@ GspSetThread(PCHAR Request)
 VOID
 GspQuery(PCHAR Request)
 {
-  PCHAR Command;
   ULONG Value;
 
-       Command = strtok (Request, ",");
-       if (strncmp (Command, "C", 1) == 0)
-  {
-    PCHAR ptr = &GspOutBuffer[2];
-
-    /* Get current thread id */
-    GspOutBuffer[0] = 'Q';
-    GspOutBuffer[1] = 'C';
-    if (NULL != GspDbgThread)
+  if (strncmp(Request, "C", 1) == 0)
     {
-      Value = (ULONG) GspDbgThread->Cid.UniqueThread;
-    }
-    else
-    {
-      Value = (ULONG) PsGetCurrentThread()->Cid.UniqueThread;
-    }
-    GspLong2Hex (&ptr, Value);
-  }
-  else if (strncmp (Command, "fThreadInfo", 11) == 0)
-  {
-    PEPROCESS Process;
-    PLIST_ENTRY AThread, AProcess;
-    PCHAR ptr = &GspOutBuffer[1];
-
-    /* Get first thread id */
-    GspEnumThread = NULL;
-    AProcess = PsActiveProcessHead.Flink;
-    while(AProcess != &PsActiveProcessHead)
-    {
-      Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
-      AThread = Process->ThreadListHead.Flink;
-      if(AThread != &Process->ThreadListHead)
-      {
-        GspEnumThread = CONTAINING_RECORD (Process->ThreadListHead.Flink,
-                                           ETHREAD, ThreadListEntry);
-        break;
-      }
-      AProcess = AProcess->Flink;
-    }
-    if(GspEnumThread != NULL)
-    {
-      GspOutBuffer[0] = 'm';
-      Value = (ULONG) GspEnumThread->Cid.UniqueThread;
-      GspLong2Hex (&ptr, Value);
+      PCHAR ptr = &GspOutBuffer[2];
+
+      /* Get current thread id */
+      GspOutBuffer[0] = 'Q';
+      GspOutBuffer[1] = 'C';
+      if (NULL != GspDbgThread)
+        {
+          Value = (ULONG) GspDbgThread->Cid.UniqueThread;
+        }
+      else
+        {
+          Value = (ULONG) PsGetCurrentThread()->Cid.UniqueThread;
+        }
+      GspLong2Hex(&ptr, Value);
     }
-    else
+  else if (strncmp(Request, "fThreadInfo", 11) == 0)
     {
-      /* FIXME - what to do here? This case should never happen though, there
-                 should always be at least one thread on the system... */
-      /* GspOutBuffer[0] = 'l'; */
-    }
-  }
-  else if (strncmp (Command, "sThreadInfo", 11) == 0)
-  {
-    PEPROCESS Process;
-    PLIST_ENTRY AThread, AProcess;
-    PCHAR ptr = &GspOutBuffer[1];
+      PEPROCESS Process;
+      PLIST_ENTRY AThread, AProcess;
+      PCHAR ptr = &GspOutBuffer[1];
 
-    /* Get next thread id */
-    if (GspEnumThread != NULL)
-    {
-      /* find the next thread */
-      Process = GspEnumThread->ThreadsProcess;
-      if(GspEnumThread->ThreadListEntry.Flink != &Process->ThreadListHead)
-      {
-        GspEnumThread = CONTAINING_RECORD (GspEnumThread->ThreadListEntry.Flink,
-                                           ETHREAD, ThreadListEntry);
-      }
-      else
-      {
-        PETHREAD Thread = NULL;
-        AProcess = Process->ActiveProcessLinks.Flink;
-        while(AProcess != &PsActiveProcessHead)
+      /* Get first thread id */
+      GspEnumThread = NULL;
+      AProcess = PsActiveProcessHead.Flink;
+      while(AProcess != &PsActiveProcessHead)
         {
           Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
           AThread = Process->ThreadListHead.Flink;
-          if(AThread != &Process->ThreadListHead)
-          {
-            Thread = CONTAINING_RECORD (Process->ThreadListHead.Flink,
-                                        ETHREAD, ThreadListEntry);
-            break;
-          }
+          if (AThread != &Process->ThreadListHead)
+            {
+              GspEnumThread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
+                                                ETHREAD, ThreadListEntry);
+              break;
+            }
           AProcess = AProcess->Flink;
         }
-        GspEnumThread = Thread;
-      }
-
       if(GspEnumThread != NULL)
-      {
-        /* return the ID */
-        GspOutBuffer[0] = 'm';
-        Value = (ULONG) GspEnumThread->Cid.UniqueThread;
-        GspLong2Hex (&ptr, Value);
-      }
+        {
+          GspOutBuffer[0] = 'm';
+          Value = (ULONG) GspEnumThread->Cid.UniqueThread;
+          GspLong2Hex(&ptr, Value);
+        }
       else
-      {
-        GspOutBuffer[0] = 'l';
-      }
+        {
+          /* FIXME - what to do here? This case should never happen though, there
+                     should always be at least one thread on the system... */
+          /* GspOutBuffer[0] = 'l'; */
+        }
     }
-    else
+  else if (strncmp(Request, "sThreadInfo", 11) == 0)
     {
-      GspOutBuffer[0] = 'l';
+      PEPROCESS Process;
+      PLIST_ENTRY AThread, AProcess;
+      PCHAR ptr = &GspOutBuffer[1];
+
+      /* Get next thread id */
+      if (GspEnumThread != NULL)
+        {
+          /* find the next thread */
+          Process = GspEnumThread->ThreadsProcess;
+          if(GspEnumThread->ThreadListEntry.Flink != &Process->ThreadListHead)
+            {
+              GspEnumThread = CONTAINING_RECORD(GspEnumThread->ThreadListEntry.Flink,
+                                                 ETHREAD, ThreadListEntry);
+            }
+          else
+            {
+              PETHREAD Thread = NULL;
+              AProcess = Process->ActiveProcessLinks.Flink;
+              while(AProcess != &PsActiveProcessHead)
+                {
+                  Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
+                  AThread = Process->ThreadListHead.Flink;
+                  if (AThread != &Process->ThreadListHead)
+                    {
+                      Thread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
+                                                 ETHREAD, ThreadListEntry);
+                      break;
+                    }
+                  AProcess = AProcess->Flink;
+                }
+              GspEnumThread = Thread;
+            }
+
+          if (GspEnumThread != NULL)
+            {
+              /* return the ID */
+              GspOutBuffer[0] = 'm';
+              Value = (ULONG) GspEnumThread->Cid.UniqueThread;
+              GspLong2Hex(&ptr, Value);
+            }
+          else
+            {
+              GspOutBuffer[0] = 'l';
+            }
+        }
+      else
+        {
+          GspOutBuffer[0] = 'l';
+        }
     }
-  }
-  else if (strncmp (Command, "ThreadExtraInfo", 15) == 0)
-  {
-    PETHREAD ThreadInfo;
-    PCHAR ptr = &Command[15];
+  else if (strncmp(Request, "ThreadExtraInfo", 15) == 0)
+    {
+      PETHREAD ThreadInfo;
 
-    /* Get thread information */
-    if (GspFindThread (ptr, &ThreadInfo))
-         {
-             PCHAR String = GspThreadStates[ThreadInfo->Tcb.State];
+      /* Get thread information */
+      if (GspFindThread(Request + 16, &ThreadInfo))
+        {
+          char Buffer[64];
+          PEPROCESS Proc;
 
-             ObDereferenceObject(ThreadInfo);
+          Proc = (PEPROCESS) ThreadInfo->ThreadsProcess;
 
-             GspMem2Hex (String, &GspOutBuffer[0], strlen (String), FALSE);
-         }
-  }
-#if 0
-       else if (strncmp (Command, "L", 1) == 0)
-  {
-    PLIST_ENTRY CurrentEntry;
-    PETHREAD Current;
-    ULONG MaxThreads = 0;
-    ULONG ThreadId = 0;
-    ULONG ThreadCount = 0;
-
-    /* List threads */
-    GspHex2Mem (&Request[1], (PCHAR) &MaxThreads, 2, TRUE);
-    GspHex2Mem (&Request[3], (PCHAR) &Value, 4, TRUE);
-    GspHex2Mem (&Request[11], (PCHAR) &ThreadId, 4, TRUE);
-
-    GspOutBuffer[0] = 'q';
-    GspOutBuffer[1] = 'M';
-    Value = 0;
-    GspMem2Hex ((PCHAR) &Value, &GspOutBuffer[5], 4, TRUE);
-    GspMem2Hex ((PCHAR) &ThreadId, &GspOutBuffer[13], 4, TRUE);
-
-    CurrentEntry = PiThreadListHead.Flink;
-    while ((CurrentEntry != &PiThreadListHead) && (ThreadCount < MaxThreads))
-      {
-        Current = CONTAINING_RECORD (CurrentEntry, ETHREAD, Tcb.ThreadListEntry);
-        Value = 0;
-        GspMem2Hex ((PCHAR) &Value, &GspOutBuffer[21+ThreadCount*16], 4, TRUE);
-        Value = (ULONG) Current->Cid.UniqueThread;
-        GspMem2Hex ((PCHAR) &Value, &GspOutBuffer[21+ThreadCount*16+8], 4, TRUE);
-        CurrentEntry = CurrentEntry->Flink;
-        ThreadCount++;
-      }
-
-    if (CurrentEntry != &PiThreadListHead)
-               {
-      GspOutBuffer[4] = '0';
-               }
-    else
-    {
-      GspOutBuffer[4] = '1';
-    }
+          Buffer[0] = '\0';
+          if (NULL != Proc )
+            {
+              sprintf(Buffer, "%s [%d:0x%x], ", Proc->ImageFileName,
+                      (int) Proc->UniqueProcessId,
+                      (int) ThreadInfo->Cid.UniqueThread);
+            }
+          strcpy(Buffer + strlen(Buffer),
+                 GspThreadStates[ThreadInfo->Tcb.State]);
 
-    GspMem2Hex ((PCHAR) &ThreadCount, &GspOutBuffer[2], 1, TRUE);
-  }
-#endif
-  else if (strncmp (Command, "Offsets", 7) == 0)
-  {
-    strcpy (GspOutBuffer, "Text=0;Data=0;Bss=0");
-  }
+          ObDereferenceObject(ThreadInfo);
+
+          GspMem2Hex(Buffer, &GspOutBuffer[0], strlen(Buffer), FALSE);
+        }
+    }
 }
 
 VOID
@@ -886,19 +907,19 @@ GspQueryThreadStatus(PCHAR Request)
   PETHREAD ThreadInfo;
   PCHAR ptr = &Request[0];
 
-  if (GspFindThread (ptr, &ThreadInfo))
-  {
-    ObDereferenceObject(ThreadInfo);
+  if (GspFindThread(ptr, &ThreadInfo))
+    {
+      ObDereferenceObject(ThreadInfo);
 
-    GspOutBuffer[0] = 'O';
-    GspOutBuffer[1] = 'K';
-    GspOutBuffer[2] = '\0';
-  }
+      GspOutBuffer[0] = 'O';
+      GspOutBuffer[1] = 'K';
+      GspOutBuffer[2] = '\0';
+    }
   else
-  {
-    GspOutBuffer[0] = 'E';
-    GspOutBuffer[1] = '\0';
-  }
+    {
+      GspOutBuffer[0] = 'E';
+      GspOutBuffer[1] = '\0';
+    }
 }
 
 
@@ -952,96 +973,98 @@ GspCorrectHwBreakpoint()
             "=r" (addr2), "=r" (addr3) : );
     } while (FALSE);
 #elif defined(_MSC_VER)
-    __asm
+  __asm
     {
-       mov eax, dr7; mov dr7_, eax;
-       mov eax, dr0; mov addr0, eax;
-       mov eax, dr1; mov addr1, eax;
-       mov eax, dr2; mov addr2, eax;
-       mov eax, dr3; mov addr3, eax;
+      mov eax, dr7; mov dr7_, eax;
+      mov eax, dr0; mov addr0, eax;
+      mov eax, dr1; mov addr1, eax;
+      mov eax, dr2; mov addr2, eax;
+      mov eax, dr3; mov addr3, eax;
     }
 #else
 #error Unknown compiler for inline assembler
 #endif
-    CorrectIt = FALSE;
-    for (BreakpointNumber = 0; BreakpointNumber < 3; BreakpointNumber++)
+  CorrectIt = FALSE;
+  for (BreakpointNumber = 0; BreakpointNumber < 3; BreakpointNumber++)
     {
-                       Bit = 2 << (BreakpointNumber << 1);
-                       if (!(dr7_ & Bit) && GspBreakpoints[BreakpointNumber].Enabled) {
-                 CorrectIt = TRUE;
-                       dr7_ |= Bit;
-                       dr7_ &= ~(0xf0000 << (BreakpointNumber << 2));
-                       dr7_ |= (((GspBreakpoints[BreakpointNumber].Length << 2) |
-        GspBreakpoints[BreakpointNumber].Type) << 16) << (BreakpointNumber << 2);
-    switch (BreakpointNumber) {
+      Bit = 2 << (BreakpointNumber << 1);
+      if (!(dr7_ & Bit) && GspBreakpoints[BreakpointNumber].Enabled)
+        {
+          CorrectIt = TRUE;
+          dr7_ |= Bit;
+          dr7_ &= ~(0xf0000 << (BreakpointNumber << 2));
+          dr7_ |= (((GspBreakpoints[BreakpointNumber].Length << 2) |
+          GspBreakpoints[BreakpointNumber].Type) << 16) << (BreakpointNumber << 2);
+          switch (BreakpointNumber)
+            {
 #if defined(__GNUC__)
-                       case 0:
-                         asm volatile ("movl %0, %%dr0\n"
-                           : : "r" (GspBreakpoints[BreakpointNumber].Address) );
-                         break;
-
-                       case 1:
-                               asm volatile ("movl %0, %%dr1\n"
-                                 : : "r" (GspBreakpoints[BreakpointNumber].Address) );
-                               break;
-
-                       case 2:
-                               asm volatile ("movl %0, %%dr2\n"
-                               : : "r" (GspBreakpoints[BreakpointNumber].Address) );
-                       break;
-
-      case 3:
-        asm volatile ("movl %0, %%dr3\n"
-          : : "r" (GspBreakpoints[BreakpointNumber].Address) );
-        break;
+            case 0:
+              asm volatile ("movl %0, %%dr0\n"
+                            : : "r" (GspBreakpoints[BreakpointNumber].Address) );
+              break;
+
+            case 1:
+              asm volatile ("movl %0, %%dr1\n"
+                            : : "r" (GspBreakpoints[BreakpointNumber].Address) );
+              break;
+
+            case 2:
+              asm volatile ("movl %0, %%dr2\n"
+                            : : "r" (GspBreakpoints[BreakpointNumber].Address) );
+              break;
+
+            case 3:
+              asm volatile ("movl %0, %%dr3\n"
+                            : : "r" (GspBreakpoints[BreakpointNumber].Address) );
+              break;
 #elif defined(_MSC_VER)
-       case 0:
-           {
-             ULONG addr = GspBreakpoints[BreakpointNumber].Address;
-             __asm mov eax, addr;
-             __asm mov dr0, eax;
-           }
-         break;
-       case 1:
-           {
-             ULONG addr = GspBreakpoints[BreakpointNumber].Address;
-             __asm mov eax, addr;
-             __asm mov dr1, eax;
-           }
-         break;
-       case 2:
-           {
-             ULONG addr = GspBreakpoints[BreakpointNumber].Address;
-             __asm mov eax, addr;
-             __asm mov dr2, eax;
-           }
-         break;
-       case 3:
-           {
-             ULONG addr = GspBreakpoints[BreakpointNumber].Address;
-             __asm mov eax, addr;
-             __asm mov dr3, eax;
-           }
-         break;
+            case 0:
+              {
+                ULONG addr = GspBreakpoints[BreakpointNumber].Address;
+                __asm mov eax, addr;
+                __asm mov dr0, eax;
+              }
+              break;
+            case 1:
+              {
+                ULONG addr = GspBreakpoints[BreakpointNumber].Address;
+                __asm mov eax, addr;
+                __asm mov dr1, eax;
+              }
+              break;
+            case 2:
+              {
+                ULONG addr = GspBreakpoints[BreakpointNumber].Address;
+                __asm mov eax, addr;
+                __asm mov dr2, eax;
+              }
+              break;
+            case 3:
+              {
+                ULONG addr = GspBreakpoints[BreakpointNumber].Address;
+                __asm mov eax, addr;
+                __asm mov dr3, eax;
+              }
+              break;
 #else
 #error Unknown compiler for inline assembler
 #endif
-      }
+            }
+        }
+      else if ((dr7_ & Bit) && !GspBreakpoints[BreakpointNumber].Enabled)
+        {
+          CorrectIt = TRUE;
+          dr7_ &= ~Bit;
+          dr7_ &= ~(0xf0000 << (BreakpointNumber << 2));
+        }
     }
-    else if ((dr7_ & Bit) && !GspBreakpoints[BreakpointNumber].Enabled)
-      {
-        CorrectIt = TRUE;
-        dr7_ &= ~Bit;
-        dr7_ &= ~(0xf0000 << (BreakpointNumber << 2));
-      }
-  }
   if (CorrectIt)
     {
 #if defined(__GNUC__)
-           asm volatile ( "movl %0, %%db7\n" : : "r" (dr7_));
+      asm volatile ( "movl %0, %%db7\n" : : "r" (dr7_));
 #elif defined(_MSC_VER)
-           __asm mov eax, dr7_;
-           __asm mov dr7, eax;
+      __asm mov eax, dr7_;
+      __asm mov dr7, eax;
 #else
 #error Unknown compiler for inline assembler
 #endif
@@ -1051,12 +1074,12 @@ GspCorrectHwBreakpoint()
 ULONG
 GspRemoveHwBreakpoint(ULONG BreakpointNumber)
 {
-       if (!GspBreakpoints[BreakpointNumber].Enabled)
+  if (!GspBreakpoints[BreakpointNumber].Enabled)
     {
-           return -1;
-       }
-       GspBreakpoints[BreakpointNumber].Enabled = 0;
-       return 0;
+      return -1;
+    }
+  GspBreakpoints[BreakpointNumber].Enabled = 0;
+  return 0;
 }
 
 
@@ -1066,18 +1089,19 @@ GspSetHwBreakpoint(ULONG BreakpointNumber,
   ULONG Length,
   ULONG Address)
 {
-       if (GspBreakpoints[BreakpointNumber].Enabled)
-         {
-               return -1;
-               }
-       GspBreakpoints[BreakpointNumber].Enabled = TRUE;
-       GspBreakpoints[BreakpointNumber].Type = Type;
-       GspBreakpoints[BreakpointNumber].Length = Length;
-       GspBreakpoints[BreakpointNumber].Address = Address;
-       return 0;
+  if (GspBreakpoints[BreakpointNumber].Enabled)
+    {
+      return -1;
+    }
+  GspBreakpoints[BreakpointNumber].Enabled = TRUE;
+  GspBreakpoints[BreakpointNumber].Type = Type;
+  GspBreakpoints[BreakpointNumber].Length = Length;
+  GspBreakpoints[BreakpointNumber].Address = Address;
+  return 0;
 }
 
 
+static BOOL gdb_attached_yet = FALSE;
 /*
  * This function does all command procesing for interfacing to gdb.
  */
@@ -1090,10 +1114,9 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
   BOOLEAN Stepping;
   LONG Address;
   LONG Length;
-  LONG SigVal;
+  LONG SigVal = 0;
   LONG NewPC;
   PCHAR ptr;
-  LONG Esp;
 
   /* FIXME: Stop on other CPUs too */
   /* Disable hardware debugging while we are inside the stub */
@@ -1112,60 +1135,76 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
     {
       GspAccessLocation = NULL;
       GspMemoryError = TRUE;
-      TrapFrame->Eip += 2;
+      Context->Eip += 3;
     }
   else
     {
-      /* Don't switch threads */
+      /* Can only debug 1 thread at a time... */
+      ExAcquireFastMutex(&GspLock);
 
-      /* Always use the current thread when entering the exception handler */
+      /* Make sure we're debugging the current thread. */
       if (NULL != GspDbgThread)
         {
+          DPRINT1("Internal error: entering stub with non-NULL GspDbgThread\n");
           ObDereferenceObject(GspDbgThread);
           GspDbgThread = NULL;
         }
 
-      /* 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++ = ':';
-
-      Esp = GspGetEspFromTrapFrame (TrapFrame);                        /* SP */
-      ptr = GspMem2Hex ((PCHAR) &Esp, ptr, 4, 0);
-      *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]);
-
+      /* ugly hack to avoid attempting to send status at the very
+       * beginning, right when GDB is trying to query the stub */
+      if (gdb_attached_yet)
+        {
+          LONG Esp;
+  
+          stop_reply:
+          /* reply to host that an exception has occurred */
+          SigVal = GspComputeSignal(ExceptionRecord->ExceptionCode);
+
+          ptr = GspOutBuffer;
+
+          *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */
+          *ptr++ = HexChars[(SigVal >> 4) & 0xf];
+          *ptr++ = HexChars[SigVal & 0xf];
+
+          *ptr++ = HexChars[ESP];
+          *ptr++ = ':';
+  
+          Esp = GspGetEspFromTrapFrame(TrapFrame);      /* SP */
+          ptr = GspMem2Hex((PCHAR) &Esp, ptr, 4, 0);
+          *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]);
+        }
+      else
+        {
+          gdb_attached_yet = 1;
+        }
+      
       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 ();
+          memset(GspOutBuffer, 0, sizeof(GspInBuffer));
+          ptr = GspGetPacket();
 
-          switch (*ptr++)
+          switch(*ptr++)
             {
             case '?':
+              /* a little hack to send more complete status information */
+              goto stop_reply;
               GspOutBuffer[0] = 'S';
               GspOutBuffer[1] = HexChars[SigVal >> 4];
               GspOutBuffer[2] = HexChars[SigVal % 16];
@@ -1174,97 +1213,123 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
             case 'd':
               GspRemoteDebug = !GspRemoteDebug; /* toggle debug flag */
               break;
-            case 'g':          /* return the value of the CPU Registers */
-              if (NULL != GspDbgThread)
-                {
-                  GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, GspDbgThread->Tcb.TrapFrame);
-                }
-              else
-                {
-                  GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame);
-                }
+            case 'g': /* return the value of the CPU Registers */
+              GspGetRegisters(GspOutBuffer, TrapFrame);
               break;
-            case 'G':          /* set the value of the CPU Registers - return OK */
+            case 'G': /* set the value of the CPU Registers - return OK */
               if (NULL != GspDbgThread)
                 {
-                  GspSetRegistersInTrapFrame (ptr, Context, GspDbgThread->Tcb.TrapFrame);
+                  GspSetRegistersInTrapFrame(ptr, Context, GspDbgThread->Tcb.TrapFrame);
                 }
               else
                 {
-                  GspSetRegistersInTrapFrame (ptr, Context, TrapFrame);
+                  GspSetRegistersInTrapFrame(ptr, Context, TrapFrame);
                 }
-              strcpy (GspOutBuffer, "OK");
+              strcpy(GspOutBuffer, "OK");
               break;
-            case 'P':          /* set the value of a single CPU register - return OK */
+            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);
-                        }
-                      else
-                        {
-                          GspSetSingleRegisterInTrapFrame (ptr, Register, Context, TrapFrame);
-                        }
-                      strcpy (GspOutBuffer, "OK");
-                      break;
-                    }
+                if ((GspHex2Long(&ptr, &Register)) && (*ptr++ == '='))
+                  {
+                    if ((Register >= 0) && (Register < NUMREGS))
+                      {
+                        if (GspDbgThread)
+                          {
+                            GspSetSingleRegisterInTrapFrame(ptr, Register,
+                                                            Context,
+                                                            GspDbgThread->Tcb.TrapFrame);
+                          }
+                        else
+                          {
+                            GspSetSingleRegisterInTrapFrame(ptr, Register,
+                                                            Context, TrapFrame);
+                          }
+                        strcpy(GspOutBuffer, "OK");
+                        break;
+                      }
+                  }
 
-                strcpy (GspOutBuffer, "E01");
+                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))
+              if (GspHex2Long(&ptr, &Address) &&
+                  *(ptr++) == ',' &&
+                  GspHex2Long(&ptr, &Length))
+                {
+                  PEPROCESS DbgProcess = NULL;
+
+                  ptr = NULL;
+                  if (NULL != GspDbgThread &&
+                      PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
                     {
-                      ptr = 0;
-                      GspMemoryError = FALSE;
-                      GspMem2Hex ((PCHAR) Address, GspOutBuffer, Length, 1);
-                      if (GspMemoryError)
-                        {
-                          strcpy (GspOutBuffer, "E03");
-                          DPRINT ("Fault during memory read\n");
-                        }
+                      DbgProcess = GspDbgThread->ThreadsProcess;
+                      KeAttachProcess(&DbgProcess->Pcb);
                     }
+                  GspMemoryError = FALSE;
+                  GspMem2Hex((PCHAR) Address, GspOutBuffer, Length, 1);
+                  if (NULL != DbgProcess)
+                    {
+                      KeDetachProcess();
+                    }
+                  if (GspMemoryError)
+                    {
+                      strcpy(GspOutBuffer, "E03");
+                      DPRINT("Fault during memory read\n");
+                    }
+                }
 
-              if (ptr)
-                strcpy (GspOutBuffer, "E01");
+              if (NULL != 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 (GspHex2Long(&ptr, &Address))
+                {
+                  if (*(ptr++) == ',' &&
+                      GspHex2Long(&ptr, &Length) &&
+                      *(ptr++) == ':')
+                    {
+                      PEPROCESS DbgProcess = NULL;
 
-                        if (GspMemoryError)
-                          {
-                            strcpy (GspOutBuffer, "E03");
-                            DPRINT ("Fault during memory write\n");
-                          }
-                        else
-                          {
-                            strcpy (GspOutBuffer, "OK");
-                          }
+                      if (NULL != GspDbgThread &&
+                          PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
+                        {
+                          DbgProcess = GspDbgThread->ThreadsProcess;
+                          KeAttachProcess(&DbgProcess->Pcb);
+                        }
+                      GspMemoryError = FALSE;
+                      GspHex2Mem(ptr, (PCHAR) Address, Length, TRUE);
+                      if (NULL != DbgProcess)
+                        {
+                          KeDetachProcess();
+                        }
+                      if (GspMemoryError)
+                        {
+                          strcpy(GspOutBuffer, "E03");
+                          DPRINT("Fault during memory write\n");
+                        }
+                      else
+                        {
+                          strcpy(GspOutBuffer, "OK");
+                        }
+                      ptr = NULL;
+                    }
+                }
 
-                        ptr = NULL;
-                      }
-              if (ptr)
-                strcpy (GspOutBuffer, "E02");
+              if (NULL != ptr)
+                {
+                  strcpy(GspOutBuffer, "E02");
+                }
               break;
 
             /* cAA..AA   Continue at address AA..AA(optional) */
@@ -1278,7 +1343,9 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
 
                 /* try to read optional parameter, pc unchanged if no parm */
                 if (GspHex2Long (&ptr, &Address))
-                  Context->Eip = Address;
+                  {
+                    Context->Eip = Address;
+                  }
 
                 NewPC = Context->Eip;
 
@@ -1287,7 +1354,9 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
 
                 /* set the trace bit if we're Stepping */
                 if (Stepping)
-                  Context->EFlags |= 0x100;
+                  {
+                    Context->EFlags |= 0x100;
+                  }
 
 #if defined(__GNUC__)
                 asm volatile ("movl %%db6, %0\n" : "=r" (dr6_) : );
@@ -1320,26 +1389,32 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
 #error Unknown compiler for inline assembler
 #endif
 
-                KeContextToTrapFrame(Context, TrapFrame);
-                return ((SigVal == 5) ? (kdContinue) : (kdHandleException));
+                if (NULL != GspDbgThread)
+                  {
+                    ObDereferenceObject(GspDbgThread);
+                    GspDbgThread = NULL;
+                  }
+
+                ExReleaseFastMutex(&GspLock);
+                return kdContinue;
                 break;
               }
 
-            case 'k':  /* kill the program */
-              strcpy (GspOutBuffer, "OK");
+            case 'k':  /* kill the program */
+              strcpy(GspOutBuffer, "OK");
               break;
               /* kill the program */
 
-            case 'H':          /* Set thread */
-              GspSetThread (ptr);
+            case 'H': /* Set thread */
+              GspSetThread(ptr);
               break;
 
             case 'q': /* Query */
-              GspQuery (ptr);
+              GspQuery(ptr);
               break;
 
             case 'T': /* Query thread status */
-              GspQueryThreadStatus (ptr);
+              GspQueryThreadStatus(ptr);
               break;
 
             case 'Y':
@@ -1350,20 +1425,20 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
                 LONG Address;
 
                 ptr = &GspOutBuffer[1];
-                GspHex2Long (&ptr, &Number);
+                GspHex2Long(&ptr, &Number);
                 ptr++;
-                GspHex2Long (&ptr, &Type);
+                GspHex2Long(&ptr, &Type);
                 ptr++;
-                GspHex2Long (&ptr, &Length);
+                GspHex2Long(&ptr, &Length);
                 ptr++;
-                GspHex2Long (&ptr, &Address);
-                if (GspSetHwBreakpoint (Number & 0x3, Type & 0x3 , Length & 0x3, Address) == 0)
+                GspHex2Long(&ptr, &Address);
+                if (GspSetHwBreakpoint(Number & 0x3, Type & 0x3 , Length & 0x3, Address) == 0)
                   {
-                    strcpy (GspOutBuffer, "OK");
+                    strcpy(GspOutBuffer, "OK");
                   }
                 else
                   {
-                    strcpy (GspOutBuffer, "E");
+                    strcpy(GspOutBuffer, "E");
                   }
                 break;
               }
@@ -1375,30 +1450,36 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
 
                 ptr = &GspOutBuffer[1];
                 GspHex2Long(&ptr, &Number);
-                if (GspRemoveHwBreakpoint (Number & 0x3) == 0)
+                if (GspRemoveHwBreakpoint(Number & 0x3) == 0)
                   {
-                    strcpy (GspOutBuffer, "OK");
+                    strcpy(GspOutBuffer, "OK");
                   }
                 else
                   {
-                    strcpy (GspOutBuffer, "E");
+                    strcpy(GspOutBuffer, "E");
                   }
                 break;
               }
 
             default:
               break;
-            }                  /* switch */
+            }
 
           /* reply to the request */
-          GspPutPacket (&GspOutBuffer[0]);
+          GspPutPacket(&GspOutBuffer[0]);
         }
 
       /* not reached */
       ASSERT(0);
     }
 
-    return kdDoNotHandleException;
+  if (NULL != GspDbgThread)
+    {
+      ObDereferenceObject(GspDbgThread);
+      GspDbgThread = NULL;
+    }
+
+  return kdContinue;
 }
 
 
@@ -1413,85 +1494,41 @@ GspBreakIn(PKINTERRUPT Interrupt,
   KIRQL OldIrql;
   UCHAR Value;
 
-  DPRINT ("Break In\n");
+  DPRINT("Break In\n");
 
   DoBreakIn = FALSE;
-  while (KdPortGetByteEx (&GdbPortInfo, &Value))
+  while (KdPortGetByteEx(&GdbPortInfo, &Value))
     {
       if (Value == 0x03)
-        DoBreakIn = TRUE;
+        {
+          DoBreakIn = TRUE;
+        }
     }
 
   if (!DoBreakIn)
-    return TRUE;
+    {
+      return TRUE;
+    }
 
-  KeRaiseIrql (HIGH_LEVEL, &OldIrql);
+  KeRaiseIrql(HIGH_LEVEL, &OldIrql);
 
   TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
 
-  KeTrapFrameToContext (TrapFrame, &Context);
+  KeTrapFrameToContext(TrapFrame, NULL, &Context);
 
-  KdpGdbEnterDebuggerException (NULL, &Context, TrapFrame);
+  KdpGdbEnterDebuggerException(NULL, &Context, TrapFrame);
 
-  KeContextToTrapFrame (&Context, TrapFrame);
+  KeContextToTrapFrame(&Context, NULL, TrapFrame, KernelMode);
 
-  KeLowerIrql (OldIrql);
+  KeLowerIrql(OldIrql);
 
   return TRUE;
 }
 
-
-extern ULONG KdpPortIrq;
-
-
 VOID
 STDCALL
-KdpGdbDebugPrint(PCH Message)
+KdpGdbDebugPrint(PCH Message, ULONG Length)
 {
-#if 0
-  /* This can be quite annoying! */
-  if (GspInitialized)
-         {
-           ULONG Length;
-
-           GspOutBuffer[0] = 'O';
-           GspOutBuffer[1] = '\0';
-           strcat (&GspOutBuffer[0], Message);
-           Length = strlen (Message);
-           GspOutBuffer[2 + Length] = '\n';
-           GspOutBuffer[3 + Length] = '\0';
-           GspPutPacketNoWait (&GspOutBuffer[0]);
-         }
-#endif
-}
-
-
-extern LIST_ENTRY ModuleListHead;
-
-VOID
-KdGdbListModules()
-{
-  PLIST_ENTRY CurrentEntry;
-  PMODULE_OBJECT Current;
-  ULONG ModuleCount;
-
-  DPRINT1("\n");
-
-  ModuleCount = 0;
-
-  CurrentEntry = ModuleListHead.Flink;
-  while (CurrentEntry != (&ModuleListHead))
-    {
-           Current = CONTAINING_RECORD (CurrentEntry, MODULE_OBJECT, ListEntry);
-
-      DbgPrint ("Module %S  Base 0x%.08x  Length 0x%.08x\n",
-        Current->BaseName.Buffer, Current->Base, Current->Length);
-
-      ModuleCount++;
-      CurrentEntry = CurrentEntry->Flink;
-    }
-
-  DbgPrint ("%d modules listed\n", ModuleCount);
 }
 
 /* Initialize the GDB stub */
@@ -1500,10 +1537,15 @@ STDCALL
 KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable,
                ULONG BootPhase)
 {
-    if (!KdDebuggerEnabled || !KdpDebugMode.Gdb) return;
+  if (!KdDebuggerEnabled || !KdpDebugMode.Gdb)
+    {
+      return;
+    }
 
-    if (BootPhase == 0)
+  if (BootPhase == 0)
     {
+      ExInitializeFastMutex(&GspLock);
+
       /* Write out the functions that we support for now */
       WrapperTable->KdpInitRoutine = KdpGdbStubInit;
       WrapperTable->KdpPrintRoutine = KdpGdbDebugPrint;
@@ -1512,7 +1554,7 @@ KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable,
       /* Initialize the Port */
       KdPortInitializeEx(&GdbPortInfo, 0, 0);
     }
-    else if (BootPhase == 1)
+  else if (BootPhase == 1)
     {
       GspInitialized = TRUE;
 
@@ -1522,9 +1564,9 @@ KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable,
 
       HalDisplayString("Waiting for GDB to attach\n");
       DbgPrint("Module 'hal.dll' loaded at 0x%.08x.\n", LdrHalBase);
-      DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
+      DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
     }
-    else if (BootPhase == 2)
+  else if (BootPhase == 2)
     {
       HalDisplayString("\n   GDB debugging enabled\n\n");
     }