Author: jgardou Date: Sat Apr 6 19:15:11 2013 New Revision: 58692
URL: http://svn.reactos.org/svn/reactos?rev=58692&view=rev Log: [KERNEL32_APITEST] - Add a test verifying that the filter set with SetUnhandledExceptionFilter is called. Take this as an occasion to demonstrate a bug with SSE exceptions in ReactOS
Modified: trunk/rostests/apitests/kernel32/SetUnhandledExceptionFilter.c
Modified: trunk/rostests/apitests/kernel32/SetUnhandledExceptionFilter.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/kernel32/SetUnhan... ============================================================================== --- trunk/rostests/apitests/kernel32/SetUnhandledExceptionFilter.c [iso-8859-1] (original) +++ trunk/rostests/apitests/kernel32/SetUnhandledExceptionFilter.c [iso-8859-1] Sat Apr 6 19:15:11 2013 @@ -9,6 +9,7 @@ #include <stdio.h> #include <wine/test.h> #include <ndk/rtltypes.h> +#include <xmmintrin.h>
/* * Keep these returning different values, to prevent compiler folding @@ -33,9 +34,144 @@ ok(p2 != Filter2, "SetUnhandledExceptionFilter returned what was set, not prev\n"); ok(p2 == Filter1, "SetUnhandledExceptionFilter didn't return previous filter\n"); ok(p1 != p2, "SetUnhandledExceptionFilter seems to return random stuff\n"); + + p1 = SetUnhandledExceptionFilter(NULL); + ok(p1 == Filter2, "SetUnhandledExceptionFilter didn't return previous filter\n"); +} + +static LONG WINAPI ExceptionFilterSSESupport(LPEXCEPTION_POINTERS exp) +{ + PEXCEPTION_RECORD rec = exp->ExceptionRecord; + PCONTEXT ctx = exp->ContextRecord; + + trace("Exception raised while using SSE instructions.\n"); + + ok(rec->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION, "Exception code is 0x%08x.\n", (unsigned int)rec->ExceptionCode); + + if(rec->ExceptionCode != EXCEPTION_ILLEGAL_INSTRUCTION) + { + trace("Unexpected exception code, terminating!\n"); + return EXCEPTION_EXECUTE_HANDLER; + } + + ok((ctx->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL, "Context does not contain control register.\n"); + + ctx->Eip += 3; + + return EXCEPTION_CONTINUE_EXECUTION; +} + +static BOOL ExceptionCaught = FALSE; + +static LONG WINAPI ExceptionFilterSSEException(LPEXCEPTION_POINTERS exp) +{ + PEXCEPTION_RECORD rec = exp->ExceptionRecord; + PCONTEXT ctx = exp->ContextRecord; + + trace("Exception raised while dividing by 0.\n"); + + ok(rec->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS, "Exception code is 0x%08x.\n", (unsigned int)rec->ExceptionCode); + + if(rec->ExceptionCode != STATUS_FLOAT_MULTIPLE_TRAPS) + { + trace("Unexpected exception code, terminating!\n"); + return EXCEPTION_EXECUTE_HANDLER; + } + + ok((ctx->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL, "Context does not contain control register.\n"); + + ExceptionCaught = TRUE; + + ctx->Eip += 3; + + return EXCEPTION_CONTINUE_EXECUTION; +} + +static +VOID TestSSEExceptions(VOID) +{ + LPTOP_LEVEL_EXCEPTION_FILTER p; + BOOL supportsSSE = FALSE; + unsigned int csr; + + /* Test SSE support for the CPU */ + p = SetUnhandledExceptionFilter(ExceptionFilterSSESupport); + ok(p == NULL, "Previous filter should be NULL\n"); +#ifdef _MSC_VER + __asm + { + xorps xmm0, xmm0 + mov supportsSSE, 0x1 + } +#else + __asm__( + "xorps %%xmm0, %%xmm0\n" + "movl $1, %0\n" + : "=r"(supportsSSE) + : + : + ); +#endif /* _MSC_VER */ + if(!supportsSSE) + { + skip("CPU doesn't support SSE instructions.\n"); + SetUnhandledExceptionFilter(NULL); + return; + } + /* Deliberately throw a divide by 0 exception */ + p = SetUnhandledExceptionFilter(ExceptionFilterSSEException); + ok(p == ExceptionFilterSSESupport, "Unexpected old filter : 0x%p", p); + + /* Unmask divide by 0 exception */ + csr = _mm_getcsr(); + _mm_setcsr(csr & 0xFFFFFDFF); + + /* We can't use _mm_div_ps, as it masks the exception before performing anything*/ +#if defined(_MSC_VER) + __asm + { + xorps xmm0, xmm0 + push 0x3f800000 + push 0x3f800000 + push 0x3f800000 + push 0x3f800000 + + movups xmm1, [esp] + + /* Divide by 0 */ + divps xmm1, xmm0 + + /* Clean up */ + add esp, 16 + } +#else + __asm__ ( + "xorps %%xmm0, %%xmm0\n" + "pushl $0x3f800000\n" + "pushl $0x3f800000\n" + "pushl $0x3f800000\n" + "pushl $0x3f800000\n" + "movups (%%esp), %%xmm1\n" + + /* Divide by 0 */ + "divps %%xmm0, %%xmm1\n" + + /* Clean up */ + "addl $16, %%esp\n" + : : :); +#endif /* _MSC_VER */ + + /* Restore mxcsr */ + _mm_setcsr(csr); + + ok(ExceptionCaught, "The exception was not caught.\n"); + + p = SetUnhandledExceptionFilter(NULL); + ok(p == ExceptionFilterSSEException, "Unexpected old filter : 0x%p", p); }
START_TEST(SetUnhandledExceptionFilter) { TestSetUnhandledExceptionFilter(); + TestSSEExceptions(); }