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