exp.c
来自「一个类似windows」· C语言 代码 · 共 1,362 行 · 第 1/3 页
C
1,362 行
Context->Edi = TrapFrame->Edi;
}
/* Handle extended registers */
if (((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
CONTEXT_EXTENDED_REGISTERS) &&
((TrapFrame->SegCs & MODE_MASK) == UserMode))
{
/* Get the FX Save Area */
FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
/* Make sure NPX is present */
if (KeI386NpxPresent)
{
/* Future use */
}
/* Old code */
FxSaveArea = KiGetFpuState(KeGetCurrentThread());
if (FxSaveArea != NULL)
{
memcpy(Context->ExtendedRegisters, &FxSaveArea->U.FxArea,
min(sizeof (Context->ExtendedRegisters), sizeof (FxSaveArea->U.FxArea)) );
}
else
{
Context->ContextFlags &= (~CONTEXT_EXTENDED_REGISTERS) | CONTEXT_i386;
}
}
/* Handle Floating Point */
if (((Context->ContextFlags & CONTEXT_FLOATING_POINT) ==
CONTEXT_FLOATING_POINT) &&
((TrapFrame->SegCs & MODE_MASK) == UserMode))
{
/* Get the FX Save Area */
FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
/* Make sure we have an NPX */
if (KeI386NpxPresent)
{
/* Future use */
}
else
{
/* Future Use */
}
/* Old code */
FxSaveArea = KiGetFpuState(KeGetCurrentThread());
if (FxSaveArea != NULL)
{
KiFxSaveAreaToFloatingSaveArea(&Context->FloatSave, FxSaveArea);
}
else
{
Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
}
}
/* Handle debug registers */
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
CONTEXT_DEBUG_REGISTERS)
{
/* Copy the debug registers */
Context->Dr0 = TrapFrame->Dr0;
Context->Dr1 = TrapFrame->Dr1;
Context->Dr2 = TrapFrame->Dr2;
Context->Dr3 = TrapFrame->Dr3;
Context->Dr6 = TrapFrame->Dr6;
/* For user-mode, only set DR7 if a debugger is active */
if (((TrapFrame->SegCs & MODE_MASK) ||
(TrapFrame->EFlags & EFLAGS_V86_MASK)) &&
(KeGetCurrentThread()->DispatcherHeader.DebugActive))
{
/* Copy it over */
Context->Dr7 = TrapFrame->Dr7;
}
else
{
/* Clear it */
Context->Dr7 = 0;
}
}
}
VOID
NTAPI
KeDumpStackFrames(PULONG Frame)
{
PULONG StackBase, StackEnd;
MEMORY_BASIC_INFORMATION mbi;
ULONG ResultLength = sizeof(mbi);
NTSTATUS Status;
DbgPrint("Frames:\n");
_SEH_TRY
{
Status = MiQueryVirtualMemory (
(HANDLE)-1,
Frame,
MemoryBasicInformation,
&mbi,
sizeof(mbi),
&ResultLength );
if ( !NT_SUCCESS(Status) )
{
DPRINT1("Can't dump stack frames: MiQueryVirtualMemory() failed: %x\n", Status );
return;
}
StackBase = Frame;
StackEnd = (PULONG)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize);
while ( Frame >= StackBase && Frame < StackEnd )
{
ULONG Addr = Frame[1];
if (!KeRosPrintAddress((PVOID)Addr))
DbgPrint("<%X>", Addr);
if ( Addr == 0 || Addr == 0xDEADBEEF )
break;
StackBase = Frame;
Frame = (PULONG)Frame[0];
DbgPrint("\n");
}
}
_SEH_HANDLE
{
}
_SEH_END;
DbgPrint("\n");
}
VOID STDCALL
KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
{
ULONG i=0;
PULONG StackBase, StackEnd;
MEMORY_BASIC_INFORMATION mbi;
ULONG ResultLength = sizeof(mbi);
NTSTATUS Status;
DbgPrint("Frames: ");
_SEH_TRY
{
if ( !Frame )
{
#if defined __GNUC__
__asm__("mov %%ebp, %0" : "=r" (Frame) : );
#elif defined(_MSC_VER)
__asm mov [Frame], ebp
#endif
//Frame = (PULONG)Frame[0]; // step out of KeRosDumpStackFrames
}
Status = MiQueryVirtualMemory (
(HANDLE)-1,
Frame,
MemoryBasicInformation,
&mbi,
sizeof(mbi),
&ResultLength );
if ( !NT_SUCCESS(Status) )
{
DPRINT1("Can't dump stack frames: MiQueryVirtualMemory() failed: %x\n", Status );
return;
}
StackBase = Frame;
StackEnd = (PULONG)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize);
while ( Frame >= StackBase && Frame < StackEnd && i++ < FrameCount )
{
ULONG Addr = Frame[1];
if (!KeRosPrintAddress((PVOID)Addr))
DbgPrint("<%X>", Addr);
if ( Addr == 0 || Addr == 0xDEADBEEF )
break;
StackBase = Frame;
Frame = (PULONG)Frame[0];
DbgPrint(" ");
}
}
_SEH_HANDLE
{
}
_SEH_END;
DbgPrint("\n");
}
ULONG STDCALL
KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount )
{
ULONG Count = 0;
PULONG StackBase, StackEnd, Frame;
MEMORY_BASIC_INFORMATION mbi;
ULONG ResultLength = sizeof(mbi);
NTSTATUS Status;
_SEH_TRY
{
#if defined __GNUC__
__asm__("mov %%ebp, %0" : "=r" (Frame) : );
#elif defined(_MSC_VER)
__asm mov [Frame], ebp
#endif
Status = MiQueryVirtualMemory (
(HANDLE)-1,
Frame,
MemoryBasicInformation,
&mbi,
sizeof(mbi),
&ResultLength );
if ( !NT_SUCCESS(Status) )
{
DPRINT1("Can't get stack frames: MiQueryVirtualMemory() failed: %x\n", Status );
return 0;
}
StackBase = Frame;
StackEnd = (PULONG)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize);
while ( Count < FrameCount && Frame >= StackBase && Frame < StackEnd )
{
Frames[Count++] = Frame[1];
StackBase = Frame;
Frame = (PULONG)Frame[0];
}
}
_SEH_HANDLE
{
}
_SEH_END;
return Count;
}
VOID
INIT_FUNCTION
NTAPI
KeInitExceptions(VOID)
{
ULONG i;
USHORT FlippedSelector;
/* 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;
}
}
VOID
NTAPI
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PKEXCEPTION_FRAME ExceptionFrame,
PKTRAP_FRAME TrapFrame,
KPROCESSOR_MODE PreviousMode,
BOOLEAN FirstChance)
{
CONTEXT Context;
KD_CONTINUE_TYPE Action;
ULONG_PTR Stack, NewStack;
ULONG Size;
BOOLEAN UserDispatch = FALSE;
DPRINT("KiDispatchException() called\n");
/* Increase number of Exception Dispatches */
KeGetCurrentPrcb()->KeExceptionDispatchCount++;
/* Set the context flags */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
/* Check if User Mode */
if (PreviousMode == UserMode)
{
/* Add the FPU Flag */
Context.ContextFlags |= CONTEXT_FLOATING_POINT;
if (KeI386FxsrPresent) Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
}
/* Get a Context */
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
/* Handle kernel-mode first, it's simpler */
if (PreviousMode == KernelMode)
{
/* Check if this is a first-chance exception */
if (FirstChance == TRUE)
{
/* Break into the debugger for the first time */
Action = KdpEnterDebuggerException(ExceptionRecord,
PreviousMode,
&Context,
TrapFrame,
TRUE,
TRUE);
/* If the debugger said continue, then continue */
if (Action == kdContinue) goto Handled;
/* If the Debugger couldn't handle it, dispatch the exception */
if (RtlDispatchException(ExceptionRecord, &Context))
{
/* It was handled by an exception handler, continue */
goto Handled;
}
}
/* This is a second-chance exception, only for the debugger */
Action = KdpEnterDebuggerException(ExceptionRecord,
PreviousMode,
&Context,
TrapFrame,
FALSE,
FALSE);
/* If the debugger said continue, then continue */
if (Action == kdContinue) goto Handled;
/* Third strike; you're out */
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
ExceptionRecord->ExceptionCode,
(ULONG_PTR)ExceptionRecord->ExceptionAddress,
ExceptionRecord->ExceptionInformation[0],
ExceptionRecord->ExceptionInformation[1],
TrapFrame);
}
else
{
/* User mode exception, was it first-chance? */
if (FirstChance)
{
/* Enter Debugger if available */
Action = KdpEnterDebuggerException(ExceptionRecord,
PreviousMode,
&Context,
TrapFrame,
TRUE,
TRUE);
/* Exit if we're continuing */
if (Action == kdContinue) goto Handled;
/* FIXME: Forward exception to user mode debugger */
/* Set up the user-stack */
_SEH_TRY
{
/* Align context size and get stack pointer */
Size = (sizeof(CONTEXT) + 3) & ~3;
Stack = (Context.Esp & ~3) - Size;
DPRINT("Stack: %lx\n", Stack);
/* Probe stack and copy Context */
ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
RtlCopyMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
/* Align exception record size and get stack pointer */
Size = (sizeof(EXCEPTION_RECORD) -
(EXCEPTION_MAXIMUM_PARAMETERS - ExceptionRecord->NumberParameters) *
sizeof(ULONG) + 3) & ~3;
NewStack = Stack - Size;
DPRINT("NewStack: %lx\n", NewStack);
/* Probe stack and copy exception record. Don't forget to add the two params */
ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
Size + 2 * sizeof(ULONG_PTR),
sizeof(ULONG));
RtlCopyMemory((PVOID)NewStack, ExceptionRecord, Size);
/* Now write the two params for the user-mode dispatcher */
*(PULONG_PTR)(NewStack - 1 * sizeof(ULONG_PTR)) = Stack;
*(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
/* Set new Stack Pointer */
KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
/* Set EIP to the User-mode Dispathcer */
TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
UserDispatch = TRUE;
_SEH_LEAVE;
}
_SEH_HANDLE
{
/* Do second-chance */
}
_SEH_END;
}
/* If we dispatch to user, return now */
if (UserDispatch) return;
/* FIXME: Forward the exception to the debugger for 2nd chance */
/* 3rd strike, kill the thread */
DPRINT1("Unhandled UserMode exception, terminating thread\n");
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
ExceptionRecord->ExceptionCode,
(ULONG_PTR)ExceptionRecord->ExceptionAddress,
ExceptionRecord->ExceptionInformation[0],
ExceptionRecord->ExceptionInformation[1],
TrapFrame);
}
Handled:
/* Convert the context back into Trap/Exception Frames */
KeContextToTrapFrame(&Context,
NULL,
TrapFrame,
Context.ContextFlags,
PreviousMode);
return;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
KeRaiseUserException(IN NTSTATUS ExceptionCode)
{
ULONG OldEip;
PKTHREAD Thread = KeGetCurrentThread();
/* Make sure we can access the TEB */
_SEH_TRY
{
Thread->Teb->ExceptionCode = ExceptionCode;
}
_SEH_HANDLE
{
return(ExceptionCode);
}
_SEH_END;
/* Get the old EIP */
OldEip = Thread->TrapFrame->Eip;
/* Change it to the user-mode dispatcher */
Thread->TrapFrame->Eip = (ULONG_PTR)KeRaiseUserExceptionDispatcher;
/* Return the old EIP */
return((NTSTATUS)OldEip);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?