1 //===-- tsan_interface_ann.cc ---------------------------------------------===// 2 // 3 // This file is distributed under the University of Illinois Open Source 4 // License. See LICENSE.TXT for details. 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 // This file is a part of ThreadSanitizer (TSan), a race detector. 9 // 10 //===----------------------------------------------------------------------===// 11 #include "sanitizer_common/sanitizer_libc.h" 12 #include "sanitizer_common/sanitizer_internal_defs.h" 13 #include "sanitizer_common/sanitizer_placement_new.h" 14 #include "sanitizer_common/sanitizer_stacktrace.h" 15 #include "tsan_interface_ann.h" 16 #include "tsan_mutex.h" 17 #include "tsan_report.h" 18 #include "tsan_rtl.h" 19 #include "tsan_mman.h" 20 #include "tsan_flags.h" 21 #include "tsan_platform.h" 22 #include "tsan_vector.h" 23 24 #define CALLERPC ((uptr)__builtin_return_address(0)) 25 26 using namespace __tsan; // NOLINT 27 28 namespace __tsan { 29 30 class ScopedAnnotation { 31 public: 32 ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l, 33 uptr pc) 34 : thr_(thr) { 35 FuncEntry(thr_, pc); 36 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l); 37 } 38 39 ~ScopedAnnotation() { 40 FuncExit(thr_); 41 CheckNoLocks(thr_); 42 } 43 private: 44 ThreadState *const thr_; 45 }; 46 47 #define SCOPED_ANNOTATION(typ) \ 48 if (!flags()->enable_annotations) \ 49 return; \ 50 ThreadState *thr = cur_thread(); \ 51 const uptr caller_pc = (uptr)__builtin_return_address(0); \ 52 StatInc(thr, StatAnnotation); \ 53 StatInc(thr, Stat##typ); \ 54 ScopedAnnotation sa(thr, __func__, f, l, caller_pc); \ 55 const uptr pc = StackTrace::GetCurrentPc(); \ 56 (void)pc; \ 57 /**/ 58 59 static const int kMaxDescLen = 128; 60 61 struct ExpectRace { 62 ExpectRace *next; 63 ExpectRace *prev; 64 int hitcount; 65 int 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() 79 : mtx(MutexTypeAnnotations, StatMtxAnnotations) { 80 } 81 }; 82 83 static DynamicAnnContext *dyn_ann_ctx; 84 static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64); 85 86 static void AddExpectRace(ExpectRace *list, 87 char *f, int l, uptr addr, uptr size, char *desc) { 88 ExpectRace *race = list->next; 89 for (; race != list; race = race->next) { 90 if (race->addr == addr && race->size == size) { 91 race->addcount++; 92 return; 93 } 94 } 95 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace)); 96 race->addr = addr; 97 race->size = size; 98 race->file = f; 99 race->line = l; 100 race->desc[0] = 0; 101 race->hitcount = 0; 102 race->addcount = 1; 103 if (desc) { 104 int i = 0; 105 for (; i < kMaxDescLen - 1 && desc[i]; i++) 106 race->desc[i] = desc[i]; 107 race->desc[i] = 0; 108 } 109 race->prev = list; 110 race->next = list->next; 111 race->next->prev = race; 112 list->next = race; 113 } 114 115 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) { 116 for (ExpectRace *race = list->next; race != list; race = race->next) { 117 uptr maxbegin = max(race->addr, addr); 118 uptr minend = min(race->addr + race->size, addr + size); 119 if (maxbegin < minend) 120 return race; 121 } 122 return 0; 123 } 124 125 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) { 126 ExpectRace *race = FindRace(list, addr, size); 127 if (race == 0) 128 return false; 129 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n", 130 race->desc, race->addr, (int)race->size, race->file, race->line); 131 race->hitcount++; 132 return true; 133 } 134 135 static void InitList(ExpectRace *list) { 136 list->next = list; 137 list->prev = list; 138 } 139 140 void InitializeDynamicAnnotations() { 141 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext; 142 InitList(&dyn_ann_ctx->expect); 143 InitList(&dyn_ann_ctx->benign); 144 } 145 146 bool IsExpectedReport(uptr addr, uptr size) { 147 Lock lock(&dyn_ann_ctx->mtx); 148 if (CheckContains(&dyn_ann_ctx->expect, addr, size)) 149 return true; 150 if (CheckContains(&dyn_ann_ctx->benign, addr, size)) 151 return true; 152 return false; 153 } 154 155 static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched, 156 int *unique_count, int *hit_count, int ExpectRace::*counter) { 157 ExpectRace *list = &dyn_ann_ctx->benign; 158 for (ExpectRace *race = list->next; race != list; race = race->next) { 159 (*unique_count)++; 160 if (race->*counter == 0) 161 continue; 162 (*hit_count) += race->*counter; 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 race0->*counter += race->*counter; 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(MBlockScopedBuf); 184 CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count, 185 &ExpectRace::hitcount); 186 Vector<ExpectRace> add_matched(MBlockScopedBuf); 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 hit_matched[i].hitcount, hit_matched[i].file, 195 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 add_matched[i].addcount, add_matched[i].file, 205 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; // NOLINT 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, true, true, false); 252 } 253 254 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) { 255 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic); 256 MutexCreate(thr, pc, m, true, true, true); 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 MutexLock(thr, pc, m); 269 else 270 MutexReadLock(thr, pc, m); 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 (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 } // extern "C" 458