Author: jgardou Date: Mon Aug 22 22:24:30 2016 New Revision: 72435
URL: http://svn.reactos.org/svn/reactos?rev=72435&view=rev Log: [KDGDB] - Implement setting and removing breakpoints - Implement single-stepping - Only get past the breakpoint instruction when it comes from RtlpBreakWithStatus - Implement writing to memory - Always send the thread raising the exception to GDB to avoid confusing it - Let GDB find the program counter alone by querying the registers (support was already there before.) - Properly escape special characters on input Ladies and gentlemen : the almost-fully functional GDB stub. (still no real multi-process support :-( ) To enable , in CMakeCache.txt : - Set GDB:BOOL=TRUE - Set _WINKD_:BOOL=TRUE - Set KDBG:BOOL=FALSE To do : give GDB the list of loaded drivers. Loading ntoskrnl.exe symbols at 0x80801000 already does a good enough job. Default output is on COM1. Can be configure to any othe COM port with usual kernel options. Hope you'll like it as much as I do ;-)
Modified: trunk/reactos/drivers/base/kdgdb/gdb_input.c trunk/reactos/drivers/base/kdgdb/gdb_receive.c trunk/reactos/drivers/base/kdgdb/gdb_send.c trunk/reactos/drivers/base/kdgdb/i386_sup.c trunk/reactos/drivers/base/kdgdb/kdcom.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_inpu... ============================================================================== --- trunk/reactos/drivers/base/kdgdb/gdb_input.c [iso-8859-1] (original) +++ trunk/reactos/drivers/base/kdgdb/gdb_input.c [iso-8859-1] Mon Aug 22 22:24:30 2016 @@ -9,6 +9,11 @@
/* LOCALS *********************************************************************/ static ULONG_PTR gdb_run_tid; +static struct +{ + ULONG_PTR Address; + ULONG Handle; +} BreakPointHandles[32];
/* GLOBALS ********************************************************************/ @@ -203,16 +208,15 @@
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; - - /* Start with idle thread */ -#if MONOPROCESS - ptr = gdb_out + sprintf(gdb_out, "m1"); -#else - ptr = gdb_out + sprintf(gdb_out, "mp1.1"); -#endif FirstThread = FALSE; }
@@ -306,8 +310,8 @@ Thread = find_thread(Pid, Tid); Process = CONTAINING_RECORD(Thread->Tcb.Process, EPROCESS, Pcb); #else - Pid = hex_to_pid(&gdb_input[2]); - Tid = hex_to_tid(strstr(gdb_input, ".") + 1); + Pid = hex_to_pid(&gdb_input[18]); + Tid = hex_to_tid(strstr(&gdb_input[18], ".") + 1);
/* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL. * So loop. */ @@ -394,21 +398,23 @@ KDDBGPRINT("Wrong API number (%lu) after DbgKdReadVirtualMemoryApi request.\n", State->ApiNumber); }
- /* Check status */ - if (!NT_SUCCESS(State->ReturnStatus)) + /* Check status. Allow to send partial data. */ + if (!MessageData->Length && !NT_SUCCESS(State->ReturnStatus)) send_gdb_ntstatus(State->ReturnStatus); else send_gdb_memory(MessageData->Buffer, MessageData->Length); KdpSendPacketHandler = NULL; KdpManipulateStateHandler = NULL;
-#if !MONOPROCESS +#if MONOPROCESS + if (gdb_dbg_tid != 0) /* Reset the TLB */ +#else if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) +#endif { __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]); } -#endif }
static @@ -427,8 +433,29 @@ MessageData->Length = 0; *MessageLength = 0;
-#if !MONOPROCESS /* Set the TLB according to the process being read. Pid 0 means any process. */ +#if MONOPROCESS + if ((gdb_dbg_tid != 0) && gdb_tid_to_handle(gdb_dbg_tid) != PsGetCurrentThreadId()) + { + PETHREAD AttachedThread = find_thread(0, gdb_dbg_tid); + PKPROCESS AttachedProcess; + if (AttachedThread == NULL) + { + KDDBGPRINT("The current GDB debug thread is invalid!"); + send_gdb_packet("E03"); + return (KDSTATUS)-1; + } + + AttachedProcess = AttachedThread->Tcb.Process; + if (AttachedProcess == NULL) + { + KDDBGPRINT("The current GDB debug thread is invalid!"); + send_gdb_packet("E03"); + return (KDSTATUS)-1; + } + __writecr3(AttachedProcess->DirectoryTableBase[0]); + } +#else if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) { PEPROCESS AttachedProcess = find_process(gdb_dbg_pid); @@ -436,7 +463,7 @@ { KDDBGPRINT("The current GDB debug thread is invalid!"); send_gdb_packet("E03"); - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); + return (KDSTATUS)-1; } __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]); } @@ -448,6 +475,388 @@ /* KD will reply with KdSendPacket. Catch it */ KdpSendPacketHandler = ReadMemorySendHandler;
+ return KdPacketReceived; +} + +static +void +WriteMemorySendHandler( + _In_ ULONG PacketType, + _In_ PSTRING MessageHeader, + _In_ PSTRING MessageData) +{ + DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; + + if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) + { + // KdAssert + KDDBGPRINT("Wrong packet type (%lu) received after DbgKdWriteVirtualMemoryApi request.\n", PacketType); + while (1); + } + + if (State->ApiNumber != DbgKdWriteVirtualMemoryApi) + { + KDDBGPRINT("Wrong API number (%lu) after DbgKdWriteVirtualMemoryApi request.\n", State->ApiNumber); + } + + /* Check status */ + if (!NT_SUCCESS(State->ReturnStatus)) + send_gdb_ntstatus(State->ReturnStatus); + else + send_gdb_packet("OK"); + KdpSendPacketHandler = NULL; + KdpManipulateStateHandler = NULL; + +#if MONOPROCESS + if (gdb_dbg_tid != 0) + /* Reset the TLB */ +#else + if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) +#endif + { + __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]); + } +} + +static +KDSTATUS +handle_gdb_write_mem( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext) +{ + /* Maximal input buffer is 0x1000. Each byte is encoded on two bytes by GDB */ + static UCHAR OutBuffer[0x800]; + ULONG BufferLength; + char* blob_ptr; + UCHAR* OutPtr; + + State->ApiNumber = DbgKdWriteVirtualMemoryApi; + State->ReturnStatus = STATUS_SUCCESS; /* ? */ + State->Processor = CurrentStateChange.Processor; + State->ProcessorLevel = CurrentStateChange.ProcessorLevel; + + /* Set the TLB according to the process being read. Pid 0 means any process. */ +#if MONOPROCESS + if ((gdb_dbg_tid != 0) && gdb_tid_to_handle(gdb_dbg_tid) != PsGetCurrentThreadId()) + { + PETHREAD AttachedThread = find_thread(0, gdb_dbg_tid); + PKPROCESS AttachedProcess; + if (AttachedThread == NULL) + { + KDDBGPRINT("The current GDB debug thread is invalid!"); + send_gdb_packet("E03"); + return (KDSTATUS)-1; + } + + AttachedProcess = AttachedThread->Tcb.Process; + if (AttachedProcess == NULL) + { + KDDBGPRINT("The current GDB debug thread is invalid!"); + send_gdb_packet("E03"); + return (KDSTATUS)-1; + } + __writecr3(AttachedProcess->DirectoryTableBase[0]); + } +#else + if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) + { + PEPROCESS AttachedProcess = find_process(gdb_dbg_pid); + if (AttachedProcess == NULL) + { + KDDBGPRINT("The current GDB debug thread is invalid!"); + send_gdb_packet("E03"); + return (KDSTATUS)-1; + } + __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]); + } +#endif + + State->u.WriteMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]); + BufferLength = hex_to_address(strstr(&gdb_input[1], ",") + 1); + if (BufferLength == 0) + { + /* Nothing to do */ + send_gdb_packet("OK"); + return (KDSTATUS)-1; + } + + State->u.WriteMemory.TransferCount = BufferLength; + MessageData->Length = BufferLength; + MessageData->Buffer = (CHAR*)OutBuffer; + + OutPtr = OutBuffer; + blob_ptr = strstr(strstr(&gdb_input[1], ",") + 1, ":") + 1; + while (BufferLength) + { + if (BufferLength >= 4) + { + *((ULONG*)OutPtr) = *((ULONG*)blob_ptr); + OutPtr += 4; + blob_ptr += 4; + BufferLength -= 4; + } + else if (BufferLength >= 2) + { + *((USHORT*)OutPtr) = *((USHORT*)blob_ptr); + OutPtr += 2; + blob_ptr += 2; + BufferLength -= 2; + } + else + { + *OutPtr++ = *blob_ptr++; + BufferLength--; + } + } + + /* KD will reply with KdSendPacket. Catch it */ + KdpSendPacketHandler = WriteMemorySendHandler; + + return KdPacketReceived; +} + +static +void +WriteBreakPointSendHandler( + _In_ ULONG PacketType, + _In_ PSTRING MessageHeader, + _In_ PSTRING MessageData) +{ + DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; + + if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) + { + // KdAssert + KDDBGPRINT("Wrong packet type (%lu) received after DbgKdWriteBreakPointApi request.\n", PacketType); + while (1); + } + + if (State->ApiNumber != DbgKdWriteBreakPointApi) + { + KDDBGPRINT("Wrong API number (%lu) after DbgKdWriteBreakPointApi request.\n", State->ApiNumber); + } + + /* Check status */ + if (!NT_SUCCESS(State->ReturnStatus)) + { + KDDBGPRINT("Inserting breakpoint failed!\n"); + send_gdb_ntstatus(State->ReturnStatus); + } + else + { + /* Keep track of the address+handle couple */ + ULONG i; + for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) + { + if (BreakPointHandles[i].Address == 0) + { + BreakPointHandles[i].Address = (ULONG_PTR)State->u.WriteBreakPoint.BreakPointAddress; + BreakPointHandles[i].Handle = State->u.WriteBreakPoint.BreakPointHandle; + break; + } + } + send_gdb_packet("OK"); + } + KdpSendPacketHandler = NULL; + KdpManipulateStateHandler = NULL; +} + +static +KDSTATUS +handle_gdb_insert_breakpoint( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext) +{ + State->ReturnStatus = STATUS_SUCCESS; /* ? */ + State->Processor = CurrentStateChange.Processor; + State->ProcessorLevel = CurrentStateChange.ProcessorLevel; + if (MessageData) + MessageData->Length = 0; + *MessageLength = 0; + + switch (gdb_input[1]) + { + case '0': + { + ULONG_PTR Address = hex_to_address(&gdb_input[3]); + ULONG i; + BOOLEAN HasFreeSlot = FALSE; + + KDDBGPRINT("Inserting breakpoint at %p.\n", (void*)Address); + + for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) + { + if (BreakPointHandles[i].Address == 0) + HasFreeSlot = TRUE; + } + + if (!HasFreeSlot) + { + /* 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; + } + + State->ApiNumber = DbgKdWriteBreakPointApi; + State->u.WriteBreakPoint.BreakPointAddress = Address; + /* FIXME : ignoring all other Z0 arguments */ + + /* KD will reply with KdSendPacket. Catch it */ + KdpSendPacketHandler = WriteBreakPointSendHandler; + return KdPacketReceived; + } + } + + KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input); + send_gdb_packet("E01"); + return (KDSTATUS)-1; +} + +static +void +RestoreBreakPointSendHandler( + _In_ ULONG PacketType, + _In_ PSTRING MessageHeader, + _In_ PSTRING MessageData) +{ + DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; + ULONG i; + + if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) + { + // KdAssert + KDDBGPRINT("Wrong packet type (%lu) received after DbgKdRestoreBreakPointApi request.\n", PacketType); + while (1); + } + + if (State->ApiNumber != DbgKdRestoreBreakPointApi) + { + KDDBGPRINT("Wrong API number (%lu) after DbgKdRestoreBreakPointApi request.\n", State->ApiNumber); + } + + /* We ignore failure here. If DbgKdRestoreBreakPointApi fails, + * this means that the breakpoint was already invalid for KD. So clean it up on our side. */ + for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) + { + if (BreakPointHandles[i].Handle == State->u.RestoreBreakPoint.BreakPointHandle) + { + BreakPointHandles[i].Address = 0; + BreakPointHandles[i].Handle = 0; + break; + } + } + + send_gdb_packet("OK"); + + KdpSendPacketHandler = NULL; + KdpManipulateStateHandler = NULL; +} + +static +KDSTATUS +handle_gdb_remove_breakpoint( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext) +{ + State->ReturnStatus = STATUS_SUCCESS; /* ? */ + State->Processor = CurrentStateChange.Processor; + State->ProcessorLevel = CurrentStateChange.ProcessorLevel; + if (MessageData) + MessageData->Length = 0; + *MessageLength = 0; + + switch (gdb_input[1]) + { + case '0': + { + ULONG_PTR Address = hex_to_address(&gdb_input[3]); + ULONG i, Handle = 0; + + KDDBGPRINT("Removing breakpoint on %p.\n", (void*)Address); + + for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) + { + if (BreakPointHandles[i].Address == Address) + { + Handle = BreakPointHandles[i].Handle; + break; + } + } + + if (Handle == 0) + { + KDDBGPRINT("Received %s, but breakpoint was never inserted ?!\n", gdb_input); + send_gdb_packet("E01"); + return (KDSTATUS)-1; + } + + State->ApiNumber = DbgKdRestoreBreakPointApi; + State->u.RestoreBreakPoint.BreakPointHandle = Handle; + /* FIXME : ignoring all other z0 arguments */ + + /* KD will reply with KdSendPacket. Catch it */ + KdpSendPacketHandler = RestoreBreakPointSendHandler; + return KdPacketReceived; + } + } + + KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input); + send_gdb_packet("E01"); + return (KDSTATUS)-1; +} + +static +KDSTATUS +handle_gdb_c( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext) +{ + /* Tell GDB everything is fine, we will handle it */ + send_gdb_packet("OK"); + + if (CurrentStateChange.NewState == DbgKdExceptionStateChange) + { + DBGKM_EXCEPTION64* Exception = &CurrentStateChange.u.Exception; + ULONG_PTR ProgramCounter = KdpGetContextPc(&CurrentContext); + + /* See if we should update the program counter */ + if (Exception && (Exception->ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT) + && ProgramCounter == KdDebuggerDataBlock->BreakpointWithStatus.Pointer) + { + /* We must get past the breakpoint instruction */ + KdpSetContextPc(&CurrentContext, ProgramCounter + KD_BREAKPOINT_SIZE); + + SetContextManipulateHandler(State, MessageData, MessageLength, KdContext); + KdpManipulateStateHandler = ContinueManipulateStateHandler; + return KdPacketReceived; + } + } + + return ContinueManipulateStateHandler(State, MessageData, MessageLength, KdContext); +} + +static +KDSTATUS +handle_gdb_s( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext) +{ + KDDBGPRINT("Single stepping.\n"); + /* Set CPU single step mode and continue */ + KdpSetSingleStep(&CurrentContext); + SetContextManipulateHandler(State, MessageData, MessageLength, KdContext); + KdpManipulateStateHandler = ContinueManipulateStateHandler; return KdPacketReceived; }
@@ -464,36 +873,19 @@ if (gdb_input[5] == '?') { /* Report what we support */ - send_gdb_packet("vCont;c;C;s;S"); + send_gdb_packet("vCont;c;s"); return (KDSTATUS)-1; }
if (strncmp(gdb_input, "vCont;c", 7) == 0) { - DBGKM_EXCEPTION64* Exception = NULL; - - /* Tell GDB everything is fine, we will handle it */ - send_gdb_packet("OK"); - - if (CurrentStateChange.NewState == DbgKdExceptionStateChange) - Exception = &CurrentStateChange.u.Exception; - - /* See if we should update the program counter (unlike windbg, gdb doesn't do it for us) */ - if (Exception && (Exception->ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT) - && (Exception->ExceptionRecord.ExceptionInformation[0] == 0)) - { - ULONG_PTR ProgramCounter; - - /* So we must get past the breakpoint instruction */ - ProgramCounter = KdpGetContextPc(&CurrentContext); - KdpSetContextPc(&CurrentContext, ProgramCounter + KD_BREAKPOINT_SIZE); - - SetContextManipulateHandler(State, MessageData, MessageLength, KdContext); - KdpManipulateStateHandler = ContinueManipulateStateHandler; - return KdPacketReceived; - } - - return ContinueManipulateStateHandler(State, MessageData, MessageLength, KdContext); + return handle_gdb_c(State, MessageData, MessageLength, KdContext); + } + + if (strncmp(gdb_input, "vCont;s", 7) == 0) + { + + return handle_gdb_s(State, MessageData, MessageLength, KdContext); } }
@@ -524,11 +916,14 @@ { case '?': /* Send the Status */ - gdb_send_exception(TRUE); + gdb_send_exception(); break; case '!': send_gdb_packet("OK"); break; + case 'c': + Status = handle_gdb_c(State, MessageData, MessageLength, KdContext); + break; case 'g': gdb_send_registers(); break; @@ -544,17 +939,28 @@ case 'q': handle_gdb_query(); break; + case 's': + Status = handle_gdb_s(State, MessageData, MessageLength, KdContext); + break; case 'T': handle_gdb_thread_alive(); break; case 'v': Status = handle_gdb_v(State, MessageData, MessageLength, KdContext); break; + case 'X': + Status = handle_gdb_write_mem(State, MessageData, MessageLength, KdContext); + break; + case 'z': + Status = handle_gdb_remove_breakpoint(State, MessageData, MessageLength, KdContext); + break; + case 'Z': + Status = handle_gdb_insert_breakpoint(State, MessageData, MessageLength, KdContext); + break; default: - /* We don't know how to handle this request. Maybe this is something for KD */ - State->ReturnStatus = STATUS_NOT_SUPPORTED; + /* We don't know how to handle this request. */ KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input); - return KdPacketReceived; + send_gdb_packet(""); } } while (Status == (KDSTATUS)-1);
Modified: trunk/reactos/drivers/base/kdgdb/gdb_receive.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/gdb_rece... ============================================================================== --- trunk/reactos/drivers/base/kdgdb/gdb_receive.c [iso-8859-1] (original) +++ trunk/reactos/drivers/base/kdgdb/gdb_receive.c [iso-8859-1] Mon Aug 22 22:24:30 2016 @@ -30,7 +30,7 @@ NTAPI gdb_receive_packet(_Inout_ PKD_CONTEXT KdContext) { - char* ByteBuffer = gdb_input; + UCHAR* ByteBuffer = (UCHAR*)gdb_input; UCHAR Byte; KDSTATUS Status; CHAR CheckSum = 0, ReceivedCheckSum; @@ -60,9 +60,18 @@ *ByteBuffer = '\0'; break; } - + CheckSum += (CHAR)Byte; + + /* See if we should escape */ + if (Byte == 0x7d) + { + Status = KdpReceiveByte(&Byte); + if (Status != KdPacketReceived) + return Status; + CheckSum += (CHAR)Byte; + Byte ^= 0x20; + } *ByteBuffer++ = Byte; - CheckSum += (CHAR)Byte; }
/* Get Check sum (two bytes) */ @@ -80,6 +89,7 @@ if (ReceivedCheckSum != CheckSum) { /* Do not acknowledge to GDB */ + KDDBGPRINT("Check sums don't match!"); KdpSendByte('-'); return KdPacketNeedsResend; }
Modified: trunk/reactos/drivers/base/kdgdb/gdb_send.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/gdb_send... ============================================================================== --- trunk/reactos/drivers/base/kdgdb/gdb_send.c [iso-8859-1] (original) +++ trunk/reactos/drivers/base/kdgdb/gdb_send.c [iso-8859-1] Mon Aug 22 22:24:30 2016 @@ -168,7 +168,7 @@ }
void -gdb_send_exception(BOOLEAN WithThread) +gdb_send_exception() { char gdb_out[1024]; char* ptr = gdb_out; @@ -184,20 +184,16 @@ } else ptr += sprintf(ptr, "05"); - if (WithThread) - { + #if MONOPROCESS - ptr += sprintf(ptr, "thread:%" PRIxPTR ";", - handle_to_gdb_tid(PsGetThreadId(Thread))); + ptr += sprintf(ptr, "thread:%" PRIxPTR ";", + handle_to_gdb_tid(PsGetThreadId(Thread))); #else - ptr += sprintf(ptr, "thread:p%" PRIxPTR ".%" PRIxPTR ";", - handle_to_gdb_pid(PsGetThreadProcessId(Thread)), - handle_to_gdb_tid(PsGetThreadId(Thread))); + ptr += sprintf(ptr, "thread:p%" PRIxPTR ".%" PRIxPTR ";", + handle_to_gdb_pid(PsGetThreadProcessId(Thread)), + handle_to_gdb_tid(PsGetThreadId(Thread))); #endif - } ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor); - /* Add program counter */ - gdb_append_pc_to_exception(Thread, ptr); send_gdb_packet(gdb_out); }
Modified: trunk/reactos/drivers/base/kdgdb/i386_sup.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/i386_sup... ============================================================================== --- trunk/reactos/drivers/base/kdgdb/i386_sup.c [iso-8859-1] (original) +++ trunk/reactos/drivers/base/kdgdb/i386_sup.c [iso-8859-1] Mon Aug 22 22:24:30 2016 @@ -251,28 +251,4 @@ } }
-char* -gdb_append_pc_to_exception( - _In_ PETHREAD Thread, - _Inout_ char* ptr) -{ - /* Get EIP */ - unsigned short ptrSize; - unsigned char* EipPtr = thread_to_reg(Thread, EIP, &ptrSize); - - /* Print it */ - ptr += sprintf(ptr, "08:"); - *ptr++ = hex_chars[EipPtr[0] >> 4]; - *ptr++ = hex_chars[EipPtr[0] & 0xF]; - *ptr++ = hex_chars[EipPtr[1] >> 4]; - *ptr++ = hex_chars[EipPtr[1] & 0xF]; - *ptr++ = hex_chars[EipPtr[2] >> 4]; - *ptr++ = hex_chars[EipPtr[2] & 0xF]; - *ptr++ = hex_chars[EipPtr[3] >> 4]; - *ptr++ = hex_chars[EipPtr[3] & 0xF]; - *ptr++ = ';'; - *ptr++ = '\0'; - - return ptr; -} - +
Modified: trunk/reactos/drivers/base/kdgdb/kdcom.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/kdcom.c?... ============================================================================== --- trunk/reactos/drivers/base/kdgdb/kdcom.c [iso-8859-1] (original) +++ trunk/reactos/drivers/base/kdgdb/kdcom.c [iso-8859-1] Mon Aug 22 22:24:30 2016 @@ -303,7 +303,6 @@ return KdPacketReceived; }
- KDDBGPRINT("CpGetByte returned %u.\n", CpStatus); return KdPacketTimedOut; }
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] Mon Aug 22 22:24:30 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 @@ -83,7 +83,7 @@ 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(BOOLEAN WithThread); +void gdb_send_exception(void); void send_gdb_ntstatus(_In_ NTSTATUS Status); extern const char hex_chars[];
@@ -113,15 +113,18 @@ /* arch_sup.c */ extern void gdb_send_register(void); extern void gdb_send_registers(void); -extern char* gdb_append_pc_to_exception(_In_ PETHREAD Thread, _Inout_ char* ptr);
/* Architecture specific defines. See ntoskrnl/include/internal/arch/ke.h */ #ifdef _M_IX86 +/* Handling passing over the breakpoint instruction */ # define KdpGetContextPc(Context) \ ((Context)->Eip) # define KdpSetContextPc(Context, ProgramCounter) \ ((Context)->Eip = (ProgramCounter)) # define KD_BREAKPOINT_SIZE sizeof(UCHAR) +/* Single step mode */ +# define KdpSetSingleStep(Context) \ + ((Context)->EFlags |= EFLAGS_TF) #else # error "Please define relevant macros for your architecture" #endif
Modified: trunk/reactos/drivers/base/kdgdb/kdpacket.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/kdpacket... ============================================================================== --- trunk/reactos/drivers/base/kdgdb/kdpacket.c [iso-8859-1] (original) +++ trunk/reactos/drivers/base/kdgdb/kdpacket.c [iso-8859-1] Mon Aug 22 22:24:30 2016 @@ -160,7 +160,7 @@ #else gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread)); #endif - gdb_send_exception(FALSE); + gdb_send_exception(); /* Next receive call will ask for the context */ KdpManipulateStateHandler = GetContextManipulateHandler; break; @@ -394,6 +394,13 @@ IN PSTRING MessageData, IN OUT PKD_CONTEXT KdContext) { + /* Override if we have some debug print from KD. */ + if (PacketType == PACKET_TYPE_KD_DEBUG_IO) + { + send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData); + return; + } + /* Maybe we are in a send <-> receive loop that GDB doesn't need to know about */ if (KdpSendPacketHandler) {