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