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