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