brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · 73340b3 Raw
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