📄 exp.c
字号:
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ke/i386/exp.c
* PURPOSE: Exception Dispatching and Context<->Trap Frame Conversion
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Gregor Anich
* Skywing (skywing@valhallalegends.com)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#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 *****************************************************************/
_SEH_DEFINE_LOCALS(KiCopyInfo)
{
volatile EXCEPTION_RECORD SehExceptRecord;
};
_SEH_FILTER(KiCopyInformation)
{
_SEH_ACCESS_LOCALS(KiCopyInfo);
/* Copy the exception records and return to the handler */
RtlCopyMemory((PVOID)&_SEH_VAR(SehExceptRecord),
_SEH_GetExceptionPointers()->ExceptionRecord,
sizeof(EXCEPTION_RECORD));
return EXCEPTION_EXECUTE_HANDLER;
}
VOID
INIT_FUNCTION
NTAPI
KeInitExceptions(VOID)
{
ULONG i;
USHORT FlippedSelector;
extern KIDTENTRY KiIdt[MAXIMUM_IDTVECTOR];
/* Loop the IDT */
for (i = 0; i <= MAXIMUM_IDTVECTOR; i ++)
{
/* Save the current Selector */
FlippedSelector = KiIdt[i].Selector;
/* Flip Selector and Extended Offset */
KiIdt[i].Selector = KiIdt[i].ExtendedOffset;
KiIdt[i].ExtendedOffset = FlippedSelector;
}
}
ULONG
FASTCALL
KiUpdateDr7(IN ULONG Dr7)
{
ULONG DebugMask = KeGetCurrentThread()->DispatcherHeader.DebugActive;
/* Check if debugging is enabled */
if (DebugMask & DR_MASK(DR7_OVERRIDE_V))
{
/* Sanity checks */
ASSERT((DebugMask & DR_REG_MASK) != 0);
ASSERT((Dr7 & ~DR7_RESERVED_MASK) == DR7_OVERRIDE_MASK);
return 0;
}
/* Return DR7 itself */
return Dr7;
}
BOOLEAN
FASTCALL
KiRecordDr7(OUT PULONG Dr7Ptr,
OUT PULONG DrMask)
{
ULONG NewMask, Mask;
UCHAR Result;
/* Check if the caller gave us a mask */
if (!DrMask)
{
/* He didn't use the one from the thread */
Mask = KeGetCurrentThread()->DispatcherHeader.DebugActive;
}
else
{
/* He did, read it */
Mask = *DrMask;
}
/* Sanity check */
ASSERT((*Dr7Ptr & DR7_RESERVED_MASK) == 0);
/* Check if DR7 is empty */
NewMask = Mask;
if (!(*Dr7Ptr))
{
/* Assume failure */
Result = FALSE;
/* Check the DR mask */
NewMask &= ~(DR_MASK(7));
if (NewMask & DR_REG_MASK)
{
/* Set the active mask */
NewMask |= DR_MASK(DR7_OVERRIDE_V);
/* Set DR7 override */
*DrMask |= DR7_OVERRIDE_MASK;
}
else
{
/* Sanity check */
ASSERT(NewMask == 0);
}
}
else
{
/* Check if we have a mask or not */
Result = NewMask ? TRUE: FALSE;
/* Update the mask to disable debugging */
NewMask &= ~(DR_MASK(DR7_OVERRIDE_V));
NewMask |= DR_MASK(7);
}
/* Check if caller wants the new mask */
if (DrMask)
{
/* Update it */
*DrMask = NewMask;
}
else
{
/* Check if the mask changed */
if (Mask != NewMask)
{
/* Update it */
KeGetCurrentThread()->DispatcherHeader.DebugActive =
(BOOLEAN)NewMask;
}
}
/* Return the result */
return Result;
}
ULONG
NTAPI
KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
{
/* Check if this is user-mode or V86 */
if ((TrapFrame->SegCs & MODE_MASK) ||
(TrapFrame->EFlags & EFLAGS_V86_MASK))
{
/* Return it directly */
return TrapFrame->HardwareEsp;
}
else
{
/* Edited frame */
if (!(TrapFrame->SegCs & FRAME_EDITED))
{
/* Return edited value */
return TrapFrame->TempEsp;
}
else
{
/* Virgin frame, calculate */
return (ULONG)&TrapFrame->HardwareEsp;
}
}
}
VOID
NTAPI
KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
IN ULONG Esp)
{
KIRQL OldIrql;
ULONG Previous;
/* Raise to APC_LEVEL if needed */
OldIrql = KeGetCurrentIrql();
if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
/* Get the old ESP */
Previous = KiEspFromTrapFrame(TrapFrame);
/* Check if this is user-mode or V86 */
if ((TrapFrame->SegCs & MODE_MASK) ||
(TrapFrame->EFlags & EFLAGS_V86_MASK))
{
/* Write it directly */
TrapFrame->HardwareEsp = Esp;
}
else
{
/* Don't allow ESP to be lowered, this is illegal */
if (Esp < Previous) KeBugCheckEx(SET_OF_INVALID_CONTEXT,
Esp,
Previous,
(ULONG_PTR)TrapFrame,
0);
/* Create an edit frame, check if it was alrady */
if (!(TrapFrame->SegCs & FRAME_EDITED))
{
/* Update the value */
TrapFrame->TempEsp = Esp;
}
else
{
/* Check if ESP changed */
if (Previous != Esp)
{
/* Save CS */
TrapFrame->TempSegCs = TrapFrame->SegCs;
TrapFrame->SegCs &= ~FRAME_EDITED;
/* Save ESP */
TrapFrame->TempEsp = Esp;
}
}
}
/* Restore IRQL */
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
}
ULONG
NTAPI
KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
{
/* If this was V86 Mode */
if (TrapFrame->EFlags & EFLAGS_V86_MASK)
{
/* Just return it */
return TrapFrame->HardwareSegSs;
}
else if (TrapFrame->SegCs & MODE_MASK)
{
/* Usermode, return the User SS */
return TrapFrame->HardwareSegSs | RPL_MASK;
}
else
{
/* Kernel mode */
return KGDT_R0_DATA;
}
}
VOID
NTAPI
KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
IN ULONG Ss)
{
/* Remove the high-bits */
Ss &= 0xFFFF;
/* If this was V86 Mode */
if (TrapFrame->EFlags & EFLAGS_V86_MASK)
{
/* Just write it */
TrapFrame->HardwareSegSs = Ss;
}
else if (TrapFrame->SegCs & MODE_MASK)
{
/* Usermode, save the User SS */
TrapFrame->HardwareSegSs = Ss | RPL_MASK;
}
}
USHORT
NTAPI
KiTagWordFnsaveToFxsave(USHORT TagWord)
{
INT FxTagWord = ~TagWord;
/*
* Empty is now 00, any 2 bits containing 1 mean valid
* Now convert the rest (11->0 and the rest to 1)
*/
FxTagWord = (FxTagWord | (FxTagWord >> 1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
FxTagWord = (FxTagWord | (FxTagWord >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
FxTagWord = (FxTagWord | (FxTagWord >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
FxTagWord = (FxTagWord | (FxTagWord >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
return FxTagWord;
}
VOID
NTAPI
KeContextToTrapFrame(IN PCONTEXT Context,
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PKTRAP_FRAME TrapFrame,
IN ULONG ContextFlags,
IN KPROCESSOR_MODE PreviousMode)
{
PFX_SAVE_AREA FxSaveArea;
ULONG i;
BOOLEAN V86Switch = FALSE;
KIRQL OldIrql;
ULONG DrMask = 0;
PVOID SafeDr;
/* Do this at APC_LEVEL */
OldIrql = KeGetCurrentIrql();
if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
/* Start with the basic Registers */
if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
{
/* Check if we went through a V86 switch */
if ((Context->EFlags & EFLAGS_V86_MASK) !=
(TrapFrame->EFlags & EFLAGS_V86_MASK))
{
/* We did, remember this for later */
V86Switch = TRUE;
}
/* Copy EFLAGS and sanitize them*/
TrapFrame->EFlags = Ke386SanitizeFlags(Context->EFlags, PreviousMode);
/* Copy EBP and EIP */
TrapFrame->Ebp = Context->Ebp;
TrapFrame->Eip = Context->Eip;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -