]> git.proxmox.com Git - rustc.git/blame - src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
New upstream version 1.25.0+dfsg1
[rustc.git] / src / libcompiler_builtins / compiler-rt / lib / tsan / rtl / tsan_suppressions.cc
CommitLineData
1a4d82fc
JJ
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
7cac9316 24#if !SANITIZER_GO
1a4d82fc
JJ
25// Suppressions for true/false positives in standard libraries.
26static 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.
3157f602
XL
37SANITIZER_WEAK_DEFAULT_IMPL
38const char *__tsan_default_suppressions() {
1a4d82fc
JJ
39 return 0;
40}
41#endif
42
43namespace __tsan {
44
92a42be0
SL
45ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
46static SuppressionContext *suppression_ctx = nullptr;
47static const char *kSuppressionTypes[] = {
48 kSuppressionRace, kSuppressionRaceTop, kSuppressionMutex,
49 kSuppressionThread, kSuppressionSignal, kSuppressionLib,
50 kSuppressionDeadlock};
1a4d82fc
JJ
51
52void InitializeSuppressions() {
92a42be0
SL
53 CHECK_EQ(nullptr, suppression_ctx);
54 suppression_ctx = new (suppression_placeholder) // NOLINT
55 SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
56 suppression_ctx->ParseFromFile(flags()->suppressions);
7cac9316 57#if !SANITIZER_GO
92a42be0
SL
58 suppression_ctx->Parse(__tsan_default_suppressions());
59 suppression_ctx->Parse(std_suppressions);
1a4d82fc
JJ
60#endif
61}
62
92a42be0
SL
63SuppressionContext *Suppressions() {
64 CHECK(suppression_ctx);
65 return suppression_ctx;
1a4d82fc
JJ
66}
67
92a42be0 68static const char *conv(ReportType typ) {
1a4d82fc 69 if (typ == ReportTypeRace)
92a42be0 70 return kSuppressionRace;
1a4d82fc 71 else if (typ == ReportTypeVptrRace)
92a42be0 72 return kSuppressionRace;
1a4d82fc 73 else if (typ == ReportTypeUseAfterFree)
92a42be0
SL
74 return kSuppressionRace;
75 else if (typ == ReportTypeVptrUseAfterFree)
76 return kSuppressionRace;
2c00a5a8
XL
77 else if (typ == ReportTypeExternalRace)
78 return kSuppressionRace;
1a4d82fc 79 else if (typ == ReportTypeThreadLeak)
92a42be0 80 return kSuppressionThread;
1a4d82fc 81 else if (typ == ReportTypeMutexDestroyLocked)
92a42be0 82 return kSuppressionMutex;
1a4d82fc 83 else if (typ == ReportTypeMutexDoubleLock)
92a42be0 84 return kSuppressionMutex;
5bcae85e
SL
85 else if (typ == ReportTypeMutexInvalidAccess)
86 return kSuppressionMutex;
1a4d82fc 87 else if (typ == ReportTypeMutexBadUnlock)
92a42be0 88 return kSuppressionMutex;
1a4d82fc 89 else if (typ == ReportTypeMutexBadReadLock)
92a42be0 90 return kSuppressionMutex;
1a4d82fc 91 else if (typ == ReportTypeMutexBadReadUnlock)
92a42be0 92 return kSuppressionMutex;
1a4d82fc 93 else if (typ == ReportTypeSignalUnsafe)
92a42be0 94 return kSuppressionSignal;
1a4d82fc 95 else if (typ == ReportTypeErrnoInSignal)
92a42be0 96 return kSuppressionNone;
1a4d82fc 97 else if (typ == ReportTypeDeadlock)
92a42be0 98 return kSuppressionDeadlock;
5bcae85e 99 Printf("ThreadSanitizer: unknown report type %d\n", typ);
1a4d82fc
JJ
100 Die();
101}
102
92a42be0
SL
103static uptr IsSuppressed(const char *stype, const AddressInfo &info,
104 Suppression **sp) {
105 if (suppression_ctx->Match(info.function, stype, sp) ||
106 suppression_ctx->Match(info.file, stype, sp) ||
107 suppression_ctx->Match(info.module, stype, sp)) {
108 VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", (*sp)->templ);
109 atomic_fetch_add(&(*sp)->hit_count, 1, memory_order_relaxed);
110 return info.address;
111 }
112 return 0;
113}
114
1a4d82fc 115uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
92a42be0
SL
116 CHECK(suppression_ctx);
117 if (!suppression_ctx->SuppressionCount() || stack == 0 ||
118 !stack->suppressable)
1a4d82fc 119 return 0;
92a42be0
SL
120 const char *stype = conv(typ);
121 if (0 == internal_strcmp(stype, kSuppressionNone))
122 return 0;
123 for (const SymbolizedStack *frame = stack->frames; frame;
124 frame = frame->next) {
125 uptr pc = IsSuppressed(stype, frame->info, sp);
126 if (pc != 0)
127 return pc;
1a4d82fc 128 }
92a42be0
SL
129 if (0 == internal_strcmp(stype, kSuppressionRace) && stack->frames != nullptr)
130 return IsSuppressed(kSuppressionRaceTop, stack->frames->info, sp);
1a4d82fc
JJ
131 return 0;
132}
133
134uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
92a42be0
SL
135 CHECK(suppression_ctx);
136 if (!suppression_ctx->SuppressionCount() || loc == 0 ||
137 loc->type != ReportLocationGlobal || !loc->suppressable)
1a4d82fc 138 return 0;
92a42be0
SL
139 const char *stype = conv(typ);
140 if (0 == internal_strcmp(stype, kSuppressionNone))
1a4d82fc
JJ
141 return 0;
142 Suppression *s;
92a42be0
SL
143 const DataInfo &global = loc->global;
144 if (suppression_ctx->Match(global.name, stype, &s) ||
145 suppression_ctx->Match(global.module, stype, &s)) {
146 VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", s->templ);
147 atomic_fetch_add(&s->hit_count, 1, memory_order_relaxed);
1a4d82fc 148 *sp = s;
92a42be0 149 return global.start;
1a4d82fc
JJ
150 }
151 return 0;
152}
153
154void PrintMatchedSuppressions() {
1a4d82fc 155 InternalMmapVector<Suppression *> matched(1);
92a42be0
SL
156 CHECK(suppression_ctx);
157 suppression_ctx->GetMatched(&matched);
1a4d82fc
JJ
158 if (!matched.size())
159 return;
160 int hit_count = 0;
161 for (uptr i = 0; i < matched.size(); i++)
92a42be0 162 hit_count += atomic_load_relaxed(&matched[i]->hit_count);
1a4d82fc
JJ
163 Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
164 (int)internal_getpid());
165 for (uptr i = 0; i < matched.size(); i++) {
3157f602
XL
166 Printf("%d %s:%s\n", atomic_load_relaxed(&matched[i]->hit_count),
167 matched[i]->type, matched[i]->templ);
1a4d82fc
JJ
168 }
169}
170} // namespace __tsan