Viewing file: sanitizer_termination.cpp (2.98 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//===-- sanitizer_termination.cpp -------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// This file contains the Sanitizer termination functions CheckFailed and Die, /// and the callback functionalities associated with them. /// //===----------------------------------------------------------------------===//
#include "sanitizer_common.h" #include "sanitizer_libc.h"
namespace __sanitizer {
static const int kMaxNumOfInternalDieCallbacks = 5; static DieCallbackType InternalDieCallbacks[kMaxNumOfInternalDieCallbacks];
bool AddDieCallback(DieCallbackType callback) { for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) { if (InternalDieCallbacks[i] == nullptr) { InternalDieCallbacks[i] = callback; return true; } } return false; }
bool RemoveDieCallback(DieCallbackType callback) { for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) { if (InternalDieCallbacks[i] == callback) { internal_memmove(&InternalDieCallbacks[i], &InternalDieCallbacks[i + 1], sizeof(InternalDieCallbacks[0]) * (kMaxNumOfInternalDieCallbacks - i - 1)); InternalDieCallbacks[kMaxNumOfInternalDieCallbacks - 1] = nullptr; return true; } } return false; }
static DieCallbackType UserDieCallback; void SetUserDieCallback(DieCallbackType callback) { UserDieCallback = callback; }
void NORETURN Die() { if (UserDieCallback) UserDieCallback(); for (int i = kMaxNumOfInternalDieCallbacks - 1; i >= 0; i--) { if (InternalDieCallbacks[i]) InternalDieCallbacks[i](); } if (common_flags()->abort_on_error) Abort(); internal__exit(common_flags()->exitcode); }
static void (*CheckUnwindCallback)(); void SetCheckUnwindCallback(void (*callback)()) { CheckUnwindCallback = callback; }
void NORETURN CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2) { u32 tid = GetTid(); Printf("%s: CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx) (tid=%u)\n", SanitizerToolName, StripModuleName(file), line, cond, (uptr)v1, (uptr)v2, tid); static atomic_uint32_t first_tid; u32 cmp = 0; if (!atomic_compare_exchange_strong(&first_tid, &cmp, tid, memory_order_relaxed)) { if (cmp == tid) { // Recursing into CheckFailed. } else { // Another thread fails already, let it print the stack and terminate. SleepForSeconds(2); } Trap(); } if (CheckUnwindCallback) CheckUnwindCallback(); Die(); }
} // namespace __sanitizer
using namespace __sanitizer;
extern "C" { SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_set_death_callback(void (*callback)(void)) { SetUserDieCallback(callback); } } // extern "C"
|