Alexey Samsonov | 603c4be | 2012-06-04 13:55:19 +0000 | [diff] [blame] | 1 | //===-- tsan_suppressions.cc ----------------------------------------------===// |
Kostya Serebryany | 7ac4148 | 2012-05-10 13:48:04 +0000 | [diff] [blame] | 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 | |
Alexey Samsonov | 0969bcf | 2012-06-18 08:44:30 +0000 | [diff] [blame] | 14 | #include "sanitizer_common/sanitizer_common.h" |
Alexey Samsonov | 7f9c5a2 | 2012-06-05 07:46:31 +0000 | [diff] [blame] | 15 | #include "sanitizer_common/sanitizer_libc.h" |
Sergey Matveev | a52e5c6 | 2013-06-26 15:37:14 +0000 | [diff] [blame] | 16 | #include "sanitizer_common/sanitizer_placement_new.h" |
| 17 | #include "sanitizer_common/sanitizer_suppressions.h" |
Kostya Serebryany | 7ac4148 | 2012-05-10 13:48:04 +0000 | [diff] [blame] | 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 | |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 24 | #ifndef SANITIZER_GO |
Dmitry Vyukov | a117492 | 2013-09-03 11:43:04 +0000 | [diff] [blame] | 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" |
Dmitry Vyukov | a117492 | 2013-09-03 11:43:04 +0000 | [diff] [blame] | 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. |
Alexey Samsonov | da506a9 | 2013-09-03 11:50:48 +0000 | [diff] [blame] | 34 | "race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n"; |
Dmitry Vyukov | a117492 | 2013-09-03 11:43:04 +0000 | [diff] [blame] | 35 | |
Dmitry Vyukov | c2b9f1c | 2013-01-24 13:50:10 +0000 | [diff] [blame] | 36 | // Can be overriden in frontend. |
Dmitry Vyukov | c2b9f1c | 2013-01-24 13:50:10 +0000 | [diff] [blame] | 37 | extern "C" const char *WEAK __tsan_default_suppressions() { |
| 38 | return 0; |
| 39 | } |
| 40 | #endif |
| 41 | |
Kostya Serebryany | 7ac4148 | 2012-05-10 13:48:04 +0000 | [diff] [blame] | 42 | namespace __tsan { |
| 43 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 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}; |
Kostya Serebryany | 7ac4148 | 2012-05-10 13:48:04 +0000 | [diff] [blame] | 49 | |
Kostya Serebryany | 7ac4148 | 2012-05-10 13:48:04 +0000 | [diff] [blame] | 50 | void InitializeSuppressions() { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 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); |
Dmitry Vyukov | c2b9f1c | 2013-01-24 13:50:10 +0000 | [diff] [blame] | 58 | #endif |
Dmitry Vyukov | 4af0f21 | 2013-10-03 13:37:17 +0000 | [diff] [blame] | 59 | } |
| 60 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 61 | SuppressionContext *Suppressions() { |
| 62 | CHECK(suppression_ctx); |
| 63 | return suppression_ctx; |
| 64 | } |
| 65 | |
| 66 | static const char *conv(ReportType typ) { |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 67 | if (typ == ReportTypeRace) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 68 | return kSuppressionRace; |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 69 | else if (typ == ReportTypeVptrRace) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 70 | return kSuppressionRace; |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 71 | else if (typ == ReportTypeUseAfterFree) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 72 | return kSuppressionRace; |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 73 | else if (typ == ReportTypeVptrUseAfterFree) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 74 | return kSuppressionRace; |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 75 | else if (typ == ReportTypeThreadLeak) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 76 | return kSuppressionThread; |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 77 | else if (typ == ReportTypeMutexDestroyLocked) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 78 | return kSuppressionMutex; |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 79 | else if (typ == ReportTypeMutexDoubleLock) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 80 | return kSuppressionMutex; |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 81 | else if (typ == ReportTypeMutexBadUnlock) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 82 | return kSuppressionMutex; |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 83 | else if (typ == ReportTypeMutexBadReadLock) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 84 | return kSuppressionMutex; |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 85 | else if (typ == ReportTypeMutexBadReadUnlock) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 86 | return kSuppressionMutex; |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 87 | else if (typ == ReportTypeSignalUnsafe) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 88 | return kSuppressionSignal; |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 89 | else if (typ == ReportTypeErrnoInSignal) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 90 | return kSuppressionNone; |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 91 | else if (typ == ReportTypeDeadlock) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 92 | return kSuppressionDeadlock; |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 93 | Printf("ThreadSanitizer: unknown report type %d\n", typ), |
| 94 | Die(); |
| 95 | } |
| 96 | |
Dmitry Vyukov | f754eb5 | 2013-03-27 17:59:57 +0000 | [diff] [blame] | 97 | uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 98 | CHECK(suppression_ctx); |
| 99 | if (!suppression_ctx->SuppressionCount() || stack == 0 || |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 100 | !stack->suppressable) |
Stephen Hines | 6a211c5 | 2014-07-21 00:49:56 -0700 | [diff] [blame] | 101 | return 0; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 102 | const char *stype = conv(typ); |
| 103 | if (0 == internal_strcmp(stype, kSuppressionNone)) |
Dmitry Vyukov | 24cdfee | 2013-05-29 11:23:54 +0000 | [diff] [blame] | 104 | return 0; |
Sergey Matveev | a52e5c6 | 2013-06-26 15:37:14 +0000 | [diff] [blame] | 105 | Suppression *s; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 106 | for (const SymbolizedStack *frame = stack->frames; frame; |
| 107 | frame = frame->next) { |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 108 | const AddressInfo &info = frame->info; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 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)) { |
Sergey Matveev | a52e5c6 | 2013-06-26 15:37:14 +0000 | [diff] [blame] | 112 | DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ); |
| 113 | s->hit_count++; |
| 114 | *sp = s; |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 115 | return info.address; |
Kostya Serebryany | 7ac4148 | 2012-05-10 13:48:04 +0000 | [diff] [blame] | 116 | } |
| 117 | } |
Dmitry Vyukov | 158c6ac | 2012-10-05 15:51:32 +0000 | [diff] [blame] | 118 | return 0; |
Kostya Serebryany | 7ac4148 | 2012-05-10 13:48:04 +0000 | [diff] [blame] | 119 | } |
Dmitry Vyukov | f754eb5 | 2013-03-27 17:59:57 +0000 | [diff] [blame] | 120 | |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 121 | uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 122 | CHECK(suppression_ctx); |
| 123 | if (!suppression_ctx->SuppressionCount() || loc == 0 || |
Stephen Hines | 6a211c5 | 2014-07-21 00:49:56 -0700 | [diff] [blame] | 124 | loc->type != ReportLocationGlobal || !loc->suppressable) |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 125 | return 0; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 126 | const char *stype = conv(typ); |
| 127 | if (0 == internal_strcmp(stype, kSuppressionNone)) |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 128 | return 0; |
Sergey Matveev | a52e5c6 | 2013-06-26 15:37:14 +0000 | [diff] [blame] | 129 | Suppression *s; |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 130 | const DataInfo &global = loc->global; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 131 | if (suppression_ctx->Match(global.name, stype, &s) || |
| 132 | suppression_ctx->Match(global.module, stype, &s)) { |
Sergey Matveev | f2c8445 | 2013-06-26 16:49:34 +0000 | [diff] [blame] | 133 | DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ); |
Sergey Matveev | a52e5c6 | 2013-06-26 15:37:14 +0000 | [diff] [blame] | 134 | s->hit_count++; |
| 135 | *sp = s; |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 136 | return global.start; |
Dmitry Vyukov | 3996833 | 2013-06-10 15:38:44 +0000 | [diff] [blame] | 137 | } |
| 138 | return 0; |
| 139 | } |
| 140 | |
Dmitry Vyukov | f754eb5 | 2013-03-27 17:59:57 +0000 | [diff] [blame] | 141 | void PrintMatchedSuppressions() { |
Sergey Matveev | a52e5c6 | 2013-06-26 15:37:14 +0000 | [diff] [blame] | 142 | InternalMmapVector<Suppression *> matched(1); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 143 | CHECK(suppression_ctx); |
| 144 | suppression_ctx->GetMatched(&matched); |
Sergey Matveev | a52e5c6 | 2013-06-26 15:37:14 +0000 | [diff] [blame] | 145 | if (!matched.size()) |
Dmitry Vyukov | f754eb5 | 2013-03-27 17:59:57 +0000 | [diff] [blame] | 146 | return; |
Sergey Matveev | a52e5c6 | 2013-06-26 15:37:14 +0000 | [diff] [blame] | 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++) { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 153 | Printf("%d %s:%s\n", matched[i]->hit_count, matched[i]->type, |
| 154 | matched[i]->templ); |
Dmitry Vyukov | f754eb5 | 2013-03-27 17:59:57 +0000 | [diff] [blame] | 155 | } |
| 156 | } |
Kostya Serebryany | 7ac4148 | 2012-05-10 13:48:04 +0000 | [diff] [blame] | 157 | } // namespace __tsan |