1 //===-- sanitizer_termination.cc --------------------------------*- C++ -*-===// 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 /// This file contains the Sanitizer termination functions CheckFailed and Die, 11 /// and the callback functionalities associated with them. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "sanitizer_common.h" 16 #include "sanitizer_libc.h" 17 18 namespace __sanitizer { 19 20 static const int kMaxNumOfInternalDieCallbacks = 5; 21 static DieCallbackType InternalDieCallbacks[kMaxNumOfInternalDieCallbacks]; 22 23 bool AddDieCallback(DieCallbackType callback) { 24 for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) { 25 if (InternalDieCallbacks[i] == nullptr) { 26 InternalDieCallbacks[i] = callback; 27 return true; 28 } 29 } 30 return false; 31 } 32 33 bool RemoveDieCallback(DieCallbackType callback) { 34 for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) { 35 if (InternalDieCallbacks[i] == callback) { 36 internal_memmove(&InternalDieCallbacks[i], &InternalDieCallbacks[i + 1], 37 sizeof(InternalDieCallbacks[0]) * 38 (kMaxNumOfInternalDieCallbacks - i - 1)); 39 InternalDieCallbacks[kMaxNumOfInternalDieCallbacks - 1] = nullptr; 40 return true; 41 } 42 } 43 return false; 44 } 45 46 static DieCallbackType UserDieCallback; 47 void SetUserDieCallback(DieCallbackType callback) { 48 UserDieCallback = callback; 49 } 50 51 void NORETURN Die() { 52 if (UserDieCallback) 53 UserDieCallback(); 54 for (int i = kMaxNumOfInternalDieCallbacks - 1; i >= 0; i--) { 55 if (InternalDieCallbacks[i]) 56 InternalDieCallbacks[i](); 57 } 58 if (common_flags()->abort_on_error) 59 Abort(); 60 internal__exit(common_flags()->exitcode); 61 } 62 63 static CheckFailedCallbackType CheckFailedCallback; 64 void SetCheckFailedCallback(CheckFailedCallbackType callback) { 65 CheckFailedCallback = callback; 66 } 67 68 const int kSecondsToSleepWhenRecursiveCheckFailed = 2; 69 70 void NORETURN CheckFailed(const char *file, int line, const char *cond, 71 u64 v1, u64 v2) { 72 static atomic_uint32_t num_calls; 73 if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) > 10) { 74 SleepForSeconds(kSecondsToSleepWhenRecursiveCheckFailed); 75 Trap(); 76 } 77 78 if (CheckFailedCallback) { 79 CheckFailedCallback(file, line, cond, v1, v2); 80 } 81 Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file, line, cond, 82 v1, v2); 83 Die(); 84 } 85 86 } // namespace __sanitizer 87