1 //===--- rtsan_suppressions.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of the RTSan runtime, providing support for suppressions 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "rtsan/rtsan_suppressions.h" 14 15 #include "rtsan/rtsan_flags.h" 16 17 #include "sanitizer_common/sanitizer_common.h" 18 #include "sanitizer_common/sanitizer_internal_defs.h" 19 #include "sanitizer_common/sanitizer_suppressions.h" 20 #include "sanitizer_common/sanitizer_symbolizer.h" 21 22 #include <new> 23 24 using namespace __sanitizer; 25 using namespace __rtsan; 26 27 namespace { 28 enum class ErrorType { 29 #define RTSAN_CHECK(Name, FSanitizeFlagName) Name, 30 #include "rtsan_checks.inc" 31 #undef RTSAN_CHECK 32 }; 33 } // namespace 34 35 alignas(64) static char suppression_placeholder[sizeof(SuppressionContext)]; 36 static SuppressionContext *suppression_ctx = nullptr; 37 38 static const char *kSuppressionTypes[] = { 39 #define RTSAN_CHECK(Name, FSanitizeFlagName) FSanitizeFlagName, 40 #include "rtsan_checks.inc" 41 #undef RTSAN_CHECK 42 }; 43 44 static const char *ConvertTypeToFlagName(ErrorType Type) { 45 switch (Type) { 46 #define RTSAN_CHECK(Name, FSanitizeFlagName) \ 47 case ErrorType::Name: \ 48 return FSanitizeFlagName; 49 #include "rtsan_checks.inc" 50 #undef RTSAN_CHECK 51 } 52 UNREACHABLE("unknown ErrorType!"); 53 } 54 55 void __rtsan::InitializeSuppressions() { 56 CHECK_EQ(nullptr, suppression_ctx); 57 58 // We will use suppression_ctx == nullptr as an early out 59 if (!flags().ContainsSuppresionFile()) 60 return; 61 62 suppression_ctx = new (suppression_placeholder) 63 SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes)); 64 suppression_ctx->ParseFromFile(flags().suppressions); 65 } 66 67 bool __rtsan::IsStackTraceSuppressed(const StackTrace &stack) { 68 if (suppression_ctx == nullptr) 69 return false; 70 71 const char *call_stack_flag = 72 ConvertTypeToFlagName(ErrorType::CallStackContains); 73 if (!suppression_ctx->HasSuppressionType(call_stack_flag)) 74 return false; 75 76 Symbolizer *symbolizer = Symbolizer::GetOrInit(); 77 for (uptr i = 0; i < stack.size && stack.trace[i]; i++) { 78 const uptr addr = stack.trace[i]; 79 80 SymbolizedStackHolder symbolized_stack(symbolizer->SymbolizePC(addr)); 81 const SymbolizedStack *frames = symbolized_stack.get(); 82 CHECK(frames); 83 for (const SymbolizedStack *cur = frames; cur; cur = cur->next) { 84 const char *function_name = cur->info.function; 85 if (!function_name) 86 continue; 87 88 Suppression *s; 89 if (suppression_ctx->Match(function_name, call_stack_flag, &s)) 90 return true; 91 } 92 } 93 return false; 94 } 95 96 bool __rtsan::IsFunctionSuppressed(const char *function_name) { 97 if (suppression_ctx == nullptr) 98 return false; 99 100 const char *flag_name = ConvertTypeToFlagName(ErrorType::FunctionNameMatches); 101 102 if (!suppression_ctx->HasSuppressionType(flag_name)) 103 return false; 104 105 Suppression *s; 106 return suppression_ctx->Match(function_name, flag_name, &s); 107 } 108