Home | History | Annotate | Line # | Download | only in tsan
      1  1.1  mrg //===-- tsan_suppressions.cpp ---------------------------------------------===//
      2  1.1  mrg //
      3  1.1  mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4  1.1  mrg // See https://llvm.org/LICENSE.txt for license information.
      5  1.1  mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6  1.1  mrg //
      7  1.1  mrg //===----------------------------------------------------------------------===//
      8  1.1  mrg //
      9  1.1  mrg // This file is a part of ThreadSanitizer (TSan), a race detector.
     10  1.1  mrg //
     11  1.1  mrg //===----------------------------------------------------------------------===//
     12  1.1  mrg 
     13  1.4  mrg #include "tsan_suppressions.h"
     14  1.4  mrg 
     15  1.1  mrg #include "sanitizer_common/sanitizer_common.h"
     16  1.1  mrg #include "sanitizer_common/sanitizer_libc.h"
     17  1.1  mrg #include "sanitizer_common/sanitizer_placement_new.h"
     18  1.1  mrg #include "sanitizer_common/sanitizer_suppressions.h"
     19  1.1  mrg #include "tsan_flags.h"
     20  1.1  mrg #include "tsan_mman.h"
     21  1.1  mrg #include "tsan_platform.h"
     22  1.4  mrg #include "tsan_rtl.h"
     23  1.1  mrg 
     24  1.1  mrg #if !SANITIZER_GO
     25  1.1  mrg // Suppressions for true/false positives in standard libraries.
     26  1.1  mrg static const char *const std_suppressions =
     27  1.1  mrg // Libstdc++ 4.4 has data races in std::string.
     28  1.1  mrg // See http://crbug.com/181502 for an example.
     29  1.1  mrg "race:^_M_rep$\n"
     30  1.1  mrg "race:^_M_is_leaked$\n"
     31  1.1  mrg // False positive when using std <thread>.
     32  1.1  mrg // Happens because we miss atomic synchronization in libstdc++.
     33  1.1  mrg // See http://llvm.org/bugs/show_bug.cgi?id=17066 for details.
     34  1.1  mrg "race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n";
     35  1.1  mrg 
     36  1.1  mrg // Can be overriden in frontend.
     37  1.1  mrg SANITIZER_WEAK_DEFAULT_IMPL
     38  1.1  mrg const char *__tsan_default_suppressions() {
     39  1.1  mrg   return 0;
     40  1.1  mrg }
     41  1.1  mrg #endif
     42  1.1  mrg 
     43  1.1  mrg namespace __tsan {
     44  1.1  mrg 
     45  1.1  mrg ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
     46  1.1  mrg static SuppressionContext *suppression_ctx = nullptr;
     47  1.1  mrg static const char *kSuppressionTypes[] = {
     48  1.1  mrg     kSuppressionRace,   kSuppressionRaceTop, kSuppressionMutex,
     49  1.1  mrg     kSuppressionThread, kSuppressionSignal, kSuppressionLib,
     50  1.1  mrg     kSuppressionDeadlock};
     51  1.1  mrg 
     52  1.1  mrg void InitializeSuppressions() {
     53  1.1  mrg   CHECK_EQ(nullptr, suppression_ctx);
     54  1.1  mrg   suppression_ctx = new (suppression_placeholder)
     55  1.1  mrg       SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
     56  1.1  mrg   suppression_ctx->ParseFromFile(flags()->suppressions);
     57  1.1  mrg #if !SANITIZER_GO
     58  1.1  mrg   suppression_ctx->Parse(__tsan_default_suppressions());
     59  1.1  mrg   suppression_ctx->Parse(std_suppressions);
     60  1.1  mrg #endif
     61  1.1  mrg }
     62  1.1  mrg 
     63  1.1  mrg SuppressionContext *Suppressions() {
     64  1.1  mrg   CHECK(suppression_ctx);
     65  1.1  mrg   return suppression_ctx;
     66  1.1  mrg }
     67  1.1  mrg 
     68  1.1  mrg static const char *conv(ReportType typ) {
     69  1.1  mrg   switch (typ) {
     70  1.1  mrg     case ReportTypeRace:
     71  1.1  mrg     case ReportTypeVptrRace:
     72  1.1  mrg     case ReportTypeUseAfterFree:
     73  1.1  mrg     case ReportTypeVptrUseAfterFree:
     74  1.1  mrg     case ReportTypeExternalRace:
     75  1.1  mrg       return kSuppressionRace;
     76  1.1  mrg     case ReportTypeThreadLeak:
     77  1.1  mrg       return kSuppressionThread;
     78  1.1  mrg     case ReportTypeMutexDestroyLocked:
     79  1.1  mrg     case ReportTypeMutexDoubleLock:
     80  1.1  mrg     case ReportTypeMutexInvalidAccess:
     81  1.1  mrg     case ReportTypeMutexBadUnlock:
     82  1.1  mrg     case ReportTypeMutexBadReadLock:
     83  1.1  mrg     case ReportTypeMutexBadReadUnlock:
     84  1.4  mrg     case ReportTypeMutexHeldWrongContext:
     85  1.1  mrg       return kSuppressionMutex;
     86  1.1  mrg     case ReportTypeSignalUnsafe:
     87  1.1  mrg     case ReportTypeErrnoInSignal:
     88  1.1  mrg       return kSuppressionSignal;
     89  1.1  mrg     case ReportTypeDeadlock:
     90  1.1  mrg       return kSuppressionDeadlock;
     91  1.1  mrg     // No default case so compiler warns us if we miss one
     92  1.1  mrg   }
     93  1.1  mrg   UNREACHABLE("missing case");
     94  1.1  mrg }
     95  1.1  mrg 
     96  1.1  mrg static uptr IsSuppressed(const char *stype, const AddressInfo &info,
     97  1.1  mrg     Suppression **sp) {
     98  1.1  mrg   if (suppression_ctx->Match(info.function, stype, sp) ||
     99  1.1  mrg       suppression_ctx->Match(info.file, stype, sp) ||
    100  1.1  mrg       suppression_ctx->Match(info.module, stype, sp)) {
    101  1.1  mrg     VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", (*sp)->templ);
    102  1.1  mrg     atomic_fetch_add(&(*sp)->hit_count, 1, memory_order_relaxed);
    103  1.1  mrg     return info.address;
    104  1.1  mrg   }
    105  1.1  mrg   return 0;
    106  1.1  mrg }
    107  1.1  mrg 
    108  1.1  mrg uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
    109  1.1  mrg   CHECK(suppression_ctx);
    110  1.1  mrg   if (!suppression_ctx->SuppressionCount() || stack == 0 ||
    111  1.1  mrg       !stack->suppressable)
    112  1.1  mrg     return 0;
    113  1.1  mrg   const char *stype = conv(typ);
    114  1.1  mrg   if (0 == internal_strcmp(stype, kSuppressionNone))
    115  1.1  mrg     return 0;
    116  1.1  mrg   for (const SymbolizedStack *frame = stack->frames; frame;
    117  1.1  mrg       frame = frame->next) {
    118  1.1  mrg     uptr pc = IsSuppressed(stype, frame->info, sp);
    119  1.1  mrg     if (pc != 0)
    120  1.1  mrg       return pc;
    121  1.1  mrg   }
    122  1.1  mrg   if (0 == internal_strcmp(stype, kSuppressionRace) && stack->frames != nullptr)
    123  1.1  mrg     return IsSuppressed(kSuppressionRaceTop, stack->frames->info, sp);
    124  1.1  mrg   return 0;
    125  1.1  mrg }
    126  1.1  mrg 
    127  1.1  mrg uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
    128  1.1  mrg   CHECK(suppression_ctx);
    129  1.1  mrg   if (!suppression_ctx->SuppressionCount() || loc == 0 ||
    130  1.1  mrg       loc->type != ReportLocationGlobal || !loc->suppressable)
    131  1.1  mrg     return 0;
    132  1.1  mrg   const char *stype = conv(typ);
    133  1.1  mrg   if (0 == internal_strcmp(stype, kSuppressionNone))
    134  1.1  mrg     return 0;
    135  1.1  mrg   Suppression *s;
    136  1.1  mrg   const DataInfo &global = loc->global;
    137  1.1  mrg   if (suppression_ctx->Match(global.name, stype, &s) ||
    138  1.1  mrg       suppression_ctx->Match(global.module, stype, &s)) {
    139  1.1  mrg       VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", s->templ);
    140  1.1  mrg       atomic_fetch_add(&s->hit_count, 1, memory_order_relaxed);
    141  1.1  mrg       *sp = s;
    142  1.1  mrg       return global.start;
    143  1.1  mrg   }
    144  1.1  mrg   return 0;
    145  1.1  mrg }
    146  1.1  mrg 
    147  1.1  mrg void PrintMatchedSuppressions() {
    148  1.1  mrg   InternalMmapVector<Suppression *> matched;
    149  1.1  mrg   CHECK(suppression_ctx);
    150  1.1  mrg   suppression_ctx->GetMatched(&matched);
    151  1.1  mrg   if (!matched.size())
    152  1.1  mrg     return;
    153  1.1  mrg   int hit_count = 0;
    154  1.1  mrg   for (uptr i = 0; i < matched.size(); i++)
    155  1.1  mrg     hit_count += atomic_load_relaxed(&matched[i]->hit_count);
    156  1.1  mrg   Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
    157  1.1  mrg          (int)internal_getpid());
    158  1.1  mrg   for (uptr i = 0; i < matched.size(); i++) {
    159  1.1  mrg     Printf("%d %s:%s\n", atomic_load_relaxed(&matched[i]->hit_count),
    160  1.1  mrg            matched[i]->type, matched[i]->templ);
    161  1.1  mrg   }
    162  1.1  mrg }
    163  1.1  mrg }  // namespace __tsan
    164