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_inp…
==============================================================================
--- 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_sen…
==============================================================================
--- 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_su…
==============================================================================
--- 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…
==============================================================================
--- 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/kdpacke…
==============================================================================
--- 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);