1 //===-- tsan_suppressions.cc ----------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of ThreadSanitizer (TSan), a race detector.
12 //===----------------------------------------------------------------------===//
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"
20 #include "tsan_flags.h"
21 #include "tsan_mman.h"
22 #include "tsan_platform.h"
24 // Suppressions for true/false positives in standard libraries.
25 static const char *const std_suppressions =
26 // Libstdc++ 4.4 has data races in std::string.
27 // See http://crbug.com/181502 for an example.
29 "race:^_M_is_leaked$\n"
30 // False positive when using std <thread>.
31 // Happens because we miss atomic synchronization in libstdc++.
32 // See http://llvm.org/bugs/show_bug.cgi?id=17066 for details.
33 "race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n";
35 // Can be overriden in frontend.
37 extern "C" const char *WEAK __tsan_default_suppressions() {
44 static bool suppressions_inited = false;
46 void InitializeSuppressions() {
47 CHECK(!suppressions_inited);
48 SuppressionContext::InitIfNecessary();
50 SuppressionContext::Get()->Parse(__tsan_default_suppressions());
51 SuppressionContext::Get()->Parse(std_suppressions);
53 suppressions_inited = true;
56 SuppressionType conv(ReportType typ) {
57 if (typ == ReportTypeRace)
58 return SuppressionRace;
59 else if (typ == ReportTypeVptrRace)
60 return SuppressionRace;
61 else if (typ == ReportTypeUseAfterFree)
62 return SuppressionRace;
63 else if (typ == ReportTypeVptrUseAfterFree)
64 return SuppressionRace;
65 else if (typ == ReportTypeThreadLeak)
66 return SuppressionThread;
67 else if (typ == ReportTypeMutexDestroyLocked)
68 return SuppressionMutex;
69 else if (typ == ReportTypeMutexDoubleLock)
70 return SuppressionMutex;
71 else if (typ == ReportTypeMutexBadUnlock)
72 return SuppressionMutex;
73 else if (typ == ReportTypeMutexBadReadLock)
74 return SuppressionMutex;
75 else if (typ == ReportTypeMutexBadReadUnlock)
76 return SuppressionMutex;
77 else if (typ == ReportTypeSignalUnsafe)
78 return SuppressionSignal;
79 else if (typ == ReportTypeErrnoInSignal)
80 return SuppressionNone;
81 else if (typ == ReportTypeDeadlock)
82 return SuppressionDeadlock;
83 Printf("ThreadSanitizer: unknown report type %d\n", typ),
87 uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
88 if (!SuppressionContext::Get()->SuppressionCount() || stack == 0 ||
91 SuppressionType stype = conv(typ);
92 if (stype == SuppressionNone)
95 for (const SymbolizedStack *frame = stack->frames; frame;
96 frame = frame->next) {
97 const AddressInfo &info = frame->info;
98 if (SuppressionContext::Get()->Match(info.function, stype, &s) ||
99 SuppressionContext::Get()->Match(info.file, stype, &s) ||
100 SuppressionContext::Get()->Match(info.module, stype, &s)) {
101 DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
110 uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
111 if (!SuppressionContext::Get()->SuppressionCount() || loc == 0 ||
112 loc->type != ReportLocationGlobal || !loc->suppressable)
114 SuppressionType stype = conv(typ);
115 if (stype == SuppressionNone)
118 const DataInfo &global = loc->global;
119 if (SuppressionContext::Get()->Match(global.name, stype, &s) ||
120 SuppressionContext::Get()->Match(global.module, stype, &s)) {
121 DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
129 void PrintMatchedSuppressions() {
130 InternalMmapVector<Suppression *> matched(1);
131 SuppressionContext::Get()->GetMatched(&matched);
135 for (uptr i = 0; i < matched.size(); i++)
136 hit_count += matched[i]->hit_count;
137 Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
138 (int)internal_getpid());
139 for (uptr i = 0; i < matched.size(); i++) {
140 Printf("%d %s:%s\n", matched[i]->hit_count,
141 SuppressionTypeString(matched[i]->type), matched[i]->templ);
144 } // namespace __tsan