Author: jgardou
Date: Thu Sep  1 22:58:15 2016
New Revision: 72533

URL: http://svn.reactos.org/svn/reactos?rev=72533&view=rev
Log:
[KDGDB]
 - Better report kernel stack (real back traces for all threads!)
 - Support reporting loaded libraries (== drivers, hal, etc.). You can even 
debug KDGDB inside KDGDB :-)
 - A few improvements here and there
CORE-8531

Modified:
    trunk/reactos/drivers/base/kdgdb/gdb_input.c
    trunk/reactos/drivers/base/kdgdb/gdb_send.c
    trunk/reactos/drivers/base/kdgdb/i386_sup.c
    trunk/reactos/drivers/base/kdgdb/kdgdb.h
    trunk/reactos/drivers/base/kdgdb/kdpacket.c

Modified: trunk/reactos/drivers/base/kdgdb/gdb_input.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/gdb_input.c?rev=72533&r1=72532&r2=72533&view=diff
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/gdb_input.c        [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/gdb_input.c        [iso-8859-1] Thu Sep  1 
22:58:15 2016
@@ -20,6 +20,13 @@
 UINT_PTR gdb_dbg_pid;
 UINT_PTR gdb_dbg_tid;
 
+static inline
+KDSTATUS
+LOOP_IF_SUCCESS(x)
+{
+    return (x == KdPacketReceived) ? (KDSTATUS)-1 : x;
+}
+
 /* PRIVATE FUNCTIONS 
**********************************************************/
 static
 UINT_PTR
@@ -58,9 +65,11 @@
 
 /* H* packets */
 static
-void
+KDSTATUS
 handle_gdb_set_thread(void)
 {
+    KDSTATUS Status;
+
     switch (gdb_input[1])
     {
     case 'c':
@@ -68,7 +77,7 @@
             gdb_run_tid = (ULONG_PTR)-1;
         else
             gdb_run_tid = hex_to_tid(&gdb_input[2]);
-        send_gdb_packet("OK");
+        Status = send_gdb_packet("OK");
         break;
     case 'g':
         KDDBGPRINT("Setting debug thread: %s.\n", gdb_input);
@@ -98,20 +107,23 @@
                 gdb_dbg_tid = hex_to_tid(ptr);
         }
 #endif
-        send_gdb_packet("OK");
+        Status = send_gdb_packet("OK");
         break;
     default:
         KDDBGPRINT("KDGBD: Unknown 'H' command: %s\n", gdb_input);
-        send_gdb_packet("");
-    }
-}
-
-static
-void
+        Status = send_gdb_packet("");
+    }
+
+    return Status;
+}
+
+static
+KDSTATUS
 handle_gdb_thread_alive(void)
 {
     ULONG_PTR Pid, Tid;
     PETHREAD Thread;
+    KDSTATUS Status;
 
 #if MONOPROCESS
     Pid = 0;
@@ -131,45 +143,44 @@
     Thread = find_thread(Pid, Tid);
 
     if (Thread != NULL)
-        send_gdb_packet("OK");
+        Status = send_gdb_packet("OK");
     else
-        send_gdb_packet("E03");
+        Status = send_gdb_packet("E03");
+
+    return Status;
 }
 
 /* q* packets */
 static
-void
+KDSTATUS
 handle_gdb_query(void)
 {
     if (strncmp(gdb_input, "qSupported:", 11) == 0)
     {
 #if MONOPROCESS
-        send_gdb_packet("PacketSize=1000;");
-#else
-        send_gdb_packet("PacketSize=1000;multiprocess+;");
-#endif
-        return;
+        return send_gdb_packet("PacketSize=1000;qXfer:libraries:read+;");
+#else
+        return 
send_gdb_packet("PacketSize=1000;multiprocess+;qXfer:libraries:read+;");
+#endif
     }
 
     if (strncmp(gdb_input, "qAttached", 9) == 0)
     {
 #if MONOPROCESS
-        send_gdb_packet("1");
+        return send_gdb_packet("1");
 #else
         UINT_PTR queried_pid = hex_to_pid(&gdb_input[10]);
         /* Let's say we created system process */
         if (gdb_pid_to_handle(queried_pid) == NULL)
-            send_gdb_packet("0");
+            return send_gdb_packet("0");
         else
-            send_gdb_packet("1");
-#endif
-        return;
+            return send_gdb_packet("1");
+#endif
     }
 
     if (strncmp(gdb_input, "qRcmd,", 6) == 0)
     {
-        send_gdb_packet("OK");
-        return;
+        return send_gdb_packet("OK");
     }
 
     if (strcmp(gdb_input, "qC") == 0)
@@ -183,112 +194,69 @@
             
handle_to_gdb_pid(PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)),
             
handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)));
 #endif
-        send_gdb_packet(gdb_out);
-        return;
-    }
-
-    if ((strncmp(gdb_input, "qfThreadInfo", 12) == 0)
-            || (strncmp(gdb_input, "qsThreadInfo", 12) == 0))
-    {
-        BOOLEAN FirstThread = TRUE;
+        return send_gdb_packet(gdb_out);
+    }
+
+    if (strncmp(gdb_input, "qfThreadInfo", 12) == 0)
+    {
         PEPROCESS Process;
-        PETHREAD Thread;
-        char gdb_out[1024];
-        char* ptr = gdb_out;
-        BOOLEAN Resuming = strncmp(gdb_input, "qsThreadInfo", 12) == 0;
-        /* Keep track of where we are. */
-        static LIST_ENTRY* CurrentProcessEntry;
-        static LIST_ENTRY* CurrentThreadEntry;
-
-        ptr = gdb_out;
-
-        *ptr++ = 'm';
-        /* NULL terminate in case we got nothing more to iterate */
-        *ptr  = '\0';
-
-        if (!Resuming)
-        {
-        /* Report the idle thread */
-#if MONOPROCESS
-            ptr += sprintf(ptr, "1");
-#else
-            ptr += sprintf(gdb, "p1.1");
-#endif
-            /* Initialize the entries */
-            CurrentProcessEntry = ProcessListHead->Flink;
-            CurrentThreadEntry = NULL;
-            FirstThread = FALSE;
-        }
-
+        char gdb_out[40];
+        LIST_ENTRY* CurrentProcessEntry;
+
+        CurrentProcessEntry = ProcessListHead->Flink;
         if (CurrentProcessEntry == NULL) /* Ps is not initialized */
         {
-            send_gdb_packet(Resuming ? "l" : gdb_out);
-            return;
-        }
+#if MONOPROCESS
+            return send_gdb_packet("m1");
+#else
+            return send_gdb_packet("mp1.1");
+#endif
+        }
+
+        /* We will push threads as we find them */
+        start_gdb_packet();
+
+        /* Start with the system thread */
+#if MONOPROCESS
+        send_gdb_partial_packet("m1");
+#else
+        send_gdb_partial_packet("mp1.1");
+#endif
 
         /* List all the processes */
         for ( ;
             CurrentProcessEntry != ProcessListHead;
             CurrentProcessEntry = CurrentProcessEntry->Flink)
         {
+            LIST_ENTRY* CurrentThreadEntry;
 
             Process = CONTAINING_RECORD(CurrentProcessEntry, EPROCESS, 
ActiveProcessLinks);
 
-            if (CurrentThreadEntry != NULL)
-                CurrentThreadEntry = CurrentThreadEntry->Flink;
-            else
-                CurrentThreadEntry = Process->ThreadListHead.Flink;
-
             /* List threads from this process */
-            for ( ;
+            for ( CurrentThreadEntry = Process->ThreadListHead.Flink;
                  CurrentThreadEntry != &Process->ThreadListHead;
                  CurrentThreadEntry = CurrentThreadEntry->Flink)
             {
-                Thread = CONTAINING_RECORD(CurrentThreadEntry, ETHREAD, 
ThreadListEntry);
-
-                /* See if we should add a comma */
-                if (FirstThread)
-                {
-                    FirstThread = FALSE;
-                }
-                else
-                {
-                    *ptr++ = ',';
-                }
-
-#if MONOPROCESS
-                ptr += _snprintf(ptr, 1024 - (ptr - gdb_out),
-                    "%p",
-                    handle_to_gdb_tid(Thread->Cid.UniqueThread));
-#else
-                ptr += _snprintf(ptr, 1024 - (ptr - gdb_out),
-                    "p%p.%p",
+                PETHREAD Thread = CONTAINING_RECORD(CurrentThreadEntry, 
ETHREAD, ThreadListEntry);
+
+#if MONOPROCESS
+                _snprintf(gdb_out, 40, ",%p", 
handle_to_gdb_tid(Thread->Cid.UniqueThread));
+#else
+                _snprintf(gdb_out, 40, ",p%p.%p",
                     handle_to_gdb_pid(Process->UniqueProcessId),
                     handle_to_gdb_tid(Thread->Cid.UniqueThread));
 #endif
-                if (ptr > (gdb_out + 1024))
-                {
-                    /* send what we got */
-                    send_gdb_packet(gdb_out);
-                    /* GDB can ask anything at this point, it isn't 
necessarily a qsThreadInfo packet */
-                    return;
-                }
+                send_gdb_partial_packet(gdb_out);
             }
-            /* We're done for this process */
-            CurrentThreadEntry = NULL;
-        }
-
-        if (gdb_out[1] == '\0')
-        {
-            /* We didn't iterate over anything, meaning we were already done */
-            send_gdb_packet("l");
-        }
-        else
-        {
-            send_gdb_packet(gdb_out);
-        }
-        /* GDB can ask anything at this point, it isn't necessarily a 
qsThreadInfo packet */
-        return;
+        }
+
+        return finish_gdb_packet();
+    }
+
+    if (strncmp(gdb_input, "qsThreadInfo", 12) == 0)
+    {
+        /* We sent the whole thread list on first qfThreadInfo call */
+        return send_gdb_packet("l");
     }
 
     if (strncmp(gdb_input, "qThreadExtraInfo,", 17) == 0)
@@ -330,27 +298,117 @@
             String.Length = sprintf(out_string, "%.*s", 16, 
Process->ImageFileName);
         }
 
-        gdb_send_debug_io(&String, FALSE);
-        return;
+        return gdb_send_debug_io(&String, FALSE);
     }
 
     if (strncmp(gdb_input, "qOffsets", 8) == 0)
     {
         /* We load ntoskrnl at 0x80800000 while compiling it at 0x00800000 
base adress */
-        send_gdb_packet("TextSeg=80000000");
-        return;
+        return send_gdb_packet("TextSeg=80000000");
     }
 
     if (strcmp(gdb_input, "qTStatus") == 0)
     {
         /* No tracepoint support */
-        send_gdb_packet("T0");
-        return;
+        return send_gdb_packet("T0");
+    }
+
+    if (strcmp(gdb_input, "qSymbol::") == 0)
+    {
+        /* No need */
+        return send_gdb_packet("OK");
+    }
+
+    if (strncmp(gdb_input, "qXfer:libraries:read::", 22) == 0)
+    {
+        static LIST_ENTRY* CurrentEntry = NULL;
+        char str_helper[256];
+        char name_helper[64];        
+        ULONG_PTR Offset = hex_to_address(&gdb_input[22]);
+        ULONG_PTR ToSend = hex_to_address(strstr(&gdb_input[22], ",") + 1);
+        ULONG Sent = 0;
+        static BOOLEAN allDone = FALSE;
+
+        KDDBGPRINT("KDGDB: qXfer:libraries:read !\n");
+
+        /* Start the packet */
+        start_gdb_packet();
+
+        if (allDone)
+        {
+            send_gdb_partial_packet("l");
+            allDone = FALSE;
+            return finish_gdb_packet();
+        }
+
+        send_gdb_partial_packet("m");
+        Sent++;
+
+        /* Are we starting ? */
+        if (Offset == 0)
+        {
+            Sent += send_gdb_partial_binary("<?xml version=\"1.0\"?>", 21);
+            Sent += send_gdb_partial_binary("<library-list>", 14);
+
+            CurrentEntry = ModuleListHead->Flink;
+
+            if (!CurrentEntry)
+            {
+                /* Ps is not initialized. Send end of XML data or mark that we 
are finished. */
+                Sent += send_gdb_partial_binary("</library-list>", 15);
+                allDone = TRUE;
+                return finish_gdb_packet();
+            }
+        }
+
+        for ( ;
+            CurrentEntry != ModuleListHead;
+            CurrentEntry = CurrentEntry->Flink)
+        {
+            PLDR_DATA_TABLE_ENTRY TableEntry = CONTAINING_RECORD(CurrentEntry, 
LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+            PVOID DllBase = (PVOID)((ULONG_PTR)TableEntry->DllBase + 0x1000);
+            LONG mem_length;
+            char* ptr;
+
+            /* Convert names to lower case. Yes this _is_ ugly */
+            _snprintf(name_helper, 64, "%wZ", &TableEntry->BaseDllName);
+            for (ptr = name_helper; *ptr; ptr++)
+            {
+                if (*ptr >= 'A' && *ptr <= 'Z')
+                    *ptr += 'a' - 'A';
+            }
+
+            /* GDB doesn't load the file if you don't prefix it with a drive 
letter... */
+            mem_length = _snprintf(str_helper, 256, "<library 
name=\"C:\\%s\"><segment address=\"0x%p\"/></library>", &name_helper, DllBase);
+            
+            /* DLL name must be too long. */
+            if (mem_length < 0)
+            {
+                KDDBGPRINT("Failed to report %wZ\n", &TableEntry->BaseDllName);
+                continue;
+            }
+
+            if ((Sent + mem_length) > ToSend)
+            {
+                /* We're done for this pass */
+                return finish_gdb_packet();
+            }
+                
+            Sent += send_gdb_partial_binary(str_helper, mem_length);
+        }
+
+        if ((ToSend - Sent) > 15)
+        {
+            Sent += send_gdb_partial_binary("</library-list>", 15);
+            allDone = TRUE;
+        }
+
+        return finish_gdb_packet();
+   
     }
 
     KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input);
-    send_gdb_packet("");
-    return;
+    return send_gdb_packet("");
 }
 
 #if 0
@@ -413,7 +471,9 @@
     if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != 
PsGetCurrentProcessId())
 #endif
     {
-        __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
+        /* Only do this if Ps is initialized */
+        if (ProcessListHead->Flink)
+            __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
     }
 }
 
@@ -442,16 +502,14 @@
         if (AttachedThread == NULL)
         {
             KDDBGPRINT("The current GDB debug thread is invalid!");
-            send_gdb_packet("E03");
-            return (KDSTATUS)-1;
+            return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
         }
 
         AttachedProcess = AttachedThread->Tcb.Process;
         if (AttachedProcess == NULL)
         {
             KDDBGPRINT("The current GDB debug thread is invalid!");
-            send_gdb_packet("E03");
-            return (KDSTATUS)-1;
+            return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
         }
         __writecr3(AttachedProcess->DirectoryTableBase[0]);
     }
@@ -462,10 +520,11 @@
         if (AttachedProcess == NULL)
         {
             KDDBGPRINT("The current GDB debug thread is invalid!");
-            send_gdb_packet("E03");
-            return (KDSTATUS)-1;
-        }
-        __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]);
+            return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
+        }
+        /* Only do this if Ps is initialized */
+        if (ProcessListHead->Flink)
+            __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]);
     }
 #endif
 
@@ -474,7 +533,6 @@
 
     /* KD will reply with KdSendPacket. Catch it */
     KdpSendPacketHandler = ReadMemorySendHandler;
-
     return KdPacketReceived;
 }
 
@@ -514,7 +572,9 @@
     if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != 
PsGetCurrentProcessId())
 #endif
     {
-        __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
+        /* Only do this if Ps is initialized */
+        if (ProcessListHead->Flink)
+            __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
     }
 }
 
@@ -546,16 +606,14 @@
         if (AttachedThread == NULL)
         {
             KDDBGPRINT("The current GDB debug thread is invalid!");
-            send_gdb_packet("E03");
-            return (KDSTATUS)-1;
+            return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
         }
 
         AttachedProcess = AttachedThread->Tcb.Process;
         if (AttachedProcess == NULL)
         {
             KDDBGPRINT("The current GDB debug thread is invalid!");
-            send_gdb_packet("E03");
-            return (KDSTATUS)-1;
+            return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
         }
         __writecr3(AttachedProcess->DirectoryTableBase[0]);
     }
@@ -566,10 +624,11 @@
         if (AttachedProcess == NULL)
         {
             KDDBGPRINT("The current GDB debug thread is invalid!");
-            send_gdb_packet("E03");
-            return (KDSTATUS)-1;
-        }
-        __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]);
+            return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
+        }
+        /* Only do this if Ps is initialized */
+        if (ProcessListHead->Flink)
+            __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]);
     }
 #endif
 
@@ -578,8 +637,7 @@
     if (BufferLength == 0)
     {
         /* Nothing to do */
-        send_gdb_packet("OK");
-        return (KDSTATUS)-1;
+        return LOOP_IF_SUCCESS(send_gdb_packet("OK"));
     }
     
     State->u.WriteMemory.TransferCount = BufferLength;
@@ -613,7 +671,6 @@
 
     /* KD will reply with KdSendPacket. Catch it */
     KdpSendPacketHandler = WriteMemorySendHandler;
-
     return KdPacketReceived;
 }
 
@@ -698,8 +755,7 @@
             {
                 /* We don't have a way to keep track of this break point. 
Fail. */
                 KDDBGPRINT("No breakpoint slot available!\n");
-                send_gdb_packet("E01");
-                return (KDSTATUS)-1;
+                return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
             }
 
             State->ApiNumber = DbgKdWriteBreakPointApi;
@@ -713,8 +769,7 @@
     }
 
     KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input);
-    send_gdb_packet("E01");
-    return (KDSTATUS)-1;
+    return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
 }
 
 static
@@ -793,8 +848,7 @@
             if (Handle == 0)
             {
                 KDDBGPRINT("Received %s, but breakpoint was never inserted 
?!\n", gdb_input);
-                send_gdb_packet("E01");
-                return (KDSTATUS)-1;
+                return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
             }
 
             State->ApiNumber = DbgKdRestoreBreakPointApi;
@@ -808,8 +862,7 @@
     }
 
     KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input);
-    send_gdb_packet("E01");
-    return (KDSTATUS)-1;
+    return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
 }
 
 static
@@ -820,8 +873,13 @@
     _Out_ PULONG MessageLength,
     _Inout_ PKD_CONTEXT KdContext)
 {
+    KDSTATUS Status;
+
     /* Tell GDB everything is fine, we will handle it */
-    send_gdb_packet("OK");
+    Status = send_gdb_packet("OK");
+    if (Status != KdPacketReceived)
+        return Status;
+        
 
     if (CurrentStateChange.NewState == DbgKdExceptionStateChange)
     {
@@ -873,8 +931,7 @@
         if (gdb_input[5] == '?')
         {
             /* Report what we support */
-            send_gdb_packet("vCont;c;s");
-            return (KDSTATUS)-1;
+            return LOOP_IF_SUCCESS(send_gdb_packet("vCont;c;s"));
         }
 
         if (strncmp(gdb_input, "vCont;c", 7) == 0)
@@ -890,7 +947,7 @@
     }
 
     KDDBGPRINT("Unhandled 'v' packet: %s\n", gdb_input);
-    return KdPacketReceived;
+    return LOOP_IF_SUCCESS(send_gdb_packet(""));
 }
 
 KDSTATUS
@@ -904,8 +961,9 @@
 
     do
     {
+        KDDBGPRINT("KDGBD: Receiving packet.\n");
         Status = gdb_receive_packet(KdContext);
-        KDDBGPRINT("KDGBD: Packet received with status %u\n", Status);
+        KDDBGPRINT("KDGBD: Packet \"%s\" received with status %u\n", 
gdb_input, Status);
 
         if (Status != KdPacketReceived)
             return Status;
@@ -916,34 +974,34 @@
         {
         case '?':
             /* Send the Status */
-            gdb_send_exception();
+            Status = LOOP_IF_SUCCESS(gdb_send_exception());
             break;
         case '!':
-            send_gdb_packet("OK");
+            Status = LOOP_IF_SUCCESS(send_gdb_packet("OK"));
             break;
         case 'c':
             Status = handle_gdb_c(State, MessageData, MessageLength, 
KdContext);
             break;
         case 'g':
-            gdb_send_registers();
+            Status = LOOP_IF_SUCCESS(gdb_send_registers());
             break;
         case 'H':
-            handle_gdb_set_thread();
+            Status = LOOP_IF_SUCCESS(handle_gdb_set_thread());
             break;
         case 'm':
             Status = handle_gdb_read_mem(State, MessageData, MessageLength, 
KdContext);
             break;
         case 'p':
-            gdb_send_register();
+            Status = LOOP_IF_SUCCESS(gdb_send_register());
             break;
         case 'q':
-            handle_gdb_query();
+            Status = LOOP_IF_SUCCESS(handle_gdb_query());
             break;
         case 's':
             Status = handle_gdb_s(State, MessageData, MessageLength, 
KdContext);
             break;
         case 'T':
-            handle_gdb_thread_alive();
+            Status = LOOP_IF_SUCCESS(handle_gdb_thread_alive());
             break;
         case 'v':
             Status = handle_gdb_v(State, MessageData, MessageLength, 
KdContext);
@@ -960,7 +1018,7 @@
         default:
             /* We don't know how to handle this request. */
             KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input);
-            send_gdb_packet("");
+            Status = LOOP_IF_SUCCESS(send_gdb_packet(""));
         }
     } while (Status == (KDSTATUS)-1);
 

Modified: trunk/reactos/drivers/base/kdgdb/gdb_send.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/gdb_send.c?rev=72533&r1=72532&r2=72533&view=diff
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/gdb_send.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/gdb_send.c [iso-8859-1] Thu Sep  1 
22:58:15 2016
@@ -9,6 +9,7 @@
 
 /* LOCALS 
*********************************************************************/
 const char hex_chars[] = "0123456789abcdef";
+static CHAR currentChecksum = 0;
 
 /* PRIVATE FUNCTIONS 
**********************************************************/
 static
@@ -48,126 +49,151 @@
 
 /* GLOBAL FUNCTIONS 
***********************************************************/
 void
-send_gdb_packet(_In_ CHAR* Buffer)
+start_gdb_packet(void)
+{
+    /* Start the start byte and begin checksum calculation */
+    KdpSendByte('$');
+    currentChecksum = 0;
+}
+
+void
+send_gdb_partial_packet(_In_ const CHAR* Buffer)
+{
+    const CHAR* ptr = Buffer;
+
+    /* Update check sum and send */
+    while (*ptr)
+    {
+        currentChecksum += *ptr;
+        KdpSendByte(*ptr++);
+    }
+}
+
+
+KDSTATUS
+finish_gdb_packet(void)
 {
     UCHAR ack;
-
-    do {
-        CHAR* ptr = Buffer;
-        CHAR check_sum = 0;
-
-        KdpSendByte('$');
-
-        /* Calculate checksum */
-        check_sum = 0;
-        while (*ptr)
+    KDSTATUS Status;
+
+    /* Send finish byte and append checksum */
+    KdpSendByte('#');
+    KdpSendByte(hex_chars[(currentChecksum >> 4) & 0xf]);
+    KdpSendByte(hex_chars[currentChecksum & 0xf]);
+
+    /* Wait for acknowledgement */
+    Status = KdpReceiveByte(&ack);
+
+    if (Status != KdPacketReceived)
+    {
+        KD_DEBUGGER_NOT_PRESENT = TRUE;
+        return Status;
+    }
+
+    if (ack != '+')
+        return KdPacketNeedsResend;
+
+    return KdPacketReceived;
+}
+
+KDSTATUS
+send_gdb_packet(_In_ const CHAR* Buffer)
+{
+    start_gdb_packet();
+    send_gdb_partial_packet(Buffer);
+    return finish_gdb_packet();
+}
+
+ULONG 
+send_gdb_partial_binary(
+    _In_ const VOID* Buffer,
+    _In_ size_t Length)
+{
+    const UCHAR* ptr = Buffer;
+    ULONG Sent = Length;
+
+    while(Length--)
+    {
+        UCHAR Byte = *ptr++;
+
+        switch (Byte)
         {
-            check_sum += *ptr;
-            KdpSendByte(*ptr++);
+            case 0x7d:
+            case 0x23:
+            case 0x24:
+            case 0x2a:
+                currentChecksum += 0x7d;
+                KdpSendByte(0x7d);
+                Byte ^= 0x20;
+                Sent++;
+            /* Fall-through */
+            default:
+                currentChecksum += Byte;
+                KdpSendByte(Byte);
         }
-
-        /* append it */
-        KdpSendByte('#');
-        KdpSendByte(hex_chars[(check_sum >> 4) & 0xf]);
-        KdpSendByte(hex_chars[check_sum & 0xf]);
-
-        /* Wait for acknowledgement */
-        if (KdpReceiveByte(&ack) != KdPacketReceived)
-        {
-            KD_DEBUGGER_NOT_PRESENT = TRUE;
-            break;
-        }
-    } while (ack != '+');
-}
-
-void
+    }
+
+    return Sent;
+}
+
+void 
+send_gdb_partial_memory(
+    _In_ const VOID* Buffer,
+    _In_ size_t Length)
+{
+    const UCHAR* ptr = Buffer;
+    CHAR gdb_out[3];
+
+    gdb_out[2] = '\0';
+
+    while(Length--)
+    {
+        gdb_out[0] = hex_chars[(*ptr >> 4) & 0xf];
+        gdb_out[1] = hex_chars[*ptr++ & 0xf];
+        send_gdb_partial_packet(gdb_out);
+    }
+}
+
+KDSTATUS
 send_gdb_memory(
-    _In_ VOID* Buffer,
+    _In_ const VOID* Buffer,
     _In_ size_t Length)
 {
-    UCHAR ack;
-
-    do {
-        CHAR* ptr = Buffer;
-        CHAR check_sum = 0;
-        size_t len = Length;
-        CHAR Byte;
-
-        KdpSendByte('$');
-
-        /* Send the data */
-        check_sum = 0;
-        while (len--)
-        {
-            Byte = hex_chars[(*ptr >> 4) & 0xf];
-            KdpSendByte(Byte);
-            check_sum += Byte;
-            Byte = hex_chars[*ptr++ & 0xf];
-            KdpSendByte(Byte);
-            check_sum += Byte;
-        }
-
-        /* append check sum */
-        KdpSendByte('#');
-        KdpSendByte(hex_chars[(check_sum >> 4) & 0xf]);
-        KdpSendByte(hex_chars[check_sum & 0xf]);
-
-        /* Wait for acknowledgement */
-        if (KdpReceiveByte(&ack) != KdPacketReceived)
-        {
-            KD_DEBUGGER_NOT_PRESENT = TRUE;
-            break;
-        }
-    } while (ack != '+');
-}
-
-void
+    start_gdb_packet();
+    send_gdb_partial_memory(Buffer, Length);
+    return finish_gdb_packet();
+}
+
+KDSTATUS
 gdb_send_debug_io(
     _In_ PSTRING String,
     _In_ BOOLEAN WithPrefix)
 {
-    UCHAR ack;
-
-    do {
-        CHAR* ptr = String->Buffer;
-        CHAR check_sum = 0;
-        USHORT Length = String->Length;
-        CHAR Byte;
-
-        KdpSendByte('$');
-
-        if (WithPrefix)
-        {
-            KdpSendByte('O');
-            check_sum = 'O';
-        }
-
-        /* Send the data */
-        while (Length--)
-        {
-            Byte = hex_chars[(*ptr >> 4) & 0xf];
-            KdpSendByte(Byte);
-            check_sum += Byte;
-            Byte = hex_chars[*ptr++ & 0xf];
-            KdpSendByte(Byte);
-            check_sum += Byte;
-        }
-
-        /* append check sum */
-        KdpSendByte('#');
-        KdpSendByte(hex_chars[(check_sum >> 4) & 0xf]);
-        KdpSendByte(hex_chars[check_sum & 0xf]);
-
-        /* Wait for acknowledgement */
-        if (KdpReceiveByte(&ack) != KdPacketReceived)
-        {
-            KD_DEBUGGER_NOT_PRESENT = TRUE;
-            break;
-        }
-    } while (ack != '+');
-}
-
-void
+    CHAR gdb_out[3];
+    CHAR* ptr = String->Buffer;
+    USHORT Length = String->Length;
+    
+    gdb_out[2] = '\0';
+
+    start_gdb_packet();
+
+    if (WithPrefix)
+    {
+        send_gdb_partial_packet("O");
+    }
+
+    /* Send the data */
+    while (Length--)
+    {
+        gdb_out[0] = hex_chars[(*ptr >> 4) & 0xf];
+        gdb_out[1] = hex_chars[*ptr++ & 0xf];
+        send_gdb_partial_packet(gdb_out);
+    }
+
+    return finish_gdb_packet();
+}
+
+KDSTATUS
 gdb_send_exception()
 {
     char gdb_out[1024];
@@ -184,6 +210,9 @@
     }
     else
         ptr += sprintf(ptr, "05");
+
+    if (CurrentStateChange.NewState == DbgKdLoadSymbolsStateChange)
+        ptr += sprintf(ptr, "library:");
 
 #if MONOPROCESS
     ptr += sprintf(ptr, "thread:%" PRIxPTR ";",
@@ -193,8 +222,9 @@
         handle_to_gdb_pid(PsGetThreadProcessId(Thread)),
         handle_to_gdb_tid(PsGetThreadId(Thread)));
 #endif
+
     ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor);
-    send_gdb_packet(gdb_out);
+    return send_gdb_packet(gdb_out);
 }
 
 void

Modified: trunk/reactos/drivers/base/kdgdb/i386_sup.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/i386_sup.c?rev=72533&r1=72532&r2=72533&view=diff
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/i386_sup.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/i386_sup.c [iso-8859-1] Thu Sep  1 
22:58:15 2016
@@ -83,10 +83,10 @@
 void*
 thread_to_reg(PETHREAD Thread, enum reg_name reg_name, unsigned short* size)
 {
-    /* See if the guy got a stack */
-    if (Thread->Tcb.InitialStack == NULL)
-    {
-        static const void* NullValue = NULL;
+    static const void* NullValue = NULL;
+
+    if (!Thread->Tcb.InitialStack)
+    {
         /* Terminated thread ? */
         switch (reg_name)
         {
@@ -130,28 +130,33 @@
     }
     else
     {
-        /* The thread was not yet scheduled */
+        static PULONG Esp;
+        Esp = Thread->Tcb.KernelStack;
         *size = 4;
         switch(reg_name)
         {
-            case ESP: return &Thread->Tcb.KernelStack;
-            case EBP: return &((ULONG*)Thread->Tcb.KernelStack)[4];
-            case EIP: return &Thread->StartAddress;
+            case EBP: return &Esp[3];
+            case ESP: return &Esp;
+            case EIP: return &NullValue;
             default:
                 return NULL;
         }
     }
+
     return NULL;
 }
 
-void
+KDSTATUS
 gdb_send_registers(void)
 {
-    CHAR Registers[16*8 + 1];
+    CHAR RegisterStr[9];
     UCHAR* RegisterPtr;
     unsigned i;
     unsigned short size;
-    CHAR* ptr = Registers;
+
+    RegisterStr[8] = '\0';
+
+    start_gdb_packet();
 
     KDDBGPRINT("Sending registers of thread %" PRIxPTR ".\n", gdb_dbg_tid);
     KDDBGPRINT("Current thread_id: %p.\n", 
PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread));
@@ -161,14 +166,16 @@
         for(i=0; i < 16; i++)
         {
             RegisterPtr = ctx_to_reg(&CurrentContext, i, &size);
-            *ptr++ = hex_chars[RegisterPtr[0] >> 4];
-            *ptr++ = hex_chars[RegisterPtr[0] & 0xF];
-            *ptr++ = hex_chars[RegisterPtr[1] >> 4];
-            *ptr++ = hex_chars[RegisterPtr[1] & 0xF];
-            *ptr++ = hex_chars[RegisterPtr[2] >> 4];
-            *ptr++ = hex_chars[RegisterPtr[2] & 0xF];
-            *ptr++ = hex_chars[RegisterPtr[3] >> 4];
-            *ptr++ = hex_chars[RegisterPtr[3] & 0xF];
+            RegisterStr[0] = hex_chars[RegisterPtr[0] >> 4];
+            RegisterStr[1] = hex_chars[RegisterPtr[0] & 0xF];
+            RegisterStr[2] = hex_chars[RegisterPtr[1] >> 4];
+            RegisterStr[3] = hex_chars[RegisterPtr[1] & 0xF];
+            RegisterStr[4] = hex_chars[RegisterPtr[2] >> 4];
+            RegisterStr[5] = hex_chars[RegisterPtr[2] & 0xF];
+            RegisterStr[6] = hex_chars[RegisterPtr[3] >> 4];
+            RegisterStr[7] = hex_chars[RegisterPtr[3] & 0xF];
+
+            send_gdb_partial_packet(RegisterStr);
         }
     }
     else
@@ -180,8 +187,8 @@
         if (DbgThread == NULL)
         {
             /* Thread is dead */
-            send_gdb_packet("E03");
-            return;
+            send_gdb_partial_packet("E03");
+            return finish_gdb_packet();
         }
 
         for(i=0; i < 16; i++)
@@ -189,26 +196,29 @@
             RegisterPtr = thread_to_reg(DbgThread, i, &size);
             if (RegisterPtr)
             {
-                *ptr++ = hex_chars[RegisterPtr[0] >> 4];
-                *ptr++ = hex_chars[RegisterPtr[0] & 0xF];
-                *ptr++ = hex_chars[RegisterPtr[1] >> 4];
-                *ptr++ = hex_chars[RegisterPtr[1] & 0xF];
-                *ptr++ = hex_chars[RegisterPtr[2] >> 4];
-                *ptr++ = hex_chars[RegisterPtr[2] & 0xF];
-                *ptr++ = hex_chars[RegisterPtr[3] >> 4];
-                *ptr++ = hex_chars[RegisterPtr[3] & 0xF];
+                RegisterPtr = ctx_to_reg(&CurrentContext, i, &size);
+                RegisterStr[0] = hex_chars[RegisterPtr[0] >> 4];
+                RegisterStr[1] = hex_chars[RegisterPtr[0] & 0xF];
+                RegisterStr[2] = hex_chars[RegisterPtr[1] >> 4];
+                RegisterStr[3] = hex_chars[RegisterPtr[1] & 0xF];
+                RegisterStr[4] = hex_chars[RegisterPtr[2] >> 4];
+                RegisterStr[5] = hex_chars[RegisterPtr[2] & 0xF];
+                RegisterStr[6] = hex_chars[RegisterPtr[3] >> 4];
+                RegisterStr[7] = hex_chars[RegisterPtr[3] & 0xF];
+
+                send_gdb_partial_packet(RegisterStr);
             }
             else
             {
-                ptr += sprintf(ptr, "xxxxxxxx");
+                send_gdb_partial_packet("xxxxxxxx");
             }
         }
     }
-    *ptr = '\0';
-    send_gdb_packet(Registers);
-}
-
-void
+    
+    return finish_gdb_packet();
+}
+
+KDSTATUS
 gdb_send_register(void)
 {
     enum reg_name reg_name;
@@ -233,8 +243,7 @@
         if (DbgThread == NULL)
         {
             /* Thread is dead */
-            send_gdb_packet("E03");
-            return;
+            return send_gdb_packet("E03");
         }
 
         ptr = thread_to_reg(DbgThread, reg_name, &size);
@@ -243,12 +252,13 @@
     if (!ptr)
     {
         /* Undefined. Let's assume 32 bit register */
-        send_gdb_packet("xxxxxxxx");
-    }
-    else
-    {
-        send_gdb_memory(ptr, size);
-    }
-}
-
-
+        return send_gdb_packet("xxxxxxxx");
+    }
+    else
+    {
+        KDDBGPRINT("KDDBG : Sending registers as memory.\n");
+        return send_gdb_memory(ptr, size);
+    }
+}
+
+

Modified: trunk/reactos/drivers/base/kdgdb/kdgdb.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/kdgdb.h?rev=72533&r1=72532&r2=72533&view=diff
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/kdgdb.h    [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/kdgdb.h    [iso-8859-1] Thu Sep  1 
22:58:15 2016
@@ -19,7 +19,7 @@
 
 #include <pstypes.h>
 
-//#define KDDEBUG /* uncomment to enable debugging this dll */
+// #define KDDEBUG /* uncomment to enable debugging this dll */
 
 /* To undefine once https://sourceware.org/bugzilla/show_bug.cgi?id=17397 is 
resolved */
 #define MONOPROCESS 1
@@ -80,10 +80,15 @@
 char hex_value(char ch);
 
 /* gdb_send.c */
-void send_gdb_packet(_In_ CHAR* Buffer);
-void send_gdb_memory(_In_ VOID* Buffer, size_t Length);
-void gdb_send_debug_io(_In_ PSTRING String, _In_ BOOLEAN WithPrefix);
-void gdb_send_exception(void);
+KDSTATUS send_gdb_packet(_In_ const CHAR* Buffer);
+void start_gdb_packet(void);
+void send_gdb_partial_packet(_In_ const CHAR* Buffer);
+KDSTATUS finish_gdb_packet(void);
+KDSTATUS send_gdb_memory(_In_ const VOID* Buffer, size_t Length);
+void send_gdb_partial_memory(_In_ const VOID* Buffer, _In_ size_t Length);
+ULONG send_gdb_partial_binary(_In_ const VOID* Buffer, _In_ size_t Length);
+KDSTATUS gdb_send_debug_io(_In_ PSTRING String, _In_ BOOLEAN WithPrefix);
+KDSTATUS gdb_send_exception(void);
 void send_gdb_ntstatus(_In_ NTSTATUS Status);
 extern const char hex_chars[];
 
@@ -98,6 +103,7 @@
 extern DBGKD_GET_VERSION64 KdVersion;
 extern KDDEBUGGER_DATA64* KdDebuggerDataBlock;
 extern LIST_ENTRY* ProcessListHead;
+extern LIST_ENTRY* ModuleListHead;
 extern KDP_SEND_HANDLER KdpSendPacketHandler;
 extern KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler;
 /* Commone ManipulateState handlers */
@@ -111,8 +117,8 @@
 extern PETHREAD find_thread(_In_ UINT_PTR Pid, _In_ UINT_PTR Tid);
 
 /* arch_sup.c */
-extern void gdb_send_register(void);
-extern void gdb_send_registers(void);
+extern KDSTATUS gdb_send_register(void);
+extern KDSTATUS gdb_send_registers(void);
 
 /* Architecture specific defines. See ntoskrnl/include/internal/arch/ke.h */
 #ifdef _M_IX86

Modified: trunk/reactos/drivers/base/kdgdb/kdpacket.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/kdpacket.c?rev=72533&r1=72532&r2=72533&view=diff
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/kdpacket.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/kdpacket.c [iso-8859-1] Thu Sep  1 
22:58:15 2016
@@ -20,6 +20,7 @@
 DBGKD_GET_VERSION64 KdVersion;
 KDDEBUGGER_DATA64* KdDebuggerDataBlock;
 LIST_ENTRY* ProcessListHead;
+LIST_ENTRY* ModuleListHead;
 /* Callbacks used to communicate with KD aside from GDB */
 KDP_SEND_HANDLER KdpSendPacketHandler = FirstSendHandler;
 KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler = NULL;
@@ -139,11 +140,6 @@
     switch (StateChange->NewState)
     {
     case DbgKdLoadSymbolsStateChange:
-    {
-        /* We don't care about symbols loading */
-        KdpManipulateStateHandler = ContinueManipulateStateHandler;
-        break;
-    }
     case DbgKdExceptionStateChange:
     {
         PETHREAD Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread;
@@ -264,6 +260,7 @@
     DebuggerDataList = (LIST_ENTRY*)(ULONG_PTR)KdVersion.DebuggerDataList;
     KdDebuggerDataBlock = CONTAINING_RECORD(DebuggerDataList->Flink, 
KDDEBUGGER_DATA64, Header.List);
     ProcessListHead = 
(LIST_ENTRY*)KdDebuggerDataBlock->PsActiveProcessHead.Pointer;
+    ModuleListHead = 
(LIST_ENTRY*)KdDebuggerDataBlock->PsLoadedModuleList.Pointer;
 
     /* Now we can get the context for the current state */
     KdpSendPacketHandler = NULL;
@@ -363,6 +360,8 @@
     _Out_ PULONG DataLength,
     _Inout_ PKD_CONTEXT KdContext)
 {
+    KDDBGPRINT("KdReceivePacket.\n");
+
     if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN)
     {
         return KdpPollBreakIn();
@@ -382,7 +381,10 @@
 
         /* Maybe we are in a send<->receive loop that GDB doesn't need to know 
about */
         if (KdpManipulateStateHandler != NULL)
+        {
+            KDDBGPRINT("KDGBD: We have a manipulate state handler.\n");
             return KdpManipulateStateHandler(State, MessageData, DataLength, 
KdContext);
+        }
 
         /* Receive data from GDB  and interpret it */
         return gdb_receive_and_interpret_packet(State, MessageData, 
DataLength, KdContext);


Reply via email to