* Add missing ChangeLog entry.
[official-gcc.git] / libsanitizer / tsan / tsan_suppressions.cc
blob6b42d3a67b83af8c12278e806c911ee2b3f4af7e
1 //===-- tsan_suppressions.cc ----------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
9 //
10 //===----------------------------------------------------------------------===//
12 #include "sanitizer_common/sanitizer_common.h"
13 #include "sanitizer_common/sanitizer_libc.h"
14 #include "sanitizer_common/sanitizer_placement_new.h"
15 #include "sanitizer_common/sanitizer_suppressions.h"
16 #include "tsan_suppressions.h"
17 #include "tsan_rtl.h"
18 #include "tsan_flags.h"
19 #include "tsan_mman.h"
20 #include "tsan_platform.h"
22 // Suppressions for true/false positives in standard libraries.
23 static const char *const std_suppressions =
24 // Libstdc++ 4.4 has data races in std::string.
25 // See http://crbug.com/181502 for an example.
26 "race:^_M_rep$\n"
27 "race:^_M_is_leaked$\n"
28 // False positive when using std <thread>.
29 // Happens because we miss atomic synchronization in libstdc++.
30 // See http://llvm.org/bugs/show_bug.cgi?id=17066 for details.
31 "race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n";
33 // Can be overriden in frontend.
34 #ifndef TSAN_GO
35 extern "C" const char *WEAK __tsan_default_suppressions() {
36 return 0;
38 #endif
40 namespace __tsan {
42 static bool suppressions_inited = false;
44 void InitializeSuppressions() {
45 CHECK(!suppressions_inited);
46 SuppressionContext::InitIfNecessary();
47 #ifndef TSAN_GO
48 SuppressionContext::Get()->Parse(__tsan_default_suppressions());
49 SuppressionContext::Get()->Parse(std_suppressions);
50 #endif
51 suppressions_inited = true;
54 SuppressionType conv(ReportType typ) {
55 if (typ == ReportTypeRace)
56 return SuppressionRace;
57 else if (typ == ReportTypeVptrRace)
58 return SuppressionRace;
59 else if (typ == ReportTypeUseAfterFree)
60 return SuppressionRace;
61 else if (typ == ReportTypeThreadLeak)
62 return SuppressionThread;
63 else if (typ == ReportTypeMutexDestroyLocked)
64 return SuppressionMutex;
65 else if (typ == ReportTypeMutexDoubleLock)
66 return SuppressionMutex;
67 else if (typ == ReportTypeMutexBadUnlock)
68 return SuppressionMutex;
69 else if (typ == ReportTypeMutexBadReadLock)
70 return SuppressionMutex;
71 else if (typ == ReportTypeMutexBadReadUnlock)
72 return SuppressionMutex;
73 else if (typ == ReportTypeSignalUnsafe)
74 return SuppressionSignal;
75 else if (typ == ReportTypeErrnoInSignal)
76 return SuppressionNone;
77 else if (typ == ReportTypeDeadlock)
78 return SuppressionDeadlock;
79 Printf("ThreadSanitizer: unknown report type %d\n", typ),
80 Die();
83 uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
84 if (!SuppressionContext::Get()->SuppressionCount() || stack == 0 ||
85 !stack->suppressable)
86 return 0;
87 SuppressionType stype = conv(typ);
88 if (stype == SuppressionNone)
89 return 0;
90 Suppression *s;
91 for (const ReportStack *frame = stack; frame; frame = frame->next) {
92 if (SuppressionContext::Get()->Match(frame->func, stype, &s) ||
93 SuppressionContext::Get()->Match(frame->file, stype, &s) ||
94 SuppressionContext::Get()->Match(frame->module, stype, &s)) {
95 DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
96 s->hit_count++;
97 *sp = s;
98 return frame->pc;
101 return 0;
104 uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
105 if (!SuppressionContext::Get()->SuppressionCount() || loc == 0 ||
106 loc->type != ReportLocationGlobal || !loc->suppressable)
107 return 0;
108 SuppressionType stype = conv(typ);
109 if (stype == SuppressionNone)
110 return 0;
111 Suppression *s;
112 if (SuppressionContext::Get()->Match(loc->name, stype, &s) ||
113 SuppressionContext::Get()->Match(loc->file, stype, &s) ||
114 SuppressionContext::Get()->Match(loc->module, stype, &s)) {
115 DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
116 s->hit_count++;
117 *sp = s;
118 return loc->addr;
120 return 0;
123 void PrintMatchedSuppressions() {
124 InternalMmapVector<Suppression *> matched(1);
125 SuppressionContext::Get()->GetMatched(&matched);
126 if (!matched.size())
127 return;
128 int hit_count = 0;
129 for (uptr i = 0; i < matched.size(); i++)
130 hit_count += matched[i]->hit_count;
131 Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
132 (int)internal_getpid());
133 for (uptr i = 0; i < matched.size(); i++) {
134 Printf("%d %s:%s\n", matched[i]->hit_count,
135 SuppressionTypeString(matched[i]->type), matched[i]->templ);
138 } // namespace __tsan