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 26using namespace __tsan; // NOLINT 27 28namespace __tsan { 29 30class 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 59static const int kMaxDescLen = 128; 60 61struct 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 73struct DynamicAnnContext { 74 Mutex mtx; 75 ExpectRace expect; 76 ExpectRace benign; 77 78 DynamicAnnContext() 79 : mtx(MutexTypeAnnotations, StatMtxAnnotations) { 80 } 81}; 82 83static DynamicAnnContext *dyn_ann_ctx; 84static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64); 85 86static 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 115static 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 125static 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 135static void InitList(ExpectRace *list) { 136 list->next = list; 137 list->prev = list; 138} 139 140void 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 146bool 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 155static 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 178void 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 210static 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 219using namespace __tsan; // NOLINT 220 221extern "C" { 222void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) { 223 SCOPED_ANNOTATION(AnnotateHappensBefore); 224 Release(thr, pc, addr); 225} 226 227void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) { 228 SCOPED_ANNOTATION(AnnotateHappensAfter); 229 Acquire(thr, pc, addr); 230} 231 232void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) { 233 SCOPED_ANNOTATION(AnnotateCondVarSignal); 234} 235 236void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) { 237 SCOPED_ANNOTATION(AnnotateCondVarSignalAll); 238} 239 240void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) { 241 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB); 242} 243 244void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv, 245 uptr lock) { 246 SCOPED_ANNOTATION(AnnotateCondVarWait); 247} 248 249void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) { 250 SCOPED_ANNOTATION(AnnotateRWLockCreate); 251 MutexCreate(thr, pc, m, true, true, false); 252} 253 254void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) { 255 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic); 256 MutexCreate(thr, pc, m, true, true, true); 257} 258 259void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) { 260 SCOPED_ANNOTATION(AnnotateRWLockDestroy); 261 MutexDestroy(thr, pc, m); 262} 263 264void 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 273void 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 282void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) { 283 SCOPED_ANNOTATION(AnnotateTraceMemory); 284} 285 286void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) { 287 SCOPED_ANNOTATION(AnnotateFlushState); 288} 289 290void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem, 291 uptr size) { 292 SCOPED_ANNOTATION(AnnotateNewMemory); 293} 294 295void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) { 296 SCOPED_ANNOTATION(AnnotateNoOp); 297} 298 299void 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 314void 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 320void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar( 321 char *f, int l, uptr mu) { 322 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar); 323} 324 325void INTERFACE_ATTRIBUTE AnnotatePCQGet( 326 char *f, int l, uptr pcq) { 327 SCOPED_ANNOTATION(AnnotatePCQGet); 328} 329 330void INTERFACE_ATTRIBUTE AnnotatePCQPut( 331 char *f, int l, uptr pcq) { 332 SCOPED_ANNOTATION(AnnotatePCQPut); 333} 334 335void INTERFACE_ATTRIBUTE AnnotatePCQDestroy( 336 char *f, int l, uptr pcq) { 337 SCOPED_ANNOTATION(AnnotatePCQDestroy); 338} 339 340void INTERFACE_ATTRIBUTE AnnotatePCQCreate( 341 char *f, int l, uptr pcq) { 342 SCOPED_ANNOTATION(AnnotatePCQCreate); 343} 344 345void 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 354static 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. 363void 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 369void 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 375void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) { 376 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin); 377 ThreadIgnoreBegin(thr, pc); 378} 379 380void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) { 381 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd); 382 ThreadIgnoreEnd(thr, pc); 383} 384 385void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) { 386 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin); 387 ThreadIgnoreBegin(thr, pc); 388} 389 390void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) { 391 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd); 392 ThreadIgnoreEnd(thr, pc); 393} 394 395void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) { 396 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin); 397 ThreadIgnoreSyncBegin(thr, pc); 398} 399 400void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) { 401 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd); 402 ThreadIgnoreSyncEnd(thr, pc); 403} 404 405void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange( 406 char *f, int l, uptr addr, uptr size) { 407 SCOPED_ANNOTATION(AnnotatePublishMemoryRange); 408} 409 410void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange( 411 char *f, int l, uptr addr, uptr size) { 412 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange); 413} 414 415void 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. 424void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) { 425 SCOPED_ANNOTATION(AnnotateHappensBefore); 426} 427 428void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) { 429 SCOPED_ANNOTATION(AnnotateHappensAfter); 430} 431 432void 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 438int INTERFACE_ATTRIBUTE RunningOnValgrind() { 439 return flags()->running_on_valgrind; 440} 441 442double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) { 443 return 10.0; 444} 445 446const 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 453void INTERFACE_ATTRIBUTE 454AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {} 455void INTERFACE_ATTRIBUTE 456AnnotateMemoryIsUninitialized(char *f, int l, uptr mem, uptr sz) {} 457} // extern "C" 458