tsan_suppressions.cc revision a52e5c6f371bcc66e89792db1219a557664aab8d
1//===-- tsan_suppressions.cc ----------------------------------------------===// 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 14#include "sanitizer_common/sanitizer_common.h" 15#include "sanitizer_common/sanitizer_libc.h" 16#include "sanitizer_common/sanitizer_placement_new.h" 17#include "sanitizer_common/sanitizer_suppressions.h" 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 24// Can be overriden in frontend. 25#ifndef TSAN_GO 26extern "C" const char *WEAK __tsan_default_suppressions() { 27 return 0; 28} 29#endif 30 31namespace __tsan { 32 33static SuppressionContext* g_ctx; 34 35static char *ReadFile(const char *filename) { 36 if (filename == 0 || filename[0] == 0) 37 return 0; 38 InternalScopedBuffer<char> tmp(4*1024); 39 if (filename[0] == '/' || GetPwd() == 0) 40 internal_snprintf(tmp.data(), tmp.size(), "%s", filename); 41 else 42 internal_snprintf(tmp.data(), tmp.size(), "%s/%s", GetPwd(), filename); 43 uptr openrv = OpenFile(tmp.data(), false); 44 if (internal_iserror(openrv)) { 45 Printf("ThreadSanitizer: failed to open suppressions file '%s'\n", 46 tmp.data()); 47 Die(); 48 } 49 fd_t fd = openrv; 50 const uptr fsize = internal_filesize(fd); 51 if (fsize == (uptr)-1) { 52 Printf("ThreadSanitizer: failed to stat suppressions file '%s'\n", 53 tmp.data()); 54 Die(); 55 } 56 char *buf = (char*)internal_alloc(MBlockSuppression, fsize + 1); 57 if (fsize != internal_read(fd, buf, fsize)) { 58 Printf("ThreadSanitizer: failed to read suppressions file '%s'\n", 59 tmp.data()); 60 Die(); 61 } 62 internal_close(fd); 63 buf[fsize] = 0; 64 return buf; 65} 66 67void InitializeSuppressions() { 68 ALIGNED(64) static char placeholder_[sizeof(SuppressionContext)]; 69 g_ctx = new(placeholder_) SuppressionContext; 70 const char *supp = ReadFile(flags()->suppressions); 71 g_ctx->Parse(supp); 72#ifndef TSAN_GO 73 supp = __tsan_default_suppressions(); 74 g_ctx->Parse(supp); 75#endif 76} 77 78SuppressionType conv(ReportType typ) { 79 if (typ == ReportTypeRace) 80 return SuppressionRace; 81 else if (typ == ReportTypeVptrRace) 82 return SuppressionRace; 83 else if (typ == ReportTypeUseAfterFree) 84 return SuppressionNone; 85 else if (typ == ReportTypeThreadLeak) 86 return SuppressionThread; 87 else if (typ == ReportTypeMutexDestroyLocked) 88 return SuppressionMutex; 89 else if (typ == ReportTypeSignalUnsafe) 90 return SuppressionSignal; 91 else if (typ == ReportTypeErrnoInSignal) 92 return SuppressionNone; 93 Printf("ThreadSanitizer: unknown report type %d\n", typ), 94 Die(); 95} 96 97uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) { 98 CHECK(g_ctx); 99 if (!g_ctx->SuppressionCount() || stack == 0) return 0; 100 SuppressionType stype = conv(typ); 101 if (stype == SuppressionNone) 102 return 0; 103 Suppression *s; 104 for (const ReportStack *frame = stack; frame; frame = frame->next) { 105 if (g_ctx->Match(frame->func, stype, &s) || 106 g_ctx->Match(frame->file, stype, &s) || 107 g_ctx->Match(frame->module, stype, &s)) { 108 DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ); 109 s->hit_count++; 110 *sp = s; 111 return frame->pc; 112 } 113 } 114 return 0; 115} 116 117uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) { 118 CHECK(g_ctx); 119 if (!g_ctx->SuppressionCount() || loc == 0 || 120 loc->type != ReportLocationGlobal) 121 return 0; 122 SuppressionType stype = conv(typ); 123 if (stype == SuppressionNone) 124 return 0; 125 Suppression *s; 126 if (g_ctx->Match(loc->name, stype, &s) || 127 g_ctx->Match(loc->file, stype, &s) || 128 g_ctx->Match(loc->module, stype, &s)) { 129 DPrintf("ThreadSanitizer: matched suppression '%s'\n", templ); 130 s->hit_count++; 131 *sp = s; 132 return loc->addr; 133 } 134 return 0; 135} 136 137void PrintMatchedSuppressions() { 138 CHECK(g_ctx); 139 InternalMmapVector<Suppression *> matched(1); 140 g_ctx->GetMatched(&matched); 141 if (!matched.size()) 142 return; 143 int hit_count = 0; 144 for (uptr i = 0; i < matched.size(); i++) 145 hit_count += matched[i]->hit_count; 146 Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count, 147 (int)internal_getpid()); 148 for (uptr i = 0; i < matched.size(); i++) { 149 Printf("%d %s:%s\n", matched[i]->hit_count, 150 SuppressionTypeString(matched[i]->type), matched[i]->templ); 151 } 152} 153} // namespace __tsan 154