mirror of
https://github.com/reactos/reactos.git
synced 2025-05-17 16:27:00 +00:00
[NTOS]
Isolate KD a bit by replacing Rtl* memory routines with internal versions. Lets one put breakpoints inside kernel memcpy/memset without making KD very, very sad. Fix MmDbgCopyMemory to also not use RtlCopyMemory -- there is no need for it since it only performs 1-to-8 byte copies anyway. Minor fixes in the print/prompt routines. svn path=/trunk/; revision=69539
This commit is contained in:
parent
017269e128
commit
8ea1ea856d
5 changed files with 147 additions and 53 deletions
|
@ -351,6 +351,24 @@ KdpCopyMemoryChunks(
|
|||
OUT PULONG ActualSize OPTIONAL
|
||||
);
|
||||
|
||||
//
|
||||
// Internal memory handling routines for KD isolation
|
||||
//
|
||||
VOID
|
||||
NTAPI
|
||||
KdpMoveMemory(
|
||||
IN PVOID Destination,
|
||||
IN PVOID Source,
|
||||
IN SIZE_T Length
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdpZeroMemory(
|
||||
IN PVOID Destination,
|
||||
IN SIZE_T Length
|
||||
);
|
||||
|
||||
//
|
||||
// Low Level Support Routines for the KD API
|
||||
//
|
||||
|
|
|
@ -15,6 +15,32 @@
|
|||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdpMoveMemory(IN PVOID Destination,
|
||||
IN PVOID Source,
|
||||
IN SIZE_T Length)
|
||||
{
|
||||
PCHAR DestinationBytes, SourceBytes;
|
||||
|
||||
/* Copy the buffers 1 byte at a time */
|
||||
DestinationBytes = Destination;
|
||||
SourceBytes = Source;
|
||||
while (Length--) *DestinationBytes++ = *SourceBytes++;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdpZeroMemory(IN PVOID Destination,
|
||||
IN SIZE_T Length)
|
||||
{
|
||||
PCHAR DestinationBytes;
|
||||
|
||||
/* Zero the buffer 1 byte at a time */
|
||||
DestinationBytes = Destination;
|
||||
while (Length--) *DestinationBytes++ = 0;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdpCopyMemoryChunks(IN ULONG64 Address,
|
||||
|
@ -368,7 +394,7 @@ KdpSetCommonState(IN ULONG NewState,
|
|||
WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
|
||||
|
||||
/* Zero out the entire Control Report */
|
||||
RtlZeroMemory(&WaitStateChange->AnyControlReport,
|
||||
KdpZeroMemory(&WaitStateChange->AnyControlReport,
|
||||
sizeof(DBGKD_ANY_CONTROL_REPORT));
|
||||
|
||||
/* Now copy the instruction stream and set the count */
|
||||
|
@ -402,7 +428,9 @@ NTAPI
|
|||
KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version)
|
||||
{
|
||||
/* Copy the version block */
|
||||
RtlCopyMemory(Version, &KdVersionBlock, sizeof(DBGKD_GET_VERSION64));
|
||||
KdpMoveMemory(Version,
|
||||
&KdVersionBlock,
|
||||
sizeof(DBGKD_GET_VERSION64));
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -711,7 +739,9 @@ KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,
|
|||
}
|
||||
|
||||
/* Copy it over to the debugger */
|
||||
RtlCopyMemory(Data->Buffer, TargetContext, sizeof(CONTEXT));
|
||||
KdpMoveMemory(Data->Buffer,
|
||||
TargetContext,
|
||||
sizeof(CONTEXT));
|
||||
Data->Length = sizeof(CONTEXT);
|
||||
|
||||
/* Let the debugger set the context now */
|
||||
|
@ -765,7 +795,9 @@ KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,
|
|||
}
|
||||
|
||||
/* Copy the new context to it */
|
||||
RtlCopyMemory(TargetContext, Data->Buffer, sizeof(CONTEXT));
|
||||
KdpMoveMemory(TargetContext,
|
||||
Data->Buffer,
|
||||
sizeof(CONTEXT));
|
||||
|
||||
/* Finish up */
|
||||
State->ReturnStatus = STATUS_SUCCESS;
|
||||
|
@ -819,7 +851,7 @@ KdpGetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,
|
|||
}
|
||||
|
||||
/* Copy what is requested */
|
||||
RtlCopyMemory(Data->Buffer,
|
||||
KdpMoveMemory(Data->Buffer,
|
||||
(PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
|
||||
ContextEx->ByteCount);
|
||||
|
||||
|
@ -883,7 +915,7 @@ KdpSetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,
|
|||
}
|
||||
|
||||
/* Copy what is requested */
|
||||
RtlCopyMemory((PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
|
||||
KdpMoveMemory((PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
|
||||
Data->Buffer,
|
||||
ContextEx->ByteCount);
|
||||
|
||||
|
@ -1639,7 +1671,7 @@ KdpReportCommandStringStateChange(IN PSTRING NameString,
|
|||
KdpSetContextState(&WaitStateChange, Context);
|
||||
|
||||
/* Clear the command string structure */
|
||||
RtlZeroMemory(&WaitStateChange.u.CommandString,
|
||||
KdpZeroMemory(&WaitStateChange.u.CommandString,
|
||||
sizeof(DBGKD_COMMAND_STRING));
|
||||
|
||||
/* Normalize name string to max */
|
||||
|
@ -1709,15 +1741,22 @@ KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
|
|||
/* Build the architecture common parts of the message */
|
||||
KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
|
||||
|
||||
/* Copy the Exception Record and set First Chance flag */
|
||||
#if !defined(_WIN64)
|
||||
|
||||
/* Convert it and copy it over */
|
||||
ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
|
||||
&WaitStateChange.u.Exception.ExceptionRecord);
|
||||
|
||||
#else
|
||||
RtlCopyMemory(&WaitStateChange.u.Exception.ExceptionRecord,
|
||||
|
||||
/* Just copy it directly, no need to convert */
|
||||
KdpMoveMemory(&WaitStateChange.u.Exception.ExceptionRecord,
|
||||
ExceptionRecord,
|
||||
sizeof(EXCEPTION_RECORD));
|
||||
|
||||
#endif
|
||||
|
||||
/* Set the First Chance flag */
|
||||
WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
|
||||
|
||||
/* Now finish creating the structure */
|
||||
|
|
|
@ -21,12 +21,15 @@ KdpPrintString(IN PSTRING Output)
|
|||
{
|
||||
STRING Data, Header;
|
||||
DBGKD_DEBUG_IO DebugIo;
|
||||
USHORT Length = Output->Length;
|
||||
USHORT Length;
|
||||
|
||||
/* Copy the string */
|
||||
RtlMoveMemory(KdpMessageBuffer, Output->Buffer, Length);
|
||||
KdpMoveMemory(KdpMessageBuffer,
|
||||
Output->Buffer,
|
||||
Output->Length);
|
||||
|
||||
/* Make sure we don't exceed the KD Packet size */
|
||||
Length = Output->Length;
|
||||
if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE)
|
||||
{
|
||||
/* Normalize length */
|
||||
|
@ -59,15 +62,16 @@ KdpPromptString(IN PSTRING PromptString,
|
|||
{
|
||||
STRING Data, Header;
|
||||
DBGKD_DEBUG_IO DebugIo;
|
||||
ULONG Length = PromptString->Length;
|
||||
ULONG Length;
|
||||
KDSTATUS Status;
|
||||
|
||||
/* Copy the string to the message buffer */
|
||||
RtlCopyMemory(KdpMessageBuffer,
|
||||
KdpMoveMemory(KdpMessageBuffer,
|
||||
PromptString->Buffer,
|
||||
PromptString->Length);
|
||||
|
||||
/* Make sure we don't exceed the KD Packet size */
|
||||
Length = PromptString->Length;
|
||||
if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE)
|
||||
{
|
||||
/* Normalize length */
|
||||
|
@ -84,7 +88,7 @@ KdpPromptString(IN PSTRING PromptString,
|
|||
Header.Buffer = (PCHAR)&DebugIo;
|
||||
|
||||
/* Build the data */
|
||||
Data.Length = PromptString->Length;
|
||||
Data.Length = Length;
|
||||
Data.Buffer = KdpMessageBuffer;
|
||||
|
||||
/* Send the packet */
|
||||
|
@ -111,10 +115,13 @@ KdpPromptString(IN PSTRING PromptString,
|
|||
} while (Status != KdPacketReceived);
|
||||
|
||||
/* Don't copy back a larger response than there is room for */
|
||||
Length = min(Length, ResponseString->MaximumLength);
|
||||
Length = min(Length,
|
||||
ResponseString->MaximumLength);
|
||||
|
||||
/* Copy back the string and return the length */
|
||||
RtlCopyMemory(ResponseString->Buffer, KdpMessageBuffer, Length);
|
||||
KdpMoveMemory(ResponseString->Buffer,
|
||||
KdpMessageBuffer,
|
||||
Length);
|
||||
ResponseString->Length = (USHORT)Length;
|
||||
|
||||
/* Success; we don't need to resend */
|
||||
|
@ -141,7 +148,7 @@ KdpCommandString(IN PSTRING NameString,
|
|||
|
||||
/* Save the CPU Control State and save the context */
|
||||
KiSaveProcessorControlState(&Prcb->ProcessorState);
|
||||
RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
|
||||
KdpMoveMemory(&Prcb->ProcessorState.ContextFrame,
|
||||
ContextRecord,
|
||||
sizeof(CONTEXT));
|
||||
|
||||
|
@ -151,7 +158,7 @@ KdpCommandString(IN PSTRING NameString,
|
|||
&Prcb->ProcessorState.ContextFrame);
|
||||
|
||||
/* Restore the processor state */
|
||||
RtlCopyMemory(ContextRecord,
|
||||
KdpMoveMemory(ContextRecord,
|
||||
&Prcb->ProcessorState.ContextFrame,
|
||||
sizeof(CONTEXT));
|
||||
KiRestoreProcessorControlState(&Prcb->ProcessorState);
|
||||
|
@ -181,7 +188,7 @@ KdpSymbol(IN PSTRING DllPath,
|
|||
|
||||
/* Save the CPU Control State and save the context */
|
||||
KiSaveProcessorControlState(&Prcb->ProcessorState);
|
||||
RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
|
||||
KdpMoveMemory(&Prcb->ProcessorState.ContextFrame,
|
||||
ContextRecord,
|
||||
sizeof(CONTEXT));
|
||||
|
||||
|
@ -192,7 +199,7 @@ KdpSymbol(IN PSTRING DllPath,
|
|||
&Prcb->ProcessorState.ContextFrame);
|
||||
|
||||
/* Restore the processor state */
|
||||
RtlCopyMemory(ContextRecord,
|
||||
KdpMoveMemory(ContextRecord,
|
||||
&Prcb->ProcessorState.ContextFrame,
|
||||
sizeof(CONTEXT));
|
||||
KiRestoreProcessorControlState(&Prcb->ProcessorState);
|
||||
|
@ -216,38 +223,48 @@ KdpPrompt(IN LPSTR PromptString,
|
|||
PVOID CapturedPrompt, CapturedResponse;
|
||||
|
||||
/* Normalize the lengths */
|
||||
PromptLength = min(PromptLength, 512);
|
||||
MaximumResponseLength = min(MaximumResponseLength, 512);
|
||||
PromptLength = min(PromptLength,
|
||||
512);
|
||||
MaximumResponseLength = min(MaximumResponseLength,
|
||||
512);
|
||||
|
||||
/* Check if we need to verify the string */
|
||||
if (PreviousMode != KernelMode)
|
||||
{
|
||||
/* Capture user-mode buffers */
|
||||
/* Handle user-mode buffers safely */
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForRead(PromptString, PromptLength, 1);
|
||||
CapturedPrompt = alloca(512);
|
||||
RtlMoveMemory(CapturedPrompt, PromptString, PromptLength);
|
||||
/* Probe the prompt */
|
||||
ProbeForRead(PromptString,
|
||||
PromptLength,
|
||||
1);
|
||||
|
||||
/* Capture prompt */
|
||||
CapturedPrompt = _alloca(PromptLength);
|
||||
KdpMoveMemory(CapturedPrompt,
|
||||
PromptString,
|
||||
PromptLength);
|
||||
PromptString = CapturedPrompt;
|
||||
|
||||
ProbeForWrite(ResponseString, MaximumResponseLength, 1);
|
||||
CapturedResponse = alloca(512);
|
||||
/* Probe and make room for response */
|
||||
ProbeForWrite(ResponseString,
|
||||
MaximumResponseLength,
|
||||
1);
|
||||
CapturedResponse = _alloca(MaximumResponseLength);
|
||||
ResponseString = CapturedResponse;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Bad string pointer, bail out */
|
||||
_SEH2_YIELD(return 0);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
CapturedResponse = ResponseString;
|
||||
}
|
||||
|
||||
/* Setup the prompt and response buffers */
|
||||
PromptBuffer.Buffer = PromptString;
|
||||
PromptBuffer.Length = PromptLength;
|
||||
ResponseBuffer.Buffer = CapturedResponse;
|
||||
ResponseBuffer.Buffer = ResponseString;
|
||||
ResponseBuffer.Length = 0;
|
||||
ResponseBuffer.MaximumLength = MaximumResponseLength;
|
||||
|
||||
|
@ -274,10 +291,14 @@ KdpPrompt(IN LPSTR PromptString,
|
|||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
RtlMoveMemory(ResponseString, ResponseBuffer.Buffer, ResponseBuffer.Length);
|
||||
/* Safely copy back response to user mode */
|
||||
KdpMoveMemory(ResponseString,
|
||||
ResponseBuffer.Buffer,
|
||||
ResponseBuffer.Length);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* String became invalid after we exited, fail */
|
||||
_SEH2_YIELD(return 0);
|
||||
}
|
||||
_SEH2_END;
|
||||
|
@ -326,13 +347,21 @@ KdpPrint(IN ULONG ComponentId,
|
|||
/* Capture user-mode buffers */
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForRead(String, Length, 1);
|
||||
CapturedString = alloca(512);
|
||||
RtlMoveMemory(CapturedString, String, Length);
|
||||
/* Probe the string */
|
||||
ProbeForRead(String,
|
||||
Length,
|
||||
1);
|
||||
|
||||
/* Capture it */
|
||||
CapturedString = alloca(Length);
|
||||
KdpMoveMemory(CapturedString,
|
||||
String,
|
||||
Length);
|
||||
String = CapturedString;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Bad pointer, fail the print */
|
||||
_SEH2_YIELD(return STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
_SEH2_END;
|
||||
|
|
|
@ -58,13 +58,14 @@ KdpReport(IN PKTRAP_FRAME TrapFrame,
|
|||
{
|
||||
BOOLEAN Enable, Handled;
|
||||
PKPRCB Prcb;
|
||||
NTSTATUS ExceptionCode = ExceptionRecord->ExceptionCode;
|
||||
NTSTATUS ExceptionCode;
|
||||
|
||||
/*
|
||||
* Determine whether to pass the exception to the debugger.
|
||||
* First, check if this is a "debug exception", meaning breakpoint
|
||||
* (including debug service), single step and assertion failure exceptions.
|
||||
*/
|
||||
ExceptionCode = ExceptionRecord->ExceptionCode;
|
||||
if ((ExceptionCode == STATUS_BREAKPOINT) ||
|
||||
(ExceptionCode == STATUS_SINGLE_STEP) ||
|
||||
(ExceptionCode == STATUS_ASSERTION_FAILURE))
|
||||
|
@ -92,8 +93,8 @@ KdpReport(IN PKTRAP_FRAME TrapFrame,
|
|||
else if (SecondChanceException == FALSE)
|
||||
{
|
||||
/*
|
||||
* This isn't a debug exception and the stop-on-exception flag isn't
|
||||
* set, so don't bother
|
||||
* This isn't a debug exception and the stop-on-exception flag isn't set,
|
||||
* so don't bother handling it
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -107,7 +108,7 @@ KdpReport(IN PKTRAP_FRAME TrapFrame,
|
|||
*/
|
||||
Prcb = KeGetCurrentPrcb();
|
||||
KiSaveProcessorControlState(&Prcb->ProcessorState);
|
||||
RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
|
||||
KdpMoveMemory(&Prcb->ProcessorState.ContextFrame,
|
||||
ContextRecord,
|
||||
sizeof(CONTEXT));
|
||||
|
||||
|
@ -118,7 +119,7 @@ KdpReport(IN PKTRAP_FRAME TrapFrame,
|
|||
SecondChanceException);
|
||||
|
||||
/* Now restore the processor state, manually again. */
|
||||
RtlCopyMemory(ContextRecord,
|
||||
KdpMoveMemory(ContextRecord,
|
||||
&Prcb->ProcessorState.ContextFrame,
|
||||
sizeof(CONTEXT));
|
||||
KiRestoreProcessorControlState(&Prcb->ProcessorState);
|
||||
|
@ -138,7 +139,7 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame,
|
|||
IN KPROCESSOR_MODE PreviousMode,
|
||||
IN BOOLEAN SecondChanceException)
|
||||
{
|
||||
BOOLEAN Unload = FALSE;
|
||||
BOOLEAN Unload;
|
||||
ULONG_PTR ProgramCounter;
|
||||
BOOLEAN Handled;
|
||||
NTSTATUS ReturnStatus;
|
||||
|
@ -156,6 +157,7 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame,
|
|||
ProgramCounter = KeGetContextPc(ContextRecord);
|
||||
|
||||
/* Check what kind of operation was requested from us */
|
||||
Unload = FALSE;
|
||||
switch (ExceptionRecord->ExceptionInformation[0])
|
||||
{
|
||||
/* DbgPrint */
|
||||
|
@ -164,27 +166,24 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame,
|
|||
/* Call the worker routine */
|
||||
ReturnStatus = KdpPrint((ULONG)KdpGetParameterThree(ContextRecord),
|
||||
(ULONG)KdpGetParameterFour(ContextRecord),
|
||||
(LPSTR)ExceptionRecord->
|
||||
ExceptionInformation[1],
|
||||
(USHORT)ExceptionRecord->
|
||||
ExceptionInformation[2],
|
||||
(LPSTR)ExceptionRecord->ExceptionInformation[1],
|
||||
(USHORT)ExceptionRecord->ExceptionInformation[2],
|
||||
PreviousMode,
|
||||
TrapFrame,
|
||||
ExceptionFrame,
|
||||
&Handled);
|
||||
|
||||
/* Update the return value for the caller */
|
||||
KeSetContextReturnRegister(ContextRecord, ReturnStatus);
|
||||
KeSetContextReturnRegister(ContextRecord,
|
||||
ReturnStatus);
|
||||
break;
|
||||
|
||||
/* DbgPrompt */
|
||||
case BREAKPOINT_PROMPT:
|
||||
|
||||
/* Call the worker routine */
|
||||
ReturnLength = KdpPrompt((LPSTR)ExceptionRecord->
|
||||
ExceptionInformation[1],
|
||||
(USHORT)ExceptionRecord->
|
||||
ExceptionInformation[2],
|
||||
ReturnLength = KdpPrompt((LPSTR)ExceptionRecord->ExceptionInformation[1],
|
||||
(USHORT)ExceptionRecord->ExceptionInformation[2],
|
||||
(LPSTR)KdpGetParameterThree(ContextRecord),
|
||||
(USHORT)KdpGetParameterFour(ContextRecord),
|
||||
PreviousMode,
|
||||
|
@ -276,9 +275,10 @@ KdpStub(IN PKTRAP_FRAME TrapFrame,
|
|||
IN KPROCESSOR_MODE PreviousMode,
|
||||
IN BOOLEAN SecondChanceException)
|
||||
{
|
||||
ULONG_PTR ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
|
||||
ULONG_PTR ExceptionCommand;
|
||||
|
||||
/* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
|
||||
ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
|
||||
if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
|
||||
(ExceptionRecord->NumberParameters > 0) &&
|
||||
((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
|
||||
|
|
|
@ -44,6 +44,14 @@ MiInitializeSessionWsSupport(VOID)
|
|||
InitializeListHead(&MmWorkingSetExpansionHead);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
MmIsSessionAddress(IN PVOID Address)
|
||||
{
|
||||
/* Check if it is in range */
|
||||
return MI_IS_SESSION_ADDRESS(Address) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
LCID
|
||||
NTAPI
|
||||
MmGetSessionLocaleId(VOID)
|
||||
|
|
Loading…
Reference in a new issue