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