Only debug 1 thread at a time
[reactos.git] / reactos / ntoskrnl / kd / wrappers / gdbstub.c
index 4eae20b..fb307df 100644 (file)
@@ -103,6 +103,8 @@ 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 */
 
@@ -125,8 +127,6 @@ typedef struct _CPU_REGISTER
   BOOLEAN SetInContext;
 } CPU_REGISTER, *PCPU_REGISTER;
 
-#define EIP_REGNO 8
-
 static CPU_REGISTER GspRegisters[NUMREGS] =
 {
   { 4, FIELD_OFFSET(KTRAP_FRAME, Eax), FIELD_OFFSET(CONTEXT, Eax), TRUE },
@@ -516,44 +516,97 @@ GspGetEspFromTrapFrame(PKTRAP_FRAME TrapFrame)
 }
 
 
-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 (NULL == GspDbgThread)
+    {
+      Thread = PsGetCurrentThread();
+    }
+  else
+    {
+      TrapFrame = GspDbgThread->Tcb.TrapFrame;
+      Thread = GspDbgThread;
+    }
+
+  if (Waiting == Thread->Tcb.State)
     {
-      if (TrapFrame)
+      KernelStack = Thread->Tcb.KernelStack;
+      for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
         {
-          if (ESP == i)
+          switch(i)
             {
-              Value = GspGetEspFromTrapFrame(TrapFrame);
+              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
             {
-              p = (PULONG)((ULONG_PTR) TrapFrame + GspRegisters[i].OffsetInTF);
-              Value = *p;
+              Value = 0;
             }
+          Address = GspMem2Hex((PCHAR) &Value, Address,
+                               GspRegisters[i].Size, FALSE);
         }
-      else if (i == EIP_REGNO)
-        {
-          /*
-           * This thread has not been sheduled yet so assume it
-           * is still in PsBeginThreadWithContextInternal().
-           */
-          Value = (ULONG)KiThreadStartup;
-        }
-      else
-        {
-          Value = 0;
-        }
-      Buffer = GspMem2Hex((PCHAR) &Value, Buffer, GspRegisters[i].Size, FALSE);
     }
 }
 
@@ -1086,6 +1139,9 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
     }
   else
     {
+      /* Can only debug 1 thread at a time... */
+      ExAcquireFastMutex(&GspLock);
+
       /* Make sure we're debugging the current thread. */
       if (NULL != GspDbgThread)
         {
@@ -1158,14 +1214,7 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
               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);
-                }
+              GspGetRegisters(GspOutBuffer, TrapFrame);
               break;
             case 'G': /* set the value of the CPU Registers - return OK */
               if (NULL != GspDbgThread)
@@ -1252,7 +1301,6 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
                     {
                       PEPROCESS DbgProcess = NULL;
 
-                      ptr = NULL;
                       if (NULL != GspDbgThread &&
                           PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
                         {
@@ -1274,6 +1322,7 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
                         {
                           strcpy(GspOutBuffer, "OK");
                         }
+                      ptr = NULL;
                     }
                 }
 
@@ -1346,6 +1395,7 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
                     GspDbgThread = NULL;
                   }
 
+                ExReleaseFastMutex(&GspLock);
                 return kdContinue;
                 break;
               }
@@ -1494,6 +1544,8 @@ KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable,
 
   if (BootPhase == 0)
     {
+      ExInitializeFastMutex(&GspLock);
+
       /* Write out the functions that we support for now */
       WrapperTable->KdpInitRoutine = KdpGdbStubInit;
       WrapperTable->KdpPrintRoutine = KdpGdbDebugPrint;