Author: ion Date: Wed Aug 30 20:58:12 2006 New Revision: 23802
URL: http://svn.reactos.org/svn/reactos?rev=23802&view=rev Log: - Some fixes to KiDispatchException: Add support for forwarding exception back to user-mode, protect against V86 or invalid-stack faults, handle stack overflow exception while handling usermode exception (Thanks KJK for the SEH_FILTER help). Decrement EIP by one when hitting an INT3, to get the correct address. - Remove two associated kernel fun entries.
Modified: trunk/reactos/ntoskrnl/KrnlFun.c trunk/reactos/ntoskrnl/dbgk/debug.c trunk/reactos/ntoskrnl/include/internal/dbgk.h trunk/reactos/ntoskrnl/include/internal/ke.h trunk/reactos/ntoskrnl/ke/i386/exp.c
Modified: trunk/reactos/ntoskrnl/KrnlFun.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/KrnlFun.c?rev=2380... ============================================================================== --- trunk/reactos/ntoskrnl/KrnlFun.c (original) +++ trunk/reactos/ntoskrnl/KrnlFun.c Wed Aug 30 20:58:12 2006 @@ -25,9 +25,7 @@ // - Use Object Type Mutex/Lock. // // Ke: -// - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord). // - Get rid of KiRosPrintAddress and use KiDumpParameterImages instead. -// - Forward exceptions to user-mode debugger. // - Sanitize some context fields during conversions. // - Implement stack fault and segment fault handlers. // - Implement kernel-mode GPF handler, possibly fixing below:
Modified: trunk/reactos/ntoskrnl/dbgk/debug.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/dbgk/debug.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/dbgk/debug.c (original) +++ trunk/reactos/ntoskrnl/dbgk/debug.c Wed Aug 30 20:58:12 2006 @@ -24,6 +24,17 @@ { /* FIXME: Implement */ } + +BOOLEAN +NTAPI +DbgkForwardException(IN PEXCEPTION_RECORD ExceptionRecord, + IN BOOLEAN DebugPort, + IN BOOLEAN SecondChance) +{ + /* FIXME: Implement */ + return FALSE; +} +
NTSTATUS NTAPI
Modified: trunk/reactos/ntoskrnl/include/internal/dbgk.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/d... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/dbgk.h (original) +++ trunk/reactos/ntoskrnl/include/internal/dbgk.h Wed Aug 30 20:58:12 2006 @@ -20,6 +20,14 @@ IN PEPROCESS Parent );
+BOOLEAN +NTAPI +DbgkForwardException( + IN PEXCEPTION_RECORD ExceptionRecord, + IN BOOLEAN DebugPort, + IN BOOLEAN SecondChance +); + extern POBJECT_TYPE DbgkDebugObjectType; #endif
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/k... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ke.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ke.h Wed Aug 30 20:58:12 2006 @@ -691,13 +691,6 @@ ULONG FrameCount );
-ULONG -STDCALL -KeRosGetStackFrames( - PULONG Frames, - ULONG FrameCount -); - VOID NTAPI KiSetSystemTime(PLARGE_INTEGER NewSystemTime);
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/exp.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/exp.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/exp.c Wed Aug 30 20:58:12 2006 @@ -15,6 +15,22 @@ #include <debug.h>
/* 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 */ + RtlMoveMemory((PVOID)&_SEH_VAR(SehExceptRecord), + _SEH_GetExceptionPointers()->ExceptionRecord, + sizeof(EXCEPTION_RECORD)); + return EXCEPTION_EXECUTE_HANDLER; +}
VOID INIT_FUNCTION @@ -588,7 +604,8 @@ KD_CONTINUE_TYPE Action; ULONG_PTR Stack, NewStack; ULONG Size; - BOOLEAN UserDispatch = FALSE; + EXCEPTION_RECORD LocalExceptRecord; + _SEH_DECLARE_LOCALS(KiCopyInfo);
/* Increase number of Exception Dispatches */ KeGetCurrentPrcb()->KeExceptionDispatchCount++; @@ -596,16 +613,32 @@ /* Set the context flags */ Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
- /* Check if User Mode */ - if (PreviousMode == UserMode) + /* Check if User Mode or if the debugger isenabled */ + if ((PreviousMode == UserMode) || (KdDebuggerEnabled)) { /* Add the FPU Flag */ Context.ContextFlags |= CONTEXT_FLOATING_POINT; - if (KeI386FxsrPresent) Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS; + + /* Check for NPX Support */ + if (KeI386FxsrPresent) + { + /* Save those too */ + Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS; + } }
/* Get a Context */ KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context); + + /* Fix up EIP */ + if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) + { + /* Decrement EIP by one */ + Context.Eip--; + } + + ASSERT(!((PreviousMode == KernelMode) && + (Context.EFlags & EFLAGS_V86_MASK)));
/* Handle kernel-mode first, it's simpler */ if (PreviousMode == KernelMode) @@ -625,11 +658,7 @@ 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; - } + if (RtlDispatchException(ExceptionRecord, &Context)) goto Handled; }
/* This is a second-chance exception, only for the debugger */ @@ -644,12 +673,11 @@ 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); + KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, + ExceptionRecord->ExceptionCode, + (ULONG_PTR)ExceptionRecord->ExceptionAddress, + ExceptionRecord->ExceptionInformation[0], + ExceptionRecord->ExceptionInformation[1]); } else { @@ -668,27 +696,39 @@ if (Action == kdContinue) goto Handled;
/* FIXME: Forward exception to user mode debugger */ + if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) goto Exit;
/* Set up the user-stack */ +DispatchToUser: _SEH_TRY { + /* Make sure we have a valid SS and that this isn't V86 mode */ + if ((TrapFrame->HardwareSegSs != (KGDT_R3_DATA | RPL_MASK)) || + (TrapFrame->EFlags & EFLAGS_V86_MASK)) + { + /* Raise an exception instead */ + LocalExceptRecord.ExceptionCode = STATUS_ACCESS_VIOLATION; + LocalExceptRecord.ExceptionFlags = 0; + LocalExceptRecord.NumberParameters = 0; + RtlRaiseException(&LocalExceptRecord); + } + /* 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; + 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 */ + + /* Probe stack and copy exception record */ ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)), Size + 2 * sizeof(ULONG_PTR), sizeof(ULONG)); @@ -699,34 +739,59 @@ *(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
/* Set new Stack Pointer */ + KiSsToTrapFrame(TrapFrame, KGDT_R3_DATA); KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR)); + + /* Force correct segments */ + TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK; + TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK; + TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK; + TrapFrame->SegFs = KGDT_R3_TEB | RPL_MASK; + TrapFrame->SegGs = 0;
/* Set EIP to the User-mode Dispathcer */ TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher; - UserDispatch = TRUE; _SEH_LEAVE; } - _SEH_HANDLE - { - /* Do second-chance */ + _SEH_EXCEPT(KiCopyInformation) + { + /* Check if we got a stack overflow and raise that instead */ + if (_SEH_VAR(SehExceptRecord).ExceptionCode == + STATUS_STACK_OVERFLOW) + { + /* Copy the exception address and record */ + _SEH_VAR(SehExceptRecord).ExceptionAddress = + ExceptionRecord->ExceptionAddress; + RtlMoveMemory(ExceptionRecord, + (PVOID)&_SEH_VAR(SehExceptRecord), + sizeof(EXCEPTION_RECORD)); + + /* Do the exception again */ + goto DispatchToUser; + } } _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); + /* Try second chance */ + if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) + { + /* Handled, get out */ + goto Exit; + } + else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE)) + { + /* Handled, get out */ + goto Exit; + } + + /* 3rd strike, kill the process */ + ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode); + KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, + ExceptionRecord->ExceptionCode, + (ULONG_PTR)ExceptionRecord->ExceptionAddress, + ExceptionRecord->ExceptionInformation[0], + ExceptionRecord->ExceptionInformation[1]); }
Handled: @@ -736,6 +801,7 @@ TrapFrame, Context.ContextFlags, PreviousMode); +Exit: return; }