blob: 731572980e3d8c07e6fa5b17e184d57aa4735975 [file] [log] [blame]
Alexey Samsonov603c4be2012-06-04 13:55:19 +00001//===-- tsan_suppressions.cc ----------------------------------------------===//
Kostya Serebryany7ac41482012-05-10 13:48:04 +00002//
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
Alexey Samsonov0969bcf2012-06-18 08:44:30 +000014#include "sanitizer_common/sanitizer_common.h"
Alexey Samsonov7f9c5a22012-06-05 07:46:31 +000015#include "sanitizer_common/sanitizer_libc.h"
Sergey Matveeva52e5c62013-06-26 15:37:14 +000016#include "sanitizer_common/sanitizer_placement_new.h"
17#include "sanitizer_common/sanitizer_suppressions.h"
Kostya Serebryany7ac41482012-05-10 13:48:04 +000018#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
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070024#ifndef SANITIZER_GO
Dmitry Vyukova1174922013-09-03 11:43:04 +000025// 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"
Dmitry Vyukova1174922013-09-03 11:43:04 +000031// 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.
Alexey Samsonovda506a92013-09-03 11:50:48 +000034"race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n";
Dmitry Vyukova1174922013-09-03 11:43:04 +000035
Dmitry Vyukovc2b9f1c2013-01-24 13:50:10 +000036// Can be overriden in frontend.
Dmitry Vyukovc2b9f1c2013-01-24 13:50:10 +000037extern "C" const char *WEAK __tsan_default_suppressions() {
38 return 0;
39}
40#endif
41
Kostya Serebryany7ac41482012-05-10 13:48:04 +000042namespace __tsan {
43
Stephen Hines86277eb2015-03-23 12:06:32 -070044ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
45static SuppressionContext *suppression_ctx = nullptr;
46static const char *kSuppressionTypes[] = {
47 kSuppressionRace, kSuppressionMutex, kSuppressionThread,
48 kSuppressionSignal, kSuppressionLib, kSuppressionDeadlock};
Kostya Serebryany7ac41482012-05-10 13:48:04 +000049
Kostya Serebryany7ac41482012-05-10 13:48:04 +000050void InitializeSuppressions() {
Stephen Hines86277eb2015-03-23 12:06:32 -070051 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);
Dmitry Vyukovc2b9f1c2013-01-24 13:50:10 +000058#endif
Dmitry Vyukov4af0f212013-10-03 13:37:17 +000059}
60
Stephen Hines86277eb2015-03-23 12:06:32 -070061SuppressionContext *Suppressions() {
62 CHECK(suppression_ctx);
63 return suppression_ctx;
64}
65
66static const char *conv(ReportType typ) {
Dmitry Vyukov39968332013-06-10 15:38:44 +000067 if (typ == ReportTypeRace)
Stephen Hines86277eb2015-03-23 12:06:32 -070068 return kSuppressionRace;
Dmitry Vyukov39968332013-06-10 15:38:44 +000069 else if (typ == ReportTypeVptrRace)
Stephen Hines86277eb2015-03-23 12:06:32 -070070 return kSuppressionRace;
Dmitry Vyukov39968332013-06-10 15:38:44 +000071 else if (typ == ReportTypeUseAfterFree)
Stephen Hines86277eb2015-03-23 12:06:32 -070072 return kSuppressionRace;
Stephen Hines6d186232014-11-26 17:56:19 -080073 else if (typ == ReportTypeVptrUseAfterFree)
Stephen Hines86277eb2015-03-23 12:06:32 -070074 return kSuppressionRace;
Dmitry Vyukov39968332013-06-10 15:38:44 +000075 else if (typ == ReportTypeThreadLeak)
Stephen Hines86277eb2015-03-23 12:06:32 -070076 return kSuppressionThread;
Dmitry Vyukov39968332013-06-10 15:38:44 +000077 else if (typ == ReportTypeMutexDestroyLocked)
Stephen Hines86277eb2015-03-23 12:06:32 -070078 return kSuppressionMutex;
Stephen Hines2d1fdb22014-05-28 23:58:16 -070079 else if (typ == ReportTypeMutexDoubleLock)
Stephen Hines86277eb2015-03-23 12:06:32 -070080 return kSuppressionMutex;
Stephen Hines2d1fdb22014-05-28 23:58:16 -070081 else if (typ == ReportTypeMutexBadUnlock)
Stephen Hines86277eb2015-03-23 12:06:32 -070082 return kSuppressionMutex;
Stephen Hines2d1fdb22014-05-28 23:58:16 -070083 else if (typ == ReportTypeMutexBadReadLock)
Stephen Hines86277eb2015-03-23 12:06:32 -070084 return kSuppressionMutex;
Stephen Hines2d1fdb22014-05-28 23:58:16 -070085 else if (typ == ReportTypeMutexBadReadUnlock)
Stephen Hines86277eb2015-03-23 12:06:32 -070086 return kSuppressionMutex;
Dmitry Vyukov39968332013-06-10 15:38:44 +000087 else if (typ == ReportTypeSignalUnsafe)
Stephen Hines86277eb2015-03-23 12:06:32 -070088 return kSuppressionSignal;
Dmitry Vyukov39968332013-06-10 15:38:44 +000089 else if (typ == ReportTypeErrnoInSignal)
Stephen Hines86277eb2015-03-23 12:06:32 -070090 return kSuppressionNone;
Stephen Hines2d1fdb22014-05-28 23:58:16 -070091 else if (typ == ReportTypeDeadlock)
Stephen Hines86277eb2015-03-23 12:06:32 -070092 return kSuppressionDeadlock;
Dmitry Vyukov39968332013-06-10 15:38:44 +000093 Printf("ThreadSanitizer: unknown report type %d\n", typ),
94 Die();
95}
96
Dmitry Vyukovf754eb52013-03-27 17:59:57 +000097uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
Stephen Hines86277eb2015-03-23 12:06:32 -070098 CHECK(suppression_ctx);
99 if (!suppression_ctx->SuppressionCount() || stack == 0 ||
Stephen Hines6d186232014-11-26 17:56:19 -0800100 !stack->suppressable)
Stephen Hines6a211c52014-07-21 00:49:56 -0700101 return 0;
Stephen Hines86277eb2015-03-23 12:06:32 -0700102 const char *stype = conv(typ);
103 if (0 == internal_strcmp(stype, kSuppressionNone))
Dmitry Vyukov24cdfee2013-05-29 11:23:54 +0000104 return 0;
Sergey Matveeva52e5c62013-06-26 15:37:14 +0000105 Suppression *s;
Stephen Hines86277eb2015-03-23 12:06:32 -0700106 for (const SymbolizedStack *frame = stack->frames; frame;
107 frame = frame->next) {
Stephen Hines6d186232014-11-26 17:56:19 -0800108 const AddressInfo &info = frame->info;
Stephen Hines86277eb2015-03-23 12:06:32 -0700109 if (suppression_ctx->Match(info.function, stype, &s) ||
110 suppression_ctx->Match(info.file, stype, &s) ||
111 suppression_ctx->Match(info.module, stype, &s)) {
Sergey Matveeva52e5c62013-06-26 15:37:14 +0000112 DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
113 s->hit_count++;
114 *sp = s;
Stephen Hines6d186232014-11-26 17:56:19 -0800115 return info.address;
Kostya Serebryany7ac41482012-05-10 13:48:04 +0000116 }
117 }
Dmitry Vyukov158c6ac2012-10-05 15:51:32 +0000118 return 0;
Kostya Serebryany7ac41482012-05-10 13:48:04 +0000119}
Dmitry Vyukovf754eb52013-03-27 17:59:57 +0000120
Dmitry Vyukov39968332013-06-10 15:38:44 +0000121uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700122 CHECK(suppression_ctx);
123 if (!suppression_ctx->SuppressionCount() || loc == 0 ||
Stephen Hines6a211c52014-07-21 00:49:56 -0700124 loc->type != ReportLocationGlobal || !loc->suppressable)
Dmitry Vyukov39968332013-06-10 15:38:44 +0000125 return 0;
Stephen Hines86277eb2015-03-23 12:06:32 -0700126 const char *stype = conv(typ);
127 if (0 == internal_strcmp(stype, kSuppressionNone))
Dmitry Vyukov39968332013-06-10 15:38:44 +0000128 return 0;
Sergey Matveeva52e5c62013-06-26 15:37:14 +0000129 Suppression *s;
Stephen Hines6d186232014-11-26 17:56:19 -0800130 const DataInfo &global = loc->global;
Stephen Hines86277eb2015-03-23 12:06:32 -0700131 if (suppression_ctx->Match(global.name, stype, &s) ||
132 suppression_ctx->Match(global.module, stype, &s)) {
Sergey Matveevf2c84452013-06-26 16:49:34 +0000133 DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
Sergey Matveeva52e5c62013-06-26 15:37:14 +0000134 s->hit_count++;
135 *sp = s;
Stephen Hines6d186232014-11-26 17:56:19 -0800136 return global.start;
Dmitry Vyukov39968332013-06-10 15:38:44 +0000137 }
138 return 0;
139}
140
Dmitry Vyukovf754eb52013-03-27 17:59:57 +0000141void PrintMatchedSuppressions() {
Sergey Matveeva52e5c62013-06-26 15:37:14 +0000142 InternalMmapVector<Suppression *> matched(1);
Stephen Hines86277eb2015-03-23 12:06:32 -0700143 CHECK(suppression_ctx);
144 suppression_ctx->GetMatched(&matched);
Sergey Matveeva52e5c62013-06-26 15:37:14 +0000145 if (!matched.size())
Dmitry Vyukovf754eb52013-03-27 17:59:57 +0000146 return;
Sergey Matveeva52e5c62013-06-26 15:37:14 +0000147 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++) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700153 Printf("%d %s:%s\n", matched[i]->hit_count, matched[i]->type,
154 matched[i]->templ);
Dmitry Vyukovf754eb52013-03-27 17:59:57 +0000155 }
156}
Kostya Serebryany7ac41482012-05-10 13:48:04 +0000157} // namespace __tsan