1 //===-- sanitizer_termination.cpp -------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 /// This file contains the Sanitizer termination functions CheckFailed and Die,
10 /// and the callback functionalities associated with them.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_common.h"
15 #include "sanitizer_libc.h"
17 namespace __sanitizer
{
19 static const int kMaxNumOfInternalDieCallbacks
= 5;
20 static DieCallbackType InternalDieCallbacks
[kMaxNumOfInternalDieCallbacks
];
22 bool AddDieCallback(DieCallbackType callback
) {
23 for (int i
= 0; i
< kMaxNumOfInternalDieCallbacks
; i
++) {
24 if (InternalDieCallbacks
[i
] == nullptr) {
25 InternalDieCallbacks
[i
] = callback
;
32 bool 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;
45 static DieCallbackType UserDieCallback
;
46 void SetUserDieCallback(DieCallbackType callback
) {
47 UserDieCallback
= callback
;
53 for (int i
= kMaxNumOfInternalDieCallbacks
- 1; i
>= 0; i
--) {
54 if (InternalDieCallbacks
[i
])
55 InternalDieCallbacks
[i
]();
57 if (common_flags()->abort_on_error
)
59 internal__exit(common_flags()->exitcode
);
62 static void (*CheckUnwindCallback
)();
63 void SetCheckUnwindCallback(void (*callback
)()) {
64 CheckUnwindCallback
= callback
;
67 void NORETURN
CheckFailed(const char *file
, int line
, const char *cond
,
70 Printf("%s: CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx) (tid=%u)\n",
71 SanitizerToolName
, StripModuleName(file
), line
, cond
, (uptr
)v1
,
73 static atomic_uint32_t first_tid
;
75 if (!atomic_compare_exchange_strong(&first_tid
, &cmp
, tid
,
76 memory_order_relaxed
)) {
78 // Recursing into CheckFailed.
80 // Another thread fails already, let it print the stack and terminate.
85 if (CheckUnwindCallback
)
86 CheckUnwindCallback();
90 } // namespace __sanitizer
92 using namespace __sanitizer
;
95 SANITIZER_INTERFACE_ATTRIBUTE
96 void __sanitizer_set_death_callback(void (*callback
)(void)) {
97 SetUserDieCallback(callback
);