1 //===-- tsan_interface_ann.cpp --------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
10 //
11 //===----------------------------------------------------------------------===//
12 #include "sanitizer_common/sanitizer_libc.h"
13 #include "sanitizer_common/sanitizer_internal_defs.h"
14 #include "sanitizer_common/sanitizer_placement_new.h"
15 #include "sanitizer_common/sanitizer_stacktrace.h"
16 #include "sanitizer_common/sanitizer_vector.h"
17 #include "tsan_interface_ann.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 
26 using namespace __tsan;
27 
28 namespace __tsan {
29 
30 class ScopedAnnotation {
31  public:
32   ScopedAnnotation(ThreadState *thr, const char *aname, uptr pc)
33       : thr_(thr) {
34     FuncEntry(thr_, pc);
35     DPrintf("#%d: annotation %s()\n", thr_->tid, aname);
36   }
37 
38   ~ScopedAnnotation() {
39     FuncExit(thr_);
40     CheckedMutex::CheckNoLocks();
41   }
42  private:
43   ThreadState *const thr_;
44 };
45 
46 #define SCOPED_ANNOTATION_RET(typ, ret)                     \
47   if (!flags()->enable_annotations)                         \
48     return ret;                                             \
49   ThreadState *thr = cur_thread();                          \
50   const uptr caller_pc = (uptr)__builtin_return_address(0); \
51   ScopedAnnotation sa(thr, __func__, caller_pc);            \
52   const uptr pc = StackTrace::GetCurrentPc();               \
53   (void)pc;
54 
55 #define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )
56 
57 static const int kMaxDescLen = 128;
58 
59 struct ExpectRace {
60   ExpectRace *next;
61   ExpectRace *prev;
62   atomic_uintptr_t hitcount;
63   atomic_uintptr_t addcount;
64   uptr addr;
65   uptr size;
66   char *file;
67   int line;
68   char desc[kMaxDescLen];
69 };
70 
71 struct DynamicAnnContext {
72   Mutex mtx;
73   ExpectRace expect;
74   ExpectRace benign;
75 
76   DynamicAnnContext() : mtx(MutexTypeAnnotations) {}
77 };
78 
79 static DynamicAnnContext *dyn_ann_ctx;
80 static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
81 
82 static void AddExpectRace(ExpectRace *list,
83     char *f, int l, uptr addr, uptr size, char *desc) {
84   ExpectRace *race = list->next;
85   for (; race != list; race = race->next) {
86     if (race->addr == addr && race->size == size) {
87       atomic_store_relaxed(&race->addcount,
88           atomic_load_relaxed(&race->addcount) + 1);
89       return;
90     }
91   }
92   race = (ExpectRace *)internal_alloc(sizeof(ExpectRace));
93   race->addr = addr;
94   race->size = size;
95   race->file = f;
96   race->line = l;
97   race->desc[0] = 0;
98   atomic_store_relaxed(&race->hitcount, 0);
99   atomic_store_relaxed(&race->addcount, 1);
100   if (desc) {
101     int i = 0;
102     for (; i < kMaxDescLen - 1 && desc[i]; i++)
103       race->desc[i] = desc[i];
104     race->desc[i] = 0;
105   }
106   race->prev = list;
107   race->next = list->next;
108   race->next->prev = race;
109   list->next = race;
110 }
111 
112 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
113   for (ExpectRace *race = list->next; race != list; race = race->next) {
114     uptr maxbegin = max(race->addr, addr);
115     uptr minend = min(race->addr + race->size, addr + size);
116     if (maxbegin < minend)
117       return race;
118   }
119   return 0;
120 }
121 
122 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
123   ExpectRace *race = FindRace(list, addr, size);
124   if (race == 0)
125     return false;
126   DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
127       race->desc, race->addr, (int)race->size, race->file, race->line);
128   atomic_fetch_add(&race->hitcount, 1, memory_order_relaxed);
129   return true;
130 }
131 
132 static void InitList(ExpectRace *list) {
133   list->next = list;
134   list->prev = list;
135 }
136 
137 void InitializeDynamicAnnotations() {
138   dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
139   InitList(&dyn_ann_ctx->expect);
140   InitList(&dyn_ann_ctx->benign);
141 }
142 
143 bool IsExpectedReport(uptr addr, uptr size) {
144   ReadLock lock(&dyn_ann_ctx->mtx);
145   if (CheckContains(&dyn_ann_ctx->expect, addr, size))
146     return true;
147   if (CheckContains(&dyn_ann_ctx->benign, addr, size))
148     return true;
149   return false;
150 }
151 
152 static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
153     int *unique_count, int *hit_count, atomic_uintptr_t ExpectRace::*counter) {
154   ExpectRace *list = &dyn_ann_ctx->benign;
155   for (ExpectRace *race = list->next; race != list; race = race->next) {
156     (*unique_count)++;
157     const uptr cnt = atomic_load_relaxed(&(race->*counter));
158     if (cnt == 0)
159       continue;
160     *hit_count += cnt;
161     uptr i = 0;
162     for (; i < matched->Size(); i++) {
163       ExpectRace *race0 = &(*matched)[i];
164       if (race->line == race0->line
165           && internal_strcmp(race->file, race0->file) == 0
166           && internal_strcmp(race->desc, race0->desc) == 0) {
167         atomic_fetch_add(&(race0->*counter), cnt, memory_order_relaxed);
168         break;
169       }
170     }
171     if (i == matched->Size())
172       matched->PushBack(*race);
173   }
174 }
175 
176 void PrintMatchedBenignRaces() {
177   Lock lock(&dyn_ann_ctx->mtx);
178   int unique_count = 0;
179   int hit_count = 0;
180   int add_count = 0;
181   Vector<ExpectRace> hit_matched;
182   CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
183       &ExpectRace::hitcount);
184   Vector<ExpectRace> add_matched;
185   CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
186       &ExpectRace::addcount);
187   if (hit_matched.Size()) {
188     Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
189         hit_count, (int)internal_getpid());
190     for (uptr i = 0; i < hit_matched.Size(); i++) {
191       Printf("%d %s:%d %s\n",
192           atomic_load_relaxed(&hit_matched[i].hitcount),
193           hit_matched[i].file, hit_matched[i].line, hit_matched[i].desc);
194     }
195   }
196   if (hit_matched.Size()) {
197     Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
198            " (pid=%d):\n",
199         add_count, unique_count, (int)internal_getpid());
200     for (uptr i = 0; i < add_matched.Size(); i++) {
201       Printf("%d %s:%d %s\n",
202           atomic_load_relaxed(&add_matched[i].addcount),
203           add_matched[i].file, add_matched[i].line, add_matched[i].desc);
204     }
205   }
206 }
207 
208 static void ReportMissedExpectedRace(ExpectRace *race) {
209   Printf("==================\n");
210   Printf("WARNING: ThreadSanitizer: missed expected data race\n");
211   Printf("  %s addr=%zx %s:%d\n",
212       race->desc, race->addr, race->file, race->line);
213   Printf("==================\n");
214 }
215 }  // namespace __tsan
216 
217 using namespace __tsan;
218 
219 extern "C" {
220 void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
221   SCOPED_ANNOTATION(AnnotateHappensBefore);
222   Release(thr, pc, addr);
223 }
224 
225 void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
226   SCOPED_ANNOTATION(AnnotateHappensAfter);
227   Acquire(thr, pc, addr);
228 }
229 
230 void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
231   SCOPED_ANNOTATION(AnnotateCondVarSignal);
232 }
233 
234 void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
235   SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
236 }
237 
238 void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
239   SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
240 }
241 
242 void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
243                                              uptr lock) {
244   SCOPED_ANNOTATION(AnnotateCondVarWait);
245 }
246 
247 void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
248   SCOPED_ANNOTATION(AnnotateRWLockCreate);
249   MutexCreate(thr, pc, m, MutexFlagWriteReentrant);
250 }
251 
252 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
253   SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
254   MutexCreate(thr, pc, m, MutexFlagWriteReentrant | MutexFlagLinkerInit);
255 }
256 
257 void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
258   SCOPED_ANNOTATION(AnnotateRWLockDestroy);
259   MutexDestroy(thr, pc, m);
260 }
261 
262 void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
263                                                 uptr is_w) {
264   SCOPED_ANNOTATION(AnnotateRWLockAcquired);
265   if (is_w)
266     MutexPostLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
267   else
268     MutexPostReadLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
269 }
270 
271 void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
272                                                 uptr is_w) {
273   SCOPED_ANNOTATION(AnnotateRWLockReleased);
274   if (is_w)
275     MutexUnlock(thr, pc, m);
276   else
277     MutexReadUnlock(thr, pc, m);
278 }
279 
280 void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
281   SCOPED_ANNOTATION(AnnotateTraceMemory);
282 }
283 
284 void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
285   SCOPED_ANNOTATION(AnnotateFlushState);
286 }
287 
288 void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
289                                            uptr size) {
290   SCOPED_ANNOTATION(AnnotateNewMemory);
291 }
292 
293 void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
294   SCOPED_ANNOTATION(AnnotateNoOp);
295 }
296 
297 void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
298   SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
299   Lock lock(&dyn_ann_ctx->mtx);
300   while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
301     ExpectRace *race = dyn_ann_ctx->expect.next;
302     if (atomic_load_relaxed(&race->hitcount) == 0) {
303       ctx->nmissed_expected++;
304       ReportMissedExpectedRace(race);
305     }
306     race->prev->next = race->next;
307     race->next->prev = race->prev;
308     internal_free(race);
309   }
310 }
311 
312 void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
313     char *f, int l, int enable) {
314   SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
315   // FIXME: Reconsider this functionality later. It may be irrelevant.
316 }
317 
318 void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
319     char *f, int l, uptr mu) {
320   SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
321 }
322 
323 void INTERFACE_ATTRIBUTE AnnotatePCQGet(
324     char *f, int l, uptr pcq) {
325   SCOPED_ANNOTATION(AnnotatePCQGet);
326 }
327 
328 void INTERFACE_ATTRIBUTE AnnotatePCQPut(
329     char *f, int l, uptr pcq) {
330   SCOPED_ANNOTATION(AnnotatePCQPut);
331 }
332 
333 void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
334     char *f, int l, uptr pcq) {
335   SCOPED_ANNOTATION(AnnotatePCQDestroy);
336 }
337 
338 void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
339     char *f, int l, uptr pcq) {
340   SCOPED_ANNOTATION(AnnotatePCQCreate);
341 }
342 
343 void INTERFACE_ATTRIBUTE AnnotateExpectRace(
344     char *f, int l, uptr mem, char *desc) {
345   SCOPED_ANNOTATION(AnnotateExpectRace);
346   Lock lock(&dyn_ann_ctx->mtx);
347   AddExpectRace(&dyn_ann_ctx->expect,
348                 f, l, mem, 1, desc);
349   DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
350 }
351 
352 static void BenignRaceImpl(
353     char *f, int l, uptr mem, uptr size, char *desc) {
354   Lock lock(&dyn_ann_ctx->mtx);
355   AddExpectRace(&dyn_ann_ctx->benign,
356                 f, l, mem, size, desc);
357   DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
358 }
359 
360 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
361 void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
362     char *f, int l, uptr mem, uptr size, char *desc) {
363   SCOPED_ANNOTATION(AnnotateBenignRaceSized);
364   BenignRaceImpl(f, l, mem, size, desc);
365 }
366 
367 void INTERFACE_ATTRIBUTE AnnotateBenignRace(
368     char *f, int l, uptr mem, char *desc) {
369   SCOPED_ANNOTATION(AnnotateBenignRace);
370   BenignRaceImpl(f, l, mem, 1, desc);
371 }
372 
373 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
374   SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
375   ThreadIgnoreBegin(thr, pc);
376 }
377 
378 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
379   SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
380   ThreadIgnoreEnd(thr);
381 }
382 
383 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
384   SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
385   ThreadIgnoreBegin(thr, pc);
386 }
387 
388 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
389   SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
390   ThreadIgnoreEnd(thr);
391 }
392 
393 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
394   SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
395   ThreadIgnoreSyncBegin(thr, pc);
396 }
397 
398 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
399   SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
400   ThreadIgnoreSyncEnd(thr);
401 }
402 
403 void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
404     char *f, int l, uptr addr, uptr size) {
405   SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
406 }
407 
408 void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
409     char *f, int l, uptr addr, uptr size) {
410   SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
411 }
412 
413 void INTERFACE_ATTRIBUTE AnnotateThreadName(
414     char *f, int l, char *name) {
415   SCOPED_ANNOTATION(AnnotateThreadName);
416   ThreadSetName(thr, name);
417 }
418 
419 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
420 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
421 // atomic operations, which should be handled by ThreadSanitizer correctly.
422 void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
423   SCOPED_ANNOTATION(AnnotateHappensBefore);
424 }
425 
426 void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
427   SCOPED_ANNOTATION(AnnotateHappensAfter);
428 }
429 
430 void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
431     char *f, int l, uptr mem, uptr sz, char *desc) {
432   SCOPED_ANNOTATION(AnnotateBenignRaceSized);
433   BenignRaceImpl(f, l, mem, sz, desc);
434 }
435 
436 int INTERFACE_ATTRIBUTE RunningOnValgrind() {
437   return flags()->running_on_valgrind;
438 }
439 
440 double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
441   return 10.0;
442 }
443 
444 const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
445   if (internal_strcmp(query, "pure_happens_before") == 0)
446     return "1";
447   else
448     return "0";
449 }
450 
451 void INTERFACE_ATTRIBUTE
452 AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
453 void INTERFACE_ATTRIBUTE
454 AnnotateMemoryIsUninitialized(char *f, int l, uptr mem, uptr sz) {}
455 
456 // Note: the parameter is called flagz, because flags is already taken
457 // by the global function that returns flags.
458 INTERFACE_ATTRIBUTE
459 void __tsan_mutex_create(void *m, unsigned flagz) {
460   SCOPED_ANNOTATION(__tsan_mutex_create);
461   MutexCreate(thr, pc, (uptr)m, flagz & MutexCreationFlagMask);
462 }
463 
464 INTERFACE_ATTRIBUTE
465 void __tsan_mutex_destroy(void *m, unsigned flagz) {
466   SCOPED_ANNOTATION(__tsan_mutex_destroy);
467   MutexDestroy(thr, pc, (uptr)m, flagz);
468 }
469 
470 INTERFACE_ATTRIBUTE
471 void __tsan_mutex_pre_lock(void *m, unsigned flagz) {
472   SCOPED_ANNOTATION(__tsan_mutex_pre_lock);
473   if (!(flagz & MutexFlagTryLock)) {
474     if (flagz & MutexFlagReadLock)
475       MutexPreReadLock(thr, pc, (uptr)m);
476     else
477       MutexPreLock(thr, pc, (uptr)m);
478   }
479   ThreadIgnoreBegin(thr, 0);
480   ThreadIgnoreSyncBegin(thr, 0);
481 }
482 
483 INTERFACE_ATTRIBUTE
484 void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) {
485   SCOPED_ANNOTATION(__tsan_mutex_post_lock);
486   ThreadIgnoreSyncEnd(thr);
487   ThreadIgnoreEnd(thr);
488   if (!(flagz & MutexFlagTryLockFailed)) {
489     if (flagz & MutexFlagReadLock)
490       MutexPostReadLock(thr, pc, (uptr)m, flagz);
491     else
492       MutexPostLock(thr, pc, (uptr)m, flagz, rec);
493   }
494 }
495 
496 INTERFACE_ATTRIBUTE
497 int __tsan_mutex_pre_unlock(void *m, unsigned flagz) {
498   SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock, 0);
499   int ret = 0;
500   if (flagz & MutexFlagReadLock) {
501     CHECK(!(flagz & MutexFlagRecursiveUnlock));
502     MutexReadUnlock(thr, pc, (uptr)m);
503   } else {
504     ret = MutexUnlock(thr, pc, (uptr)m, flagz);
505   }
506   ThreadIgnoreBegin(thr, 0);
507   ThreadIgnoreSyncBegin(thr, 0);
508   return ret;
509 }
510 
511 INTERFACE_ATTRIBUTE
512 void __tsan_mutex_post_unlock(void *m, unsigned flagz) {
513   SCOPED_ANNOTATION(__tsan_mutex_post_unlock);
514   ThreadIgnoreSyncEnd(thr);
515   ThreadIgnoreEnd(thr);
516 }
517 
518 INTERFACE_ATTRIBUTE
519 void __tsan_mutex_pre_signal(void *addr, unsigned flagz) {
520   SCOPED_ANNOTATION(__tsan_mutex_pre_signal);
521   ThreadIgnoreBegin(thr, 0);
522   ThreadIgnoreSyncBegin(thr, 0);
523 }
524 
525 INTERFACE_ATTRIBUTE
526 void __tsan_mutex_post_signal(void *addr, unsigned flagz) {
527   SCOPED_ANNOTATION(__tsan_mutex_post_signal);
528   ThreadIgnoreSyncEnd(thr);
529   ThreadIgnoreEnd(thr);
530 }
531 
532 INTERFACE_ATTRIBUTE
533 void __tsan_mutex_pre_divert(void *addr, unsigned flagz) {
534   SCOPED_ANNOTATION(__tsan_mutex_pre_divert);
535   // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
536   ThreadIgnoreSyncEnd(thr);
537   ThreadIgnoreEnd(thr);
538 }
539 
540 INTERFACE_ATTRIBUTE
541 void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
542   SCOPED_ANNOTATION(__tsan_mutex_post_divert);
543   ThreadIgnoreBegin(thr, 0);
544   ThreadIgnoreSyncBegin(thr, 0);
545 }
546 }  // extern "C"
547