https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2046a17ef475ac8d80bfdcffc09d35712e14ec4a
commit 2046a17ef475ac8d80bfdcffc09d35712e14ec4a Author: Hermès Bélusca-Maïto <hermes.belusca-ma...@reactos.org> AuthorDate: Tue Mar 21 18:42:29 2023 +0100 Commit: Hermès Bélusca-Maïto <hermes.belusca-ma...@reactos.org> CommitDate: Thu Aug 31 16:07:51 2023 +0200 [NTOS:KD:KDBG] Integration into KD framework (Part 1/3) Split KdSendPacket and KdReceivePacket into those that manipulate the KDBG state proper (reside in kdbg/kdbg.c), and those that deal only with debug input/output that will reside in a KDTERM "KD Terminal Driver" DLL. Based on some previous preparatory work by Hervé Poussineau in PR #4600. (Equivalents of commits 5162bf106 and partly e9bcf7275.) --- ntoskrnl/include/internal/kd.h | 7 -- ntoskrnl/include/ntoskrnl.h | 12 +-- ntoskrnl/kd/kdio.c | 151 +++++++----------------------------- ntoskrnl/kdbg/kdb.h | 28 ++++--- ntoskrnl/kdbg/kdb_print.c | 22 ++++-- ntoskrnl/kdbg/kdbg.c | 170 +++++++++++++++++++++++++++++++++++++++++ ntoskrnl/ntos.cmake | 1 + 7 files changed, 242 insertions(+), 149 deletions(-) diff --git a/ntoskrnl/include/internal/kd.h b/ntoskrnl/include/internal/kd.h index a180acf5478..caeb605cb12 100644 --- a/ntoskrnl/include/internal/kd.h +++ b/ntoskrnl/include/internal/kd.h @@ -30,13 +30,6 @@ KdPortPutByteEx( /* KD GLOBALS ****************************************************************/ -typedef enum _KD_CONTINUE_TYPE -{ - kdContinue = 0, - kdDoNotHandleException, - kdHandleException -} KD_CONTINUE_TYPE; - /* KD Internal Debug Services */ typedef enum _KDP_DEBUG_SERVICE { diff --git a/ntoskrnl/include/ntoskrnl.h b/ntoskrnl/include/ntoskrnl.h index 6f2f5379bec..4d70fd91627 100644 --- a/ntoskrnl/include/ntoskrnl.h +++ b/ntoskrnl/include/ntoskrnl.h @@ -88,13 +88,15 @@ #define NOEXTAPI #include <windbgkd.h> #include <wdbgexts.h> +#include <kddll.h> #ifdef KDBG -#define KdDebuggerInitialize0 KdpDebuggerInitialize0 -#define KdDebuggerInitialize1 KdpDebuggerInitialize1 -#define KdSendPacket KdpSendPacket -#define KdReceivePacket KdpReceivePacket + /* Define new names for these exports also present in KDBG */ + #define KdSendPacket KdbgSendPacket + #define KdReceivePacket KdbgReceivePacket + /* And reload the definitions with these new names */ + #undef _KDDLL_ + #include <kddll.h> #endif -#include <kddll.h> #ifdef __ROS_ROSSYM__ #include <reactos/rossym.h> #endif diff --git a/ntoskrnl/kd/kdio.c b/ntoskrnl/kd/kdio.c index 82a1ade1ed7..1a9c4c5fbb4 100644 --- a/ntoskrnl/kd/kdio.c +++ b/ntoskrnl/kd/kdio.c @@ -20,6 +20,9 @@ #define NDEBUG #include <debug.h> +#undef KdSendPacket +#undef KdReceivePacket + /* GLOBALS *******************************************************************/ #define KdpBufferSize (1024 * 512) @@ -54,12 +57,6 @@ PKDP_INIT_ROUTINE InitRoutines[KdMax] = #endif }; -static ULONG KdbgNextApiNumber = DbgKdContinueApi; -static CONTEXT KdbgContext; -static EXCEPTION_RECORD64 KdbgExceptionRecord; -static BOOLEAN KdbgFirstChanceException; -static NTSTATUS KdbgContinueStatus = STATUS_SUCCESS; - /* LOCKING FUNCTIONS *********************************************************/ KIRQL @@ -607,93 +604,36 @@ KdSendPacket( _In_opt_ PSTRING MessageData, _Inout_ PKD_CONTEXT Context) { - if (PacketType == PACKET_TYPE_KD_DEBUG_IO) - { - ULONG ApiNumber = ((PDBGKD_DEBUG_IO)MessageHeader->Buffer)->ApiNumber; - - /* Validate API call */ - if (MessageHeader->Length != sizeof(DBGKD_DEBUG_IO)) - return; - if ((ApiNumber != DbgKdPrintStringApi) && - (ApiNumber != DbgKdGetStringApi)) - { - return; - } - if (!MessageData) - return; + PDBGKD_DEBUG_IO DebugIo; - /* NOTE: MessageData->Length should be equal to - * DebugIo.u.PrintString.LengthOfString, or to - * DebugIo.u.GetString.LengthOfPromptString */ + if (PacketType != PACKET_TYPE_KD_DEBUG_IO) + { + KdIoPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType); + return; + } - if (!KdpDebugMode.Value) - return; + DebugIo = (PDBGKD_DEBUG_IO)MessageHeader->Buffer; - /* Print the string proper */ - KdIoPrintString(MessageData->Buffer, MessageData->Length); + /* Validate API call */ + if (MessageHeader->Length != sizeof(DBGKD_DEBUG_IO)) return; - } - else if (PacketType == PACKET_TYPE_KD_STATE_CHANGE64) + if ((DebugIo->ApiNumber != DbgKdPrintStringApi) && + (DebugIo->ApiNumber != DbgKdGetStringApi)) { - PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange = (PDBGKD_ANY_WAIT_STATE_CHANGE)MessageHeader->Buffer; - if (WaitStateChange->NewState == DbgKdLoadSymbolsStateChange) - { -#ifdef KDBG - PLDR_DATA_TABLE_ENTRY LdrEntry; - /* Load symbols. Currently implemented only for KDBG! */ - if (KdbpSymFindModule((PVOID)(ULONG_PTR)WaitStateChange->u.LoadSymbols.BaseOfDll, -1, &LdrEntry)) - { - KdbSymProcessSymbols(LdrEntry, !WaitStateChange->u.LoadSymbols.UnloadSymbols); - } -#endif - return; - } - else if (WaitStateChange->NewState == DbgKdExceptionStateChange) - { - KdbgNextApiNumber = DbgKdGetContextApi; - KdbgExceptionRecord = WaitStateChange->u.Exception.ExceptionRecord; - KdbgFirstChanceException = WaitStateChange->u.Exception.FirstChance; - return; - } + 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; + if (!MessageData) + return; -#ifdef KDBG - /* 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); - } + /* NOTE: MessageData->Length should be equal to + * DebugIo.u.PrintString.LengthOfString, or to + * DebugIo.u.GetString.LengthOfPromptString */ - Result = KdbEnterDebuggerException(&KdbgExceptionRecord, - KdbgContext.SegCs & 1, - &KdbgContext, - KdbgFirstChanceException); -#else - /* We'll 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; - } - } - UNIMPLEMENTED; + if (!KdpDebugMode.Value) + return; + + /* Print the string proper */ + KdIoPrintString(MessageData->Buffer, MessageData->Length); } KDSTATUS @@ -705,48 +645,16 @@ KdReceivePacket( _Out_ PULONG DataLength, _Inout_ PKD_CONTEXT Context) { -#ifdef KDBG - STRING ResponseString; PDBGKD_DEBUG_IO DebugIo; + STRING ResponseString; CHAR MessageBuffer[512]; -#endif - - 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) - { - UNIMPLEMENTED; - } - ManipulateState->ApiNumber = DbgKdContinueApi; - ManipulateState->u.Continue.ContinueStatus = KdbgContinueStatus; - - /* Prepare for next time */ - KdbgNextApiNumber = DbgKdContinueApi; - KdbgContinueStatus = STATUS_SUCCESS; - - return KdPacketReceived; - } if (PacketType != PACKET_TYPE_KD_DEBUG_IO) + { + KdIoPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType); return KdPacketTimedOut; + } -#ifdef KDBG DebugIo = (PDBGKD_DEBUG_IO)MessageHeader->Buffer; /* Validate API call */ @@ -795,7 +703,6 @@ KdReceivePacket( /* Only now we can copy back the data into MessageData->Buffer */ RtlCopyMemory(MessageData->Buffer, ResponseString.Buffer, *DataLength); -#endif return KdPacketReceived; } diff --git a/ntoskrnl/kdbg/kdb.h b/ntoskrnl/kdbg/kdb.h index 2170be54f9f..df2945a7d9c 100644 --- a/ntoskrnl/kdbg/kdb.h +++ b/ntoskrnl/kdbg/kdb.h @@ -51,6 +51,25 @@ typedef enum _KDB_ENTER_CONDITION KdbEnterFromUmode } KDB_ENTER_CONDITION; +typedef enum _KD_CONTINUE_TYPE +{ + kdContinue = 0, + kdDoNotHandleException, + kdHandleException +} KD_CONTINUE_TYPE; + + +/* GLOBALS *******************************************************************/ + +extern PCHAR KdbInitFileBuffer; + +extern PEPROCESS KdbCurrentProcess; +extern PETHREAD KdbCurrentThread; +extern LONG KdbLastBreakPointNr; +extern ULONG KdbNumSingleSteps; +extern BOOLEAN KdbSingleStepOver; +extern PKDB_KTRAP_FRAME KdbCurrentTrapFrame; + /* FUNCTIONS *****************************************************************/ @@ -74,8 +93,6 @@ KdbpStackSwitchAndCall( /* from kdb_cli.c */ -extern PCHAR KdbInitFileBuffer; - NTSTATUS NTAPI KdbInitialize( @@ -175,13 +192,6 @@ KdbSymInit( /* from kdb.c */ -extern PEPROCESS KdbCurrentProcess; -extern PETHREAD KdbCurrentThread; -extern LONG KdbLastBreakPointNr; -extern ULONG KdbNumSingleSteps; -extern BOOLEAN KdbSingleStepOver; -extern PKDB_KTRAP_FRAME KdbCurrentTrapFrame; - LONG KdbpGetNextBreakPointNr( IN ULONG Start OPTIONAL); diff --git a/ntoskrnl/kdbg/kdb_print.c b/ntoskrnl/kdbg/kdb_print.c index 257b37e1225..85b3ac20a6c 100644 --- a/ntoskrnl/kdbg/kdb_print.c +++ b/ntoskrnl/kdbg/kdb_print.c @@ -13,6 +13,14 @@ /* FUNCTIONS *****************************************************************/ +static KD_CONTEXT KdbgKdContext; + +#undef KdSendPacket +#define pKdSendPacket KdSendPacket + +#undef KdReceivePacket +#define pKdReceivePacket KdReceivePacket + static VOID KdbPrintStringWorker( _In_ const CSTRING* Output, @@ -48,7 +56,8 @@ KdbPrintStringWorker( Data->Buffer = (PCHAR)Output->Buffer; /* Send the packet */ - KdSendPacket(PACKET_TYPE_KD_DEBUG_IO, Header, Data, &KdpContext); + /* IO packet: call KdTerm */ + pKdSendPacket(PACKET_TYPE_KD_DEBUG_IO, Header, Data, &KdbgKdContext); } VOID @@ -88,11 +97,12 @@ KdbPromptStringWorker( do { /* Get our reply */ - Status = KdReceivePacket(PACKET_TYPE_KD_DEBUG_IO, - &Header, - &Data, - &Length, - &KdpContext); + /* IO packet: call KdTerm */ + Status = pKdReceivePacket(PACKET_TYPE_KD_DEBUG_IO, + &Header, + &Data, + &Length, + &KdbgKdContext); /* Return TRUE if we need to resend */ if (Status == KdPacketNeedsResend) diff --git a/ntoskrnl/kdbg/kdbg.c b/ntoskrnl/kdbg/kdbg.c new file mode 100644 index 00000000000..ac78f72b7e3 --- /dev/null +++ b/ntoskrnl/kdbg/kdbg.c @@ -0,0 +1,170 @@ +/* + * 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 <hpous...@reactos.org> + * Copyright 2021 Jérôme Gardou <jerome.gar...@reactos.org> + * Copyright 2023 Hermès Bélusca-Maïto <hermes.belusca-ma...@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 *****************************************************************/ + +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 */ diff --git a/ntoskrnl/ntos.cmake b/ntoskrnl/ntos.cmake index dddb6cae4ab..a85cb19e39a 100644 --- a/ntoskrnl/ntos.cmake +++ b/ntoskrnl/ntos.cmake @@ -404,6 +404,7 @@ if(NOT _WINKD_) if(KDBG) list(APPEND SOURCE + ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdbg.c ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb.c ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb_cli.c ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb_cmdhist.c