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