tsan_interface_ann.cc revision 2d1fdb26e458c4ddc04155c1d421bced3ba90cd0
1//===-- tsan_interface_ann.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#include "sanitizer_common/sanitizer_libc.h" 14#include "sanitizer_common/sanitizer_internal_defs.h" 15#include "sanitizer_common/sanitizer_placement_new.h" 16#include "sanitizer_common/sanitizer_stacktrace.h" 17#include "tsan_interface_ann.h" 18#include "tsan_mutex.h" 19#include "tsan_report.h" 20#include "tsan_rtl.h" 21#include "tsan_mman.h" 22#include "tsan_flags.h" 23#include "tsan_platform.h" 24#include "tsan_vector.h" 25 26#define CALLERPC ((uptr)__builtin_return_address(0)) 27 28using namespace __tsan; // NOLINT 29 30namespace __tsan { 31 32class ScopedAnnotation { 33 public: 34 ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l, 35 uptr pc) 36 : thr_(thr) { 37 FuncEntry(thr_, pc); 38 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l); 39 } 40 41 ~ScopedAnnotation() { 42 FuncExit(thr_); 43 } 44 private: 45 ThreadState *const thr_; 46}; 47 48#define SCOPED_ANNOTATION(typ) \ 49 if (!flags()->enable_annotations) \ 50 return; \ 51 ThreadState *thr = cur_thread(); \ 52 const uptr caller_pc = (uptr)__builtin_return_address(0); \ 53 StatInc(thr, StatAnnotation); \ 54 StatInc(thr, Stat##typ); \ 55 ScopedAnnotation sa(thr, __func__, f, l, caller_pc); \ 56 const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \ 57 (void)pc; \ 58/**/ 59 60static const int kMaxDescLen = 128; 61 62struct ExpectRace { 63 ExpectRace *next; 64 ExpectRace *prev; 65 int hitcount; 66 int addcount; 67 uptr addr; 68 uptr size; 69 char *file; 70 int line; 71 char desc[kMaxDescLen]; 72}; 73 74struct DynamicAnnContext { 75 Mutex mtx; 76 ExpectRace expect; 77 ExpectRace benign; 78 79 DynamicAnnContext() 80 : mtx(MutexTypeAnnotations, StatMtxAnnotations) { 81 } 82}; 83 84static DynamicAnnContext *dyn_ann_ctx; 85static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64); 86 87static void AddExpectRace(ExpectRace *list, 88 char *f, int l, uptr addr, uptr size, char *desc) { 89 ExpectRace *race = list->next; 90 for (; race != list; race = race->next) { 91 if (race->addr == addr && race->size == size) { 92 race->addcount++; 93 return; 94 } 95 } 96 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace)); 97 race->addr = addr; 98 race->size = size; 99 race->file = f; 100 race->line = l; 101 race->desc[0] = 0; 102 race->hitcount = 0; 103 race->addcount = 1; 104 if (desc) { 105 int i = 0; 106 for (; i < kMaxDescLen - 1 && desc[i]; i++) 107 race->desc[i] = desc[i]; 108 race->desc[i] = 0; 109 } 110 race->prev = list; 111 race->next = list->next; 112 race->next->prev = race; 113 list->next = race; 114} 115 116static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) { 117 for (ExpectRace *race = list->next; race != list; race = race->next) { 118 uptr maxbegin = max(race->addr, addr); 119 uptr minend = min(race->addr + race->size, addr + size); 120 if (maxbegin < minend) 121 return race; 122 } 123 return 0; 124} 125 126static bool CheckContains(ExpectRace *list, uptr addr, uptr size) { 127 ExpectRace *race = FindRace(list, addr, size); 128 if (race == 0 && AlternativeAddress(addr)) 129 race = FindRace(list, AlternativeAddress(addr), size); 130 if (race == 0) 131 return false; 132 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n", 133 race->desc, race->addr, (int)race->size, race->file, race->line); 134 race->hitcount++; 135 return true; 136} 137 138static void InitList(ExpectRace *list) { 139 list->next = list; 140 list->prev = list; 141} 142 143void InitializeDynamicAnnotations() { 144 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext; 145 InitList(&dyn_ann_ctx->expect); 146 InitList(&dyn_ann_ctx->benign); 147} 148 149bool IsExpectedReport(uptr addr, uptr size) { 150 Lock lock(&dyn_ann_ctx->mtx); 151 if (CheckContains(&dyn_ann_ctx->expect, addr, size)) 152 return true; 153 if (CheckContains(&dyn_ann_ctx->benign, addr, size)) 154 return true; 155 return false; 156} 157 158static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched, 159 int *unique_count, int *hit_count, int ExpectRace::*counter) { 160 ExpectRace *list = &dyn_ann_ctx->benign; 161 for (ExpectRace *race = list->next; race != list; race = race->next) { 162 (*unique_count)++; 163 if (race->*counter == 0) 164 continue; 165 (*hit_count) += race->*counter; 166 uptr i = 0; 167 for (; i < matched->Size(); i++) { 168 ExpectRace *race0 = &(*matched)[i]; 169 if (race->line == race0->line 170 && internal_strcmp(race->file, race0->file) == 0 171 && internal_strcmp(race->desc, race0->desc) == 0) { 172 race0->*counter += race->*counter; 173 break; 174 } 175 } 176 if (i == matched->Size()) 177 matched->PushBack(*race); 178 } 179} 180 181void PrintMatchedBenignRaces() { 182 Lock lock(&dyn_ann_ctx->mtx); 183 int unique_count = 0; 184 int hit_count = 0; 185 int add_count = 0; 186 Vector<ExpectRace> hit_matched(MBlockScopedBuf); 187 CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count, 188 &ExpectRace::hitcount); 189 Vector<ExpectRace> add_matched(MBlockScopedBuf); 190 CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count, 191 &ExpectRace::addcount); 192 if (hit_matched.Size()) { 193 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n", 194 hit_count, (int)internal_getpid()); 195 for (uptr i = 0; i < hit_matched.Size(); i++) { 196 Printf("%d %s:%d %s\n", 197 hit_matched[i].hitcount, hit_matched[i].file, 198 hit_matched[i].line, hit_matched[i].desc); 199 } 200 } 201 if (hit_matched.Size()) { 202 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique" 203 " (pid=%d):\n", 204 add_count, unique_count, (int)internal_getpid()); 205 for (uptr i = 0; i < add_matched.Size(); i++) { 206 Printf("%d %s:%d %s\n", 207 add_matched[i].addcount, add_matched[i].file, 208 add_matched[i].line, add_matched[i].desc); 209 } 210 } 211} 212 213static void ReportMissedExpectedRace(ExpectRace *race) { 214 Printf("==================\n"); 215 Printf("WARNING: ThreadSanitizer: missed expected data race\n"); 216 Printf(" %s addr=%zx %s:%d\n", 217 race->desc, race->addr, race->file, race->line); 218 Printf("==================\n"); 219} 220} // namespace __tsan 221 222using namespace __tsan; // NOLINT 223 224extern "C" { 225void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) { 226 SCOPED_ANNOTATION(AnnotateHappensBefore); 227 Release(thr, pc, addr); 228} 229 230void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) { 231 SCOPED_ANNOTATION(AnnotateHappensAfter); 232 Acquire(thr, pc, addr); 233} 234 235void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) { 236 SCOPED_ANNOTATION(AnnotateCondVarSignal); 237} 238 239void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) { 240 SCOPED_ANNOTATION(AnnotateCondVarSignalAll); 241} 242 243void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) { 244 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB); 245} 246 247void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv, 248 uptr lock) { 249 SCOPED_ANNOTATION(AnnotateCondVarWait); 250} 251 252void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) { 253 SCOPED_ANNOTATION(AnnotateRWLockCreate); 254 MutexCreate(thr, pc, m, true, true, false); 255} 256 257void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) { 258 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic); 259 MutexCreate(thr, pc, m, true, true, true); 260} 261 262void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) { 263 SCOPED_ANNOTATION(AnnotateRWLockDestroy); 264 MutexDestroy(thr, pc, m); 265} 266 267void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m, 268 uptr is_w) { 269 SCOPED_ANNOTATION(AnnotateRWLockAcquired); 270 if (is_w) 271 MutexLock(thr, pc, m); 272 else 273 MutexReadLock(thr, pc, m); 274} 275 276void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m, 277 uptr is_w) { 278 SCOPED_ANNOTATION(AnnotateRWLockReleased); 279 if (is_w) 280 MutexUnlock(thr, pc, m); 281 else 282 MutexReadUnlock(thr, pc, m); 283} 284 285void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) { 286 SCOPED_ANNOTATION(AnnotateTraceMemory); 287} 288 289void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) { 290 SCOPED_ANNOTATION(AnnotateFlushState); 291} 292 293void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem, 294 uptr size) { 295 SCOPED_ANNOTATION(AnnotateNewMemory); 296} 297 298void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) { 299 SCOPED_ANNOTATION(AnnotateNoOp); 300} 301 302void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) { 303 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces); 304 Lock lock(&dyn_ann_ctx->mtx); 305 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) { 306 ExpectRace *race = dyn_ann_ctx->expect.next; 307 if (race->hitcount == 0) { 308 ctx->nmissed_expected++; 309 ReportMissedExpectedRace(race); 310 } 311 race->prev->next = race->next; 312 race->next->prev = race->prev; 313 internal_free(race); 314 } 315} 316 317void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection( 318 char *f, int l, int enable) { 319 SCOPED_ANNOTATION(AnnotateEnableRaceDetection); 320 // FIXME: Reconsider this functionality later. It may be irrelevant. 321} 322 323void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar( 324 char *f, int l, uptr mu) { 325 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar); 326} 327 328void INTERFACE_ATTRIBUTE AnnotatePCQGet( 329 char *f, int l, uptr pcq) { 330 SCOPED_ANNOTATION(AnnotatePCQGet); 331} 332 333void INTERFACE_ATTRIBUTE AnnotatePCQPut( 334 char *f, int l, uptr pcq) { 335 SCOPED_ANNOTATION(AnnotatePCQPut); 336} 337 338void INTERFACE_ATTRIBUTE AnnotatePCQDestroy( 339 char *f, int l, uptr pcq) { 340 SCOPED_ANNOTATION(AnnotatePCQDestroy); 341} 342 343void INTERFACE_ATTRIBUTE AnnotatePCQCreate( 344 char *f, int l, uptr pcq) { 345 SCOPED_ANNOTATION(AnnotatePCQCreate); 346} 347 348void INTERFACE_ATTRIBUTE AnnotateExpectRace( 349 char *f, int l, uptr mem, char *desc) { 350 SCOPED_ANNOTATION(AnnotateExpectRace); 351 Lock lock(&dyn_ann_ctx->mtx); 352 AddExpectRace(&dyn_ann_ctx->expect, 353 f, l, mem, 1, desc); 354 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l); 355} 356 357static void BenignRaceImpl( 358 char *f, int l, uptr mem, uptr size, char *desc) { 359 Lock lock(&dyn_ann_ctx->mtx); 360 AddExpectRace(&dyn_ann_ctx->benign, 361 f, l, mem, size, desc); 362 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l); 363} 364 365// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm. 366void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized( 367 char *f, int l, uptr mem, uptr size, char *desc) { 368 SCOPED_ANNOTATION(AnnotateBenignRaceSized); 369 BenignRaceImpl(f, l, mem, size, desc); 370} 371 372void INTERFACE_ATTRIBUTE AnnotateBenignRace( 373 char *f, int l, uptr mem, char *desc) { 374 SCOPED_ANNOTATION(AnnotateBenignRace); 375 BenignRaceImpl(f, l, mem, 1, desc); 376} 377 378void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) { 379 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin); 380 ThreadIgnoreBegin(thr, pc); 381} 382 383void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) { 384 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd); 385 ThreadIgnoreEnd(thr, pc); 386} 387 388void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) { 389 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin); 390 ThreadIgnoreBegin(thr, pc); 391} 392 393void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) { 394 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd); 395 ThreadIgnoreEnd(thr, pc); 396} 397 398void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) { 399 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin); 400 ThreadIgnoreSyncBegin(thr, pc); 401} 402 403void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) { 404 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd); 405 ThreadIgnoreSyncEnd(thr, pc); 406} 407 408void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange( 409 char *f, int l, uptr addr, uptr size) { 410 SCOPED_ANNOTATION(AnnotatePublishMemoryRange); 411} 412 413void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange( 414 char *f, int l, uptr addr, uptr size) { 415 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange); 416} 417 418void INTERFACE_ATTRIBUTE AnnotateThreadName( 419 char *f, int l, char *name) { 420 SCOPED_ANNOTATION(AnnotateThreadName); 421 ThreadSetName(thr, name); 422} 423 424// We deliberately omit the implementation of WTFAnnotateHappensBefore() and 425// WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate 426// atomic operations, which should be handled by ThreadSanitizer correctly. 427void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) { 428 SCOPED_ANNOTATION(AnnotateHappensBefore); 429} 430 431void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) { 432 SCOPED_ANNOTATION(AnnotateHappensAfter); 433} 434 435void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized( 436 char *f, int l, uptr mem, uptr sz, char *desc) { 437 SCOPED_ANNOTATION(AnnotateBenignRaceSized); 438 BenignRaceImpl(f, l, mem, sz, desc); 439} 440 441int INTERFACE_ATTRIBUTE RunningOnValgrind() { 442 return flags()->running_on_valgrind; 443} 444 445double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) { 446 return 10.0; 447} 448 449const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) { 450 if (internal_strcmp(query, "pure_happens_before") == 0) 451 return "1"; 452 else 453 return "0"; 454} 455 456void INTERFACE_ATTRIBUTE 457AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {} 458} // extern "C" 459