mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 09:52:56 +00:00
[NTOSKRNL]
- Implement saving / restoring debug registers on traps - Replace the loop in KeContextToTrapFrame with something less ridiculous - fixes a number of ntdd exception winetests svn path=/trunk/; revision=56357
This commit is contained in:
parent
ebccbcb163
commit
038a2fbb39
5 changed files with 191 additions and 120 deletions
|
@ -539,28 +539,6 @@ Ke386SanitizeFlags(IN ULONG Eflags,
|
||||||
(EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
|
(EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Gets a DR register from a CONTEXT structure
|
|
||||||
//
|
|
||||||
FORCEINLINE
|
|
||||||
PVOID
|
|
||||||
KiDrFromContext(IN ULONG Dr,
|
|
||||||
IN PCONTEXT Context)
|
|
||||||
{
|
|
||||||
return *(PVOID*)((ULONG_PTR)Context + KiDebugRegisterContextOffsets[Dr]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Gets a DR register from a KTRAP_FRAME structure
|
|
||||||
//
|
|
||||||
FORCEINLINE
|
|
||||||
PVOID*
|
|
||||||
KiDrFromTrapFrame(IN ULONG Dr,
|
|
||||||
IN PKTRAP_FRAME TrapFrame)
|
|
||||||
{
|
|
||||||
return (PVOID*)((ULONG_PTR)TrapFrame + KiDebugRegisterTrapOffsets[Dr]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanitizes a Debug Register
|
// Sanitizes a Debug Register
|
||||||
//
|
//
|
||||||
|
|
|
@ -95,18 +95,37 @@ KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame)
|
||||||
TrapFrame->PreviousPreviousMode = -1;
|
TrapFrame->PreviousPreviousMode = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DR7_RESERVED_READ_AS_1 0x400
|
||||||
|
|
||||||
|
#define CheckDr(DrNumner, ExpectedValue) \
|
||||||
|
{ \
|
||||||
|
ULONG DrValue = __readdr(DrNumner); \
|
||||||
|
if (DrValue != (ExpectedValue)) \
|
||||||
|
{ \
|
||||||
|
DbgPrint("Dr%ld: expected %.8lx, got %.8lx\n", \
|
||||||
|
DrNumner, ExpectedValue, DrValue); \
|
||||||
|
__debugbreak(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
extern BOOLEAN StopChecking;
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
|
KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
|
||||||
IN BOOLEAN SkipPreviousMode)
|
IN BOOLEAN SkipPreviousMode)
|
||||||
{
|
{
|
||||||
|
/* Don't check recursively */
|
||||||
|
if (StopChecking) return;
|
||||||
|
StopChecking = TRUE;
|
||||||
|
|
||||||
/* Make sure interrupts are disabled */
|
/* Make sure interrupts are disabled */
|
||||||
if (__readeflags() & EFLAGS_INTERRUPT_MASK)
|
if (__readeflags() & EFLAGS_INTERRUPT_MASK)
|
||||||
{
|
{
|
||||||
DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
|
DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure this is a real trap frame */
|
/* Make sure this is a real trap frame */
|
||||||
if (TrapFrame->DbgArgMark != 0xBADB0D00)
|
if (TrapFrame->DbgArgMark != 0xBADB0D00)
|
||||||
{
|
{
|
||||||
|
@ -114,34 +133,61 @@ KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
|
||||||
KiDumpTrapFrame(TrapFrame);
|
KiDumpTrapFrame(TrapFrame);
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we're not in user-mode or something */
|
/* Make sure we're not in user-mode or something */
|
||||||
if (Ke386GetFs() != KGDT_R0_PCR)
|
if (Ke386GetFs() != KGDT_R0_PCR)
|
||||||
{
|
{
|
||||||
DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
|
DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we have a valid SEH chain */
|
/* Make sure we have a valid SEH chain */
|
||||||
if (KeGetPcr()->NtTib.ExceptionList == 0)
|
if (KeGetPcr()->NtTib.ExceptionList == 0)
|
||||||
{
|
{
|
||||||
DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib.ExceptionList);
|
DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib.ExceptionList);
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we're restoring a valid SEH chain */
|
/* Make sure we're restoring a valid SEH chain */
|
||||||
if (TrapFrame->ExceptionList == 0)
|
if (TrapFrame->ExceptionList == 0)
|
||||||
{
|
{
|
||||||
DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame->ExceptionList);
|
DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame->ExceptionList);
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're ignoring previous mode, make sure caller doesn't actually want it */
|
/* If we're ignoring previous mode, make sure caller doesn't actually want it */
|
||||||
if (SkipPreviousMode && (TrapFrame->PreviousPreviousMode != -1))
|
if (SkipPreviousMode && (TrapFrame->PreviousPreviousMode != -1))
|
||||||
{
|
{
|
||||||
DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame->PreviousPreviousMode);
|
DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame->PreviousPreviousMode);
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check DR values */
|
||||||
|
if (TrapFrame->SegCs & MODE_MASK)
|
||||||
|
{
|
||||||
|
/* Check for active debugging */
|
||||||
|
if (KeGetCurrentThread()->Header.DebugActive)
|
||||||
|
{
|
||||||
|
if ((TrapFrame->Dr7 & ~DR7_RESERVED_MASK) == 0) __debugbreak();
|
||||||
|
|
||||||
|
CheckDr(0, TrapFrame->Dr0);
|
||||||
|
CheckDr(1, TrapFrame->Dr1);
|
||||||
|
CheckDr(2, TrapFrame->Dr2);
|
||||||
|
CheckDr(3, TrapFrame->Dr3);
|
||||||
|
CheckDr(7, TrapFrame->Dr7 | DR7_RESERVED_READ_AS_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||||
|
CheckDr(0, Prcb->ProcessorState.SpecialRegisters.KernelDr0);
|
||||||
|
CheckDr(1, Prcb->ProcessorState.SpecialRegisters.KernelDr1);
|
||||||
|
CheckDr(2, Prcb->ProcessorState.SpecialRegisters.KernelDr2);
|
||||||
|
CheckDr(3, Prcb->ProcessorState.SpecialRegisters.KernelDr3);
|
||||||
|
//CheckDr(7, Prcb->ProcessorState.SpecialRegisters.KernelDr7);
|
||||||
|
}
|
||||||
|
|
||||||
|
StopChecking = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -150,7 +196,7 @@ KiExitSystemCallDebugChecks(IN ULONG SystemCall,
|
||||||
IN PKTRAP_FRAME TrapFrame)
|
IN PKTRAP_FRAME TrapFrame)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
/* Check if this was a user call */
|
/* Check if this was a user call */
|
||||||
if (KiUserTrap(TrapFrame))
|
if (KiUserTrap(TrapFrame))
|
||||||
{
|
{
|
||||||
|
@ -161,7 +207,7 @@ KiExitSystemCallDebugChecks(IN ULONG SystemCall,
|
||||||
/* Forcibly put us in a sane state */
|
/* Forcibly put us in a sane state */
|
||||||
KeGetPcr()->Irql = PASSIVE_LEVEL;
|
KeGetPcr()->Irql = PASSIVE_LEVEL;
|
||||||
_disable();
|
_disable();
|
||||||
|
|
||||||
/* Fail */
|
/* Fail */
|
||||||
KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
|
KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
|
||||||
SystemCall,
|
SystemCall,
|
||||||
|
@ -208,6 +254,53 @@ VOID
|
||||||
|
|
||||||
extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
|
extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save user mode debug registers and restore kernel values
|
||||||
|
//
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
KiHandleDebugRegistersOnTrapEntry(
|
||||||
|
IN PKTRAP_FRAME TrapFrame)
|
||||||
|
{
|
||||||
|
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||||
|
|
||||||
|
/* Save all debug registers in the trap frame */
|
||||||
|
TrapFrame->Dr0 = __readdr(0);
|
||||||
|
TrapFrame->Dr1 = __readdr(1);
|
||||||
|
TrapFrame->Dr2 = __readdr(2);
|
||||||
|
TrapFrame->Dr3 = __readdr(3);
|
||||||
|
TrapFrame->Dr6 = __readdr(6);
|
||||||
|
TrapFrame->Dr7 = __readdr(7);
|
||||||
|
|
||||||
|
/* Disable all active debugging */
|
||||||
|
__writedr(7, 0);
|
||||||
|
|
||||||
|
/* Restore kernel values */
|
||||||
|
__writedr(0, Prcb->ProcessorState.SpecialRegisters.KernelDr0);
|
||||||
|
__writedr(1, Prcb->ProcessorState.SpecialRegisters.KernelDr1);
|
||||||
|
__writedr(2, Prcb->ProcessorState.SpecialRegisters.KernelDr2);
|
||||||
|
__writedr(3, Prcb->ProcessorState.SpecialRegisters.KernelDr3);
|
||||||
|
__writedr(6, Prcb->ProcessorState.SpecialRegisters.KernelDr6);
|
||||||
|
__writedr(7, Prcb->ProcessorState.SpecialRegisters.KernelDr7);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
KiHandleDebugRegistersOnTrapExit(
|
||||||
|
PKTRAP_FRAME TrapFrame)
|
||||||
|
{
|
||||||
|
/* Disable all active debugging */
|
||||||
|
__writedr(7, 0);
|
||||||
|
|
||||||
|
/* Load all debug registers from the trap frame */
|
||||||
|
__writedr(0, TrapFrame->Dr0);
|
||||||
|
__writedr(1, TrapFrame->Dr1);
|
||||||
|
__writedr(2, TrapFrame->Dr2);
|
||||||
|
__writedr(3, TrapFrame->Dr3);
|
||||||
|
__writedr(6, TrapFrame->Dr6);
|
||||||
|
__writedr(7, TrapFrame->Dr7);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Virtual 8086 Mode Optimized Trap Exit
|
// Virtual 8086 Mode Optimized Trap Exit
|
||||||
//
|
//
|
||||||
|
@ -218,7 +311,7 @@ KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
|
||||||
{
|
{
|
||||||
PKTHREAD Thread;
|
PKTHREAD Thread;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
/* Get the thread */
|
/* Get the thread */
|
||||||
Thread = KeGetCurrentThread();
|
Thread = KeGetCurrentThread();
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
|
@ -243,15 +336,14 @@ KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
|
||||||
KfLowerIrql(OldIrql);
|
KfLowerIrql(OldIrql);
|
||||||
_disable();
|
_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we got here, we're still in a valid V8086 context, so quit it */
|
/* If we got here, we're still in a valid V8086 context, so quit it */
|
||||||
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
|
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
|
||||||
{
|
{
|
||||||
/* Not handled yet */
|
/* Restore debug registers from the trap frame */
|
||||||
DbgPrint("Need Hardware Breakpoint Support!\n");
|
KiHandleDebugRegistersOnTrapExit(TrapFrame);
|
||||||
while (TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return from interrupt */
|
/* Return from interrupt */
|
||||||
KiTrapReturnNoSegments(TrapFrame);
|
KiTrapReturnNoSegments(TrapFrame);
|
||||||
}
|
}
|
||||||
|
@ -270,8 +362,8 @@ KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame)
|
||||||
TrapFrame->Dr7 = __readdr(7);
|
TrapFrame->Dr7 = __readdr(7);
|
||||||
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
|
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
|
||||||
{
|
{
|
||||||
DbgPrint("Need Hardware Breakpoint Support!\n");
|
/* Handle debug registers */
|
||||||
while (TRUE);
|
KiHandleDebugRegistersOnTrapEntry(TrapFrame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,14 +378,21 @@ KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
|
||||||
TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
|
TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
|
||||||
KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
|
KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
|
||||||
|
|
||||||
/* Flush DR7 and check for debugging */
|
/* Default to debugging disabled */
|
||||||
TrapFrame->Dr7 = 0;
|
TrapFrame->Dr7 = 0;
|
||||||
if (__builtin_expect(KeGetCurrentThread()->Header.DebugActive & 0xFF, 0))
|
|
||||||
|
/* Check if the frame was from user mode or v86 mode */
|
||||||
|
if ((TrapFrame->SegCs & MODE_MASK) ||
|
||||||
|
(TrapFrame->EFlags & EFLAGS_V86_MASK))
|
||||||
{
|
{
|
||||||
DbgPrint("Need Hardware Breakpoint Support!\n");
|
/* Check for active debugging */
|
||||||
while (TRUE);
|
if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
|
||||||
|
{
|
||||||
|
/* Handle debug registers */
|
||||||
|
KiHandleDebugRegistersOnTrapEntry(TrapFrame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set debug header */
|
/* Set debug header */
|
||||||
KiFillTrapFrameDebug(TrapFrame);
|
KiFillTrapFrameDebug(TrapFrame);
|
||||||
}
|
}
|
||||||
|
@ -307,15 +406,22 @@ KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
|
||||||
{
|
{
|
||||||
/* Save exception list */
|
/* Save exception list */
|
||||||
TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
|
TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
|
||||||
|
|
||||||
/* Flush DR7 and check for debugging */
|
/* Default to debugging disabled */
|
||||||
TrapFrame->Dr7 = 0;
|
TrapFrame->Dr7 = 0;
|
||||||
if (__builtin_expect(KeGetCurrentThread()->Header.DebugActive & 0xFF, 0))
|
|
||||||
|
/* Check if the frame was from user mode or v86 mode */
|
||||||
|
if ((TrapFrame->SegCs & MODE_MASK) ||
|
||||||
|
(TrapFrame->EFlags & EFLAGS_V86_MASK))
|
||||||
{
|
{
|
||||||
DbgPrint("Need Hardware Breakpoint Support!\n");
|
/* Check for active debugging */
|
||||||
while (TRUE);
|
if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
|
||||||
|
{
|
||||||
|
/* Handle debug registers */
|
||||||
|
KiHandleDebugRegistersOnTrapEntry(TrapFrame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set debug header */
|
/* Set debug header */
|
||||||
KiFillTrapFrameDebug(TrapFrame);
|
KiFillTrapFrameDebug(TrapFrame);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,35 +14,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
|
||||||
|
|
||||||
/* DR Registers in the CONTEXT structure */
|
|
||||||
UCHAR KiDebugRegisterContextOffsets[9] =
|
|
||||||
{
|
|
||||||
FIELD_OFFSET(CONTEXT, Dr0),
|
|
||||||
FIELD_OFFSET(CONTEXT, Dr1),
|
|
||||||
FIELD_OFFSET(CONTEXT, Dr2),
|
|
||||||
FIELD_OFFSET(CONTEXT, Dr3),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
FIELD_OFFSET(CONTEXT, Dr6),
|
|
||||||
FIELD_OFFSET(CONTEXT, Dr7),
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* DR Registers in the KTRAP_FRAME structure */
|
|
||||||
UCHAR KiDebugRegisterTrapOffsets[9] =
|
|
||||||
{
|
|
||||||
FIELD_OFFSET(KTRAP_FRAME, Dr0),
|
|
||||||
FIELD_OFFSET(KTRAP_FRAME, Dr1),
|
|
||||||
FIELD_OFFSET(KTRAP_FRAME, Dr2),
|
|
||||||
FIELD_OFFSET(KTRAP_FRAME, Dr3),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
FIELD_OFFSET(KTRAP_FRAME, Dr6),
|
|
||||||
FIELD_OFFSET(KTRAP_FRAME, Dr7),
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
@ -153,8 +124,7 @@ KiRecordDr7(OUT PULONG Dr7Ptr,
|
||||||
if (Mask != NewMask)
|
if (Mask != NewMask)
|
||||||
{
|
{
|
||||||
/* Update it */
|
/* Update it */
|
||||||
KeGetCurrentThread()->Header.DebugActive =
|
KeGetCurrentThread()->Header.DebugActive = (UCHAR)NewMask;
|
||||||
(BOOLEAN)NewMask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,11 +282,11 @@ Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame)
|
||||||
PKTHREAD Thread;
|
PKTHREAD Thread;
|
||||||
ULONG_PTR Stack;
|
ULONG_PTR Stack;
|
||||||
ULONG EFlags;
|
ULONG EFlags;
|
||||||
|
|
||||||
/* Get the current thread's stack */
|
/* Get the current thread's stack */
|
||||||
Thread = KeGetCurrentThread();
|
Thread = KeGetCurrentThread();
|
||||||
Stack = (ULONG_PTR)Thread->InitialStack;
|
Stack = (ULONG_PTR)Thread->InitialStack;
|
||||||
|
|
||||||
/* Check if we are in V8086 mode */
|
/* Check if we are in V8086 mode */
|
||||||
if (!(TrapFrame->EFlags & EFLAGS_V86_MASK))
|
if (!(TrapFrame->EFlags & EFLAGS_V86_MASK))
|
||||||
{
|
{
|
||||||
|
@ -324,17 +294,17 @@ Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame)
|
||||||
Stack -= (FIELD_OFFSET(KTRAP_FRAME, V86Gs) -
|
Stack -= (FIELD_OFFSET(KTRAP_FRAME, V86Gs) -
|
||||||
FIELD_OFFSET(KTRAP_FRAME, HardwareSegSs));
|
FIELD_OFFSET(KTRAP_FRAME, HardwareSegSs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bias the stack for the FPU area */
|
/* Bias the stack for the FPU area */
|
||||||
Stack -= sizeof(FX_SAVE_AREA);
|
Stack -= sizeof(FX_SAVE_AREA);
|
||||||
|
|
||||||
/* Disable interrupts */
|
/* Disable interrupts */
|
||||||
EFlags = __readeflags();
|
EFlags = __readeflags();
|
||||||
_disable();
|
_disable();
|
||||||
|
|
||||||
/* Set new ESP0 value in the TSS */
|
/* Set new ESP0 value in the TSS */
|
||||||
KeGetPcr()->TSS->Esp0 = Stack;
|
KeGetPcr()->TSS->Esp0 = Stack;
|
||||||
|
|
||||||
/* Restore old interrupt state */
|
/* Restore old interrupt state */
|
||||||
__writeeflags(EFlags);
|
__writeeflags(EFlags);
|
||||||
}
|
}
|
||||||
|
@ -352,7 +322,6 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
||||||
BOOLEAN V86Switch = FALSE;
|
BOOLEAN V86Switch = FALSE;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
ULONG DrMask = 0;
|
ULONG DrMask = 0;
|
||||||
PVOID SafeDr;
|
|
||||||
|
|
||||||
/* Do this at APC_LEVEL */
|
/* Do this at APC_LEVEL */
|
||||||
OldIrql = KeGetCurrentIrql();
|
OldIrql = KeGetCurrentIrql();
|
||||||
|
@ -584,26 +553,35 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle the Debug Registers */
|
/* Handle the Debug Registers */
|
||||||
if (0 && (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
|
if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
|
||||||
{
|
{
|
||||||
/* Loop DR registers */
|
/* Copy Dr0 - Dr4 */
|
||||||
for (i = 0; i < 4; i++)
|
TrapFrame->Dr0 = Context->Dr0;
|
||||||
|
TrapFrame->Dr1 = Context->Dr1;
|
||||||
|
TrapFrame->Dr2 = Context->Dr2;
|
||||||
|
TrapFrame->Dr3 = Context->Dr3;
|
||||||
|
|
||||||
|
/* If we're in user-mode */
|
||||||
|
if (PreviousMode != KernelMode)
|
||||||
{
|
{
|
||||||
/* Sanitize the context DR Address */
|
/* Make sure, no Dr address is above user space */
|
||||||
SafeDr = Ke386SanitizeDr(KiDrFromContext(i, Context), PreviousMode);
|
if (Context->Dr0 > (ULONG)MmHighestUserAddress) TrapFrame->Dr0 = 0;
|
||||||
|
if (Context->Dr1 > (ULONG)MmHighestUserAddress) TrapFrame->Dr1 = 0;
|
||||||
/* Save it in the trap frame */
|
if (Context->Dr2 > (ULONG)MmHighestUserAddress) TrapFrame->Dr2 = 0;
|
||||||
*KiDrFromTrapFrame(i, TrapFrame) = SafeDr;
|
if (Context->Dr3 > (ULONG)MmHighestUserAddress) TrapFrame->Dr3 = 0;
|
||||||
|
|
||||||
/* Check if this DR address is active and add it in the DR mask */
|
|
||||||
if (SafeDr) DrMask |= DR_MASK(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now save and sanitize DR6 */
|
/* Now sanitize and save DR6 */
|
||||||
TrapFrame->Dr6 = Context->Dr6 & DR6_LEGAL;
|
TrapFrame->Dr6 = Context->Dr6 & DR6_LEGAL;
|
||||||
|
|
||||||
|
/* Update the Dr active mask */
|
||||||
|
if (TrapFrame->Dr0) DrMask |= DR_MASK(0);
|
||||||
|
if (TrapFrame->Dr1) DrMask |= DR_MASK(1);
|
||||||
|
if (TrapFrame->Dr2) DrMask |= DR_MASK(2);
|
||||||
|
if (TrapFrame->Dr3) DrMask |= DR_MASK(3);
|
||||||
if (TrapFrame->Dr6) DrMask |= DR_MASK(6);
|
if (TrapFrame->Dr6) DrMask |= DR_MASK(6);
|
||||||
|
|
||||||
/* Save and sanitize DR7 */
|
/* Sanitize and save DR7 */
|
||||||
TrapFrame->Dr7 = Context->Dr7 & DR7_LEGAL;
|
TrapFrame->Dr7 = Context->Dr7 & DR7_LEGAL;
|
||||||
KiRecordDr7(&TrapFrame->Dr7, &DrMask);
|
KiRecordDr7(&TrapFrame->Dr7, &DrMask);
|
||||||
|
|
||||||
|
@ -611,7 +589,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
||||||
if (PreviousMode != KernelMode)
|
if (PreviousMode != KernelMode)
|
||||||
{
|
{
|
||||||
/* Save the mask */
|
/* Save the mask */
|
||||||
KeGetCurrentThread()->Header.DebugActive = (DrMask != 0);
|
KeGetCurrentThread()->Header.DebugActive = (UCHAR)DrMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -962,7 +940,7 @@ KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
/* User mode exception, was it first-chance? */
|
/* User mode exception, was it first-chance? */
|
||||||
if (FirstChance)
|
if (FirstChance)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Break into the kernel debugger unless a user mode debugger
|
* Break into the kernel debugger unless a user mode debugger
|
||||||
* is present or user mode exceptions are ignored, except if this
|
* is present or user mode exceptions are ignored, except if this
|
||||||
* is a debug service which we must always pass to KD
|
* is a debug service which we must always pass to KD
|
||||||
|
@ -1132,7 +1110,7 @@ KiDispatchExceptionFromTrapFrame(IN NTSTATUS Code,
|
||||||
ExceptionRecord.ExceptionInformation[1] = Parameter2;
|
ExceptionRecord.ExceptionInformation[1] = Parameter2;
|
||||||
ExceptionRecord.ExceptionInformation[2] = Parameter3;
|
ExceptionRecord.ExceptionInformation[2] = Parameter3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now go dispatch the exception */
|
/* Now go dispatch the exception */
|
||||||
KiDispatchException(&ExceptionRecord,
|
KiDispatchException(&ExceptionRecord,
|
||||||
NULL,
|
NULL,
|
||||||
|
|
|
@ -50,6 +50,9 @@ PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
|
||||||
PKDBG_PRESERVICEHOOK KeWin32PreServiceHook = NULL;
|
PKDBG_PRESERVICEHOOK KeWin32PreServiceHook = NULL;
|
||||||
PKDBG_POSTSERVICEHOOK KeWin32PostServiceHook = NULL;
|
PKDBG_POSTSERVICEHOOK KeWin32PostServiceHook = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
#if TRAP_DEBUG
|
||||||
|
BOOLEAN StopChecking = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* TRAP EXIT CODE *************************************************************/
|
/* TRAP EXIT CODE *************************************************************/
|
||||||
|
@ -86,12 +89,9 @@ KiCommonExit(IN PKTRAP_FRAME TrapFrame, BOOLEAN SkipPreviousMode)
|
||||||
{
|
{
|
||||||
/* Disable interrupts until we return */
|
/* Disable interrupts until we return */
|
||||||
_disable();
|
_disable();
|
||||||
|
|
||||||
/* Check for APC delivery */
|
/* Check for APC delivery */
|
||||||
KiCheckForApcDelivery(TrapFrame);
|
KiCheckForApcDelivery(TrapFrame);
|
||||||
|
|
||||||
/* Debugging checks */
|
|
||||||
KiExitTrapDebugChecks(TrapFrame, SkipPreviousMode);
|
|
||||||
|
|
||||||
/* Restore the SEH handler chain */
|
/* Restore the SEH handler chain */
|
||||||
KeGetPcr()->NtTib.ExceptionList = TrapFrame->ExceptionList;
|
KeGetPcr()->NtTib.ExceptionList = TrapFrame->ExceptionList;
|
||||||
|
@ -99,11 +99,17 @@ KiCommonExit(IN PKTRAP_FRAME TrapFrame, BOOLEAN SkipPreviousMode)
|
||||||
/* Check if there are active debug registers */
|
/* Check if there are active debug registers */
|
||||||
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
|
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
|
||||||
{
|
{
|
||||||
/* Not handled yet */
|
/* Check if the frame was from user mode or v86 mode */
|
||||||
DbgPrint("Need Hardware Breakpoint Support!\n");
|
if ((TrapFrame->SegCs & MODE_MASK) ||
|
||||||
DbgBreakPoint();
|
(TrapFrame->EFlags & EFLAGS_V86_MASK))
|
||||||
while (TRUE);
|
{
|
||||||
|
/* Handle debug registers */
|
||||||
|
KiHandleDebugRegistersOnTrapExit(TrapFrame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Debugging checks */
|
||||||
|
KiExitTrapDebugChecks(TrapFrame, SkipPreviousMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLSPEC_NORETURN
|
DECLSPEC_NORETURN
|
||||||
|
@ -841,7 +847,7 @@ KiTrap0AHandler(IN PKTRAP_FRAME TrapFrame)
|
||||||
|
|
||||||
/* Check for VDM trap */
|
/* Check for VDM trap */
|
||||||
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
|
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
|
||||||
|
|
||||||
/* Kill the system */
|
/* Kill the system */
|
||||||
KiSystemFatalException(EXCEPTION_INVALID_TSS, TrapFrame);
|
KiSystemFatalException(EXCEPTION_INVALID_TSS, TrapFrame);
|
||||||
}
|
}
|
||||||
|
@ -1068,7 +1074,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
while (TRUE);
|
while (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: The ASM trap exit code would restore segment registers by doing
|
* NOTE: The ASM trap exit code would restore segment registers by doing
|
||||||
* a POP <SEG>, which could cause an invalid segment if someone had messed
|
* a POP <SEG>, which could cause an invalid segment if someone had messed
|
||||||
|
@ -1524,12 +1530,18 @@ KiSystemCall(IN PKTRAP_FRAME TrapFrame,
|
||||||
TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
|
TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
|
||||||
KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
|
KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
|
||||||
|
|
||||||
/* Clear DR7 and check for debugging */
|
/* Default to debugging disabled */
|
||||||
TrapFrame->Dr7 = 0;
|
TrapFrame->Dr7 = 0;
|
||||||
if (__builtin_expect(Thread->Header.DebugActive & 0xFF, 0))
|
|
||||||
|
/* Check if the frame was from user mode */
|
||||||
|
if (TrapFrame->SegCs & MODE_MASK)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
/* Check for active debugging */
|
||||||
while (TRUE);
|
if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
|
||||||
|
{
|
||||||
|
/* Handle debug registers */
|
||||||
|
KiHandleDebugRegistersOnTrapEntry(TrapFrame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set thread fields */
|
/* Set thread fields */
|
||||||
|
|
|
@ -528,10 +528,7 @@ KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
|
||||||
TrapFrame->Dr7 = 0;
|
TrapFrame->Dr7 = 0;
|
||||||
|
|
||||||
/* Set some debug fields if trap debugging is enabled */
|
/* Set some debug fields if trap debugging is enabled */
|
||||||
#if TRAP_DEBUG
|
KiFillTrapFrameDebug(TrapFrame);
|
||||||
TrapFrame->DbgArgMark = 0xBADB0D00;
|
|
||||||
TrapFrame->PreviousPreviousMode = -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Disable interrupts */
|
/* Disable interrupts */
|
||||||
_disable();
|
_disable();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue