- Reapply 35812:

- RtlDispatchException: Call vectored exception handlers before doing anything else
- KiUserExceptionDispatcher: Call RtlDispatchException directly as it now takes care of vectored handling
- Rename RtlpExecuteVectoredExceptionHandlers to RtlCallVectoredExceptionHandlers, and fix return type
- References: "New Vectored Exception Handling in Windows XP" by Matt Pietrek
- New in this revision: Only call vectored handlers in user mode, as there is no such thing in kernel mode

svn path=/trunk/; revision=37137
This commit is contained in:
Stefan Ginsberg 2008-11-01 19:48:52 +00:00
parent ed9780429d
commit ae24c33a4f
5 changed files with 32 additions and 57 deletions

View file

@ -15,10 +15,6 @@
typedef NTSTATUS (NTAPI *USER_CALL)(PVOID Argument, ULONG ArgumentLength); typedef NTSTATUS (NTAPI *USER_CALL)(PVOID Argument, ULONG ArgumentLength);
EXCEPTION_DISPOSITION NTAPI
RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context);
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
/* /*
@ -32,18 +28,9 @@ KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
EXCEPTION_RECORD NestedExceptionRecord; EXCEPTION_RECORD NestedExceptionRecord;
NTSTATUS Status; NTSTATUS Status;
/* call the vectored exception handlers */
if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord,
Context) != ExceptionContinueExecution)
{
goto ContinueExecution;
}
else
{
/* Dispatch the exception and check the result */ /* Dispatch the exception and check the result */
if (RtlDispatchException(ExceptionRecord, Context)) if (RtlDispatchException(ExceptionRecord, Context))
{ {
ContinueExecution:
/* Continue executing */ /* Continue executing */
Status = NtContinue(Context, FALSE); Status = NtContinue(Context, FALSE);
} }
@ -52,7 +39,6 @@ ContinueExecution:
/* Raise an exception */ /* Raise an exception */
Status = NtRaiseException(ExceptionRecord, Context, FALSE); Status = NtRaiseException(ExceptionRecord, Context, FALSE);
} }
}
/* Setup the Exception record */ /* Setup the Exception record */
NestedExceptionRecord.ExceptionCode = Status; NestedExceptionRecord.ExceptionCode = Status;

View file

@ -183,52 +183,22 @@ _KiRaiseUserExceptionDispatcher@0:
.globl _KiUserExceptionDispatcher@8 .globl _KiUserExceptionDispatcher@8
_KiUserExceptionDispatcher@8: _KiUserExceptionDispatcher@8:
/* clear the direct flag /* Clear direction flag */
* text from bug 2279
* if it not clear it means that if an exception occurs while
* the direction flag is set (typically inside memmove), the
* exception handlers will be called with the direction flag still
* set. The Windows x86-32 and x86-64 ABI requires that the
* direction flag be Calling memset() with a compile-time constant
* size on both GCC and MSVC will result in inlining a "rep stosd"
* instruction. Because of the ABI, they will assume that the
* direction flag is clear and not emit a "cld" instruction.
* Using memset() in an exception handler therefore will
* corrupt memory if the exception occurred during a reverse copy
* such as a forward overlapping memmove().
*
* For reliability and ease of debugging, please add "cld" to the beginning of
* KiUserExceptionDispatcher. Note that the same will be true of x86-64 whenever
* that happens. This does not affect continuing execution; the CONTEXT of the
* exception has the direction flag set and will be restored upon NtContinue.
* KiUserApcDispatcher and KiUserCallbackDispatcher need to be evaluated for this
* issue.
*/
cld cld
/* Save the Context and Exception Records */ /* Save the Context and Exception Records */
mov ecx, [esp+4] mov ecx, [esp+4]
mov ebx, [esp] mov ebx, [esp]
/* Call the vectored exception handler */ /* Dispatch the exception */
push ecx push ecx
push ebx push ebx
call _RtlpExecuteVectoredExceptionHandlers@8
/* Check for success */
or al, al
jnz ContinueExecution
/* Dispatch the exception */
sub esp, 8
call _RtlDispatchException@8 call _RtlDispatchException@8
/* Check for success */ /* Check for success */
or al, al or al, al
jz RaiseException jz RaiseException
ContinueExecution:
/* Pop off the records */ /* Pop off the records */
pop ebx pop ebx
pop ecx pop ecx

View file

@ -74,6 +74,17 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
ULONG_PTR StackLow, StackHigh; ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd; ULONG_PTR RegistrationFrameEnd;
/* Perform vectored exception handling if we are in user mode */
if (RtlpGetMode() != KernelMode)
{
/* Call any registered vectored handlers */
if (RtlCallVectoredExceptionHandlers(ExceptionRecord, Context))
{
/* Exception handled, continue execution */
return TRUE;
}
}
/* Get the current stack limits and registration frame */ /* Get the current stack limits and registration frame */
RtlpGetStackLimits(&StackLow, &StackHigh); RtlpGetStackLimits(&StackLow, &StackHigh);
RegistrationFrame = RtlpGetExceptionList(); RegistrationFrame = RtlpGetExceptionList();

View file

@ -37,6 +37,13 @@ VOID
NTAPI NTAPI
RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList); RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList);
BOOLEAN
NTAPI
RtlCallVectoredExceptionHandlers(
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context
);
typedef struct _DISPATCHER_CONTEXT typedef struct _DISPATCHER_CONTEXT
{ {
PEXCEPTION_REGISTRATION_RECORD RegistrationPointer; PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;

View file

@ -28,8 +28,9 @@ typedef struct _RTL_VECTORED_EXCEPTION_HANDLER
/* FUNCTIONS ***************************************************************/ /* FUNCTIONS ***************************************************************/
EXCEPTION_DISPOSITION NTAPI BOOLEAN
RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord, NTAPI
RtlCallVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context) IN PCONTEXT Context)
{ {
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
@ -55,7 +56,7 @@ RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION) if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION)
{ {
return ExceptionContinueSearch; return TRUE;
} }
RtlEnterCriticalSection(&RtlpVectoredExceptionLock); RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
@ -63,7 +64,7 @@ RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
} }
return ExceptionContinueExecution; return FALSE;
} }
VOID VOID