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 { 27 virtual ~SmallObj() 28 { 29 TestFunc(1, this); 30 }; 31 32 int x; 33 }; 34 35 struct BigObj 36 { 37 virtual ~BigObj() 38 { 39 TestFunc(1, this); 40 }; 41 42 char x[4096]; 43 }; 44 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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) 416 int TestFunc(int, ...) 417 { 418 if (TestFuncThrows) 419 { 420 TestFuncThrows = false; 421 throw 123; 422 } 423 424 return global; 425 } 426 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 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