Author: jgardou
Date: Sun Sep 14 20:45:30 2014
New Revision: 64154
URL:
http://svn.reactos.org/svn/reactos?rev=64154&view=rev
Log:
[KDGDB]
- Always pass down the result of gdb_receive_packet up to KD, so that it knows when a
breakin packet was received. (CTRL-C) now works!
- Generalize the use of the Send <-> ManipulateState callbacks for a better code
reading.
- Get the exception context as soon as it is thrown (instead of playing with the PRCB)
- Improve the way we attach to GDB: on the first KD call, we set
KdContext->ControlCPending so that KD throws an exception. That way we can first
initialize our KD stuff, and then quietly attach to GDB
- Implement the 'p' (get one register) GDB request.
GDB is now much more reliable.
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] Sun Sep 14 20:45:30 2014
@@ -11,12 +11,13 @@
/* LOCALS *********************************************************************/
static HANDLE gdb_run_thread;
-static HANDLE gdb_dbg_process;
-HANDLE gdb_dbg_thread;
-CONTEXT CurrentContext;
/* Keep track of where we are for qfThreadInfo/qsThreadInfo */
static LIST_ENTRY* CurrentProcessEntry;
static LIST_ENTRY* CurrentThreadEntry;
+
+/* GLOBALS ********************************************************************/
+HANDLE gdb_dbg_process;
+HANDLE gdb_dbg_thread;
/* PRIVATE FUNCTIONS **********************************************************/
static
@@ -68,6 +69,7 @@
send_gdb_packet("OK");
break;
case 'g':
+ KDDBGPRINT("Setting debug thread: %s.\n", gdb_input);
if (strncmp(&gdb_input[2], "p-1", 3) == 0)
{
gdb_dbg_process = (HANDLE)-1;
@@ -90,6 +92,20 @@
}
}
+KDSTATUS
+gdb_receive_and_interpret_packet(
+ _Out_ DBGKD_MANIPULATE_STATE64* State,
+ _Out_ PSTRING MessageData,
+ _Out_ PULONG MessageLength,
+ _Inout_ PKD_CONTEXT KdContext)
+{
+ KDSTATUS Status = gdb_receive_packet(KdContext);
+
+ if (Status != KdPacketReceived)
+ return Status;
+ return gdb_interpret_input(State, MessageData, MessageLength, KdContext);
+}
+
static
void
handle_gdb_thread_alive(void)
@@ -118,7 +134,7 @@
/* q* packets */
static
-void
+KDSTATUS
handle_gdb_query(
_Out_ DBGKD_MANIPULATE_STATE64* State,
_Out_ PSTRING MessageData,
@@ -128,20 +144,20 @@
if (strncmp(gdb_input, "qSupported:", 11) == 0)
{
send_gdb_packet("PacketSize=4096;multiprocess+;");
- return;
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
if (strncmp(gdb_input, "qAttached", 9) == 0)
{
- /* Say yes: the remote server didn't create the process, ReactOS did! */
+ /* Say no: We didn't attach, we create the process! */
send_gdb_packet("0");
- return;
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
if (strncmp(gdb_input, "qRcmd,", 6) == 0)
{
send_gdb_packet("OK");
- return;
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
if (strcmp(gdb_input, "qC") == 0)
@@ -151,7 +167,7 @@
PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread),
PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread));
send_gdb_packet(gdb_out);
- return;
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
if ((strncmp(gdb_input, "qfThreadInfo", 12) == 0)
@@ -174,15 +190,13 @@
{
/* there is only one thread to tell about */
send_gdb_packet("l");
- return;
+ return gdb_receive_and_interpret_packet(State, MessageData,
MessageLength, KdContext);
}
/* Just tell GDB about the current thread */
sprintf(gdb_out, "mp%p.%p", PsGetCurrentProcessId(),
PsGetCurrentThreadId());
send_gdb_packet(gdb_out);
/* GDB can ask anything at this point, it isn't necessarily a
qsThreadInfo packet */
- gdb_receive_packet(KdContext);
- gdb_interpret_input(State, MessageData, MessageLength, KdContext);
- return;
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
if (Resuming)
@@ -197,7 +211,7 @@
{
/* We're done */
send_gdb_packet("l");
- return;
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
Process = CONTAINING_RECORD(CurrentProcessEntry, EPROCESS, ActiveProcessLinks);
@@ -234,9 +248,7 @@
/* send what we got */
send_gdb_packet(gdb_out);
/* GDB can ask anything at this point, it isn't necessarily a
qsThreadInfo packet */
- gdb_receive_packet(KdContext);
- gdb_interpret_input(State, MessageData, MessageLength, KdContext);
- return;
+ return gdb_receive_and_interpret_packet(State, MessageData,
MessageLength, KdContext);
}
}
@@ -244,13 +256,12 @@
send_gdb_packet(gdb_out);
CurrentThreadEntry = NULL;
/* GDB can ask anything at this point, it isn't necessarily a qsThreadInfo
packet */
- gdb_receive_packet(KdContext);
- gdb_interpret_input(State, MessageData, MessageLength, KdContext);
- return;
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input);
send_gdb_packet("");
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
#if 0
@@ -304,6 +315,7 @@
else
send_gdb_memory(MessageData->Buffer, MessageData->Length);
KdpSendPacketHandler = NULL;
+ KdpManipulateStateHandler = NULL;
}
static
@@ -331,150 +343,6 @@
}
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));
- KdpSendPacketHandler = NULL;
-}
-
-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);
- }
-
- KdpSendPacketHandler = NULL;
-}
-
-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,
@@ -499,6 +367,9 @@
{
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;
@@ -506,15 +377,22 @@
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);
+ 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 SendContinue(State, MessageData, MessageLength, KdContext);
- }
- }
-
+ return ContinueManipulateStateHandler(State, MessageData, MessageLength,
KdContext);
+ }
+ }
+
+ KDDBGPRINT("Unhandled 'v' packet: %s\n", gdb_input);
return KdPacketReceived;
}
@@ -526,7 +404,6 @@
_Out_ PULONG MessageLength,
_Inout_ PKD_CONTEXT KdContext)
{
- KDSTATUS Status;
switch (gdb_input[0])
{
case '?':
@@ -534,16 +411,16 @@
gdb_send_exception();
break;
case 'g':
- gdb_send_registers();
- break;
+ return gdb_send_registers(State, MessageData, MessageLength, KdContext);
case 'H':
handle_gdb_set_thread();
break;
case 'm':
return handle_gdb_read_mem(State, MessageData, MessageLength);
+ case 'p':
+ return gdb_send_register(State, MessageData, MessageLength, KdContext);
case 'q':
- handle_gdb_query(State, MessageData, MessageLength, KdContext);
- break;
+ return handle_gdb_query(State, MessageData, MessageLength, KdContext);
case 'T':
handle_gdb_thread_alive();
break;
@@ -552,12 +429,8 @@
default:
/* We don't know how to handle this request. Maybe this is something for KD
*/
State->ReturnStatus = STATUS_NOT_SUPPORTED;
+ KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input);
return KdPacketReceived;
}
- /* Get the answer from GDB */
- Status = gdb_receive_packet(KdContext);
- if (Status != KdPacketReceived)
- return Status;
- /* Try interpreting this new packet */
- return gdb_interpret_input(State, MessageData, MessageLength, KdContext);
-}
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
+}
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] Sun Sep 14 20:45:30 2014
@@ -168,17 +168,12 @@
{
char gdb_out[1024];
char* ptr = gdb_out;
- DBGKM_EXCEPTION64* Exception = NULL;
-
- if (CurrentStateChange.NewState == DbgKdExceptionStateChange)
- Exception = &CurrentStateChange.u.Exception;
+ DBGKM_EXCEPTION64* Exception = &CurrentStateChange.u.Exception;
/* Report to GDB */
*ptr++ = 'T';
- if (Exception)
- ptr = exception_code_to_gdb(Exception->ExceptionRecord.ExceptionCode, ptr);
- else
- ptr += sprintf(ptr, "05");
+
+ ptr = exception_code_to_gdb(Exception->ExceptionRecord.ExceptionCode, ptr);
ptr += sprintf(ptr, "thread:p%p.%p;",
PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread),
PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread));
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] Sun Sep 14 20:45:30 2014
@@ -79,21 +79,48 @@
return 0;
}
-void
-gdb_send_registers(void)
+KDSTATUS
+gdb_send_registers(
+ _Out_ DBGKD_MANIPULATE_STATE64* State,
+ _Out_ PSTRING MessageData,
+ _Out_ PULONG MessageLength,
+ _Inout_ PKD_CONTEXT KdContext)
{
- CONTEXT* ctx;
- PKPRCB* ProcessorBlockLists;
ULONG32 Registers[16];
unsigned i;
unsigned short size;
- ProcessorBlockLists = (PKPRCB*)KdDebuggerDataBlock->KiProcessorBlock.Pointer;
- ctx = (CONTEXT*)((char*)ProcessorBlockLists[CurrentStateChange.Processor] +
KdDebuggerDataBlock->OffsetPrcbProcStateContext);
-
for(i=0; i < 16; i++)
{
- Registers[i] = *(ULONG32*)ctx_to_reg(ctx, i, &size);
+ Registers[i] = *(ULONG32*)ctx_to_reg(&CurrentContext, i, &size);
}
send_gdb_memory(Registers, sizeof(Registers));
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
+
+KDSTATUS
+gdb_send_register(
+ _Out_ DBGKD_MANIPULATE_STATE64* State,
+ _Out_ PSTRING MessageData,
+ _Out_ PULONG MessageLength,
+ _Inout_ PKD_CONTEXT KdContext)
+{
+ enum reg_name reg_name;
+ void *ptr;
+ unsigned short size;
+
+ /* Get the GDB register name (gdb_input = "pXX") */
+ reg_name = (hex_value(gdb_input[1]) << 4) | hex_value(gdb_input[2]);
+
+ ptr = ctx_to_reg(&CurrentContext, reg_name, &size);
+ if (!ptr)
+ {
+ /* Undefined. Let's assume 32 bit register */
+ send_gdb_packet("xxxxxxxx");
+ }
+ else
+ {
+ send_gdb_memory(ptr, size);
+ }
+ return gdb_receive_and_interpret_packet(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] Sun Sep 14 20:45:30 2014
@@ -25,6 +25,18 @@
#define KDDBGPRINT KdpDbgPrint
#endif
+FORCEINLINE
+VOID
+InitManipulateFromStateChange(
+ _In_ ULONG ApiNumber,
+ _In_ const DBGKD_ANY_WAIT_STATE_CHANGE* StateChange,
+ _Out_ DBGKD_MANIPULATE_STATE64* Manipulate)
+{
+ Manipulate->ApiNumber = ApiNumber;
+ Manipulate->Processor = StateChange->Processor;
+ Manipulate->ProcessorLevel = StateChange->ProcessorLevel;
+}
+
/* Callbacks to simulate a KdReceive <-> KdSend loop without GDB being aware of it
*/
typedef VOID (*KDP_SEND_HANDLER)(
_In_ ULONG PacketType,
@@ -40,7 +52,9 @@
/* 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);
+extern HANDLE gdb_dbg_process;
+extern KDSTATUS gdb_interpret_input(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_ PSTRING
MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
+extern KDSTATUS gdb_receive_and_interpret_packet(_Out_ DBGKD_MANIPULATE_STATE64* State,
_Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
/* gdb_receive.c */
extern CHAR gdb_input[];
@@ -61,14 +75,18 @@
/* kdpacket.c */
extern DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange;
+extern CONTEXT CurrentContext;
extern DBGKD_GET_VERSION64 KdVersion;
extern KDDEBUGGER_DATA64* KdDebuggerDataBlock;
extern KDP_SEND_HANDLER KdpSendPacketHandler;
extern KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler;
-
+/* Commone ManipulateState handlers */
+extern KDSTATUS ContinueManipulateStateHandler(_Out_ DBGKD_MANIPULATE_STATE64* State,
_Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
+extern KDSTATUS SetContextManipulateHandler(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_
PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
/* arch_sup.c */
-void gdb_send_registers(void);
+extern KDSTATUS gdb_send_register(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_ PSTRING
MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
+extern KDSTATUS gdb_send_registers(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_ PSTRING
MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
/* 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] Sun Sep 14 20:45:30 2014
@@ -7,61 +7,145 @@
#include "kdgdb.h"
+/* LOCALS *********************************************************************/
+static
+VOID
+FirstSendHandler(
+ _In_ ULONG PacketType,
+ _In_ PSTRING MessageHeader,
+ _In_ PSTRING MessageData);
+
/* GLOBALS ********************************************************************/
-
-DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange;
DBGKD_GET_VERSION64 KdVersion;
KDDEBUGGER_DATA64* KdDebuggerDataBlock;
+BOOLEAN InException = FALSE;
/* Callbacks used to communicate with KD aside from GDB */
-KDP_SEND_HANDLER KdpSendPacketHandler = NULL;
+KDP_SEND_HANDLER KdpSendPacketHandler = FirstSendHandler;
KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler = NULL;
-
-/* LOCALS *********************************************************************/
-static BOOLEAN FakeNextManipulatePacket = FALSE;
-static DBGKD_MANIPULATE_STATE64 FakeManipulateState = {0};
+/* Data describing the current exception */
+DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange;
+CONTEXT CurrentContext;
/* PRIVATE FUNCTIONS **********************************************************/
+
+static
+VOID
+GetContextSendHandler(
+ _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 ? */
+ KDDBGPRINT("ERROR: Received wrong packet from KD.\n");
+ while (1);
+ }
+
+ /* Just copy it */
+ RtlCopyMemory(&CurrentContext, Context, sizeof(*Context));
+ KdpSendPacketHandler = NULL;
+}
+
+static
+KDSTATUS
+GetContextManipulateHandler(
+ _Out_ DBGKD_MANIPULATE_STATE64* State,
+ _Out_ PSTRING MessageData,
+ _Out_ PULONG MessageLength,
+ _Inout_ PKD_CONTEXT KdContext
+)
+{
+ 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 = GetContextSendHandler;
+ KdpManipulateStateHandler = NULL;
+
+ return KdPacketReceived;
+}
+
+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);
+ }
+
+ KdpSendPacketHandler = NULL;
+}
+
+KDSTATUS
+SetContextManipulateHandler(
+ _Out_ DBGKD_MANIPULATE_STATE64* State,
+ _Out_ PSTRING MessageData,
+ _Out_ PULONG MessageLength,
+ _Inout_ PKD_CONTEXT KdContext
+)
+{
+ 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 = NULL;
+
+ return KdPacketReceived;
+}
+
static
void
send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE* StateChange)
{
- static BOOLEAN first = TRUE;
-
- /* Save current state for later GDB queries */
- CurrentStateChange = *StateChange;
-
- if (first)
- {
- /*
- * This is the first packet we receive.
- * We take this as an opportunity to connect with GDB and to
- * get the KD version block
- */
- FakeNextManipulatePacket = TRUE;
- FakeManipulateState.ApiNumber = DbgKdGetVersionApi;
- FakeManipulateState.Processor = StateChange->Processor;
- FakeManipulateState.ProcessorLevel = StateChange->ProcessorLevel;
- FakeManipulateState.ReturnStatus = STATUS_SUCCESS;
-
- first = FALSE;
- return;
- }
-
switch (StateChange->NewState)
{
case DbgKdLoadSymbolsStateChange:
{
/* We don't care about symbols loading */
- FakeNextManipulatePacket = TRUE;
- FakeManipulateState.ApiNumber = DbgKdContinueApi;
- FakeManipulateState.Processor = StateChange->Processor;
- FakeManipulateState.ProcessorLevel = StateChange->ProcessorLevel;
- FakeManipulateState.ReturnStatus = STATUS_SUCCESS;
- FakeManipulateState.u.Continue.ContinueStatus = STATUS_SUCCESS;
+ KdpManipulateStateHandler = ContinueManipulateStateHandler;
break;
}
case DbgKdExceptionStateChange:
+ /* Save current state for later GDB queries */
+ CurrentStateChange = *StateChange;
+ /* Unless GDB tells us otherwise, those are what we should have */
+ gdb_dbg_thread = PsGetThreadId((PETHREAD)StateChange->Thread);
+ gdb_dbg_process = PsGetThreadProcessId((PETHREAD)StateChange->Thread);
gdb_send_exception();
+ /* Next receive call will ask for the context */
+ KdpManipulateStateHandler = GetContextManipulateHandler;
break;
default:
/* FIXME */
@@ -100,19 +184,117 @@
gdb_send_registers((CONTEXT*)MessageData->Buffer);
return;
#endif
- case DbgKdGetVersionApi:
- {
- LIST_ENTRY* DebuggerDataList;
- /* Simply get a copy */
- RtlCopyMemory(&KdVersion, &State->u.GetVersion64, sizeof(KdVersion));
- DebuggerDataList = (LIST_ENTRY*)(ULONG_PTR)KdVersion.DebuggerDataList;
- KdDebuggerDataBlock = CONTAINING_RECORD(DebuggerDataList->Flink,
KDDEBUGGER_DATA64, Header.List);
- return;
- }
default:
/* FIXME */
while (1);
}
+}
+
+KDSTATUS
+ContinueManipulateStateHandler(
+ _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;
+ return KdPacketReceived;
+}
+
+static
+VOID
+GetVersionSendHandler(
+ _In_ ULONG PacketType,
+ _In_ PSTRING MessageHeader,
+ _In_ PSTRING MessageData)
+{
+ DBGKD_MANIPULATE_STATE64* State =
(DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
+ LIST_ENTRY* DebuggerDataList;
+
+ /* Confirm that all went well */
+ if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
+ || (State->ApiNumber != DbgKdGetVersionApi)
+ || !NT_SUCCESS(State->ReturnStatus))
+ {
+ /* FIXME: should detach from KD and go along without debugging */
+ KDDBGPRINT("Wrong packet received after asking for data.\n");
+ while(1);
+ }
+
+ /* Copy the relevant data */
+ RtlCopyMemory(&KdVersion, &State->u.GetVersion64, sizeof(KdVersion));
+ DebuggerDataList = (LIST_ENTRY*)(ULONG_PTR)KdVersion.DebuggerDataList;
+ KdDebuggerDataBlock = CONTAINING_RECORD(DebuggerDataList->Flink,
KDDEBUGGER_DATA64, Header.List);
+
+ /* We can tell KD to continue */
+ KdpSendPacketHandler = NULL;
+ KdpManipulateStateHandler = ContinueManipulateStateHandler;
+}
+
+static
+KDSTATUS
+GetVersionManipulateStateHandler(
+ _Out_ DBGKD_MANIPULATE_STATE64* State,
+ _Out_ PSTRING MessageData,
+ _Out_ PULONG MessageLength,
+ _Inout_ PKD_CONTEXT KdContext)
+{
+ /* Ask for the version data */
+ State->ApiNumber = DbgKdGetVersionApi;
+ State->Processor = CurrentStateChange.Processor;
+ State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
+
+ /* The next send call will serve this query */
+ KdpSendPacketHandler = GetVersionSendHandler;
+ KdpManipulateStateHandler = NULL;
+
+ /* This will make KD breakin and we will be able to properly attach to GDB */
+ KdContext->KdpControlCPending = TRUE;
+
+ return KdPacketReceived;
+}
+
+static
+VOID
+FirstSendHandler(
+ _In_ ULONG PacketType,
+ _In_ PSTRING MessageHeader,
+ _In_ PSTRING MessageData)
+{
+ DBGKD_ANY_WAIT_STATE_CHANGE* StateChange =
(DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer;
+
+ if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
+ {
+ /* This is not the packet we are waiting for */
+ send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData);
+ return;
+ }
+
+ if (PacketType != PACKET_TYPE_KD_STATE_CHANGE64)
+ {
+ KDDBGPRINT("First KD packet is not a state change!\n");
+ /* FIXME: What should we send back to KD ? */
+ while(1);
+ }
+
+ CurrentStateChange = *StateChange;
+
+ /* The next receive call will be asking for the version data */
+ KdpSendPacketHandler = NULL;
+ KdpManipulateStateHandler = GetVersionManipulateStateHandler;
}
/* PUBLIC FUNCTIONS ***********************************************************/
@@ -162,13 +344,6 @@
if (KdpManipulateStateHandler != NULL)
return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext);
- if (FakeNextManipulatePacket)
- {
- FakeNextManipulatePacket = FALSE;
- *State = FakeManipulateState;
- return KdPacketReceived;
- }
-
/* Receive data from GDB */
Status = gdb_receive_packet(KdContext);
if (Status != KdPacketReceived)