123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- //===-- 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"
|