1 // Copyright (c) Microsoft. All rights reserved.
2 // Licensed under the MIT license. See LICENSE file in the project root for
3 // full license information.
4
5 /*
6 * Exercise lots of different kinds of C++ EH frames. Compile this with
7 * every combination of opts you can to stress the C++ EH frame code in the
8 * backend.
9 */
10
11 #include <stdio.h>
12 #include <malloc.h>
13
14 #ifndef ALIGN
15 #define ALIGN 64
16 #endif
17
18 extern int TestFunc(int, ...);
19
20 int failures;
21
22 int global;
23 bool TestFuncThrows;
24
25 struct SmallObj
26 {
~SmallObjSmallObj27 virtual ~SmallObj()
28 {
29 TestFunc(1, this);
30 };
31
32 int x;
33 };
34
35 struct BigObj
36 {
~BigObjBigObj37 virtual ~BigObj()
38 {
39 TestFunc(1, this);
40 };
41
42 char x[4096];
43 };
44
Simple(int arg)45 int Simple(int arg)
46 {
47 puts(__FUNCTION__);
48 int res = 0;
49 SmallObj f;
50 return TestFunc(1, &f, &res, &arg);
51 }
52
Try(int arg)53 int Try(int arg)
54 {
55 puts(__FUNCTION__);
56 int res = 0;
57 SmallObj f;
58 try {
59 res = TestFunc(1, &f, &res, &arg);
60 } catch (double) {
61 res = TestFunc(2, &f, &res, &arg);
62 }
63 return res;
64 }
65
GSCookie(int arg)66 int GSCookie(int arg)
67 {
68 puts(__FUNCTION__);
69 int res = 0;
70 char buf[16];
71 SmallObj f;
72 return TestFunc(1, buf, &f, &res, &arg);
73 }
74
TryAndGSCookie(int arg)75 int TryAndGSCookie(int arg)
76 {
77 puts(__FUNCTION__);
78 int res = 0;
79 char buf[16];
80 SmallObj f;
81 try {
82 res = TestFunc(1, &buf, &f, &res, &arg);
83 } catch (double) {
84 res = TestFunc(2, &buf, &f, &res, &arg);
85 }
86 return res;
87 }
88
Align(int arg)89 int Align(int arg)
90 {
91 puts(__FUNCTION__);
92 int res = 0;
93 __declspec(align(ALIGN)) double d[4];
94 SmallObj f;
95 return TestFunc(1, d, &f, &res, &arg);
96 }
97
TryAndAlign(int arg)98 int TryAndAlign(int arg)
99 {
100 puts(__FUNCTION__);
101 int res = 0;
102 __declspec(align(ALIGN)) double d[4];
103 SmallObj f;
104 try {
105 res = TestFunc(1, d, &f, &res, &arg);
106 } catch (double) {
107 res = TestFunc(2, d, &f, &res, &arg);
108 }
109 return res;
110 }
111
GSCookieAndAlign(int arg)112 int GSCookieAndAlign(int arg)
113 {
114 puts(__FUNCTION__);
115 int res = 0;
116 char buf[16];
117 __declspec(align(ALIGN)) double d[4];
118 SmallObj f;
119 return TestFunc(1, buf, d, &f, &res, &arg);
120 }
121
TryAndGSCookieAndAlign(int arg)122 int TryAndGSCookieAndAlign(int arg)
123 {
124 puts(__FUNCTION__);
125 int res = 0;
126 char buf[16];
127 __declspec(align(ALIGN)) double d[4];
128 SmallObj f;
129 try {
130 res = TestFunc(1, buf, d, &f, &res, &arg);
131 } catch (double) {
132 res = TestFunc(2, buf, d, &f, &res, &arg);
133 }
134 return res;
135 }
136
Alloca(int arg)137 int Alloca(int arg)
138 {
139 puts(__FUNCTION__);
140 int res = 0;
141 SmallObj f;
142 return TestFunc(1, _alloca(global), &f, &res, &arg);
143 }
144
TryAndAlloca(int arg)145 int TryAndAlloca(int arg)
146 {
147 puts(__FUNCTION__);
148 int res = 0;
149 SmallObj f;
150 try {
151 res = TestFunc(1, _alloca(global), &f, &res, &arg);
152 } catch (double) {
153 res = TestFunc(2, &f, &res, &arg);
154 }
155 return res;
156 }
157
GSCookieAndAlloca(int arg)158 int GSCookieAndAlloca(int arg)
159 {
160 puts(__FUNCTION__);
161 int res = 0;
162 char buf[16];
163 SmallObj f;
164 return TestFunc(1, buf, _alloca(global), &f, &res, &arg);
165 }
166
TryAndGSCookieAndAlloca(int arg)167 int TryAndGSCookieAndAlloca(int arg)
168 {
169 puts(__FUNCTION__);
170 int res = 0;
171 char buf[16];
172 SmallObj f;
173 try {
174 res = TestFunc(1, &buf, _alloca(global), &f, &res, &arg);
175 } catch (double) {
176 res = TestFunc(2, &buf, &f, &res, &arg);
177 }
178 return res;
179 }
180
AlignAndAlloca(int arg)181 int AlignAndAlloca(int arg)
182 {
183 puts(__FUNCTION__);
184 int res = 0;
185 __declspec(align(ALIGN)) double d[4];
186 SmallObj f;
187 return TestFunc(1, d, _alloca(global), &f, &res, &arg);
188 }
189
TryAndAlignAndAlloca(int arg)190 int TryAndAlignAndAlloca(int arg)
191 {
192 puts(__FUNCTION__);
193 int res = 0;
194 __declspec(align(ALIGN)) double d[4];
195 SmallObj f;
196 try {
197 res = TestFunc(1, d, _alloca(global), &f, &res, &arg);
198 } catch (double) {
199 res = TestFunc(2, d, &f, &res, &arg);
200 }
201 return res;
202 }
203
GSCookieAndAlignAndAlloca(int arg)204 int GSCookieAndAlignAndAlloca(int arg)
205 {
206 puts(__FUNCTION__);
207 int res = 0;
208 char buf[16];
209 __declspec(align(ALIGN)) double d[4];
210 SmallObj f;
211 return TestFunc(1, buf, d, _alloca(global), &f, &res, &arg);
212 }
213
TryAndGSCookieAndAlignAndAlloca(int arg)214 int TryAndGSCookieAndAlignAndAlloca(int arg)
215 {
216 puts(__FUNCTION__);
217 int res = 0;
218 char buf[16];
219 __declspec(align(ALIGN)) double d[4];
220 SmallObj f;
221 try {
222 res = TestFunc(1, buf, d, _alloca(global), &f, &res, &arg);
223 } catch (double) {
224 res = TestFunc(2, buf, d, &f, &res, &arg);
225 }
226 return res;
227 }
228
229 /* The *AndBigLocals set of functions try to trigger EBP adjustment */
230
BigLocals(int arg)231 int BigLocals(int arg)
232 {
233 puts(__FUNCTION__);
234 int res = 0;
235 BigObj f1;
236 return TestFunc(1, &f1, &res, &res, &res, &res, &res, &arg);
237 }
238
TryAndBigLocals(int arg)239 int TryAndBigLocals(int arg)
240 {
241 puts(__FUNCTION__);
242 int res = 0;
243 BigObj f1;
244 try {
245 res = TestFunc(1, &f1, &res, &res, &res, &res, &res, &arg);
246 } catch (double) {
247 res = TestFunc(2, &f1, &res, &res, &res, &res, &res, &arg);
248 }
249 return res;
250 }
251
GSCookieAndBigLocals(int arg)252 int GSCookieAndBigLocals(int arg)
253 {
254 puts(__FUNCTION__);
255 int res = 0;
256 char buf[16];
257 BigObj f1;
258 return TestFunc(1, buf, &f1, &res, &res, &res, &res, &res, &arg);
259 }
260
TryAndGSCookieAndBigLocals(int arg)261 int TryAndGSCookieAndBigLocals(int arg)
262 {
263 puts(__FUNCTION__);
264 int res = 0;
265 char buf[16];
266 BigObj f1;
267 try {
268 res = TestFunc(1, &buf, &f1, &res, &res, &res, &res, &res, &arg);
269 } catch (double) {
270 res = TestFunc(2, &buf, &f1, &res, &res, &res, &res, &res, &arg);
271 }
272 return res;
273 }
274
AlignAndBigLocals(int arg)275 int AlignAndBigLocals(int arg)
276 {
277 puts(__FUNCTION__);
278 int res = 0;
279 __declspec(align(ALIGN)) double d[4];
280 BigObj f1;
281 return TestFunc(1, d, &f1, &res, &res, &res, &res, &res, &arg);
282 }
283
TryAndAlignAndBigLocals(int arg)284 int TryAndAlignAndBigLocals(int arg)
285 {
286 puts(__FUNCTION__);
287 int res = 0;
288 __declspec(align(ALIGN)) double d[4];
289 BigObj f1;
290 try {
291 res = TestFunc(1, d, &f1, &res, &res, &res, &res, &res, &arg);
292 } catch (double) {
293 res = TestFunc(2, d, &f1, &res, &res, &res, &res, &res, &arg);
294 }
295 return res;
296 }
297
GSCookieAndAlignAndBigLocals(int arg)298 int GSCookieAndAlignAndBigLocals(int arg)
299 {
300 puts(__FUNCTION__);
301 int res = 0;
302 char buf[16];
303 __declspec(align(ALIGN)) double d[4];
304 BigObj f1;
305 return TestFunc(1, buf, d, &f1, &res, &res, &res, &res, &res, &arg);
306 }
307
TryAndGSCookieAndAlignAndBigLocals(int arg)308 int TryAndGSCookieAndAlignAndBigLocals(int arg)
309 {
310 puts(__FUNCTION__);
311 int res = 0;
312 char buf[16];
313 __declspec(align(ALIGN)) double d[4];
314 BigObj f1;
315 try {
316 res = TestFunc(1, buf, d, &f1, &res, &res, &res, &res, &res, &arg);
317 } catch (double) {
318 res = TestFunc(2, buf, d, &f1, &res, &res, &res, &res, &res, &arg);
319 }
320 return res;
321 }
322
AllocaAndBigLocals(int arg)323 int AllocaAndBigLocals(int arg)
324 {
325 puts(__FUNCTION__);
326 int res = 0;
327 BigObj f1;
328 return TestFunc(1, _alloca(global), &f1, &res, &res, &res, &res, &res, &arg);
329 }
330
TryAndAllocaAndBigLocals(int arg)331 int TryAndAllocaAndBigLocals(int arg)
332 {
333 puts(__FUNCTION__);
334 int res = 0;
335 BigObj f1;
336 try {
337 res = TestFunc(1, _alloca(global), &f1, &res, &res, &res, &res, &res, &arg);
338 } catch (double) {
339 res = TestFunc(2, &f1, &res, &res, &res, &res, &res, &arg);
340 }
341 return res;
342 }
343
GSCookieAndAllocaAndBigLocals(int arg)344 int GSCookieAndAllocaAndBigLocals(int arg)
345 {
346 puts(__FUNCTION__);
347 int res = 0;
348 char buf[16];
349 BigObj f1;
350 return TestFunc(1, buf, _alloca(global), &f1, &res, &res, &res, &res, &res, &arg);
351 }
352
TryAndGSCookieAndAllocaAndBigLocals(int arg)353 int TryAndGSCookieAndAllocaAndBigLocals(int arg)
354 {
355 puts(__FUNCTION__);
356 int res = 0;
357 char buf[16];
358 BigObj f1;
359 try {
360 res = TestFunc(1, &buf, _alloca(global), &f1, &res, &res, &res, &res, &res, &arg);
361 } catch (double) {
362 res = TestFunc(2, &buf, &f1, &res, &res, &res, &res, &res, &arg);
363 }
364 return res;
365 }
366
AlignAndAllocaAndBigLocals(int arg)367 int AlignAndAllocaAndBigLocals(int arg)
368 {
369 puts(__FUNCTION__);
370 int res = 0;
371 __declspec(align(ALIGN)) double d[4];
372 BigObj f1;
373 return TestFunc(1, d, _alloca(global), &f1, &res, &res, &res, &res, &res, &arg);
374 }
375
TryAndAlignAndAllocaAndBigLocals(int arg)376 int TryAndAlignAndAllocaAndBigLocals(int arg)
377 {
378 puts(__FUNCTION__);
379 int res = 0;
380 __declspec(align(ALIGN)) double d[4];
381 BigObj f1;
382 try {
383 res = TestFunc(1, d, _alloca(global), &f1, &res, &res, &res, &res, &res, &arg);
384 } catch (double) {
385 res = TestFunc(2, d, &f1, &res, &res, &res, &res, &res, &arg);
386 }
387 return res;
388 }
389
GSCookieAndAlignAndAllocaAndBigLocals(int arg)390 int GSCookieAndAlignAndAllocaAndBigLocals(int arg)
391 {
392 puts(__FUNCTION__);
393 int res = 0;
394 char buf[16];
395 __declspec(align(ALIGN)) double d[4];
396 BigObj f1;
397 return TestFunc(1, buf, d, _alloca(global), &f1, &res, &res, &res, &res, &res, &arg);
398 }
399
TryAndGSCookieAndAlignAndAllocaAndBigLocals(int arg)400 int TryAndGSCookieAndAlignAndAllocaAndBigLocals(int arg)
401 {
402 puts(__FUNCTION__);
403 int res = 0;
404 char buf[16];
405 __declspec(align(ALIGN)) double d[4];
406 BigObj f1;
407 try {
408 res = TestFunc(1, buf, d, _alloca(global), &f1, &res, &res, &res, &res, &res, &arg);
409 } catch (double) {
410 res = TestFunc(2, buf, d, &f1, &res, &res, &res, &res, &res, &arg);
411 }
412 return res;
413 }
414
415 __declspec(noinline)
TestFunc(int,...)416 int TestFunc(int, ...)
417 {
418 if (TestFuncThrows)
419 {
420 TestFuncThrows = false;
421 throw 123;
422 }
423
424 return global;
425 }
426
RunTests()427 void RunTests()
428 {
429 puts("Test pass 1 - no throws");
430
431 try
432 {
433 Simple(1);
434 Try(1);
435 GSCookie(1);
436 TryAndGSCookie(1);
437 Align(1);
438 TryAndAlign(1);
439 GSCookieAndAlign(1);
440 TryAndGSCookieAndAlign(1);
441 Alloca(1);
442 TryAndAlloca(1);
443 GSCookieAndAlloca(1);
444 TryAndGSCookieAndAlloca(1);
445 AlignAndAlloca(1);
446 TryAndAlignAndAlloca(1);
447 GSCookieAndAlignAndAlloca(1);
448 TryAndGSCookieAndAlignAndAlloca(1);
449 BigLocals(1);
450 TryAndBigLocals(1);
451 GSCookieAndBigLocals(1);
452 TryAndGSCookieAndBigLocals(1);
453 AlignAndBigLocals(1);
454 TryAndAlignAndBigLocals(1);
455 GSCookieAndAlignAndBigLocals(1);
456 TryAndGSCookieAndAlignAndBigLocals(1);
457 AllocaAndBigLocals(1);
458 TryAndAllocaAndBigLocals(1);
459 GSCookieAndAllocaAndBigLocals(1);
460 TryAndGSCookieAndAllocaAndBigLocals(1);
461 AlignAndAllocaAndBigLocals(1);
462 TryAndAlignAndAllocaAndBigLocals(1);
463 GSCookieAndAlignAndAllocaAndBigLocals(1);
464 TryAndGSCookieAndAlignAndAllocaAndBigLocals(1);
465 }
466 catch (...)
467 {
468 puts("ERROR - throw not expected");
469 ++failures;
470 }
471
472 puts("Test pass 2 - throws");
473
474 for (int i = 0; i < 32; ++i)
475 {
476 TestFuncThrows = true;
477 bool caught = false;
478 try
479 {
480 switch (i)
481 {
482 case 0: Simple(1); break;
483 case 1: Try(1); break;
484 case 2: GSCookie(1); break;
485 case 3: TryAndGSCookie(1); break;
486 case 4: Align(1); break;
487 case 5: TryAndAlign(1); break;
488 case 6: GSCookieAndAlign(1); break;
489 case 7: TryAndGSCookieAndAlign(1); break;
490 case 8: Alloca(1); break;
491 case 9: TryAndAlloca(1); break;
492 case 10: GSCookieAndAlloca(1); break;
493 case 11: TryAndGSCookieAndAlloca(1); break;
494 case 12: AlignAndAlloca(1); break;
495 case 13: TryAndAlignAndAlloca(1); break;
496 case 14: GSCookieAndAlignAndAlloca(1); break;
497 case 15: TryAndGSCookieAndAlignAndAlloca(1); break;
498 case 16: BigLocals(1); break;
499 case 17: TryAndBigLocals(1); break;
500 case 18: GSCookieAndBigLocals(1); break;
501 case 19: TryAndGSCookieAndBigLocals(1); break;
502 case 20: AlignAndBigLocals(1); break;
503 case 21: TryAndAlignAndBigLocals(1); break;
504 case 22: GSCookieAndAlignAndBigLocals(1); break;
505 case 23: TryAndGSCookieAndAlignAndBigLocals(1); break;
506 case 24: AllocaAndBigLocals(1); break;
507 case 25: TryAndAllocaAndBigLocals(1); break;
508 case 26: GSCookieAndAllocaAndBigLocals(1); break;
509 case 27: TryAndGSCookieAndAllocaAndBigLocals(1); break;
510 case 28: AlignAndAllocaAndBigLocals(1); break;
511 case 29: TryAndAlignAndAllocaAndBigLocals(1); break;
512 case 30: GSCookieAndAlignAndAllocaAndBigLocals(1); break;
513 case 31: TryAndGSCookieAndAlignAndAllocaAndBigLocals(1); break;
514 }
515 }
516 catch (int)
517 {
518 caught = true;
519 }
520
521 if (!caught)
522 {
523 puts("ERROR - did not catch expected thrown object");
524 ++failures;
525 }
526 }
527 }
528
main()529 int main()
530 {
531 __try
532 {
533 RunTests();
534 }
535 __except (1)
536 {
537 puts("ERROR - Unexpectedly caught an exception");
538 ++failures;
539 }
540
541 if (failures)
542 {
543 printf("Test failed with %d failure%s\n",
544 failures, failures == 1 ? "" : "s");
545 }
546 else
547 {
548 puts("Test passed");
549 }
550
551 return failures;
552 }
553