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
ConvertTypeToFlagName(ErrorType Type)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
InitializeSuppressions()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
IsStackTraceSuppressed(const StackTrace & stack)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
IsFunctionSuppressed(const char * function_name)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