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