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_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 
25 #define CALLERPC ((uptr)__builtin_return_address(0))
26 
27 using namespace __tsan;
28 
29 namespace __tsan {
30 
31 class ScopedAnnotation {
32  public:
33   ScopedAnnotation(ThreadState *thr, const char *aname, uptr pc)
34       : thr_(thr) {
35     FuncEntry(thr_, pc);
36     DPrintf("#%d: annotation %s()\n", thr_->tid, aname);
37   }
38 
39   ~ScopedAnnotation() {
40     FuncExit(thr_);
41     CheckNoLocks(thr_);
42   }
43  private:
44   ThreadState *const thr_;
45 };
46 
47 #define SCOPED_ANNOTATION_RET(typ, ret) \
48     if (!flags()->enable_annotations) \
49       return ret; \
50     ThreadState *thr = cur_thread(); \
51     const uptr caller_pc = (uptr)__builtin_return_address(0); \
52     ScopedAnnotation sa(thr, __func__, caller_pc); \
53     const uptr pc = StackTrace::GetCurrentPc(); \
54     (void)pc; \
55 /**/
56 
57 #define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )
58 
59 static const int kMaxDescLen = 128;
60 
61 struct ExpectRace {
62   ExpectRace *next;
63   ExpectRace *prev;
64   atomic_uintptr_t hitcount;
65   atomic_uintptr_t 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() : mtx(MutexTypeAnnotations) {}
79 };
80 
81 static DynamicAnnContext *dyn_ann_ctx;
82 static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
83 
84 static void AddExpectRace(ExpectRace *list,
85     char *f, int l, uptr addr, uptr size, char *desc) {
86   ExpectRace *race = list->next;
87   for (; race != list; race = race->next) {
88     if (race->addr == addr && race->size == size) {
89       atomic_store_relaxed(&race->addcount,
90           atomic_load_relaxed(&race->addcount) + 1);
91       return;
92     }
93   }
94   race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
95   race->addr = addr;
96   race->size = size;
97   race->file = f;
98   race->line = l;
99   race->desc[0] = 0;
100   atomic_store_relaxed(&race->hitcount, 0);
101   atomic_store_relaxed(&race->addcount, 1);
102   if (desc) {
103     int i = 0;
104     for (; i < kMaxDescLen - 1 && desc[i]; i++)
105       race->desc[i] = desc[i];
106     race->desc[i] = 0;
107   }
108   race->prev = list;
109   race->next = list->next;
110   race->next->prev = race;
111   list->next = race;
112 }
113 
114 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
115   for (ExpectRace *race = list->next; race != list; race = race->next) {
116     uptr maxbegin = max(race->addr, addr);
117     uptr minend = min(race->addr + race->size, addr + size);
118     if (maxbegin < minend)
119       return race;
120   }
121   return 0;
122 }
123 
124 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
125   ExpectRace *race = FindRace(list, addr, size);
126   if (race == 0)
127     return false;
128   DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
129       race->desc, race->addr, (int)race->size, race->file, race->line);
130   atomic_fetch_add(&race->hitcount, 1, memory_order_relaxed);
131   return true;
132 }
133 
134 static void InitList(ExpectRace *list) {
135   list->next = list;
136   list->prev = list;
137 }
138 
139 void InitializeDynamicAnnotations() {
140   dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
141   InitList(&dyn_ann_ctx->expect);
142   InitList(&dyn_ann_ctx->benign);
143 }
144 
145 bool IsExpectedReport(uptr addr, uptr size) {
146   ReadLock lock(&dyn_ann_ctx->mtx);
147   if (CheckContains(&dyn_ann_ctx->expect, addr, size))
148     return true;
149   if (CheckContains(&dyn_ann_ctx->benign, addr, size))
150     return true;
151   return false;
152 }
153 
154 static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
155     int *unique_count, int *hit_count, atomic_uintptr_t ExpectRace::*counter) {
156   ExpectRace *list = &dyn_ann_ctx->benign;
157   for (ExpectRace *race = list->next; race != list; race = race->next) {
158     (*unique_count)++;
159     const uptr cnt = atomic_load_relaxed(&(race->*counter));
160     if (cnt == 0)
161       continue;
162     *hit_count += cnt;
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         atomic_fetch_add(&(race0->*counter), cnt, memory_order_relaxed);
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;
184   CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
185       &ExpectRace::hitcount);
186   Vector<ExpectRace> add_matched;
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           atomic_load_relaxed(&hit_matched[i].hitcount),
195           hit_matched[i].file, 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           atomic_load_relaxed(&add_matched[i].addcount),
205           add_matched[i].file, 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;
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, MutexFlagWriteReentrant);
252 }
253 
254 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
255   SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
256   MutexCreate(thr, pc, m, MutexFlagWriteReentrant | MutexFlagLinkerInit);
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     MutexPostLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
269   else
270     MutexPostReadLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
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 (atomic_load_relaxed(&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 
458 // Note: the parameter is called flagz, because flags is already taken
459 // by the global function that returns flags.
460 INTERFACE_ATTRIBUTE
461 void __tsan_mutex_create(void *m, unsigned flagz) {
462   SCOPED_ANNOTATION(__tsan_mutex_create);
463   MutexCreate(thr, pc, (uptr)m, flagz & MutexCreationFlagMask);
464 }
465 
466 INTERFACE_ATTRIBUTE
467 void __tsan_mutex_destroy(void *m, unsigned flagz) {
468   SCOPED_ANNOTATION(__tsan_mutex_destroy);
469   MutexDestroy(thr, pc, (uptr)m, flagz);
470 }
471 
472 INTERFACE_ATTRIBUTE
473 void __tsan_mutex_pre_lock(void *m, unsigned flagz) {
474   SCOPED_ANNOTATION(__tsan_mutex_pre_lock);
475   if (!(flagz & MutexFlagTryLock)) {
476     if (flagz & MutexFlagReadLock)
477       MutexPreReadLock(thr, pc, (uptr)m);
478     else
479       MutexPreLock(thr, pc, (uptr)m);
480   }
481   ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
482   ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
483 }
484 
485 INTERFACE_ATTRIBUTE
486 void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) {
487   SCOPED_ANNOTATION(__tsan_mutex_post_lock);
488   ThreadIgnoreSyncEnd(thr, pc);
489   ThreadIgnoreEnd(thr, pc);
490   if (!(flagz & MutexFlagTryLockFailed)) {
491     if (flagz & MutexFlagReadLock)
492       MutexPostReadLock(thr, pc, (uptr)m, flagz);
493     else
494       MutexPostLock(thr, pc, (uptr)m, flagz, rec);
495   }
496 }
497 
498 INTERFACE_ATTRIBUTE
499 int __tsan_mutex_pre_unlock(void *m, unsigned flagz) {
500   SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock, 0);
501   int ret = 0;
502   if (flagz & MutexFlagReadLock) {
503     CHECK(!(flagz & MutexFlagRecursiveUnlock));
504     MutexReadUnlock(thr, pc, (uptr)m);
505   } else {
506     ret = MutexUnlock(thr, pc, (uptr)m, flagz);
507   }
508   ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
509   ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
510   return ret;
511 }
512 
513 INTERFACE_ATTRIBUTE
514 void __tsan_mutex_post_unlock(void *m, unsigned flagz) {
515   SCOPED_ANNOTATION(__tsan_mutex_post_unlock);
516   ThreadIgnoreSyncEnd(thr, pc);
517   ThreadIgnoreEnd(thr, pc);
518 }
519 
520 INTERFACE_ATTRIBUTE
521 void __tsan_mutex_pre_signal(void *addr, unsigned flagz) {
522   SCOPED_ANNOTATION(__tsan_mutex_pre_signal);
523   ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
524   ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
525 }
526 
527 INTERFACE_ATTRIBUTE
528 void __tsan_mutex_post_signal(void *addr, unsigned flagz) {
529   SCOPED_ANNOTATION(__tsan_mutex_post_signal);
530   ThreadIgnoreSyncEnd(thr, pc);
531   ThreadIgnoreEnd(thr, pc);
532 }
533 
534 INTERFACE_ATTRIBUTE
535 void __tsan_mutex_pre_divert(void *addr, unsigned flagz) {
536   SCOPED_ANNOTATION(__tsan_mutex_pre_divert);
537   // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
538   ThreadIgnoreSyncEnd(thr, pc);
539   ThreadIgnoreEnd(thr, pc);
540 }
541 
542 INTERFACE_ATTRIBUTE
543 void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
544   SCOPED_ANNOTATION(__tsan_mutex_post_divert);
545   ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
546   ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
547 }
548 }  // extern "C"
549