tsan_suppressions.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 "sanitizer_common/sanitizer_common.h"
  13. #include "sanitizer_common/sanitizer_libc.h"
  14. #include "sanitizer_common/sanitizer_placement_new.h"
  15. #include "sanitizer_common/sanitizer_suppressions.h"
  16. #include "tsan_suppressions.h"
  17. #include "tsan_rtl.h"
  18. #include "tsan_flags.h"
  19. #include "tsan_mman.h"
  20. #include "tsan_platform.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. return kSuppressionMutex;
  76. case ReportTypeSignalUnsafe:
  77. case ReportTypeErrnoInSignal:
  78. return kSuppressionSignal;
  79. case ReportTypeDeadlock:
  80. return kSuppressionDeadlock;
  81. // No default case so compiler warns us if we miss one
  82. }
  83. UNREACHABLE("missing case");
  84. }
  85. static uptr IsSuppressed(const char *stype, const AddressInfo &info,
  86. Suppression **sp) {
  87. if (suppression_ctx->Match(info.function, stype, sp) ||
  88. suppression_ctx->Match(info.file, stype, sp) ||
  89. suppression_ctx->Match(info.module, stype, sp)) {
  90. VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", (*sp)->templ);
  91. atomic_fetch_add(&(*sp)->hit_count, 1, memory_order_relaxed);
  92. return info.address;
  93. }
  94. return 0;
  95. }
  96. uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
  97. CHECK(suppression_ctx);
  98. if (!suppression_ctx->SuppressionCount() || stack == 0 ||
  99. !stack->suppressable)
  100. return 0;
  101. const char *stype = conv(typ);
  102. if (0 == internal_strcmp(stype, kSuppressionNone))
  103. return 0;
  104. for (const SymbolizedStack *frame = stack->frames; frame;
  105. frame = frame->next) {
  106. uptr pc = IsSuppressed(stype, frame->info, sp);
  107. if (pc != 0)
  108. return pc;
  109. }
  110. if (0 == internal_strcmp(stype, kSuppressionRace) && stack->frames != nullptr)
  111. return IsSuppressed(kSuppressionRaceTop, stack->frames->info, sp);
  112. return 0;
  113. }
  114. uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
  115. CHECK(suppression_ctx);
  116. if (!suppression_ctx->SuppressionCount() || loc == 0 ||
  117. loc->type != ReportLocationGlobal || !loc->suppressable)
  118. return 0;
  119. const char *stype = conv(typ);
  120. if (0 == internal_strcmp(stype, kSuppressionNone))
  121. return 0;
  122. Suppression *s;
  123. const DataInfo &global = loc->global;
  124. if (suppression_ctx->Match(global.name, stype, &s) ||
  125. suppression_ctx->Match(global.module, stype, &s)) {
  126. VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", s->templ);
  127. atomic_fetch_add(&s->hit_count, 1, memory_order_relaxed);
  128. *sp = s;
  129. return global.start;
  130. }
  131. return 0;
  132. }
  133. void PrintMatchedSuppressions() {
  134. InternalMmapVector<Suppression *> matched;
  135. CHECK(suppression_ctx);
  136. suppression_ctx->GetMatched(&matched);
  137. if (!matched.size())
  138. return;
  139. int hit_count = 0;
  140. for (uptr i = 0; i < matched.size(); i++)
  141. hit_count += atomic_load_relaxed(&matched[i]->hit_count);
  142. Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
  143. (int)internal_getpid());
  144. for (uptr i = 0; i < matched.size(); i++) {
  145. Printf("%d %s:%s\n", atomic_load_relaxed(&matched[i]->hit_count),
  146. matched[i]->type, matched[i]->templ);
  147. }
  148. }
  149. } // namespace __tsan