[KDGDB]
authorJérôme Gardou <jerome.gardou@reactos.org>
Sun, 14 Sep 2014 14:27:44 +0000 (14:27 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Sun, 14 Sep 2014 14:27:44 +0000 (14:27 +0000)
 - Add support for the qfThreadInfo GDB request

svn path=/trunk/; revision=64144

reactos/drivers/base/kdgdb/gdb_input.c
reactos/drivers/base/kdgdb/gdb_send.c
reactos/drivers/base/kdgdb/kdcom.c
reactos/drivers/base/kdgdb/kdgdb.h

index 4e85422..a048b51 100644 (file)
@@ -7,6 +7,8 @@
 
 #include "kdgdb.h"
 
+#include <pstypes.h>
+
 /* LOCALS *********************************************************************/
 static HANDLE gdb_run_thread;
 static HANDLE gdb_dbg_process;
@@ -114,7 +116,7 @@ handle_gdb_thread_alive(void)
 /* q* packets */
 static
 void
-handle_gdb_query(void)
+handle_gdb_query(_Inout_ PKD_CONTEXT KdContext)
 {
     if (strncmp(gdb_input, "qSupported:", 11) == 0)
     {
@@ -145,10 +147,103 @@ handle_gdb_query(void)
         return;
     }
 
-    if (strncmp(gdb_input, "qTStatus", 8) == 0)
+    if (strncmp(gdb_input, "qfThreadInfo", 12) == 0)
     {
-        /* We don't support tracepoints. */
-        send_gdb_packet("T0");
+        LIST_ENTRY* ProcessListHead = (LIST_ENTRY*)KdDebuggerDataBlock->PsActiveProcessHead.Pointer;
+        LIST_ENTRY* ProcessEntry;
+        PEPROCESS Process;
+
+        KDDBGPRINT("ProcessListHead: %p.\n", ProcessListHead);
+
+        /* Maybe this was not initialized yet */
+        if (!ProcessListHead->Flink)
+        {
+            char gdb_out[64];
+            /* Just tell GDB about the current thread */
+            sprintf(gdb_out, "mp%p.%p", PsGetCurrentProcessId(), PsGetCurrentThreadId());
+            send_gdb_packet(gdb_out);
+            gdb_receive_packet(KdContext);
+            if (strncmp(gdb_input, "qsThreadInfo", 12) != 0)
+            {
+                // KdAssert
+                KDDBGPRINT("Received %s instead of qsThreadInfo!\n", gdb_input);
+                while(1);
+            }
+            send_gdb_packet("l");
+            return;
+        }
+
+        /* List all processes */
+        for (ProcessEntry = ProcessListHead->Flink;
+                ProcessEntry != ProcessListHead;
+                ProcessEntry = ProcessEntry->Flink)
+        {
+            BOOLEAN FirstThread = TRUE;
+            LIST_ENTRY* ThreadEntry;
+            PETHREAD Thread;
+            static char gdb_out[1024];
+            char* ptr;
+
+            ptr = gdb_out;
+            Process = CONTAINING_RECORD(ProcessEntry, EPROCESS, ActiveProcessLinks);
+
+            KDDBGPRINT("gdb_out %p.\n", gdb_out);
+
+            *ptr++ = 'm';
+            /* List threads from this process */
+            for (ThreadEntry = Process->ThreadListHead.Flink;
+                    ThreadEntry != &Process->ThreadListHead;
+                    ThreadEntry = ThreadEntry->Flink)
+            {
+                Thread = CONTAINING_RECORD(ThreadEntry, ETHREAD, ThreadListEntry);
+
+                KDDBGPRINT("ptr %p.\n", ptr);
+
+                /* See if we should add a comma */
+                if (FirstThread)
+                {
+                    FirstThread = FALSE;
+                }
+                else
+                {
+                    *ptr++ = ',';
+                }
+
+                ptr += _snprintf(ptr, 1024 - (ptr - gdb_out),
+                    "p%p.%p", PsGetProcessId(Process), PsGetThreadId(Thread));
+                if (ptr > (gdb_out + 1024))
+                {
+                    /* send what we got */
+                    KDDBGPRINT("Sending %s.\n", gdb_out);
+                    send_gdb_packet(gdb_out);
+                    gdb_receive_packet(KdContext);
+                    if (strncmp(gdb_input, "qsThreadInfo", 12) != 0)
+                    {
+                        // KdAssert
+                        KDDBGPRINT("Received %s instead of qsThreadInfo!\n", gdb_input);
+                        while(1);
+                    }
+                    /* Start anew */
+                    ptr = gdb_out;
+                    *ptr++ = 'm';
+                    FirstThread = TRUE;
+                }
+            }
+
+            /* send the list for this process */
+            KDDBGPRINT("Sending %s.\n", gdb_out);
+            send_gdb_packet(gdb_out);
+            gdb_receive_packet(KdContext);
+            if (strncmp(gdb_input, "qsThreadInfo", 12) != 0)
+            {
+                // KdAssert
+                KDDBGPRINT("Received %s instead of qsThreadInfo!\n", gdb_input);
+                while(1);
+            }
+        }
+
+        /* We're done. Send end-of-list packet */
+        send_gdb_packet("l");
         return;
     }
 
@@ -409,7 +504,7 @@ gdb_interpret_input(
     case 'm':
         return handle_gdb_read_mem(State, MessageData, MessageLength);
     case 'q':
-        handle_gdb_query();
+        handle_gdb_query(KdContext);
         break;
     case 'T':
         handle_gdb_thread_alive();
index 4e64495..980498e 100644 (file)
@@ -185,36 +185,3 @@ gdb_send_exception(void)
     ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor);
     send_gdb_packet(gdb_out);
 }
-
-#ifdef KDDEBUG
-ULONG KdpDbgPrint(const char* Format, ...)
-{
-    va_list ap;
-    CHAR Buffer[512];
-    struct _STRING Str;
-    int Length;
-
-    va_start(ap, Format);
-    Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
-    va_end(ap);
-
-    /* Check if we went past the buffer */
-    if (Length == -1)
-    {
-        /* Terminate it if we went over-board */
-        Buffer[sizeof(Buffer) - 1] = '\n';
-
-        /* Put maximum */
-        Length = sizeof(Buffer);
-    }
-
-    Str.Buffer = Buffer;
-    Str.Length = Length;
-    Str.MaximumLength = sizeof(Buffer);
-
-    gdb_send_debug_io(&Str);
-
-    return 0;
-}
-#endif
-
index f07a4d8..5c79228 100644 (file)
@@ -34,8 +34,11 @@ const ULONG BaseArray[] = {0, 0xF1012000};
 
 /* GLOBALS ********************************************************************/
 
+CPPORT KdComPort;
+ULONG  KdComPortIrq = 0; // Not used at the moment.
+#ifdef KDDEBUG
 CPPORT KdDebugComPort;
-ULONG  KdDebugComPortIrq = 0; // Not used at the moment.
+#endif
 
 
 /* FUNCTIONS ******************************************************************/
@@ -77,7 +80,7 @@ KdpPortInitialize(IN ULONG ComPortNumber,
 {
     NTSTATUS Status;
 
-    Status = CpInitialize(&KdDebugComPort,
+    Status = CpInitialize(&KdComPort,
                           UlongToPtr(BaseArray[ComPortNumber]),
                           ComPortBaudRate);
     if (!NT_SUCCESS(Status))
@@ -86,7 +89,7 @@ KdpPortInitialize(IN ULONG ComPortNumber,
     }
     else
     {
-        KdComPortInUse = KdDebugComPort.Address;
+        KdComPortInUse = KdComPort.Address;
         return STATUS_SUCCESS;
     }
 }
@@ -107,10 +110,9 @@ KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
     PCHAR CommandLine, PortString, BaudString, IrqString;
     ULONG Value;
 
-    /* Check if e have a LoaderBlock */
+    /* Check if we have a LoaderBlock */
     if (LoaderBlock)
     {
-
         /* Get the Command Line */
         CommandLine = LoaderBlock->LoadOptions;
 
@@ -182,11 +184,16 @@ KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
             {
                 /* Read and set it */
                 Value = atol(IrqString + 1);
-                if (Value) KdDebugComPortIrq = Value;
+                if (Value) KdComPortIrq = Value;
             }
         }
     }
 
+#ifdef KDDEBUG
+    /* Use DEBUGPORT=COM1 if you want to debug KDGDB, as we use COM2 for debugging it */
+    CpInitialize(&KdDebugComPort, UlongToPtr(BaseArray[2]), DEFAULT_BAUD_RATE);
+#endif
+
     /* Initialize the port */
     return KdpPortInitialize(ComPortNumber, ComPortBaudRate);
 }
@@ -210,7 +217,7 @@ NTAPI
 KdpSendByte(_In_ UCHAR Byte)
 {
     /* Send the byte */
-    CpPutByte(&KdDebugComPort, Byte);
+    CpPutByte(&KdComPort, Byte);
 }
 
 KDSTATUS
@@ -218,7 +225,7 @@ NTAPI
 KdpPollByte(OUT PUCHAR OutByte)
 {
     /* Poll the byte */
-    if (CpGetByte(&KdDebugComPort, OutByte, FALSE, FALSE) == CP_GET_SUCCESS)
+    if (CpGetByte(&KdComPort, OutByte, FALSE, FALSE) == CP_GET_SUCCESS)
     {
         return KdPacketReceived;
     }
@@ -233,7 +240,7 @@ NTAPI
 KdpReceiveByte(_Out_ PUCHAR OutByte)
 {
     /* Get the byte */
-    if (CpGetByte(&KdDebugComPort, OutByte, TRUE, FALSE) == CP_GET_SUCCESS)
+    if (CpGetByte(&KdComPort, OutByte, TRUE, FALSE) == CP_GET_SUCCESS)
     {
         return KdPacketReceived;
     }
@@ -266,4 +273,34 @@ KdpPollBreakIn(VOID)
     return KdPacketTimedOut;
 }
 
+#ifdef KDDEBUG
+ULONG KdpDbgPrint(const char* Format, ...)
+{
+    va_list ap;
+    static CHAR Buffer[512];
+    char* ptr;
+    int Length;
+
+    va_start(ap, Format);
+    Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
+    va_end(ap);
+
+    /* Check if we went past the buffer */
+    if (Length == -1)
+    {
+        /* Terminate it if we went over-board */
+        Buffer[sizeof(Buffer) - 1] = '\n';
+
+        /* Put maximum */
+        Length = sizeof(Buffer);
+    }
+
+    ptr = Buffer;
+    while (Length--)
+        CpPutByte(&KdDebugComPort, *ptr++);
+
+    return 0;
+}
+#endif
+
 /* EOF */
index e330f3e..03cac67 100644 (file)
@@ -16,7 +16,7 @@
 #include <windbgkd.h>
 #include <kddll.h>
 
-// #define KDDEBUG /* uncomment to enable debugging this dll */
+#define KDDEBUG /* uncomment to enable debugging this dll */
 
 #ifndef KDDEBUG
 #define KDDBGPRINT(...)