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