xref: /llvm-project/compiler-rt/lib/rtsan/rtsan.cpp (revision 4bdac0851f4d613890558a8254043e21b0479b1e)
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