Author: jgardou Date: Fri Sep 12 20:23:08 2014 New Revision: 64127
URL: http://svn.reactos.org/svn/reactos?rev=64127&view=rev Log: [KDGDB] - Add a callback mechanism permitting to "simulate" KD send <-> receive loop without having to actually communicate to GDB - Use that to update the program counter when cont'ing a breakpoint Now cont'ing an assertion failure is possible, since we actually get beyond the int 3 instruction
Modified: trunk/reactos/drivers/base/kdgdb/gdb_input.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] Fri Sep 12 20:23:08 2014 @@ -11,6 +11,7 @@ static HANDLE gdb_run_thread; static HANDLE gdb_dbg_process; HANDLE gdb_dbg_thread; +CONTEXT CurrentContext;
/* PRIVATE FUNCTIONS **********************************************************/ static @@ -200,6 +201,147 @@ }
static +VOID +GetCurrentContextSendHandler( + _In_ ULONG PacketType, + _In_ PSTRING MessageHeader, + _In_ PSTRING MessageData +) +{ + DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; + const CONTEXT* Context = (const CONTEXT*)MessageData->Buffer; + + if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) + || (State->ApiNumber != DbgKdGetContextApi) + || (MessageData->Length < sizeof(*Context))) + { + /* Should we bugcheck ? */ + while (1); + } + + /* Just copy it */ + RtlCopyMemory(&CurrentContext, Context, sizeof(*Context)); +} + +static +VOID +GetCurrentContext( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext, + _In_opt_ KDP_MANIPULATESTATE_HANDLER ManipulateStateHandler +) +{ + State->ApiNumber = DbgKdGetContextApi; + State->Processor = CurrentStateChange.Processor; + State->ReturnStatus = STATUS_SUCCESS; + State->ProcessorLevel = CurrentStateChange.ProcessorLevel; + MessageData->Length = 0; + + /* Update the send <-> receive loop handler */ + KdpSendPacketHandler = GetCurrentContextSendHandler; + KdpManipulateStateHandler = ManipulateStateHandler; +} + +static +VOID +SetContextSendHandler( + _In_ ULONG PacketType, + _In_ PSTRING MessageHeader, + _In_ PSTRING MessageData +) +{ + DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; + + /* We just confirm that all went well */ + if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) + || (State->ApiNumber != DbgKdSetContextApi) + || (State->ReturnStatus != STATUS_SUCCESS)) + { + /* Should we bugcheck ? */ + while (1); + } +} + +static +KDSTATUS +SetContext( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext, + _In_opt_ KDP_MANIPULATESTATE_HANDLER ManipulateStateHandler +) +{ + State->ApiNumber = DbgKdSetContextApi; + State->Processor = CurrentStateChange.Processor; + State->ReturnStatus = STATUS_SUCCESS; + State->ProcessorLevel = CurrentStateChange.ProcessorLevel; + MessageData->Length = sizeof(CurrentContext); + + if (MessageData->MaximumLength < sizeof(CurrentContext)) + { + while (1); + } + + RtlCopyMemory(MessageData->Buffer, &CurrentContext, sizeof(CurrentContext)); + + /* Update the send <-> receive loop handlers */ + KdpSendPacketHandler = SetContextSendHandler; + KdpManipulateStateHandler = ManipulateStateHandler; + + return KdPacketReceived; +} + +static +KDSTATUS +SendContinue( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext +) +{ + /* Let's go on */ + State->ApiNumber = DbgKdContinueApi; + State->ReturnStatus = STATUS_SUCCESS; /* ? */ + State->Processor = CurrentStateChange.Processor; + State->ProcessorLevel = CurrentStateChange.ProcessorLevel; + if (MessageData) + MessageData->Length = 0; + *MessageLength = 0; + State->u.Continue.ContinueStatus = STATUS_SUCCESS; + + /* We definitely are at the end of the send <-> receive loop, if any */ + KdpSendPacketHandler = NULL; + KdpManipulateStateHandler = NULL; + + /* Tell GDB we are fine */ + send_gdb_packet("OK"); + return KdPacketReceived; +} + +static +KDSTATUS +UpdateProgramCounterSendContinue( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext) +{ + ULONG_PTR ProgramCounter; + + /* So we must get past the breakpoint instruction */ + ProgramCounter = KdpGetContextPc(&CurrentContext); + KdpSetContextPc(&CurrentContext, ProgramCounter + KD_BREAKPOINT_SIZE); + + /* Set the context and continue */ + SetContext(State, MessageData, MessageLength, KdContext, SendContinue); + return KdPacketReceived; +} + +static KDSTATUS handle_gdb_v( _Out_ DBGKD_MANIPULATE_STATE64* State, @@ -222,18 +364,21 @@
if (strcmp(gdb_input, "vCont;c") == 0) { - /* Let's go on */ - State->ApiNumber = DbgKdContinueApi; - State->ReturnStatus = STATUS_SUCCESS; /* ? */ - State->Processor = CurrentStateChange.Processor; - State->ProcessorLevel = CurrentStateChange.ProcessorLevel; - if (MessageData) - MessageData->Length = 0; - *MessageLength = 0; - State->u.Continue.ContinueStatus = STATUS_SUCCESS; - /* Tell GDB we are fine */ - send_gdb_packet("OK"); - return KdPacketReceived; + DBGKM_EXCEPTION64* Exception = NULL; + + 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)) + { + /* So we get the context, update it and send it back */ + GetCurrentContext(State, MessageData, MessageLength, KdContext, UpdateProgramCounterSendContinue); + return KdPacketReceived; + } + + return SendContinue(State, MessageData, MessageLength, KdContext); } }
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] Fri Sep 12 20:23:08 2014 @@ -25,6 +25,19 @@ #define KDDBGPRINT KdpDbgPrint #endif
+/* Callbacks to simulate a KdReceive <-> KdSend loop without GDB being aware of it */ +typedef VOID (*KDP_SEND_HANDLER)( + _In_ ULONG PacketType, + _In_ PSTRING MessageHeader, + _In_ PSTRING MessageData +); +typedef KDSTATUS (*KDP_MANIPULATESTATE_HANDLER)( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext +); + /* gdb_input.c */ extern HANDLE gdb_dbg_thread; KDSTATUS gdb_interpret_input(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext); @@ -49,8 +62,22 @@ extern DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange; extern DBGKD_GET_VERSION64 KdVersion; extern KDDEBUGGER_DATA64* KdDebuggerDataBlock; +extern KDP_SEND_HANDLER KdpSendPacketHandler; +extern KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler; +
/* arch_sup.c */ void gdb_send_registers(void);
+/* Architecture specific defines. See ntoskrnl/include/internal/arch/ke.h */ +#ifdef _M_IX86 +# define KdpGetContextPc(Context) \ + ((Context)->Eip) +# define KdpSetContextPc(Context, ProgramCounter) \ + ((Context)->Eip = (ProgramCounter)) +# define KD_BREAKPOINT_SIZE sizeof(UCHAR) +#else +# error "Please define relevant macros for your architecture" +#endif + #endif /* _KDGDB_H_ */
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] Fri Sep 12 20:23:08 2014 @@ -12,6 +12,9 @@ DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange; DBGKD_GET_VERSION64 KdVersion; KDDEBUGGER_DATA64* KdDebuggerDataBlock; +/* Callbacks used to communicate with KD aside from GDB */ +KDP_SEND_HANDLER KdpSendPacketHandler = NULL; +KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler = NULL;
/* LOCALS *********************************************************************/ static BOOLEAN FakeNextManipulatePacket = FALSE; @@ -159,6 +162,10 @@
State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
+ /* Maybe we are in a send<->receive loop that GDB doesn't need to know about */ + if (KdpManipulateStateHandler != NULL) + return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext); + if (FakeNextManipulatePacket) { FakeNextManipulatePacket = FALSE; @@ -183,6 +190,13 @@ IN PSTRING MessageData, IN OUT PKD_CONTEXT KdContext) { + /* Maybe we are in a send <-> receive loop that GDB doesn't need to know about */ + if (KdpSendPacketHandler) + { + KdpSendPacketHandler(PacketType, MessageHeader, MessageData); + return; + } + switch (PacketType) { case PACKET_TYPE_KD_STATE_CHANGE64: