ReactOS  0.4.15-dev-3177-gd6a0299
SetUnhandledExceptionFilter.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS api tests
3  * LICENSE: GPLv2+ - See COPYING in the top level directory
4  * PURPOSE: Test for SetUnhandledExceptionFilter
5  * PROGRAMMER: Mike "tamlin" Nordell
6  */
7 
8 #include "precomp.h"
9 
10 #include <xmmintrin.h>
11 
12 /*
13  * Keep these returning different values, to prevent compiler folding
14  * them into a single function, thereby voiding the test
15  */
18 
19 
20 /*
21  * Verify that SetUnhandledExceptionFilter actually returns the
22  * _previous_ handler.
23  */
24 static
25 VOID
27 {
31  ok(p1 != Filter1, "SetUnhandledExceptionFilter returned what was set, not prev\n");
32  ok(p2 != Filter2, "SetUnhandledExceptionFilter returned what was set, not prev\n");
33  ok(p2 == Filter1, "SetUnhandledExceptionFilter didn't return previous filter\n");
34  ok(p1 != p2, "SetUnhandledExceptionFilter seems to return random stuff\n");
35 
37  ok(p1 == Filter2, "SetUnhandledExceptionFilter didn't return previous filter\n");
38 }
39 
41 {
42  PEXCEPTION_RECORD rec = exp->ExceptionRecord;
43  PCONTEXT ctx = exp->ContextRecord;
44 
45  trace("Exception raised while using SSE instructions.\n");
46 
47  ok(rec->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION, "Exception code is 0x%08x.\n", (unsigned int)rec->ExceptionCode);
48 
50  {
51  trace("Unexpected exception code, terminating!\n");
53  }
54 
55  ok((ctx->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL, "Context does not contain control register.\n");
56 
57 #ifdef _M_IX86
58  ctx->Eip += 3;
59 #elif defined(_M_AMD64)
60  ctx->Rip += 3;
61 #else
62 #error Architecture not handled
63 #endif
64 
66 }
67 
69 
71 {
72  PEXCEPTION_RECORD rec = exp->ExceptionRecord;
73  PCONTEXT ctx = exp->ContextRecord;
74 #ifdef _M_AMD64
75  ULONG ExpectedExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO;
76 #else
77  ULONG ExpectedExceptionCode = STATUS_FLOAT_MULTIPLE_TRAPS;
78 #endif
79 
80  trace("Exception raised while dividing by 0.\n");
81 
82  ok(rec->ExceptionCode == ExpectedExceptionCode, "Exception code is 0x%08x.\n", (unsigned int)rec->ExceptionCode);
83 
84  if(rec->ExceptionCode != ExpectedExceptionCode)
85  {
86  trace("Unexpected exception code, terminating!\n");
88  }
89 
90  ok((ctx->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL, "Context does not contain control register.\n");
91 
93 
94 #ifdef _M_IX86
95  ctx->Eip += 3;
96 #elif defined(_M_AMD64)
97  ctx->Rip += 3;
98 #else
99 #error Architecture not handled
100 #endif
101 
103 }
104 
105 #if defined(__clang__) || defined(__GNUC__)
106 __attribute__((__target__("sse")))
107 #endif
108 static
110 {
112  unsigned int csr;
113 
114  /* Test SSE support for the CPU */
116  ok(p == NULL, "Previous filter should be NULL\n");
117 
118 #if !defined(_M_AMD64)
119  {
120  BOOL supportsSSE = FALSE;
121 #ifdef _MSC_VER
122  __asm
123  {
124  xorps xmm0, xmm0
125  mov supportsSSE, 0x1
126  }
127 #else
128  __asm__(
129  "xorps %%xmm0, %%xmm0\n"
130  "movl $1, %0\n"
131  : "=r"(supportsSSE)
132  );
133 #endif /* _MSC_VER */
134 
135  if(!supportsSSE)
136  {
137  skip("CPU doesn't support SSE instructions.\n");
139  return;
140  }
141  }
142 #endif /* !defined(_M_AMD64) */
143 
144  /* Deliberately throw a divide by 0 exception */
146  ok(p == ExceptionFilterSSESupport, "Unexpected old filter : 0x%p", p);
147 
148  /* Unmask divide by 0 exception */
149  csr = _mm_getcsr();
150  _mm_setcsr(csr & 0xFFFFFDFF);
151 
152  /* We can't use _mm_div_ps, as it masks the exception before performing anything*/
153 #if defined(_MSC_VER)
154 #if defined(_M_AMD64)
155  {
156  __m128 xmm1 = { { 1., 1. } }, xmm2 = { { 0 } };
157  /* Wait, aren't exceptions masked? Yes, but actually no. */
158  xmm1 = _mm_div_ps(xmm1, xmm2);
159  }
160 #else
161  __asm
162  {
163  xorps xmm0, xmm0
164  push 0x3f800000
165  push 0x3f800000
166  push 0x3f800000
167  push 0x3f800000
168 
169  movups xmm1, [esp]
170 
171  /* Divide by 0 */
172  divps xmm1, xmm0
173 
174  /* Clean up */
175  add esp, 16
176  }
177 #endif
178 #else
179  ULONG zeros[4] = {0, 0, 0, 0};
180  ULONG ones[4] = {0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000};
181  __asm__ (
182  "movups (%0), %%xmm0\n"
183  "movups (%1), %%xmm1\n"
184  /* Divide by 0 */
185  "divps %%xmm0, %%xmm1\n"
186 
187  : : "r"(&zeros), "r"(&ones) : "xmm0", "xmm1"
188  );
189 #endif /* _MSC_VER */
190 
191  /* Restore mxcsr */
192  _mm_setcsr(csr);
193 
194  ok(ExceptionCaught, "The exception was not caught.\n");
195 
197  ok(p == ExceptionFilterSSEException, "Unexpected old filter : 0x%p", p);
198 }
199 
201 {
204 }
#define CONTEXT_CONTROL
Definition: nt_native.h:1369
static VOID TestSetUnhandledExceptionFilter(VOID)
#define TRUE
Definition: types.h:120
static LONG WINAPI ExceptionFilterSSESupport(LPEXCEPTION_POINTERS exp)
static BOOL ExceptionCaught
LONG WINAPI Filter1(LPEXCEPTION_POINTERS p)
__INTRIN_INLINE void _mm_setcsr(unsigned int val)
Definition: xmmintrin.h:107
__asm__("\n\t \ NewInt3Handler:\n\t \ pushl $" STR(REASON_INT3) "\n\t \ // call debugger loop\n\t \ jmp NewInt31Handler\n\t \ ")
#define STATUS_FLOAT_DIVIDE_BY_ZERO
Definition: ntstatus.h:378
#define EXCEPTION_CONTINUE_EXECUTION
Definition: excpt.h:87
DWORD ExceptionCode
Definition: compat.h:208
#define __attribute__(x)
Definition: wpp_private.h:207
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI DECLSPEC_HOTPATCH SetUnhandledExceptionFilter(IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
Definition: except.c:788
__m128 _mm_div_ps(__m128 a, __m128 b)
LONG WINAPI Filter2(LPEXCEPTION_POINTERS p)
START_TEST(SetUnhandledExceptionFilter)
#define trace
Definition: atltest.h:70
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
__INTRIN_INLINE unsigned int _mm_getcsr(void)
Definition: xmmintrin.h:98
#define WINAPI
Definition: msvc.h:6
static VOID TestSSEExceptions(VOID)
__m128
Definition: xmmintrin.h:35
PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER
Definition: winbase.h:1435
#define STATUS_FLOAT_MULTIPLE_TRAPS
Definition: ntstatus.h:808
static LONG WINAPI ExceptionFilterSSEException(LPEXCEPTION_POINTERS exp)
#define ok(value,...)
Definition: atltest.h:57
#define NULL
Definition: types.h:112
DWORD exp
Definition: msg.c:16033
#define EXCEPTION_ILLEGAL_INSTRUCTION
Definition: winbase.h:324
#define skip(...)
Definition: atltest.h:64
unsigned int ULONG
Definition: retypes.h:1
GLfloat GLfloat p
Definition: glext.h:8902
static void push(calc_node_t *op)
Definition: rpn_ieee.c:113