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