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