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_inp…
==============================================================================
--- 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/kdpacke…
==============================================================================
--- 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: