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 "tsan_interface_ann.h" 17#include "tsan_mutex.h" 18#include "tsan_report.h" 19#include "tsan_rtl.h" 20#include "tsan_mman.h" 21#include "tsan_flags.h" 22#include "tsan_platform.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 , in_rtl_(thr->in_rtl) { 36 CHECK_EQ(thr_->in_rtl, 0); 37 FuncEntry(thr_, pc); 38 thr_->in_rtl++; 39 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l); 40 } 41 42 ~ScopedAnnotation() { 43 thr_->in_rtl--; 44 CHECK_EQ(in_rtl_, thr_->in_rtl); 45 FuncExit(thr_); 46 } 47 private: 48 ThreadState *const thr_; 49 const int in_rtl_; 50}; 51 52#define SCOPED_ANNOTATION(typ) \ 53 if (!flags()->enable_annotations) \ 54 return; \ 55 ThreadState *thr = cur_thread(); \ 56 const uptr pc = (uptr)__builtin_return_address(0); \ 57 StatInc(thr, StatAnnotation); \ 58 StatInc(thr, Stat##typ); \ 59 ScopedAnnotation sa(thr, __FUNCTION__, f, l, \ 60 (uptr)__builtin_return_address(0)); \ 61 (void)pc; \ 62/**/ 63 64static const int kMaxDescLen = 128; 65 66struct ExpectRace { 67 ExpectRace *next; 68 ExpectRace *prev; 69 int hitcount; 70 uptr addr; 71 uptr size; 72 char *file; 73 int line; 74 char desc[kMaxDescLen]; 75}; 76 77struct DynamicAnnContext { 78 Mutex mtx; 79 ExpectRace expect; 80 ExpectRace benign; 81 82 DynamicAnnContext() 83 : mtx(MutexTypeAnnotations, StatMtxAnnotations) { 84 } 85}; 86 87static DynamicAnnContext *dyn_ann_ctx; 88static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64); 89 90static void AddExpectRace(ExpectRace *list, 91 char *f, int l, uptr addr, uptr size, char *desc) { 92 ExpectRace *race = list->next; 93 for (; race != list; race = race->next) { 94 if (race->addr == addr && race->size == size) 95 return; 96 } 97 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace)); 98 race->hitcount = 0; 99 race->addr = addr; 100 race->size = size; 101 race->file = f; 102 race->line = l; 103 race->desc[0] = 0; 104 if (desc) { 105 int i = 0; 106 for (; i < kMaxDescLen - 1 && desc[i]; i++) 107 race->desc[i] = desc[i]; 108 race->desc[i] = 0; 109 } 110 race->prev = list; 111 race->next = list->next; 112 race->next->prev = race; 113 list->next = race; 114} 115 116static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) { 117 for (ExpectRace *race = list->next; race != list; race = race->next) { 118 uptr maxbegin = max(race->addr, addr); 119 uptr minend = min(race->addr + race->size, addr + size); 120 if (maxbegin < minend) 121 return race; 122 } 123 return 0; 124} 125 126static bool CheckContains(ExpectRace *list, uptr addr, uptr size) { 127 ExpectRace *race = FindRace(list, addr, size); 128 if (race == 0 && AlternativeAddress(addr)) 129 race = FindRace(list, AlternativeAddress(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 race->hitcount++; 135 return true; 136} 137 138static void InitList(ExpectRace *list) { 139 list->next = list; 140 list->prev = list; 141} 142 143void 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 149bool IsExpectedReport(uptr addr, uptr size) { 150 Lock 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} // namespace __tsan 159 160using namespace __tsan; // NOLINT 161 162extern "C" { 163void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) { 164 SCOPED_ANNOTATION(AnnotateHappensBefore); 165 Release(cur_thread(), CALLERPC, addr); 166} 167 168void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) { 169 SCOPED_ANNOTATION(AnnotateHappensAfter); 170 Acquire(cur_thread(), CALLERPC, addr); 171} 172 173void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) { 174 SCOPED_ANNOTATION(AnnotateCondVarSignal); 175} 176 177void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) { 178 SCOPED_ANNOTATION(AnnotateCondVarSignalAll); 179} 180 181void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) { 182 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB); 183} 184 185void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv, 186 uptr lock) { 187 SCOPED_ANNOTATION(AnnotateCondVarWait); 188} 189 190void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) { 191 SCOPED_ANNOTATION(AnnotateRWLockCreate); 192 MutexCreate(thr, pc, m, true, true, false); 193} 194 195void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) { 196 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic); 197 MutexCreate(thr, pc, m, true, true, true); 198} 199 200void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) { 201 SCOPED_ANNOTATION(AnnotateRWLockDestroy); 202 MutexDestroy(thr, pc, m); 203} 204 205void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m, 206 uptr is_w) { 207 SCOPED_ANNOTATION(AnnotateRWLockAcquired); 208 if (is_w) 209 MutexLock(thr, pc, m); 210 else 211 MutexReadLock(thr, pc, m); 212} 213 214void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m, 215 uptr is_w) { 216 SCOPED_ANNOTATION(AnnotateRWLockReleased); 217 if (is_w) 218 MutexUnlock(thr, pc, m); 219 else 220 MutexReadUnlock(thr, pc, m); 221} 222 223void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) { 224 SCOPED_ANNOTATION(AnnotateTraceMemory); 225} 226 227void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) { 228 SCOPED_ANNOTATION(AnnotateFlushState); 229} 230 231void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem, 232 uptr size) { 233 SCOPED_ANNOTATION(AnnotateNewMemory); 234} 235 236void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) { 237 SCOPED_ANNOTATION(AnnotateNoOp); 238} 239 240static void ReportMissedExpectedRace(ExpectRace *race) { 241 Printf("==================\n"); 242 Printf("WARNING: ThreadSanitizer: missed expected data race\n"); 243 Printf(" %s addr=%zx %s:%d\n", 244 race->desc, race->addr, race->file, race->line); 245 Printf("==================\n"); 246} 247 248void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) { 249 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces); 250 Lock lock(&dyn_ann_ctx->mtx); 251 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) { 252 ExpectRace *race = dyn_ann_ctx->expect.next; 253 if (race->hitcount == 0) { 254 CTX()->nmissed_expected++; 255 ReportMissedExpectedRace(race); 256 } 257 race->prev->next = race->next; 258 race->next->prev = race->prev; 259 internal_free(race); 260 } 261} 262 263void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection( 264 char *f, int l, int enable) { 265 SCOPED_ANNOTATION(AnnotateEnableRaceDetection); 266 // FIXME: Reconsider this functionality later. It may be irrelevant. 267} 268 269void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar( 270 char *f, int l, uptr mu) { 271 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar); 272} 273 274void INTERFACE_ATTRIBUTE AnnotatePCQGet( 275 char *f, int l, uptr pcq) { 276 SCOPED_ANNOTATION(AnnotatePCQGet); 277} 278 279void INTERFACE_ATTRIBUTE AnnotatePCQPut( 280 char *f, int l, uptr pcq) { 281 SCOPED_ANNOTATION(AnnotatePCQPut); 282} 283 284void INTERFACE_ATTRIBUTE AnnotatePCQDestroy( 285 char *f, int l, uptr pcq) { 286 SCOPED_ANNOTATION(AnnotatePCQDestroy); 287} 288 289void INTERFACE_ATTRIBUTE AnnotatePCQCreate( 290 char *f, int l, uptr pcq) { 291 SCOPED_ANNOTATION(AnnotatePCQCreate); 292} 293 294void INTERFACE_ATTRIBUTE AnnotateExpectRace( 295 char *f, int l, uptr mem, char *desc) { 296 SCOPED_ANNOTATION(AnnotateExpectRace); 297 Lock lock(&dyn_ann_ctx->mtx); 298 AddExpectRace(&dyn_ann_ctx->expect, 299 f, l, mem, 1, desc); 300 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l); 301} 302 303static void BenignRaceImpl( 304 char *f, int l, uptr mem, uptr size, char *desc) { 305 Lock lock(&dyn_ann_ctx->mtx); 306 AddExpectRace(&dyn_ann_ctx->benign, 307 f, l, mem, size, desc); 308 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l); 309} 310 311// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm. 312void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized( 313 char *f, int l, uptr mem, uptr size, char *desc) { 314 SCOPED_ANNOTATION(AnnotateBenignRaceSized); 315 BenignRaceImpl(f, l, mem, size, desc); 316} 317 318void INTERFACE_ATTRIBUTE AnnotateBenignRace( 319 char *f, int l, uptr mem, char *desc) { 320 SCOPED_ANNOTATION(AnnotateBenignRace); 321 BenignRaceImpl(f, l, mem, 1, desc); 322} 323 324void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) { 325 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin); 326 IgnoreCtl(cur_thread(), false, true); 327} 328 329void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) { 330 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd); 331 IgnoreCtl(cur_thread(), false, false); 332} 333 334void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) { 335 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin); 336 IgnoreCtl(cur_thread(), true, true); 337} 338 339void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) { 340 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd); 341 IgnoreCtl(thr, true, false); 342} 343 344void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange( 345 char *f, int l, uptr addr, uptr size) { 346 SCOPED_ANNOTATION(AnnotatePublishMemoryRange); 347} 348 349void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange( 350 char *f, int l, uptr addr, uptr size) { 351 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange); 352} 353 354void INTERFACE_ATTRIBUTE AnnotateThreadName( 355 char *f, int l, char *name) { 356 SCOPED_ANNOTATION(AnnotateThreadName); 357 ThreadSetName(thr, name); 358} 359 360void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) { 361 SCOPED_ANNOTATION(AnnotateHappensBefore); 362} 363 364void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) { 365 SCOPED_ANNOTATION(AnnotateHappensAfter); 366} 367 368void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized( 369 char *f, int l, uptr mem, uptr sz, char *desc) { 370 SCOPED_ANNOTATION(AnnotateBenignRaceSized); 371} 372 373int INTERFACE_ATTRIBUTE RunningOnValgrind() { 374 return flags()->running_on_valgrind; 375} 376 377double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) { 378 return 10.0; 379} 380 381const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) { 382 if (internal_strcmp(query, "pure_happens_before") == 0) 383 return "1"; 384 else 385 return "0"; 386} 387} // extern "C" 388