sanitizer_termination.cpp 3.0 KB

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