mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[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.)
This commit is contained in:
parent
823b51558d
commit
2046a17ef4
7 changed files with 245 additions and 152 deletions
|
@ -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
|
||||
{
|
||||
|
|
|
@ -88,13 +88,15 @@
|
|||
#define NOEXTAPI
|
||||
#include <windbgkd.h>
|
||||
#include <wdbgexts.h>
|
||||
#ifdef KDBG
|
||||
#define KdDebuggerInitialize0 KdpDebuggerInitialize0
|
||||
#define KdDebuggerInitialize1 KdpDebuggerInitialize1
|
||||
#define KdSendPacket KdpSendPacket
|
||||
#define KdReceivePacket KdpReceivePacket
|
||||
#endif
|
||||
#include <kddll.h>
|
||||
#ifdef KDBG
|
||||
/* 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
|
||||
#ifdef __ROS_ROSSYM__
|
||||
#include <reactos/rossym.h>
|
||||
#endif
|
||||
|
|
|
@ -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,15 +604,21 @@ KdSendPacket(
|
|||
_In_opt_ PSTRING MessageData,
|
||||
_Inout_ PKD_CONTEXT Context)
|
||||
{
|
||||
if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
|
||||
PDBGKD_DEBUG_IO DebugIo;
|
||||
|
||||
if (PacketType != PACKET_TYPE_KD_DEBUG_IO)
|
||||
{
|
||||
ULONG ApiNumber = ((PDBGKD_DEBUG_IO)MessageHeader->Buffer)->ApiNumber;
|
||||
KdIoPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType);
|
||||
return;
|
||||
}
|
||||
|
||||
DebugIo = (PDBGKD_DEBUG_IO)MessageHeader->Buffer;
|
||||
|
||||
/* Validate API call */
|
||||
if (MessageHeader->Length != sizeof(DBGKD_DEBUG_IO))
|
||||
return;
|
||||
if ((ApiNumber != DbgKdPrintStringApi) &&
|
||||
(ApiNumber != DbgKdGetStringApi))
|
||||
if ((DebugIo->ApiNumber != DbgKdPrintStringApi) &&
|
||||
(DebugIo->ApiNumber != DbgKdGetStringApi))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -631,69 +634,6 @@ KdSendPacket(
|
|||
|
||||
/* Print the string proper */
|
||||
KdIoPrintString(MessageData->Buffer, MessageData->Length);
|
||||
return;
|
||||
}
|
||||
else if (PacketType == PACKET_TYPE_KD_STATE_CHANGE64)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
/* IO packet: call KdTerm */
|
||||
Status = pKdReceivePacket(PACKET_TYPE_KD_DEBUG_IO,
|
||||
&Header,
|
||||
&Data,
|
||||
&Length,
|
||||
&KdpContext);
|
||||
&KdbgKdContext);
|
||||
|
||||
/* Return TRUE if we need to resend */
|
||||
if (Status == KdPacketNeedsResend)
|
||||
|
|
170
ntoskrnl/kdbg/kdbg.c
Normal file
170
ntoskrnl/kdbg/kdbg.c
Normal file
|
@ -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@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 *****************************************************************/
|
||||
|
||||
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 */
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue