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/SetUnha…
==============================================================================
--- 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();
}