tsan_suppressions.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. //===-- tsan_suppressions.cpp ---------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of ThreadSanitizer (TSan), a race detector.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "tsan_suppressions.h"
  13. #include "sanitizer_common/sanitizer_common.h"
  14. #include "sanitizer_common/sanitizer_libc.h"
  15. #include "sanitizer_common/sanitizer_placement_new.h"
  16. #include "sanitizer_common/sanitizer_suppressions.h"
  17. #include "tsan_flags.h"
  18. #include "tsan_mman.h"
  19. #include "tsan_platform.h"
  20. #include "tsan_rtl.h"
  21. #if !SANITIZER_GO
  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";
  32. // Can be overriden in frontend.
  33. SANITIZER_WEAK_DEFAULT_IMPL
  34. const char *__tsan_default_suppressions() {
  35. return 0;
  36. }
  37. #endif
  38. namespace __tsan {
  39. ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
  40. static SuppressionContext *suppression_ctx = nullptr;
  41. static const char *kSuppressionTypes[] = {
  42. kSuppressionRace, kSuppressionRaceTop, kSuppressionMutex,
  43. kSuppressionThread, kSuppressionSignal, kSuppressionLib,
  44. kSuppressionDeadlock};
  45. void InitializeSuppressions() {
  46. CHECK_EQ(nullptr, suppression_ctx);
  47. suppression_ctx = new (suppression_placeholder)
  48. SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
  49. suppression_ctx->ParseFromFile(flags()->suppressions);
  50. #if !SANITIZER_GO
  51. suppression_ctx->Parse(__tsan_default_suppressions());
  52. suppression_ctx->Parse(std_suppressions);
  53. #endif
  54. }
  55. SuppressionContext *Suppressions() {
  56. CHECK(suppression_ctx);
  57. return suppression_ctx;
  58. }
  59. static const char *conv(ReportType typ) {
  60. switch (typ) {
  61. case ReportTypeRace:
  62. case ReportTypeVptrRace:
  63. case ReportTypeUseAfterFree:
  64. case ReportTypeVptrUseAfterFree:
  65. case ReportTypeExternalRace:
  66. return kSuppressionRace;
  67. case ReportTypeThreadLeak:
  68. return kSuppressionThread;
  69. case ReportTypeMutexDestroyLocked:
  70. case ReportTypeMutexDoubleLock:
  71. case ReportTypeMutexInvalidAccess:
  72. case ReportTypeMutexBadUnlock:
  73. case ReportTypeMutexBadReadLock:
  74. case ReportTypeMutexBadReadUnlock:
  75. case ReportTypeMutexHeldWrongContext:
  76. return kSuppressionMutex;
  77. case ReportTypeSignalUnsafe:
  78. case ReportTypeErrnoInSignal:
  79. return kSuppressionSignal;
  80. case ReportTypeDeadlock:
  81. return kSuppressionDeadlock;
  82. // No default case so compiler warns us if we miss one
  83. }
  84. UNREACHABLE("missing case");
  85. }
  86. static uptr IsSuppressed(const char *stype, const AddressInfo &info,
  87. Suppression **sp) {
  88. if (suppression_ctx->Match(info.function, stype, sp) ||
  89. suppression_ctx->Match(info.file, stype, sp) ||
  90. suppression_ctx->Match(info.module, stype, sp)) {
  91. VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", (*sp)->templ);
  92. atomic_fetch_add(&(*sp)->hit_count, 1, memory_order_relaxed);
  93. return info.address;
  94. }
  95. return 0;
  96. }
  97. uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
  98. CHECK(suppression_ctx);
  99. if (!suppression_ctx->SuppressionCount() || stack == 0 ||
  100. !stack->suppressable)
  101. return 0;
  102. const char *stype = conv(typ);
  103. if (0 == internal_strcmp(stype, kSuppressionNone))
  104. return 0;
  105. for (const SymbolizedStack *frame = stack->frames; frame;
  106. frame = frame->next) {
  107. uptr pc = IsSuppressed(stype, frame->info, sp);
  108. if (pc != 0)
  109. return pc;
  110. }
  111. if (0 == internal_strcmp(stype, kSuppressionRace) && stack->frames != nullptr)
  112. return IsSuppressed(kSuppressionRaceTop, stack->frames->info, sp);
  113. return 0;
  114. }
  115. uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
  116. CHECK(suppression_ctx);
  117. if (!suppression_ctx->SuppressionCount() || loc == 0 ||
  118. loc->type != ReportLocationGlobal || !loc->suppressable)
  119. return 0;
  120. const char *stype = conv(typ);
  121. if (0 == internal_strcmp(stype, kSuppressionNone))
  122. return 0;
  123. Suppression *s;
  124. const DataInfo &global = loc->global;
  125. if (suppression_ctx->Match(global.name, stype, &s) ||
  126. suppression_ctx->Match(global.module, stype, &s)) {
  127. VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", s->templ);
  128. atomic_fetch_add(&s->hit_count, 1, memory_order_relaxed);
  129. *sp = s;
  130. return global.start;
  131. }
  132. return 0;
  133. }
  134. void PrintMatchedSuppressions() {
  135. InternalMmapVector<Suppression *> matched;
  136. CHECK(suppression_ctx);
  137. suppression_ctx->GetMatched(&matched);
  138. if (!matched.size())
  139. return;
  140. int hit_count = 0;
  141. for (uptr i = 0; i < matched.size(); i++)
  142. hit_count += atomic_load_relaxed(&matched[i]->hit_count);
  143. Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
  144. (int)internal_getpid());
  145. for (uptr i = 0; i < matched.size(); i++) {
  146. Printf("%d %s:%s\n", atomic_load_relaxed(&matched[i]->hit_count),
  147. matched[i]->type, matched[i]->templ);
  148. }
  149. }
  150. } // namespace __tsan