1 1.1 mrg //===-- sanitizer_termination.cpp -------------------------------*- C++ -*-===// 2 1.1 mrg // 3 1.1 mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 1.1 mrg // See https://llvm.org/LICENSE.txt for license information. 5 1.1 mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 1.1 mrg // 7 1.1 mrg //===----------------------------------------------------------------------===// 8 1.1 mrg /// 9 1.1 mrg /// This file contains the Sanitizer termination functions CheckFailed and Die, 10 1.1 mrg /// and the callback functionalities associated with them. 11 1.1 mrg /// 12 1.1 mrg //===----------------------------------------------------------------------===// 13 1.1 mrg 14 1.1 mrg #include "sanitizer_common.h" 15 1.1 mrg #include "sanitizer_libc.h" 16 1.1 mrg 17 1.1 mrg namespace __sanitizer { 18 1.1 mrg 19 1.1 mrg static const int kMaxNumOfInternalDieCallbacks = 5; 20 1.1 mrg static DieCallbackType InternalDieCallbacks[kMaxNumOfInternalDieCallbacks]; 21 1.1 mrg 22 1.1 mrg bool AddDieCallback(DieCallbackType callback) { 23 1.1 mrg for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) { 24 1.1 mrg if (InternalDieCallbacks[i] == nullptr) { 25 1.1 mrg InternalDieCallbacks[i] = callback; 26 1.1 mrg return true; 27 1.1 mrg } 28 1.1 mrg } 29 1.1 mrg return false; 30 1.1 mrg } 31 1.1 mrg 32 1.1 mrg bool RemoveDieCallback(DieCallbackType callback) { 33 1.1 mrg for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) { 34 1.1 mrg if (InternalDieCallbacks[i] == callback) { 35 1.1 mrg internal_memmove(&InternalDieCallbacks[i], &InternalDieCallbacks[i + 1], 36 1.1 mrg sizeof(InternalDieCallbacks[0]) * 37 1.1 mrg (kMaxNumOfInternalDieCallbacks - i - 1)); 38 1.1 mrg InternalDieCallbacks[kMaxNumOfInternalDieCallbacks - 1] = nullptr; 39 1.1 mrg return true; 40 1.1 mrg } 41 1.1 mrg } 42 1.1 mrg return false; 43 1.1 mrg } 44 1.1 mrg 45 1.1 mrg static DieCallbackType UserDieCallback; 46 1.1 mrg void SetUserDieCallback(DieCallbackType callback) { 47 1.1 mrg UserDieCallback = callback; 48 1.1 mrg } 49 1.1 mrg 50 1.1 mrg void NORETURN Die() { 51 1.1 mrg if (UserDieCallback) 52 1.1 mrg UserDieCallback(); 53 1.1 mrg for (int i = kMaxNumOfInternalDieCallbacks - 1; i >= 0; i--) { 54 1.1 mrg if (InternalDieCallbacks[i]) 55 1.1 mrg InternalDieCallbacks[i](); 56 1.1 mrg } 57 1.1 mrg if (common_flags()->abort_on_error) 58 1.1 mrg Abort(); 59 1.1 mrg internal__exit(common_flags()->exitcode); 60 1.1 mrg } 61 1.1 mrg 62 1.1 mrg static void (*CheckUnwindCallback)(); 63 1.1 mrg void SetCheckUnwindCallback(void (*callback)()) { 64 1.1 mrg CheckUnwindCallback = callback; 65 1.1 mrg } 66 1.1 mrg 67 1.1 mrg void NORETURN CheckFailed(const char *file, int line, const char *cond, 68 1.1 mrg u64 v1, u64 v2) { 69 1.1 mrg u32 tid = GetTid(); 70 1.1 mrg Printf("%s: CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx) (tid=%u)\n", 71 1.1 mrg SanitizerToolName, StripModuleName(file), line, cond, (uptr)v1, 72 1.1 mrg (uptr)v2, tid); 73 1.1 mrg static atomic_uint32_t first_tid; 74 1.1 mrg u32 cmp = 0; 75 1.1 mrg if (!atomic_compare_exchange_strong(&first_tid, &cmp, tid, 76 1.1 mrg memory_order_relaxed)) { 77 1.1 mrg if (cmp == tid) { 78 1.1 mrg // Recursing into CheckFailed. 79 1.1 mrg } else { 80 1.1 mrg // Another thread fails already, let it print the stack and terminate. 81 1.1 mrg SleepForSeconds(2); 82 1.1 mrg } 83 1.1 mrg Trap(); 84 1.1 mrg } 85 1.1 mrg if (CheckUnwindCallback) 86 1.1 mrg CheckUnwindCallback(); 87 1.1 mrg Die(); 88 1.1 mrg } 89 1.1 mrg 90 1.1 mrg } // namespace __sanitizer 91 1.1 mrg 92 1.1 mrg using namespace __sanitizer; 93 1.1 mrg 94 1.1 mrg extern "C" { 95 1.1 mrg SANITIZER_INTERFACE_ATTRIBUTE 96 1.1 mrg void __sanitizer_set_death_callback(void (*callback)(void)) { 97 1.1 mrg SetUserDieCallback(callback); 98 1.1 mrg } 99 1.1 mrg } // extern "C" 100