brintos

brintos / llvm-project-archived public Read only

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