https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2046a17ef475ac8d80bfd…
commit 2046a17ef475ac8d80bfdcffc09d35712e14ec4a
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Tue Mar 21 18:42:29 2023 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)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 <hpoussin(a)reactos.org>
+ * Copyright 2021 Jérôme Gardou <jerome.gardou(a)reactos.org>
+ * Copyright 2023 Hermès Bélusca-Maïto
<hermes.belusca-maito(a)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