1 | //===-- nsan_suppressions.cc ----------------------------------------------===// |
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 | #include "nsan_suppressions.h" |
10 | #include "nsan_flags.h" |
11 | #include "sanitizer_common/sanitizer_placement_new.h" |
12 | #include "sanitizer_common/sanitizer_stacktrace.h" |
13 | #include "sanitizer_common/sanitizer_symbolizer.h" |
14 | |
15 | using namespace __sanitizer; |
16 | using namespace __nsan; |
17 | |
18 | SANITIZER_INTERFACE_WEAK_DEF(const char *, __nsan_default_suppressions, void) { |
19 | return 0; |
20 | } |
21 | |
22 | const char kSuppressionFcmp[] = "fcmp" ; |
23 | const char kSuppressionConsistency[] = "consistency" ; |
24 | |
25 | alignas(64) static char suppression_placeholder[sizeof(SuppressionContext)]; |
26 | static SuppressionContext *suppression_ctx; |
27 | |
28 | // The order should match the enum CheckKind. |
29 | static const char *kSuppressionTypes[] = {kSuppressionFcmp, |
30 | kSuppressionConsistency}; |
31 | |
32 | void __nsan::InitializeSuppressions() { |
33 | CHECK_EQ(nullptr, suppression_ctx); |
34 | suppression_ctx = new (suppression_placeholder) |
35 | SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes)); |
36 | suppression_ctx->ParseFromFile(filename: flags().suppressions); |
37 | suppression_ctx->Parse(str: __nsan_default_suppressions()); |
38 | } |
39 | |
40 | static Suppression *GetSuppressionForAddr(uptr addr, const char *suppr_type) { |
41 | Suppression *s = nullptr; |
42 | |
43 | // Suppress by module name. |
44 | SuppressionContext *suppressions = suppression_ctx; |
45 | if (const char *moduleName = |
46 | Symbolizer::GetOrInit()->GetModuleNameForPc(pc: addr)) { |
47 | if (suppressions->Match(str: moduleName, type: suppr_type, s: &s)) |
48 | return s; |
49 | } |
50 | |
51 | // Suppress by file or function name. |
52 | SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(address: addr); |
53 | for (SymbolizedStack *cur = frames; cur; cur = cur->next) { |
54 | if (suppressions->Match(str: cur->info.function, type: suppr_type, s: &s) || |
55 | suppressions->Match(str: cur->info.file, type: suppr_type, s: &s)) { |
56 | break; |
57 | } |
58 | } |
59 | frames->ClearAll(); |
60 | return s; |
61 | } |
62 | |
63 | Suppression *__nsan::GetSuppressionForStack(const StackTrace *stack, |
64 | CheckKind k) { |
65 | for (uptr i = 0, e = stack->size; i < e; i++) { |
66 | Suppression *s = GetSuppressionForAddr( |
67 | addr: StackTrace::GetPreviousInstructionPc(pc: stack->trace[i]), |
68 | suppr_type: kSuppressionTypes[static_cast<int>(k)]); |
69 | if (s) |
70 | return s; |
71 | } |
72 | return nullptr; |
73 | } |
74 | |