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
24using namespace __sanitizer;
25using namespace __rtsan;
26
27namespace {
28enum class ErrorType {
29#define RTSAN_CHECK(Name, FSanitizeFlagName) Name,
30#include "rtsan_checks.inc"
31#undef RTSAN_CHECK
32};
33} // namespace
34
35alignas(64) static char suppression_placeholder[sizeof(SuppressionContext)];
36static SuppressionContext *suppression_ctx = nullptr;
37
38static const char *kSuppressionTypes[] = {
39#define RTSAN_CHECK(Name, FSanitizeFlagName) FSanitizeFlagName,
40#include "rtsan_checks.inc"
41#undef RTSAN_CHECK
42};
43
44static 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
55void __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(filename: flags().suppressions);
65}
66
67bool __rtsan::IsStackTraceSuppressed(const StackTrace &stack) {
68 if (suppression_ctx == nullptr)
69 return false;
70
71 const char *call_stack_flag =
72 ConvertTypeToFlagName(Type: ErrorType::CallStackContains);
73 if (!suppression_ctx->HasSuppressionType(type: 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(address: 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(str: function_name, type: call_stack_flag, s: &s))
90 return true;
91 }
92 }
93 return false;
94}
95
96bool __rtsan::IsFunctionSuppressed(const char *function_name) {
97 if (suppression_ctx == nullptr)
98 return false;
99
100 const char *flag_name = ConvertTypeToFlagName(Type: ErrorType::FunctionNameMatches);
101
102 if (!suppression_ctx->HasSuppressionType(type: flag_name))
103 return false;
104
105 Suppression *s;
106 return suppression_ctx->Match(str: function_name, type: flag_name, s: &s);
107}
108