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);