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