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 "sanitizer_common/sanitizer_vector.h" 18 #include "tsan_interface_ann.h" 19 #include "tsan_mutex.h" 20 #include "tsan_report.h" 21 #include "tsan_rtl.h" 22 #include "tsan_mman.h" 23 #include "tsan_flags.h" 24 #include "tsan_platform.h" 25 26 #define CALLERPC ((uptr)__builtin_return_address(0)) 27 28 using namespace __tsan; // NOLINT 29 30 namespace __tsan { 31 32 class ScopedAnnotation { 33 public: 34 ScopedAnnotation(ThreadState *thr, const char *aname, uptr pc) 35 : thr_(thr) { 36 FuncEntry(thr_, pc); 37 DPrintf("#%d: annotation %s()\n", thr_->tid, aname); 38 } 39 40 ~ScopedAnnotation() { 41 FuncExit(thr_); 42 CheckNoLocks(thr_); 43 } 44 private: 45 ThreadState *const thr_; 46 }; 47 48 #define SCOPED_ANNOTATION_RET(typ, ret) \ 49 if (!flags()->enable_annotations) \ 50 return ret; \ 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__, caller_pc); \ 56 const uptr pc = StackTrace::GetCurrentPc(); \ 57 (void)pc; \ 58 /**/ 59 60 #define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, ) 61 62 static const int kMaxDescLen = 128; 63 64 struct ExpectRace { 65 ExpectRace *next; 66 ExpectRace *prev; 67 atomic_uintptr_t hitcount; 68 atomic_uintptr_t addcount; 69 uptr addr; 70 uptr size; 71 char *file; 72 int line; 73 char desc[kMaxDescLen]; 74 }; 75 76 struct DynamicAnnContext { 77 Mutex mtx; 78 ExpectRace expect; 79 ExpectRace benign; 80 81 DynamicAnnContext() 82 : mtx(MutexTypeAnnotations, StatMtxAnnotations) { 83 } 84 }; 85 86 static DynamicAnnContext *dyn_ann_ctx; 87 static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64); 88 89 static void AddExpectRace(ExpectRace *list, 90 char *f, int l, uptr addr, uptr size, char *desc) { 91 ExpectRace *race = list->next; 92 for (; race != list; race = race->next) { 93 if (race->addr == addr && race->size == size) { 94 atomic_store_relaxed(&race->addcount, 95 atomic_load_relaxed(&race->addcount) + 1); 96 return; 97 } 98 } 99 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace)); 100 race->addr = addr; 101 race->size = size; 102 race->file = f; 103 race->line = l; 104 race->desc[0] = 0; 105 atomic_store_relaxed(&race->hitcount, 0); 106 atomic_store_relaxed(&race->addcount, 1); 107 if (desc) { 108 int i = 0; 109 for (; i < kMaxDescLen - 1 && desc[i]; i++) 110 race->desc[i] = desc[i]; 111 race->desc[i] = 0; 112 } 113 race->prev = list; 114 race->next = list->next; 115 race->next->prev = race; 116 list->next = race; 117 } 118 119 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) { 120 for (ExpectRace *race = list->next; race != list; race = race->next) { 121 uptr maxbegin = max(race->addr, addr); 122 uptr minend = min(race->addr + race->size, addr + size); 123 if (maxbegin < minend) 124 return race; 125 } 126 return 0; 127 } 128 129 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) { 130 ExpectRace *race = FindRace(list, addr, size); 131 if (race == 0) 132 return false; 133 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n", 134 race->desc, race->addr, (int)race->size, race->file, race->line); 135 atomic_fetch_add(&race->hitcount, 1, memory_order_relaxed); 136 return true; 137 } 138 139 static void InitList(ExpectRace *list) { 140 list->next = list; 141 list->prev = list; 142 } 143 144 void InitializeDynamicAnnotations() { 145 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext; 146 InitList(&dyn_ann_ctx->expect); 147 InitList(&dyn_ann_ctx->benign); 148 } 149 150 bool IsExpectedReport(uptr addr, uptr size) { 151 ReadLock lock(&dyn_ann_ctx->mtx); 152 if (CheckContains(&dyn_ann_ctx->expect, addr, size)) 153 return true; 154 if (CheckContains(&dyn_ann_ctx->benign, addr, size)) 155 return true; 156 return false; 157 } 158 159 static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched, 160 int *unique_count, int *hit_count, atomic_uintptr_t ExpectRace::*counter) { 161 ExpectRace *list = &dyn_ann_ctx->benign; 162 for (ExpectRace *race = list->next; race != list; race = race->next) { 163 (*unique_count)++; 164 const uptr cnt = atomic_load_relaxed(&(race->*counter)); 165 if (cnt == 0) 166 continue; 167 *hit_count += cnt; 168 uptr i = 0; 169 for (; i < matched->Size(); i++) { 170 ExpectRace *race0 = &(*matched)[i]; 171 if (race->line == race0->line 172 && internal_strcmp(race->file, race0->file) == 0 173 && internal_strcmp(race->desc, race0->desc) == 0) { 174 atomic_fetch_add(&(race0->*counter), cnt, memory_order_relaxed); 175 break; 176 } 177 } 178 if (i == matched->Size()) 179 matched->PushBack(*race); 180 } 181 } 182 183 void PrintMatchedBenignRaces() { 184 Lock lock(&dyn_ann_ctx->mtx); 185 int unique_count = 0; 186 int hit_count = 0; 187 int add_count = 0; 188 Vector<ExpectRace> hit_matched; 189 CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count, 190 &ExpectRace::hitcount); 191 Vector<ExpectRace> add_matched; 192 CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count, 193 &ExpectRace::addcount); 194 if (hit_matched.Size()) { 195 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n", 196 hit_count, (int)internal_getpid()); 197 for (uptr i = 0; i < hit_matched.Size(); i++) { 198 Printf("%d %s:%d %s\n", 199 atomic_load_relaxed(&hit_matched[i].hitcount), 200 hit_matched[i].file, hit_matched[i].line, hit_matched[i].desc); 201 } 202 } 203 if (hit_matched.Size()) { 204 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique" 205 " (pid=%d):\n", 206 add_count, unique_count, (int)internal_getpid()); 207 for (uptr i = 0; i < add_matched.Size(); i++) { 208 Printf("%d %s:%d %s\n", 209 atomic_load_relaxed(&add_matched[i].addcount), 210 add_matched[i].file, add_matched[i].line, add_matched[i].desc); 211 } 212 } 213 } 214 215 static void ReportMissedExpectedRace(ExpectRace *race) { 216 Printf("==================\n"); 217 Printf("WARNING: ThreadSanitizer: missed expected data race\n"); 218 Printf(" %s addr=%zx %s:%d\n", 219 race->desc, race->addr, race->file, race->line); 220 Printf("==================\n"); 221 } 222 } // namespace __tsan 223 224 using namespace __tsan; // NOLINT 225 226 extern "C" { 227 void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) { 228 SCOPED_ANNOTATION(AnnotateHappensBefore); 229 Release(thr, pc, addr); 230 } 231 232 void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) { 233 SCOPED_ANNOTATION(AnnotateHappensAfter); 234 Acquire(thr, pc, addr); 235 } 236 237 void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) { 238 SCOPED_ANNOTATION(AnnotateCondVarSignal); 239 } 240 241 void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) { 242 SCOPED_ANNOTATION(AnnotateCondVarSignalAll); 243 } 244 245 void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) { 246 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB); 247 } 248 249 void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv, 250 uptr lock) { 251 SCOPED_ANNOTATION(AnnotateCondVarWait); 252 } 253 254 void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) { 255 SCOPED_ANNOTATION(AnnotateRWLockCreate); 256 MutexCreate(thr, pc, m, MutexFlagWriteReentrant); 257 } 258 259 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) { 260 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic); 261 MutexCreate(thr, pc, m, MutexFlagWriteReentrant | MutexFlagLinkerInit); 262 } 263 264 void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) { 265 SCOPED_ANNOTATION(AnnotateRWLockDestroy); 266 MutexDestroy(thr, pc, m); 267 } 268 269 void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m, 270 uptr is_w) { 271 SCOPED_ANNOTATION(AnnotateRWLockAcquired); 272 if (is_w) 273 MutexPostLock(thr, pc, m, MutexFlagDoPreLockOnPostLock); 274 else 275 MutexPostReadLock(thr, pc, m, MutexFlagDoPreLockOnPostLock); 276 } 277 278 void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m, 279 uptr is_w) { 280 SCOPED_ANNOTATION(AnnotateRWLockReleased); 281 if (is_w) 282 MutexUnlock(thr, pc, m); 283 else 284 MutexReadUnlock(thr, pc, m); 285 } 286 287 void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) { 288 SCOPED_ANNOTATION(AnnotateTraceMemory); 289 } 290 291 void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) { 292 SCOPED_ANNOTATION(AnnotateFlushState); 293 } 294 295 void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem, 296 uptr size) { 297 SCOPED_ANNOTATION(AnnotateNewMemory); 298 } 299 300 void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) { 301 SCOPED_ANNOTATION(AnnotateNoOp); 302 } 303 304 void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) { 305 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces); 306 Lock lock(&dyn_ann_ctx->mtx); 307 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) { 308 ExpectRace *race = dyn_ann_ctx->expect.next; 309 if (atomic_load_relaxed(&race->hitcount) == 0) { 310 ctx->nmissed_expected++; 311 ReportMissedExpectedRace(race); 312 } 313 race->prev->next = race->next; 314 race->next->prev = race->prev; 315 internal_free(race); 316 } 317 } 318 319 void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection( 320 char *f, int l, int enable) { 321 SCOPED_ANNOTATION(AnnotateEnableRaceDetection); 322 // FIXME: Reconsider this functionality later. It may be irrelevant. 323 } 324 325 void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar( 326 char *f, int l, uptr mu) { 327 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar); 328 } 329 330 void INTERFACE_ATTRIBUTE AnnotatePCQGet( 331 char *f, int l, uptr pcq) { 332 SCOPED_ANNOTATION(AnnotatePCQGet); 333 } 334 335 void INTERFACE_ATTRIBUTE AnnotatePCQPut( 336 char *f, int l, uptr pcq) { 337 SCOPED_ANNOTATION(AnnotatePCQPut); 338 } 339 340 void INTERFACE_ATTRIBUTE AnnotatePCQDestroy( 341 char *f, int l, uptr pcq) { 342 SCOPED_ANNOTATION(AnnotatePCQDestroy); 343 } 344 345 void INTERFACE_ATTRIBUTE AnnotatePCQCreate( 346 char *f, int l, uptr pcq) { 347 SCOPED_ANNOTATION(AnnotatePCQCreate); 348 } 349 350 void INTERFACE_ATTRIBUTE AnnotateExpectRace( 351 char *f, int l, uptr mem, char *desc) { 352 SCOPED_ANNOTATION(AnnotateExpectRace); 353 Lock lock(&dyn_ann_ctx->mtx); 354 AddExpectRace(&dyn_ann_ctx->expect, 355 f, l, mem, 1, desc); 356 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l); 357 } 358 359 static void BenignRaceImpl( 360 char *f, int l, uptr mem, uptr size, char *desc) { 361 Lock lock(&dyn_ann_ctx->mtx); 362 AddExpectRace(&dyn_ann_ctx->benign, 363 f, l, mem, size, desc); 364 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l); 365 } 366 367 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm. 368 void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized( 369 char *f, int l, uptr mem, uptr size, char *desc) { 370 SCOPED_ANNOTATION(AnnotateBenignRaceSized); 371 BenignRaceImpl(f, l, mem, size, desc); 372 } 373 374 void INTERFACE_ATTRIBUTE AnnotateBenignRace( 375 char *f, int l, uptr mem, char *desc) { 376 SCOPED_ANNOTATION(AnnotateBenignRace); 377 BenignRaceImpl(f, l, mem, 1, desc); 378 } 379 380 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) { 381 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin); 382 ThreadIgnoreBegin(thr, pc); 383 } 384 385 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) { 386 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd); 387 ThreadIgnoreEnd(thr, pc); 388 } 389 390 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) { 391 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin); 392 ThreadIgnoreBegin(thr, pc); 393 } 394 395 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) { 396 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd); 397 ThreadIgnoreEnd(thr, pc); 398 } 399 400 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) { 401 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin); 402 ThreadIgnoreSyncBegin(thr, pc); 403 } 404 405 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) { 406 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd); 407 ThreadIgnoreSyncEnd(thr, pc); 408 } 409 410 void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange( 411 char *f, int l, uptr addr, uptr size) { 412 SCOPED_ANNOTATION(AnnotatePublishMemoryRange); 413 } 414 415 void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange( 416 char *f, int l, uptr addr, uptr size) { 417 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange); 418 } 419 420 void INTERFACE_ATTRIBUTE AnnotateThreadName( 421 char *f, int l, char *name) { 422 SCOPED_ANNOTATION(AnnotateThreadName); 423 ThreadSetName(thr, name); 424 } 425 426 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and 427 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate 428 // atomic operations, which should be handled by ThreadSanitizer correctly. 429 void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) { 430 SCOPED_ANNOTATION(AnnotateHappensBefore); 431 } 432 433 void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) { 434 SCOPED_ANNOTATION(AnnotateHappensAfter); 435 } 436 437 void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized( 438 char *f, int l, uptr mem, uptr sz, char *desc) { 439 SCOPED_ANNOTATION(AnnotateBenignRaceSized); 440 BenignRaceImpl(f, l, mem, sz, desc); 441 } 442 443 int INTERFACE_ATTRIBUTE RunningOnValgrind() { 444 return flags()->running_on_valgrind; 445 } 446 447 double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) { 448 return 10.0; 449 } 450 451 const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) { 452 if (internal_strcmp(query, "pure_happens_before") == 0) 453 return "1"; 454 else 455 return "0"; 456 } 457 458 void INTERFACE_ATTRIBUTE 459 AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {} 460 void INTERFACE_ATTRIBUTE 461 AnnotateMemoryIsUninitialized(char *f, int l, uptr mem, uptr sz) {} 462 463 // Note: the parameter is called flagz, because flags is already taken 464 // by the global function that returns flags. 465 INTERFACE_ATTRIBUTE 466 void __tsan_mutex_create(void *m, unsigned flagz) { 467 SCOPED_ANNOTATION(__tsan_mutex_create); 468 MutexCreate(thr, pc, (uptr)m, flagz & MutexCreationFlagMask); 469 } 470 471 INTERFACE_ATTRIBUTE 472 void __tsan_mutex_destroy(void *m, unsigned flagz) { 473 SCOPED_ANNOTATION(__tsan_mutex_destroy); 474 MutexDestroy(thr, pc, (uptr)m, flagz); 475 } 476 477 INTERFACE_ATTRIBUTE 478 void __tsan_mutex_pre_lock(void *m, unsigned flagz) { 479 SCOPED_ANNOTATION(__tsan_mutex_pre_lock); 480 if (!(flagz & MutexFlagTryLock)) { 481 if (flagz & MutexFlagReadLock) 482 MutexPreReadLock(thr, pc, (uptr)m); 483 else 484 MutexPreLock(thr, pc, (uptr)m); 485 } 486 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false); 487 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false); 488 } 489 490 INTERFACE_ATTRIBUTE 491 void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) { 492 SCOPED_ANNOTATION(__tsan_mutex_post_lock); 493 ThreadIgnoreSyncEnd(thr, pc); 494 ThreadIgnoreEnd(thr, pc); 495 if (!(flagz & MutexFlagTryLockFailed)) { 496 if (flagz & MutexFlagReadLock) 497 MutexPostReadLock(thr, pc, (uptr)m, flagz); 498 else 499 MutexPostLock(thr, pc, (uptr)m, flagz, rec); 500 } 501 } 502 503 INTERFACE_ATTRIBUTE 504 int __tsan_mutex_pre_unlock(void *m, unsigned flagz) { 505 SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock, 0); 506 int ret = 0; 507 if (flagz & MutexFlagReadLock) { 508 CHECK(!(flagz & MutexFlagRecursiveUnlock)); 509 MutexReadUnlock(thr, pc, (uptr)m); 510 } else { 511 ret = MutexUnlock(thr, pc, (uptr)m, flagz); 512 } 513 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false); 514 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false); 515 return ret; 516 } 517 518 INTERFACE_ATTRIBUTE 519 void __tsan_mutex_post_unlock(void *m, unsigned flagz) { 520 SCOPED_ANNOTATION(__tsan_mutex_post_unlock); 521 ThreadIgnoreSyncEnd(thr, pc); 522 ThreadIgnoreEnd(thr, pc); 523 } 524 525 INTERFACE_ATTRIBUTE 526 void __tsan_mutex_pre_signal(void *addr, unsigned flagz) { 527 SCOPED_ANNOTATION(__tsan_mutex_pre_signal); 528 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false); 529 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false); 530 } 531 532 INTERFACE_ATTRIBUTE 533 void __tsan_mutex_post_signal(void *addr, unsigned flagz) { 534 SCOPED_ANNOTATION(__tsan_mutex_post_signal); 535 ThreadIgnoreSyncEnd(thr, pc); 536 ThreadIgnoreEnd(thr, pc); 537 } 538 539 INTERFACE_ATTRIBUTE 540 void __tsan_mutex_pre_divert(void *addr, unsigned flagz) { 541 SCOPED_ANNOTATION(__tsan_mutex_pre_divert); 542 // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal. 543 ThreadIgnoreSyncEnd(thr, pc); 544 ThreadIgnoreEnd(thr, pc); 545 } 546 547 INTERFACE_ATTRIBUTE 548 void __tsan_mutex_post_divert(void *addr, unsigned flagz) { 549 SCOPED_ANNOTATION(__tsan_mutex_post_divert); 550 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false); 551 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false); 552 } 553 } // extern "C" 554