1 //===- llvm/unittest/Support/CrashRecoveryTest.cpp ------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Support/Compiler.h" 10 #include "llvm/Support/CrashRecoveryContext.h" 11 #include "gtest/gtest.h" 12 13 #ifdef _WIN32 14 #define WIN32_LEAN_AND_MEAN 15 #define NOGDI 16 #include <windows.h> 17 #endif 18 19 using namespace llvm; 20 using namespace llvm::sys; 21 22 static int GlobalInt = 0; 23 static void nullDeref() { *(volatile int *)0x10 = 0; } 24 static void incrementGlobal() { ++GlobalInt; } 25 static void llvmTrap() { LLVM_BUILTIN_TRAP; } 26 27 TEST(CrashRecoveryTest, Basic) { 28 llvm::CrashRecoveryContext::Enable(); 29 GlobalInt = 0; 30 EXPECT_TRUE(CrashRecoveryContext().RunSafely(incrementGlobal)); 31 EXPECT_EQ(1, GlobalInt); 32 EXPECT_FALSE(CrashRecoveryContext().RunSafely(nullDeref)); 33 EXPECT_FALSE(CrashRecoveryContext().RunSafely(llvmTrap)); 34 } 35 36 struct IncrementGlobalCleanup : CrashRecoveryContextCleanup { 37 IncrementGlobalCleanup(CrashRecoveryContext *CRC) 38 : CrashRecoveryContextCleanup(CRC) {} 39 virtual void recoverResources() { ++GlobalInt; } 40 }; 41 42 static void noop() {} 43 44 TEST(CrashRecoveryTest, Cleanup) { 45 llvm::CrashRecoveryContext::Enable(); 46 GlobalInt = 0; 47 { 48 CrashRecoveryContext CRC; 49 CRC.registerCleanup(new IncrementGlobalCleanup(&CRC)); 50 EXPECT_TRUE(CRC.RunSafely(noop)); 51 } // run cleanups 52 EXPECT_EQ(1, GlobalInt); 53 54 GlobalInt = 0; 55 { 56 CrashRecoveryContext CRC; 57 CRC.registerCleanup(new IncrementGlobalCleanup(&CRC)); 58 EXPECT_FALSE(CRC.RunSafely(nullDeref)); 59 } // run cleanups 60 EXPECT_EQ(1, GlobalInt); 61 } 62 63 #ifdef _WIN32 64 static void raiseIt() { 65 RaiseException(123, EXCEPTION_NONCONTINUABLE, 0, NULL); 66 } 67 68 TEST(CrashRecoveryTest, RaiseException) { 69 llvm::CrashRecoveryContext::Enable(); 70 EXPECT_FALSE(CrashRecoveryContext().RunSafely(raiseIt)); 71 } 72 73 static void outputString() { 74 OutputDebugStringA("output for debugger\n"); 75 } 76 77 TEST(CrashRecoveryTest, CallOutputDebugString) { 78 llvm::CrashRecoveryContext::Enable(); 79 EXPECT_TRUE(CrashRecoveryContext().RunSafely(outputString)); 80 } 81 82 #endif 83