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