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