reactos/ntoskrnl/kdbg/kdbg.c
Hermès Bélusca-Maïto 0d0ffb7d7d
[NTOS:KD:KDBG] Integration into KD framework (Part 2/3)
Add redirections for KdSave/KdRestore and KdD0Transition/KdD3Transition.

Both KDBG and KD(TERM) need those since they will become external
transport DLLs later.
2023-08-31 16:09:49 +02:00

212 lines
6.5 KiB
C

/*
* PROJECT: ReactOS KDBG Kernel Debugger
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Kernel Debugger Initialization
* COPYRIGHT: Copyright 2020-2021 Hervé Poussineau <hpoussin@reactos.org>
* Copyright 2021 Jérôme Gardou <jerome.gardou@reactos.org>
* Copyright 2023 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#include "kdb.h"
/* GLOBALS *******************************************************************/
static ULONG KdbgNextApiNumber = DbgKdContinueApi;
static CONTEXT KdbgContext;
static EXCEPTION_RECORD64 KdbgExceptionRecord;
static BOOLEAN KdbgFirstChanceException;
static NTSTATUS KdbgContinueStatus = STATUS_SUCCESS;
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
KdD0Transition(VOID)
#undef KdD0Transition
#define pKdD0Transition KdD0Transition
{
/* Call KdTerm */
return pKdD0Transition();
}
NTSTATUS
NTAPI
KdD3Transition(VOID)
#undef KdD3Transition
#define pKdD3Transition KdD3Transition
{
/* Call KdTerm */
return pKdD3Transition();
}
NTSTATUS
NTAPI
KdSave(
_In_ BOOLEAN SleepTransition)
#undef KdSave
#define pKdSave KdSave
{
/* Call KdTerm */
return pKdSave(SleepTransition);
}
NTSTATUS
NTAPI
KdRestore(
_In_ BOOLEAN SleepTransition)
#undef KdRestore
#define pKdRestore KdRestore
{
/* Call KdTerm */
return pKdRestore(SleepTransition);
}
VOID
NTAPI
KdSendPacket(
_In_ ULONG PacketType,
_In_ PSTRING MessageHeader,
_In_opt_ PSTRING MessageData,
_Inout_ PKD_CONTEXT Context)
#undef KdSendPacket
#define pKdSendPacket KdSendPacket
{
if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
{
/* Call KdTerm */
pKdSendPacket(PacketType, MessageHeader, MessageData, Context);
return;
}
/* Debugger-only packets */
if (PacketType == PACKET_TYPE_KD_STATE_CHANGE64)
{
PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange = (PDBGKD_ANY_WAIT_STATE_CHANGE)MessageHeader->Buffer;
if (WaitStateChange->NewState == DbgKdLoadSymbolsStateChange)
{
/* Load or unload symbols */
PLDR_DATA_TABLE_ENTRY LdrEntry;
if (KdbpSymFindModule((PVOID)(ULONG_PTR)WaitStateChange->u.LoadSymbols.BaseOfDll, -1, &LdrEntry))
{
KdbSymProcessSymbols(LdrEntry, !WaitStateChange->u.LoadSymbols.UnloadSymbols);
}
return;
}
else if (WaitStateChange->NewState == DbgKdExceptionStateChange)
{
KdbgNextApiNumber = DbgKdGetContextApi;
KdbgExceptionRecord = WaitStateChange->u.Exception.ExceptionRecord;
KdbgFirstChanceException = WaitStateChange->u.Exception.FirstChance;
return;
}
}
else if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE)
{
PDBGKD_MANIPULATE_STATE64 ManipulateState = (PDBGKD_MANIPULATE_STATE64)MessageHeader->Buffer;
if (ManipulateState->ApiNumber == DbgKdGetContextApi)
{
KD_CONTINUE_TYPE Result;
/* Check if this is an assertion failure */
if (KdbgExceptionRecord.ExceptionCode == STATUS_ASSERTION_FAILURE)
{
/* Bump EIP to the instruction following the int 2C */
KeSetContextPc(&KdbgContext, KeGetContextPc(&KdbgContext) + 2);
}
Result = KdbEnterDebuggerException(&KdbgExceptionRecord,
KdbgContext.SegCs & 1,
&KdbgContext,
KdbgFirstChanceException);
#if 0
/* Manually dump the stack for the user */
KeRosDumpStackFrames(NULL, 0);
Result = kdHandleException;
#endif
if (Result != kdHandleException)
KdbgContinueStatus = STATUS_SUCCESS;
else
KdbgContinueStatus = STATUS_UNSUCCESSFUL;
KdbgNextApiNumber = DbgKdSetContextApi;
return;
}
else if (ManipulateState->ApiNumber == DbgKdSetContextApi)
{
KdbgNextApiNumber = DbgKdContinueApi;
return;
}
}
KdbPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType);
return;
}
KDSTATUS
NTAPI
KdReceivePacket(
_In_ ULONG PacketType,
_Out_ PSTRING MessageHeader,
_Out_ PSTRING MessageData,
_Out_ PULONG DataLength,
_Inout_ PKD_CONTEXT Context)
#undef KdReceivePacket
#define pKdReceivePacket KdReceivePacket
{
if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN)
{
// FIXME TODO: Implement break-in for the debugger
// and return KdPacketReceived when handled properly.
return KdPacketTimedOut;
}
if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
{
/* Call KdTerm */
return pKdReceivePacket(PacketType,
MessageHeader,
MessageData,
DataLength,
Context);
}
/* Debugger-only packets */
if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE)
{
PDBGKD_MANIPULATE_STATE64 ManipulateState = (PDBGKD_MANIPULATE_STATE64)MessageHeader->Buffer;
RtlZeroMemory(MessageHeader->Buffer, MessageHeader->MaximumLength);
if (KdbgNextApiNumber == DbgKdGetContextApi)
{
ManipulateState->ApiNumber = DbgKdGetContextApi;
MessageData->Length = 0;
MessageData->Buffer = (PCHAR)&KdbgContext;
return KdPacketReceived;
}
else if (KdbgNextApiNumber == DbgKdSetContextApi)
{
ManipulateState->ApiNumber = DbgKdSetContextApi;
MessageData->Length = sizeof(KdbgContext);
MessageData->Buffer = (PCHAR)&KdbgContext;
return KdPacketReceived;
}
else if (KdbgNextApiNumber != DbgKdContinueApi)
{
KdbPrintf("%s:%d is UNIMPLEMENTED\n", __FUNCTION__, __LINE__);
}
ManipulateState->ApiNumber = DbgKdContinueApi;
ManipulateState->u.Continue.ContinueStatus = KdbgContinueStatus;
/* Prepare for next time */
KdbgNextApiNumber = DbgKdContinueApi;
KdbgContinueStatus = STATUS_SUCCESS;
return KdPacketReceived;
}
KdbPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType);
return KdPacketTimedOut;
}
/* EOF */