exp.c
来自「一个类似windows」· C语言 代码 · 共 1,362 行 · 第 1/3 页
C
1,362 行
* Dump the stack frames
*/
KeDumpStackFrames((PULONG)Tf->Ebp);
}
ULONG
KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
/*
* FUNCTION: Called by the lowlevel execption handlers to print an amusing
* message and halt the computer
* ARGUMENTS:
* Complete CPU context
*/
{
ULONG_PTR cr2;
NTSTATUS Status;
ULONG Esp0;
ASSERT(ExceptionNr != 14);
/* Use the address of the trap frame as approximation to the ring0 esp */
Esp0 = (ULONG)&Tf->Eip;
/* Get CR2 */
cr2 = Ke386GetCr2();
Tf->DbgArgPointer = cr2;
/*
* If this was a V86 mode exception then handle it specially
*/
if (Tf->EFlags & (1 << 17))
{
DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n", Tf->EFlags, Tf->Eip, ExceptionNr);
return(KeV86Exception(ExceptionNr, Tf, cr2));
}
/*
* Check for stack underflow, this may be obsolete
*/
if (PsGetCurrentThread() != NULL &&
Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
{
DPRINT1("Stack underflow (tf->esp %x Limit %x Eip %x)\n",
Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit, Tf->Eip);
ExceptionNr = 12;
}
if (ExceptionNr == 15)
{
/*
* FIXME:
* This exception should never occur. The P6 has a bug, which does sometimes deliver
* the apic spurious interrupt as exception 15. On an athlon64, I get one exception
* in the early boot phase in apic mode (using the smp build). I've looked to the linux
* sources. Linux does ignore this exception.
*
*/
DPRINT1("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
return(0);
}
/*
* Check for a breakpoint that was only for the attention of the debugger.
*/
if (ExceptionNr == 3 && Tf->Eip == ((ULONG)DbgBreakPointNoBugCheck) + 1)
{
/*
EIP is already adjusted by the processor to point to the instruction
after the breakpoint.
*/
return(0);
}
/*
* Try to handle device-not-present, math-fault and xmm-fault exceptions.
*/
if (ExceptionNr == 7 || ExceptionNr == 16 || ExceptionNr == 19)
{
Status = KiHandleFpuFault(Tf, ExceptionNr);
if (NT_SUCCESS(Status))
{
return(0);
}
}
/*
* Handle user exceptions differently
*/
if ((Tf->SegCs & 0xFFFF) == (KGDT_R3_CODE | RPL_MASK))
{
return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
}
else
{
return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
}
}
ULONG
NTAPI
KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
{
/* Check if this is user-mode or V86 */
if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & X86_EFLAGS_VM))
{
/* 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)
{
ULONG Previous = KiEspFromTrapFrame(TrapFrame);
/* Check if this is user-mode or V86 */
if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & X86_EFLAGS_VM))
{
/* Write it directly */
TrapFrame->HardwareEsp = Esp;
}
else
{
/* Don't allow ESP to be lowered, this is illegal */
if (Esp < Previous)
{
KeBugCheck(SET_OF_INVALID_CONTEXT);
}
/* 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;
}
}
}
}
ULONG
NTAPI
KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
{
/* If this was V86 Mode */
if (TrapFrame->EFlags & X86_EFLAGS_VM)
{
/* 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 & X86_EFLAGS_VM)
{
/* Just write it */
TrapFrame->HardwareSegSs = Ss;
}
else if (TrapFrame->SegCs & MODE_MASK)
{
/* Usermode, save the User SS */
TrapFrame->HardwareSegSs = Ss | RPL_MASK;
}
}
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; Future Use
BOOLEAN V86Switch = FALSE;
/* Start with the basic Registers */
if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
{
/* Check if we went through a V86 switch */
if ((Context->EFlags & X86_EFLAGS_VM) !=
(TrapFrame->EFlags & X86_EFLAGS_VM))
{
/* We did, remember this for later */
V86Switch = TRUE;
}
/* Copy EFLAGS. FIXME: Needs to be sanitized */
TrapFrame->EFlags = Context->EFlags;
/* Copy EBP and EIP */
TrapFrame->Ebp = Context->Ebp;
TrapFrame->Eip = Context->Eip;
/* Check if we were in V86 Mode */
if (TrapFrame->EFlags & X86_EFLAGS_VM)
{
/* Simply copy the CS value */
TrapFrame->SegCs = Context->SegCs;
}
else
{
/* We weren't in V86, so sanitize the CS (FIXME!) */
TrapFrame->SegCs = Context->SegCs;
/* Don't let it under 8, that's invalid */
if ((PreviousMode != KernelMode) && (TrapFrame->SegCs < 8))
{
/* Force it to User CS */
TrapFrame->SegCs = (KGDT_R3_CODE | RPL_MASK);
}
}
/* Handle SS Specially for validation */
KiSsToTrapFrame(TrapFrame, Context->SegSs);
/* Write ESP back; take into account Edited Trap Frames */
KiEspToTrapFrame(TrapFrame, Context->Esp);
/* Handle our V86 Bias if we went through a switch */
if (V86Switch) Ki386AdjustEsp0(TrapFrame);
}
/* Process the Integer Registers */
if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
{
TrapFrame->Eax = Context->Eax;
TrapFrame->Ebx = Context->Ebx;
TrapFrame->Ecx = Context->Ecx;
TrapFrame->Edx = Context->Edx;
TrapFrame->Esi = Context->Esi;
TrapFrame->Edi = Context->Edi;
}
/* Process the Context Segments */
if ((ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
/* Check if we were in V86 Mode */
if (TrapFrame->EFlags & X86_EFLAGS_VM)
{
/* Copy the V86 Segments directlry */
TrapFrame->V86Ds = Context->SegDs;
TrapFrame->V86Es = Context->SegEs;
TrapFrame->V86Fs = Context->SegFs;
TrapFrame->V86Gs = Context->SegGs;
}
else if (!(TrapFrame->SegCs & MODE_MASK))
{
/* For kernel mode, write the standard values */
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegFs = Context->SegFs;
TrapFrame->SegGs = 0;
}
else
{
/* For user mode, return the values directlry */
TrapFrame->SegDs = Context->SegDs;
TrapFrame->SegEs = Context->SegEs;
TrapFrame->SegFs = Context->SegFs;
/* Handle GS specially */
if (TrapFrame->SegCs == (KGDT_R3_CODE | RPL_MASK))
{
/* Don't use it, if user */
TrapFrame->SegGs = 0;
}
else
{
/* Copy it if kernel */
TrapFrame->SegGs = Context->SegGs;
}
}
}
/* Handle the extended registers */
if (((ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
CONTEXT_EXTENDED_REGISTERS) &&
((TrapFrame->SegCs & MODE_MASK) == UserMode))
{
/* Get the FX Area */
FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
/* Check if NPX is present */
if (KeI386NpxPresent)
{
/* Future use */
}
}
/* Handle the floating point state */
if (((ContextFlags & CONTEXT_FLOATING_POINT) ==
CONTEXT_FLOATING_POINT) &&
((TrapFrame->SegCs & MODE_MASK) == UserMode))
{
/* Get the FX Area */
FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
/* Check if NPX is present */
if (KeI386NpxPresent)
{
/* Future use */
}
else
{
/* Future use */
}
}
/* Handle the Debug Registers */
if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
{
/* FIXME: All these should be sanitized */
TrapFrame->Dr0 = Context->Dr0;
TrapFrame->Dr1 = Context->Dr1;
TrapFrame->Dr2 = Context->Dr2;
TrapFrame->Dr3 = Context->Dr3;
TrapFrame->Dr6 = Context->Dr6;
TrapFrame->Dr7 = Context->Dr7;
/* Check if usermode */
if (PreviousMode != KernelMode)
{
/* Set the Debug Flag */
KeGetCurrentThread()->DispatcherHeader.DebugActive =
(Context->Dr7 & DR7_ACTIVE);
}
}
/* Handle FPU and Extended Registers */
KiContextToFxSaveArea((PFX_SAVE_AREA)(TrapFrame + 1), Context);
}
VOID
NTAPI
KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PCONTEXT Context)
{
PFX_SAVE_AREA FxSaveArea = NULL;
/* Start with the Control flags */
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
{
/* EBP, EIP and EFLAGS */
Context->Ebp = TrapFrame->Ebp;
Context->Eip = TrapFrame->Eip;
Context->EFlags = TrapFrame->EFlags;
/* Return the correct CS */
if (!(TrapFrame->SegCs & FRAME_EDITED) &&
!(TrapFrame->EFlags & X86_EFLAGS_VM))
{
/* Get it from the Temp location */
Context->SegCs = TrapFrame->TempSegCs & 0xFFFF;
}
else
{
/* Return it directly */
Context->SegCs = TrapFrame->SegCs & 0xFFFF;
}
/* Get the Ss and ESP */
Context->SegSs = KiSsFromTrapFrame(TrapFrame);
Context->Esp = KiEspFromTrapFrame(TrapFrame);
}
/* Handle the Segments */
if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
/* Do V86 Mode first */
if (TrapFrame->EFlags & X86_EFLAGS_VM)
{
/* Return from the V86 location */
Context->SegGs = TrapFrame->V86Gs & 0xFFFF;
Context->SegFs = TrapFrame->V86Fs & 0xFFFF;
Context->SegEs = TrapFrame->V86Es & 0xFFFF;
Context->SegDs = TrapFrame->V86Ds & 0xFFFF;
}
else
{
/* Check if this was a Kernel Trap */
if (TrapFrame->SegCs == KGDT_R0_CODE)
{
/* Set valid selectors */
TrapFrame->SegGs = 0;
TrapFrame->SegFs = KGDT_R0_PCR;
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
}
/* Return the segments */
Context->SegGs = TrapFrame->SegGs & 0xFFFF;
Context->SegFs = TrapFrame->SegFs & 0xFFFF;
Context->SegEs = TrapFrame->SegEs & 0xFFFF;
Context->SegDs = TrapFrame->SegDs & 0xFFFF;
}
}
/* Handle the simple registers */
if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
{
/* Return them directly */
Context->Eax = TrapFrame->Eax;
Context->Ebx = TrapFrame->Ebx;
Context->Ecx = TrapFrame->Ecx;
Context->Edx = TrapFrame->Edx;
Context->Esi = TrapFrame->Esi;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?