155 lines · cpp
1//===--- rtsan.cpp - Realtime Sanitizer -------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//===----------------------------------------------------------------------===//10 11#include "rtsan/rtsan.h"12#include "rtsan/rtsan_assertions.h"13#include "rtsan/rtsan_diagnostics.h"14#include "rtsan/rtsan_flags.h"15#include "rtsan/rtsan_interceptors.h"16#include "rtsan/rtsan_stats.h"17#include "rtsan/rtsan_suppressions.h"18 19#include "sanitizer_common/sanitizer_atomic.h"20#include "sanitizer_common/sanitizer_common.h"21#include "sanitizer_common/sanitizer_mutex.h"22#include "sanitizer_common/sanitizer_stackdepot.h"23 24using namespace __rtsan;25using namespace __sanitizer;26 27namespace {28enum class InitializationState : u8 {29 Uninitialized,30 Initializing,31 Initialized,32};33} // namespace34 35static StaticSpinMutex rtsan_inited_mutex;36static atomic_uint8_t rtsan_initialized = {37 static_cast<u8>(InitializationState::Uninitialized)};38 39static void SetInitializationState(InitializationState state) {40 atomic_store(&rtsan_initialized, static_cast<u8>(state),41 memory_order_release);42}43 44static InitializationState GetInitializationState() {45 return static_cast<InitializationState>(46 atomic_load(&rtsan_initialized, memory_order_acquire));47}48 49static void OnViolation(const BufferedStackTrace &stack,50 const DiagnosticsInfo &info) {51 IncrementTotalErrorCount();52 53 // If in the future we interop with other sanitizers, we will54 // need to make our own stackdepot55 StackDepotHandle handle = StackDepotPut_WithHandle(stack);56 57 const bool is_stack_novel = handle.use_count() == 0;58 if (is_stack_novel || !flags().suppress_equal_stacks) {59 IncrementUniqueErrorCount();60 61 {62 ScopedErrorReportLock l;63 PrintDiagnostics(info);64 stack.Print();65 PrintErrorSummary(info, stack);66 }67 68 handle.inc_use_count_unsafe();69 }70 71 if (flags().halt_on_error) {72 if (flags().print_stats_on_exit)73 PrintStatisticsSummary();74 Die();75 }76}77 78extern "C" {79 80SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_init() {81 CHECK(GetInitializationState() == InitializationState::Uninitialized);82 SetInitializationState(InitializationState::Initializing);83 84 SanitizerToolName = "RealtimeSanitizer";85 InitializeFlags();86 87 InitializePlatformEarly();88 89 InitializeInterceptors();90 91 InitializeSuppressions();92 93 if (flags().print_stats_on_exit)94 Atexit(PrintStatisticsSummary);95 96 SetInitializationState(InitializationState::Initialized);97}98 99SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_ensure_initialized() {100 if (LIKELY(__rtsan_is_initialized()))101 return;102 103 SpinMutexLock lock(&rtsan_inited_mutex);104 105 // Someone may have initialized us while we were waiting for the lock106 if (__rtsan_is_initialized())107 return;108 109 __rtsan_init();110}111 112SANITIZER_INTERFACE_ATTRIBUTE bool __rtsan_is_initialized() {113 return GetInitializationState() == InitializationState::Initialized;114}115 116SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_enter() {117 GetContextForThisThread().RealtimePush();118}119 120SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_exit() {121 GetContextForThisThread().RealtimePop();122}123 124SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_disable() {125 GetContextForThisThread().BypassPush();126}127 128SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_enable() {129 GetContextForThisThread().BypassPop();130}131 132SANITIZER_INTERFACE_ATTRIBUTE void133__rtsan_notify_intercepted_call(const char *func_name) {134 // While initializing, we need all intercepted functions to behave normally135 if (GetInitializationState() == InitializationState::Initializing)136 return;137 138 __rtsan_ensure_initialized();139 GET_CALLER_PC_BP;140 ExpectNotRealtime(GetContextForThisThread(),141 {DiagnosticsInfoType::InterceptedCall, func_name, pc, bp},142 OnViolation);143}144 145SANITIZER_INTERFACE_ATTRIBUTE void146__rtsan_notify_blocking_call(const char *func_name) {147 __rtsan_ensure_initialized();148 GET_CALLER_PC_BP;149 ExpectNotRealtime(GetContextForThisThread(),150 {DiagnosticsInfoType::BlockingCall, func_name, pc, bp},151 OnViolation);152}153 154} // extern "C"155