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:
ScopedAnnotation(ThreadState * thr,const char * aname,uptr pc)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
~ScopedAnnotation()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 benign;
74
DynamicAnnContext__tsan::DynamicAnnContext75 DynamicAnnContext() : mtx(MutexTypeAnnotations) {}
76 };
77
78 static DynamicAnnContext *dyn_ann_ctx;
79 alignas(64) static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)];
80
AddExpectRace(ExpectRace * list,char * f,int l,uptr addr,uptr size,char * desc)81 static void AddExpectRace(ExpectRace *list,
82 char *f, int l, uptr addr, uptr size, char *desc) {
83 ExpectRace *race = list->next;
84 for (; race != list; race = race->next) {
85 if (race->addr == addr && race->size == size) {
86 atomic_store_relaxed(&race->addcount,
87 atomic_load_relaxed(&race->addcount) + 1);
88 return;
89 }
90 }
91 race = static_cast<ExpectRace *>(Alloc(sizeof(ExpectRace)));
92 race->addr = addr;
93 race->size = size;
94 race->file = f;
95 race->line = l;
96 race->desc[0] = 0;
97 atomic_store_relaxed(&race->hitcount, 0);
98 atomic_store_relaxed(&race->addcount, 1);
99 if (desc) {
100 int i = 0;
101 for (; i < kMaxDescLen - 1 && desc[i]; i++)
102 race->desc[i] = desc[i];
103 race->desc[i] = 0;
104 }
105 race->prev = list;
106 race->next = list->next;
107 race->next->prev = race;
108 list->next = race;
109 }
110
FindRace(ExpectRace * list,uptr addr,uptr size)111 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
112 for (ExpectRace *race = list->next; race != list; race = race->next) {
113 uptr maxbegin = max(race->addr, addr);
114 uptr minend = min(race->addr + race->size, addr + size);
115 if (maxbegin < minend)
116 return race;
117 }
118 return 0;
119 }
120
CheckContains(ExpectRace * list,uptr addr,uptr size)121 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
122 ExpectRace *race = FindRace(list, addr, size);
123 if (race == 0)
124 return false;
125 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
126 race->desc, race->addr, (int)race->size, race->file, race->line);
127 atomic_fetch_add(&race->hitcount, 1, memory_order_relaxed);
128 return true;
129 }
130
InitList(ExpectRace * list)131 static void InitList(ExpectRace *list) {
132 list->next = list;
133 list->prev = list;
134 }
135
InitializeDynamicAnnotations()136 void InitializeDynamicAnnotations() {
137 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
138 InitList(&dyn_ann_ctx->benign);
139 }
140
IsExpectedReport(uptr addr,uptr size)141 bool IsExpectedReport(uptr addr, uptr size) {
142 ReadLock lock(&dyn_ann_ctx->mtx);
143 return CheckContains(&dyn_ann_ctx->benign, addr, size);
144 }
145 } // namespace __tsan
146
147 using namespace __tsan;
148
149 extern "C" {
AnnotateHappensBefore(char * f,int l,uptr addr)150 void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
151 SCOPED_ANNOTATION(AnnotateHappensBefore);
152 Release(thr, pc, addr);
153 }
154
AnnotateHappensAfter(char * f,int l,uptr addr)155 void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
156 SCOPED_ANNOTATION(AnnotateHappensAfter);
157 Acquire(thr, pc, addr);
158 }
159
AnnotateCondVarSignal(char * f,int l,uptr cv)160 void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
161 }
162
AnnotateCondVarSignalAll(char * f,int l,uptr cv)163 void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
164 }
165
AnnotateMutexIsNotPHB(char * f,int l,uptr mu)166 void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
167 }
168
AnnotateCondVarWait(char * f,int l,uptr cv,uptr lock)169 void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
170 uptr lock) {
171 }
172
AnnotateRWLockCreate(char * f,int l,uptr m)173 void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
174 SCOPED_ANNOTATION(AnnotateRWLockCreate);
175 MutexCreate(thr, pc, m, MutexFlagWriteReentrant);
176 }
177
AnnotateRWLockCreateStatic(char * f,int l,uptr m)178 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
179 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
180 MutexCreate(thr, pc, m, MutexFlagWriteReentrant | MutexFlagLinkerInit);
181 }
182
AnnotateRWLockDestroy(char * f,int l,uptr m)183 void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
184 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
185 MutexDestroy(thr, pc, m);
186 }
187
AnnotateRWLockAcquired(char * f,int l,uptr m,uptr is_w)188 void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
189 uptr is_w) {
190 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
191 if (is_w)
192 MutexPostLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
193 else
194 MutexPostReadLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
195 }
196
AnnotateRWLockReleased(char * f,int l,uptr m,uptr is_w)197 void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
198 uptr is_w) {
199 SCOPED_ANNOTATION(AnnotateRWLockReleased);
200 if (is_w)
201 MutexUnlock(thr, pc, m);
202 else
203 MutexReadUnlock(thr, pc, m);
204 }
205
AnnotateTraceMemory(char * f,int l,uptr mem)206 void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
207 }
208
AnnotateFlushState(char * f,int l)209 void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
210 }
211
AnnotateNewMemory(char * f,int l,uptr mem,uptr size)212 void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
213 uptr size) {
214 }
215
AnnotateNoOp(char * f,int l,uptr mem)216 void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
217 }
218
AnnotateFlushExpectedRaces(char * f,int l)219 void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
220 }
221
AnnotateEnableRaceDetection(char * f,int l,int enable)222 void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
223 char *f, int l, int enable) {
224 }
225
AnnotateMutexIsUsedAsCondVar(char * f,int l,uptr mu)226 void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
227 char *f, int l, uptr mu) {
228 }
229
AnnotatePCQGet(char * f,int l,uptr pcq)230 void INTERFACE_ATTRIBUTE AnnotatePCQGet(
231 char *f, int l, uptr pcq) {
232 }
233
AnnotatePCQPut(char * f,int l,uptr pcq)234 void INTERFACE_ATTRIBUTE AnnotatePCQPut(
235 char *f, int l, uptr pcq) {
236 }
237
AnnotatePCQDestroy(char * f,int l,uptr pcq)238 void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
239 char *f, int l, uptr pcq) {
240 }
241
AnnotatePCQCreate(char * f,int l,uptr pcq)242 void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
243 char *f, int l, uptr pcq) {
244 }
245
AnnotateExpectRace(char * f,int l,uptr mem,char * desc)246 void INTERFACE_ATTRIBUTE AnnotateExpectRace(
247 char *f, int l, uptr mem, char *desc) {
248 }
249
BenignRaceImpl(char * f,int l,uptr mem,uptr size,char * desc)250 static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
251 Lock lock(&dyn_ann_ctx->mtx);
252 AddExpectRace(&dyn_ann_ctx->benign,
253 f, l, mem, size, desc);
254 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
255 }
256
AnnotateBenignRaceSized(char * f,int l,uptr mem,uptr size,char * desc)257 void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
258 char *f, int l, uptr mem, uptr size, char *desc) {
259 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
260 BenignRaceImpl(f, l, mem, size, desc);
261 }
262
AnnotateBenignRace(char * f,int l,uptr mem,char * desc)263 void INTERFACE_ATTRIBUTE AnnotateBenignRace(
264 char *f, int l, uptr mem, char *desc) {
265 SCOPED_ANNOTATION(AnnotateBenignRace);
266 BenignRaceImpl(f, l, mem, 1, desc);
267 }
268
AnnotateIgnoreReadsBegin(char * f,int l)269 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
270 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
271 ThreadIgnoreBegin(thr, pc);
272 }
273
AnnotateIgnoreReadsEnd(char * f,int l)274 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
275 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
276 ThreadIgnoreEnd(thr);
277 }
278
AnnotateIgnoreWritesBegin(char * f,int l)279 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
280 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
281 ThreadIgnoreBegin(thr, pc);
282 }
283
AnnotateIgnoreWritesEnd(char * f,int l)284 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
285 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
286 ThreadIgnoreEnd(thr);
287 }
288
AnnotateIgnoreSyncBegin(char * f,int l)289 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
290 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
291 ThreadIgnoreSyncBegin(thr, pc);
292 }
293
AnnotateIgnoreSyncEnd(char * f,int l)294 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
295 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
296 ThreadIgnoreSyncEnd(thr);
297 }
298
AnnotatePublishMemoryRange(char * f,int l,uptr addr,uptr size)299 void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
300 char *f, int l, uptr addr, uptr size) {
301 }
302
AnnotateUnpublishMemoryRange(char * f,int l,uptr addr,uptr size)303 void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
304 char *f, int l, uptr addr, uptr size) {
305 }
306
AnnotateThreadName(char * f,int l,char * name)307 void INTERFACE_ATTRIBUTE AnnotateThreadName(
308 char *f, int l, char *name) {
309 SCOPED_ANNOTATION(AnnotateThreadName);
310 ThreadSetName(thr, name);
311 }
312
313 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
314 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
315 // atomic operations, which should be handled by ThreadSanitizer correctly.
WTFAnnotateHappensBefore(char * f,int l,uptr addr)316 void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
317 }
318
WTFAnnotateHappensAfter(char * f,int l,uptr addr)319 void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
320 }
321
WTFAnnotateBenignRaceSized(char * f,int l,uptr mem,uptr sz,char * desc)322 void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
323 char *f, int l, uptr mem, uptr sz, char *desc) {
324 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
325 BenignRaceImpl(f, l, mem, sz, desc);
326 }
327
RunningOnValgrind()328 int INTERFACE_ATTRIBUTE RunningOnValgrind() {
329 return flags()->running_on_valgrind;
330 }
331
ValgrindSlowdown(void)332 double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
333 return 10.0;
334 }
335
ThreadSanitizerQuery(const char * query)336 const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
337 if (internal_strcmp(query, "pure_happens_before") == 0)
338 return "1";
339 else
340 return "0";
341 }
342
343 void INTERFACE_ATTRIBUTE
AnnotateMemoryIsInitialized(char * f,int l,uptr mem,uptr sz)344 AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
345 void INTERFACE_ATTRIBUTE
AnnotateMemoryIsUninitialized(char * f,int l,uptr mem,uptr sz)346 AnnotateMemoryIsUninitialized(char *f, int l, uptr mem, uptr sz) {}
347
348 // Note: the parameter is called flagz, because flags is already taken
349 // by the global function that returns flags.
350 INTERFACE_ATTRIBUTE
__tsan_mutex_create(void * m,unsigned flagz)351 void __tsan_mutex_create(void *m, unsigned flagz) {
352 SCOPED_ANNOTATION(__tsan_mutex_create);
353 MutexCreate(thr, pc, (uptr)m, flagz & MutexCreationFlagMask);
354 }
355
356 INTERFACE_ATTRIBUTE
__tsan_mutex_destroy(void * m,unsigned flagz)357 void __tsan_mutex_destroy(void *m, unsigned flagz) {
358 SCOPED_ANNOTATION(__tsan_mutex_destroy);
359 MutexDestroy(thr, pc, (uptr)m, flagz);
360 }
361
362 INTERFACE_ATTRIBUTE
__tsan_mutex_pre_lock(void * m,unsigned flagz)363 void __tsan_mutex_pre_lock(void *m, unsigned flagz) {
364 SCOPED_ANNOTATION(__tsan_mutex_pre_lock);
365 if (!(flagz & MutexFlagTryLock)) {
366 if (flagz & MutexFlagReadLock)
367 MutexPreReadLock(thr, pc, (uptr)m);
368 else
369 MutexPreLock(thr, pc, (uptr)m);
370 }
371 ThreadIgnoreBegin(thr, 0);
372 ThreadIgnoreSyncBegin(thr, 0);
373 }
374
375 INTERFACE_ATTRIBUTE
__tsan_mutex_post_lock(void * m,unsigned flagz,int rec)376 void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) {
377 SCOPED_ANNOTATION(__tsan_mutex_post_lock);
378 ThreadIgnoreSyncEnd(thr);
379 ThreadIgnoreEnd(thr);
380 if (!(flagz & MutexFlagTryLockFailed)) {
381 if (flagz & MutexFlagReadLock)
382 MutexPostReadLock(thr, pc, (uptr)m, flagz);
383 else
384 MutexPostLock(thr, pc, (uptr)m, flagz, rec);
385 }
386 }
387
388 INTERFACE_ATTRIBUTE
__tsan_mutex_pre_unlock(void * m,unsigned flagz)389 int __tsan_mutex_pre_unlock(void *m, unsigned flagz) {
390 SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock, 0);
391 int ret = 0;
392 if (flagz & MutexFlagReadLock) {
393 CHECK(!(flagz & MutexFlagRecursiveUnlock));
394 MutexReadUnlock(thr, pc, (uptr)m);
395 } else {
396 ret = MutexUnlock(thr, pc, (uptr)m, flagz);
397 }
398 ThreadIgnoreBegin(thr, 0);
399 ThreadIgnoreSyncBegin(thr, 0);
400 return ret;
401 }
402
403 INTERFACE_ATTRIBUTE
__tsan_mutex_post_unlock(void * m,unsigned flagz)404 void __tsan_mutex_post_unlock(void *m, unsigned flagz) {
405 SCOPED_ANNOTATION(__tsan_mutex_post_unlock);
406 ThreadIgnoreSyncEnd(thr);
407 ThreadIgnoreEnd(thr);
408 }
409
410 INTERFACE_ATTRIBUTE
__tsan_mutex_pre_signal(void * addr,unsigned flagz)411 void __tsan_mutex_pre_signal(void *addr, unsigned flagz) {
412 SCOPED_ANNOTATION(__tsan_mutex_pre_signal);
413 ThreadIgnoreBegin(thr, 0);
414 ThreadIgnoreSyncBegin(thr, 0);
415 }
416
417 INTERFACE_ATTRIBUTE
__tsan_mutex_post_signal(void * addr,unsigned flagz)418 void __tsan_mutex_post_signal(void *addr, unsigned flagz) {
419 SCOPED_ANNOTATION(__tsan_mutex_post_signal);
420 ThreadIgnoreSyncEnd(thr);
421 ThreadIgnoreEnd(thr);
422 }
423
424 INTERFACE_ATTRIBUTE
__tsan_mutex_pre_divert(void * addr,unsigned flagz)425 void __tsan_mutex_pre_divert(void *addr, unsigned flagz) {
426 SCOPED_ANNOTATION(__tsan_mutex_pre_divert);
427 // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
428 ThreadIgnoreSyncEnd(thr);
429 ThreadIgnoreEnd(thr);
430 }
431
432 INTERFACE_ATTRIBUTE
__tsan_mutex_post_divert(void * addr,unsigned flagz)433 void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
434 SCOPED_ANNOTATION(__tsan_mutex_post_divert);
435 ThreadIgnoreBegin(thr, 0);
436 ThreadIgnoreSyncBegin(thr, 0);
437 }
438
ReportMutexHeldWrongContext(ThreadState * thr,uptr pc)439 static void ReportMutexHeldWrongContext(ThreadState *thr, uptr pc) {
440 ThreadRegistryLock l(&ctx->thread_registry);
441 ScopedReport rep(ReportTypeMutexHeldWrongContext);
442 for (uptr i = 0; i < thr->mset.Size(); ++i) {
443 MutexSet::Desc desc = thr->mset.Get(i);
444 rep.AddMutex(desc.addr, desc.stack_id);
445 }
446 VarSizeStackTrace trace;
447 ObtainCurrentStack(thr, pc, &trace);
448 rep.AddStack(trace, true);
449 OutputReport(thr, rep);
450 }
451
452 INTERFACE_ATTRIBUTE
__tsan_check_no_mutexes_held()453 void __tsan_check_no_mutexes_held() {
454 SCOPED_ANNOTATION(__tsan_check_no_mutexes_held);
455 if (thr->mset.Size() == 0) {
456 return;
457 }
458 ReportMutexHeldWrongContext(thr, pc);
459 }
460 } // extern "C"
461