|  | //===-- nsan_suppressions.cc ----------------------------------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "nsan_suppressions.h" | 
|  | #include "nsan_flags.h" | 
|  | #include "sanitizer_common/sanitizer_placement_new.h" | 
|  | #include "sanitizer_common/sanitizer_stacktrace.h" | 
|  | #include "sanitizer_common/sanitizer_symbolizer.h" | 
|  |  | 
|  | using namespace __sanitizer; | 
|  | using namespace __nsan; | 
|  |  | 
|  | SANITIZER_INTERFACE_WEAK_DEF(const char *, __nsan_default_suppressions, void) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | const char kSuppressionFcmp[] = "fcmp"; | 
|  | const char kSuppressionConsistency[] = "consistency"; | 
|  |  | 
|  | alignas(64) static char suppression_placeholder[sizeof(SuppressionContext)]; | 
|  | static SuppressionContext *suppression_ctx; | 
|  |  | 
|  | // The order should match the enum CheckKind. | 
|  | static const char *kSuppressionTypes[] = {kSuppressionFcmp, | 
|  | kSuppressionConsistency}; | 
|  |  | 
|  | void __nsan::InitializeSuppressions() { | 
|  | CHECK_EQ(nullptr, suppression_ctx); | 
|  | suppression_ctx = new (suppression_placeholder) | 
|  | SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes)); | 
|  | suppression_ctx->ParseFromFile(flags().suppressions); | 
|  | suppression_ctx->Parse(__nsan_default_suppressions()); | 
|  | } | 
|  |  | 
|  | static Suppression *GetSuppressionForAddr(uptr addr, const char *suppr_type) { | 
|  | Suppression *s = nullptr; | 
|  |  | 
|  | // Suppress by module name. | 
|  | SuppressionContext *suppressions = suppression_ctx; | 
|  | if (const char *moduleName = | 
|  | Symbolizer::GetOrInit()->GetModuleNameForPc(addr)) { | 
|  | if (suppressions->Match(moduleName, suppr_type, &s)) | 
|  | return s; | 
|  | } | 
|  |  | 
|  | // Suppress by file or function name. | 
|  | SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr); | 
|  | for (SymbolizedStack *cur = frames; cur; cur = cur->next) { | 
|  | if (suppressions->Match(cur->info.function, suppr_type, &s) || | 
|  | suppressions->Match(cur->info.file, suppr_type, &s)) { | 
|  | break; | 
|  | } | 
|  | } | 
|  | frames->ClearAll(); | 
|  | return s; | 
|  | } | 
|  |  | 
|  | Suppression *__nsan::GetSuppressionForStack(const StackTrace *stack, | 
|  | CheckKind k) { | 
|  | for (uptr i = 0, e = stack->size; i < e; i++) { | 
|  | Suppression *s = GetSuppressionForAddr( | 
|  | StackTrace::GetPreviousInstructionPc(stack->trace[i]), | 
|  | kSuppressionTypes[static_cast<int>(k)]); | 
|  | if (s) | 
|  | return s; | 
|  | } | 
|  | return nullptr; | 
|  | } |