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