mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
[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 svn path=/trunk/; revision=64127
This commit is contained in:
parent
476ad09335
commit
1bbea7c093
3 changed files with 198 additions and 12 deletions
|
@ -11,6 +11,7 @@
|
|||
static HANDLE gdb_run_thread;
|
||||
static HANDLE gdb_dbg_process;
|
||||
HANDLE gdb_dbg_thread;
|
||||
CONTEXT CurrentContext;
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
static
|
||||
|
@ -199,6 +200,147 @@ handle_gdb_read_mem(
|
|||
return KdPacketReceived;
|
||||
}
|
||||
|
||||
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(
|
||||
|
@ -222,18 +364,21 @@ handle_gdb_v(
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,19 @@ extern ULONG KdpDbgPrint(const char* Format, ...);
|
|||
#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 @@ KDSTATUS NTAPI KdpReceiveByte(_Out_ PUCHAR OutByte);
|
|||
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_ */
|
||||
|
|
|
@ -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 @@ KdReceivePacket(
|
|||
|
||||
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 @@ KdSendPacket(
|
|||
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:
|
||||
|
|
Loading…
Reference in a new issue