xref: /aosp_15_r20/external/compiler-rt/lib/sanitizer_common/sanitizer_termination.cc (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
1*7c3d14c8STreehugger Robot //===-- sanitizer_termination.cc --------------------------------*- C++ -*-===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot //                     The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot ///
10*7c3d14c8STreehugger Robot /// This file contains the Sanitizer termination functions CheckFailed and Die,
11*7c3d14c8STreehugger Robot /// and the callback functionalities associated with them.
12*7c3d14c8STreehugger Robot ///
13*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
14*7c3d14c8STreehugger Robot 
15*7c3d14c8STreehugger Robot #include "sanitizer_common.h"
16*7c3d14c8STreehugger Robot #include "sanitizer_libc.h"
17*7c3d14c8STreehugger Robot 
18*7c3d14c8STreehugger Robot namespace __sanitizer {
19*7c3d14c8STreehugger Robot 
20*7c3d14c8STreehugger Robot static const int kMaxNumOfInternalDieCallbacks = 5;
21*7c3d14c8STreehugger Robot static DieCallbackType InternalDieCallbacks[kMaxNumOfInternalDieCallbacks];
22*7c3d14c8STreehugger Robot 
AddDieCallback(DieCallbackType callback)23*7c3d14c8STreehugger Robot bool AddDieCallback(DieCallbackType callback) {
24*7c3d14c8STreehugger Robot   for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) {
25*7c3d14c8STreehugger Robot     if (InternalDieCallbacks[i] == nullptr) {
26*7c3d14c8STreehugger Robot       InternalDieCallbacks[i] = callback;
27*7c3d14c8STreehugger Robot       return true;
28*7c3d14c8STreehugger Robot     }
29*7c3d14c8STreehugger Robot   }
30*7c3d14c8STreehugger Robot   return false;
31*7c3d14c8STreehugger Robot }
32*7c3d14c8STreehugger Robot 
RemoveDieCallback(DieCallbackType callback)33*7c3d14c8STreehugger Robot bool RemoveDieCallback(DieCallbackType callback) {
34*7c3d14c8STreehugger Robot   for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) {
35*7c3d14c8STreehugger Robot     if (InternalDieCallbacks[i] == callback) {
36*7c3d14c8STreehugger Robot       internal_memmove(&InternalDieCallbacks[i], &InternalDieCallbacks[i + 1],
37*7c3d14c8STreehugger Robot                        sizeof(InternalDieCallbacks[0]) *
38*7c3d14c8STreehugger Robot                            (kMaxNumOfInternalDieCallbacks - i - 1));
39*7c3d14c8STreehugger Robot       InternalDieCallbacks[kMaxNumOfInternalDieCallbacks - 1] = nullptr;
40*7c3d14c8STreehugger Robot       return true;
41*7c3d14c8STreehugger Robot     }
42*7c3d14c8STreehugger Robot   }
43*7c3d14c8STreehugger Robot   return false;
44*7c3d14c8STreehugger Robot }
45*7c3d14c8STreehugger Robot 
46*7c3d14c8STreehugger Robot static DieCallbackType UserDieCallback;
SetUserDieCallback(DieCallbackType callback)47*7c3d14c8STreehugger Robot void SetUserDieCallback(DieCallbackType callback) {
48*7c3d14c8STreehugger Robot   UserDieCallback = callback;
49*7c3d14c8STreehugger Robot }
50*7c3d14c8STreehugger Robot 
Die()51*7c3d14c8STreehugger Robot void NORETURN Die() {
52*7c3d14c8STreehugger Robot   if (UserDieCallback)
53*7c3d14c8STreehugger Robot     UserDieCallback();
54*7c3d14c8STreehugger Robot   for (int i = kMaxNumOfInternalDieCallbacks - 1; i >= 0; i--) {
55*7c3d14c8STreehugger Robot     if (InternalDieCallbacks[i])
56*7c3d14c8STreehugger Robot       InternalDieCallbacks[i]();
57*7c3d14c8STreehugger Robot   }
58*7c3d14c8STreehugger Robot   if (common_flags()->abort_on_error)
59*7c3d14c8STreehugger Robot     Abort();
60*7c3d14c8STreehugger Robot   internal__exit(common_flags()->exitcode);
61*7c3d14c8STreehugger Robot }
62*7c3d14c8STreehugger Robot 
63*7c3d14c8STreehugger Robot static CheckFailedCallbackType CheckFailedCallback;
SetCheckFailedCallback(CheckFailedCallbackType callback)64*7c3d14c8STreehugger Robot void SetCheckFailedCallback(CheckFailedCallbackType callback) {
65*7c3d14c8STreehugger Robot   CheckFailedCallback = callback;
66*7c3d14c8STreehugger Robot }
67*7c3d14c8STreehugger Robot 
68*7c3d14c8STreehugger Robot const int kSecondsToSleepWhenRecursiveCheckFailed = 2;
69*7c3d14c8STreehugger Robot 
CheckFailed(const char * file,int line,const char * cond,u64 v1,u64 v2)70*7c3d14c8STreehugger Robot void NORETURN CheckFailed(const char *file, int line, const char *cond,
71*7c3d14c8STreehugger Robot                           u64 v1, u64 v2) {
72*7c3d14c8STreehugger Robot   static atomic_uint32_t num_calls;
73*7c3d14c8STreehugger Robot   if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) > 10) {
74*7c3d14c8STreehugger Robot     SleepForSeconds(kSecondsToSleepWhenRecursiveCheckFailed);
75*7c3d14c8STreehugger Robot     Trap();
76*7c3d14c8STreehugger Robot   }
77*7c3d14c8STreehugger Robot 
78*7c3d14c8STreehugger Robot   if (CheckFailedCallback) {
79*7c3d14c8STreehugger Robot     CheckFailedCallback(file, line, cond, v1, v2);
80*7c3d14c8STreehugger Robot   }
81*7c3d14c8STreehugger Robot   Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file, line, cond,
82*7c3d14c8STreehugger Robot                                                             v1, v2);
83*7c3d14c8STreehugger Robot   Die();
84*7c3d14c8STreehugger Robot }
85*7c3d14c8STreehugger Robot 
86*7c3d14c8STreehugger Robot } // namespace __sanitizer
87