1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_suppressions.cc ----------------------------------------------===//
27ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
37ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//                     The LLVM Compiler Infrastructure
47ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
57ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is distributed under the University of Illinois Open Source
67ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// License. See LICENSE.TXT for details.
77ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
87ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===//
97ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector.
117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===//
137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
140969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include "sanitizer_common/sanitizer_common.h"
157f9c5a220b2768a450696bbd157a0e6f2e9ceea3Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h"
16a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev#include "sanitizer_common/sanitizer_placement_new.h"
17a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev#include "sanitizer_common/sanitizer_suppressions.h"
187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_suppressions.h"
197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h"
207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_flags.h"
217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h"
227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h"
237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#ifndef SANITIZER_GO
25a117492b30509744a2b3e1e84c7b56e9ad76c0c9Dmitry Vyukov// Suppressions for true/false positives in standard libraries.
26a117492b30509744a2b3e1e84c7b56e9ad76c0c9Dmitry Vyukovstatic const char *const std_suppressions =
27a117492b30509744a2b3e1e84c7b56e9ad76c0c9Dmitry Vyukov// Libstdc++ 4.4 has data races in std::string.
28a117492b30509744a2b3e1e84c7b56e9ad76c0c9Dmitry Vyukov// See http://crbug.com/181502 for an example.
29a117492b30509744a2b3e1e84c7b56e9ad76c0c9Dmitry Vyukov"race:^_M_rep$\n"
30a117492b30509744a2b3e1e84c7b56e9ad76c0c9Dmitry Vyukov"race:^_M_is_leaked$\n"
31a117492b30509744a2b3e1e84c7b56e9ad76c0c9Dmitry Vyukov// False positive when using std <thread>.
32a117492b30509744a2b3e1e84c7b56e9ad76c0c9Dmitry Vyukov// Happens because we miss atomic synchronization in libstdc++.
33a117492b30509744a2b3e1e84c7b56e9ad76c0c9Dmitry Vyukov// See http://llvm.org/bugs/show_bug.cgi?id=17066 for details.
34da506a9ae831f275267ddc9ee74e5474246369b1Alexey Samsonov"race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n";
35a117492b30509744a2b3e1e84c7b56e9ad76c0c9Dmitry Vyukov
36c2b9f1c1d54e857e56462e65155381faddf398dfDmitry Vyukov// Can be overriden in frontend.
37799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga NainarSANITIZER_WEAK_DEFAULT_IMPL
38799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarconst char *__tsan_default_suppressions() {
39c2b9f1c1d54e857e56462e65155381faddf398dfDmitry Vyukov  return 0;
40c2b9f1c1d54e857e56462e65155381faddf398dfDmitry Vyukov}
41c2b9f1c1d54e857e56462e65155381faddf398dfDmitry Vyukov#endif
42c2b9f1c1d54e857e56462e65155381faddf398dfDmitry Vyukov
437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan {
447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4586277eb844c4983c81de62d7c050e92fe7155788Stephen HinesALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
4686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic SuppressionContext *suppression_ctx = nullptr;
4786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic const char *kSuppressionTypes[] = {
48799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    kSuppressionRace,   kSuppressionRaceTop, kSuppressionMutex,
49799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    kSuppressionThread, kSuppressionSignal, kSuppressionLib,
50799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    kSuppressionDeadlock};
517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid InitializeSuppressions() {
5386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_EQ(nullptr, suppression_ctx);
5486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  suppression_ctx = new (suppression_placeholder) // NOLINT
5586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
5686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  suppression_ctx->ParseFromFile(flags()->suppressions);
5786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
5886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  suppression_ctx->Parse(__tsan_default_suppressions());
5986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  suppression_ctx->Parse(std_suppressions);
60c2b9f1c1d54e857e56462e65155381faddf398dfDmitry Vyukov#endif
614af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov}
624af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
6386277eb844c4983c81de62d7c050e92fe7155788Stephen HinesSuppressionContext *Suppressions() {
6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(suppression_ctx);
6586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return suppression_ctx;
6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
6886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic const char *conv(ReportType typ) {
697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (typ == ReportTypeRace)
7086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionRace;
7124cdfee9776abddcd6c96240e398706667029e0dDmitry Vyukov  else if (typ == ReportTypeVptrRace)
7286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionRace;
7324cdfee9776abddcd6c96240e398706667029e0dDmitry Vyukov  else if (typ == ReportTypeUseAfterFree)
7486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionRace;
756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  else if (typ == ReportTypeVptrUseAfterFree)
7686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionRace;
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else if (typ == ReportTypeThreadLeak)
7886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionThread;
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else if (typ == ReportTypeMutexDestroyLocked)
8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionMutex;
812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  else if (typ == ReportTypeMutexDoubleLock)
8286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionMutex;
83c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  else if (typ == ReportTypeMutexInvalidAccess)
84c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return kSuppressionMutex;
852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  else if (typ == ReportTypeMutexBadUnlock)
8686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionMutex;
872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  else if (typ == ReportTypeMutexBadReadLock)
8886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionMutex;
892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  else if (typ == ReportTypeMutexBadReadUnlock)
9086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionMutex;
917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else if (typ == ReportTypeSignalUnsafe)
9286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionSignal;
9324cdfee9776abddcd6c96240e398706667029e0dDmitry Vyukov  else if (typ == ReportTypeErrnoInSignal)
9486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionNone;
952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  else if (typ == ReportTypeDeadlock)
9686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kSuppressionDeadlock;
97c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  Printf("ThreadSanitizer: unknown report type %d\n", typ);
9839968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukov  Die();
9939968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukov}
10039968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukov
101799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic uptr IsSuppressed(const char *stype, const AddressInfo &info,
102799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    Suppression **sp) {
103799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (suppression_ctx->Match(info.function, stype, sp) ||
104799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      suppression_ctx->Match(info.file, stype, sp) ||
105799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      suppression_ctx->Match(info.module, stype, sp)) {
106799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", (*sp)->templ);
107799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    atomic_fetch_add(&(*sp)->hit_count, 1, memory_order_relaxed);
108799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return info.address;
109799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  }
110799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return 0;
111799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar}
112799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
11339968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukovuptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
11486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(suppression_ctx);
11586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (!suppression_ctx->SuppressionCount() || stack == 0 ||
1166d1862363c88c183b0ed7740fca876342cf0474bStephen Hines      !stack->suppressable)
1176a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    return 0;
11886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  const char *stype = conv(typ);
11986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (0 == internal_strcmp(stype, kSuppressionNone))
120158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov    return 0;
12186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  for (const SymbolizedStack *frame = stack->frames; frame;
122799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      frame = frame->next) {
123799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    uptr pc = IsSuppressed(stype, frame->info, sp);
124799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    if (pc != 0)
125799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      return pc;
1267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
127799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (0 == internal_strcmp(stype, kSuppressionRace) && stack->frames != nullptr)
128799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return IsSuppressed(kSuppressionRaceTop, stack->frames->info, sp);
129158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  return 0;
1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
131f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov
13239968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukovuptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
13386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(suppression_ctx);
13486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (!suppression_ctx->SuppressionCount() || loc == 0 ||
1356a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      loc->type != ReportLocationGlobal || !loc->suppressable)
13639968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukov    return 0;
13786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  const char *stype = conv(typ);
13886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (0 == internal_strcmp(stype, kSuppressionNone))
13939968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukov    return 0;
140a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev  Suppression *s;
1416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  const DataInfo &global = loc->global;
14286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (suppression_ctx->Match(global.name, stype, &s) ||
14386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      suppression_ctx->Match(global.module, stype, &s)) {
144799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", s->templ);
145799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      atomic_fetch_add(&s->hit_count, 1, memory_order_relaxed);
146a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev      *sp = s;
1476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines      return global.start;
14839968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukov  }
14939968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukov  return 0;
15039968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukov}
15139968339a07d790aadcf27534f92a0de8c0c90fbDmitry Vyukov
152f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukovvoid PrintMatchedSuppressions() {
153a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev  InternalMmapVector<Suppression *> matched(1);
15486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(suppression_ctx);
15586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  suppression_ctx->GetMatched(&matched);
156a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev  if (!matched.size())
157f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov    return;
158a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev  int hit_count = 0;
159a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev  for (uptr i = 0; i < matched.size(); i++)
160799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    hit_count += atomic_load_relaxed(&matched[i]->hit_count);
161a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev  Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
162a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev         (int)internal_getpid());
163a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev  for (uptr i = 0; i < matched.size(); i++) {
164c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    Printf("%d %s:%s\n", atomic_load_relaxed(&matched[i]->hit_count),
165c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar           matched[i]->type, matched[i]->templ);
166f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov  }
167f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov}
1687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
169