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