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