11adb55b1SChris Apple //===--- rtsan.cpp - Realtime Sanitizer -------------------------*- C++ -*-===// 21adb55b1SChris Apple // 31adb55b1SChris Apple // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41adb55b1SChris Apple // See https://llvm.org/LICENSE.txt for license information. 51adb55b1SChris Apple // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61adb55b1SChris Apple // 71adb55b1SChris Apple //===----------------------------------------------------------------------===// 81adb55b1SChris Apple // 91adb55b1SChris Apple //===----------------------------------------------------------------------===// 101adb55b1SChris Apple 113477eb72SChris Apple #include "rtsan/rtsan.h" 123477eb72SChris Apple #include "rtsan/rtsan_assertions.h" 133477eb72SChris Apple #include "rtsan/rtsan_diagnostics.h" 143477eb72SChris Apple #include "rtsan/rtsan_flags.h" 153477eb72SChris Apple #include "rtsan/rtsan_interceptors.h" 16c3334dadSChris Apple #include "rtsan/rtsan_stats.h" 174468d580SChris Apple #include "rtsan/rtsan_suppressions.h" 181adb55b1SChris Apple 190a2a319eSChris Apple #include "sanitizer_common/sanitizer_atomic.h" 202e9b3316SChris Apple #include "sanitizer_common/sanitizer_common.h" 210a2a319eSChris Apple #include "sanitizer_common/sanitizer_mutex.h" 22f5b95db4SChris Apple #include "sanitizer_common/sanitizer_stackdepot.h" 23b177ac4aSdavidtrevelyan 240a2a319eSChris Apple using namespace __rtsan; 250a2a319eSChris Apple using namespace __sanitizer; 260a2a319eSChris Apple 2709075523SChris Apple namespace { 2809075523SChris Apple enum class InitializationState : u8 { 2909075523SChris Apple Uninitialized, 3009075523SChris Apple Initializing, 3109075523SChris Apple Initialized, 3209075523SChris Apple }; 3309075523SChris Apple } // namespace 3409075523SChris Apple 350a2a319eSChris Apple static StaticSpinMutex rtsan_inited_mutex; 3638371a18SChris Apple static atomic_uint8_t rtsan_initialized = { 3738371a18SChris Apple static_cast<u8>(InitializationState::Uninitialized)}; 380a2a319eSChris Apple 3909075523SChris Apple static void SetInitializationState(InitializationState state) { 4009075523SChris Apple atomic_store(&rtsan_initialized, static_cast<u8>(state), 4109075523SChris Apple memory_order_release); 4209075523SChris Apple } 4309075523SChris Apple 4409075523SChris Apple static InitializationState GetInitializationState() { 4509075523SChris Apple return static_cast<InitializationState>( 4609075523SChris Apple atomic_load(&rtsan_initialized, memory_order_acquire)); 470a2a319eSChris Apple } 48b177ac4aSdavidtrevelyan 493423a5e3SChris Apple static void OnViolation(const BufferedStackTrace &stack, 503423a5e3SChris Apple const DiagnosticsInfo &info) { 51c3334dadSChris Apple IncrementTotalErrorCount(); 52c3334dadSChris Apple 53f5b95db4SChris Apple // If in the future we interop with other sanitizers, we will 54f5b95db4SChris Apple // need to make our own stackdepot 55f5b95db4SChris Apple StackDepotHandle handle = StackDepotPut_WithHandle(stack); 56f5b95db4SChris Apple 57f5b95db4SChris Apple const bool is_stack_novel = handle.use_count() == 0; 58595e484cSChris Apple if (is_stack_novel || !flags().suppress_equal_stacks) { 59f5b95db4SChris Apple IncrementUniqueErrorCount(); 60f5b95db4SChris Apple 617c41b5ccSChris Apple { 627c41b5ccSChris Apple ScopedErrorReportLock l; 63c3334dadSChris Apple PrintDiagnostics(info); 64f5b95db4SChris Apple stack.Print(); 657c41b5ccSChris Apple PrintErrorSummary(info, stack); 667c41b5ccSChris Apple } 67f5b95db4SChris Apple 68f5b95db4SChris Apple handle.inc_use_count_unsafe(); 69f5b95db4SChris Apple } 70c3334dadSChris Apple 719e06e772SChris Apple if (flags().halt_on_error) { 729e06e772SChris Apple if (flags().print_stats_on_exit) 739e06e772SChris Apple PrintStatisticsSummary(); 74a04db2c7Sdavidtrevelyan Die(); 759e06e772SChris Apple } 76a04db2c7Sdavidtrevelyan } 77a04db2c7Sdavidtrevelyan 781adb55b1SChris Apple extern "C" { 791adb55b1SChris Apple 801adb55b1SChris Apple SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_init() { 8109075523SChris Apple CHECK(GetInitializationState() == InitializationState::Uninitialized); 8209075523SChris Apple SetInitializationState(InitializationState::Initializing); 832e9b3316SChris Apple 842e9b3316SChris Apple SanitizerToolName = "RealtimeSanitizer"; 852e9b3316SChris Apple InitializeFlags(); 86*4bdac085SChris Apple 87*4bdac085SChris Apple InitializePlatformEarly(); 88*4bdac085SChris Apple 89b177ac4aSdavidtrevelyan InitializeInterceptors(); 902e9b3316SChris Apple 914468d580SChris Apple InitializeSuppressions(); 924468d580SChris Apple 93c3334dadSChris Apple if (flags().print_stats_on_exit) 94c3334dadSChris Apple Atexit(PrintStatisticsSummary); 95c3334dadSChris Apple 9609075523SChris Apple SetInitializationState(InitializationState::Initialized); 970a2a319eSChris Apple } 98b177ac4aSdavidtrevelyan 990a2a319eSChris Apple SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_ensure_initialized() { 1000a2a319eSChris Apple if (LIKELY(__rtsan_is_initialized())) 1010a2a319eSChris Apple return; 1020a2a319eSChris Apple 1030a2a319eSChris Apple SpinMutexLock lock(&rtsan_inited_mutex); 1040a2a319eSChris Apple 1050a2a319eSChris Apple // Someone may have initialized us while we were waiting for the lock 1060a2a319eSChris Apple if (__rtsan_is_initialized()) 1070a2a319eSChris Apple return; 1080a2a319eSChris Apple 1090a2a319eSChris Apple __rtsan_init(); 1100a2a319eSChris Apple } 1110a2a319eSChris Apple 1120a2a319eSChris Apple SANITIZER_INTERFACE_ATTRIBUTE bool __rtsan_is_initialized() { 11309075523SChris Apple return GetInitializationState() == InitializationState::Initialized; 1141adb55b1SChris Apple } 1151adb55b1SChris Apple 1161adb55b1SChris Apple SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_enter() { 117e069434aSChris Apple GetContextForThisThread().RealtimePush(); 1181adb55b1SChris Apple } 1191adb55b1SChris Apple 1201adb55b1SChris Apple SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_exit() { 121e069434aSChris Apple GetContextForThisThread().RealtimePop(); 1221adb55b1SChris Apple } 1231adb55b1SChris Apple 124a919588dSChris Apple SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_disable() { 125e069434aSChris Apple GetContextForThisThread().BypassPush(); 1261adb55b1SChris Apple } 1271adb55b1SChris Apple 128a919588dSChris Apple SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_enable() { 129e069434aSChris Apple GetContextForThisThread().BypassPop(); 1301adb55b1SChris Apple } 1311adb55b1SChris Apple 132fee48365SChris Apple SANITIZER_INTERFACE_ATTRIBUTE void 133a04db2c7Sdavidtrevelyan __rtsan_notify_intercepted_call(const char *func_name) { 13409075523SChris Apple // While initializing, we need all intercepted functions to behave normally 13509075523SChris Apple if (GetInitializationState() == InitializationState::Initializing) 13609075523SChris Apple return; 13709075523SChris Apple 138fee48365SChris Apple __rtsan_ensure_initialized(); 1391b601938SChris Apple GET_CALLER_PC_BP; 1409ef9acbdSChris Apple ExpectNotRealtime(GetContextForThisThread(), 1413423a5e3SChris Apple {DiagnosticsInfoType::InterceptedCall, func_name, pc, bp}, 1423423a5e3SChris Apple OnViolation); 143fee48365SChris Apple } 1441b601938SChris Apple 1451b601938SChris Apple SANITIZER_INTERFACE_ATTRIBUTE void 146a04db2c7Sdavidtrevelyan __rtsan_notify_blocking_call(const char *func_name) { 1471b601938SChris Apple __rtsan_ensure_initialized(); 1481b601938SChris Apple GET_CALLER_PC_BP; 1499ef9acbdSChris Apple ExpectNotRealtime(GetContextForThisThread(), 1503423a5e3SChris Apple {DiagnosticsInfoType::BlockingCall, func_name, pc, bp}, 1513423a5e3SChris Apple OnViolation); 1521b601938SChris Apple } 1531b601938SChris Apple 1541adb55b1SChris Apple } // extern "C" 155