Path: blob/main/contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
35294 views
//===-- tsan_interface_ann.cpp --------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//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 "sanitizer_common/sanitizer_vector.h"16#include "tsan_interface_ann.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"2223#define CALLERPC ((uptr)__builtin_return_address(0))2425using namespace __tsan;2627namespace __tsan {2829class ScopedAnnotation {30public:31ScopedAnnotation(ThreadState *thr, const char *aname, uptr pc)32: thr_(thr) {33FuncEntry(thr_, pc);34DPrintf("#%d: annotation %s()\n", thr_->tid, aname);35}3637~ScopedAnnotation() {38FuncExit(thr_);39CheckedMutex::CheckNoLocks();40}41private:42ThreadState *const thr_;43};4445#define SCOPED_ANNOTATION_RET(typ, ret) \46if (!flags()->enable_annotations) \47return ret; \48ThreadState *thr = cur_thread(); \49const uptr caller_pc = (uptr)__builtin_return_address(0); \50ScopedAnnotation sa(thr, __func__, caller_pc); \51const uptr pc = StackTrace::GetCurrentPc(); \52(void)pc;5354#define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )5556static const int kMaxDescLen = 128;5758struct ExpectRace {59ExpectRace *next;60ExpectRace *prev;61atomic_uintptr_t hitcount;62atomic_uintptr_t addcount;63uptr addr;64uptr size;65char *file;66int line;67char desc[kMaxDescLen];68};6970struct DynamicAnnContext {71Mutex mtx;72ExpectRace benign;7374DynamicAnnContext() : mtx(MutexTypeAnnotations) {}75};7677static DynamicAnnContext *dyn_ann_ctx;78alignas(64) static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)];7980static void AddExpectRace(ExpectRace *list,81char *f, int l, uptr addr, uptr size, char *desc) {82ExpectRace *race = list->next;83for (; race != list; race = race->next) {84if (race->addr == addr && race->size == size) {85atomic_store_relaxed(&race->addcount,86atomic_load_relaxed(&race->addcount) + 1);87return;88}89}90race = static_cast<ExpectRace *>(Alloc(sizeof(ExpectRace)));91race->addr = addr;92race->size = size;93race->file = f;94race->line = l;95race->desc[0] = 0;96atomic_store_relaxed(&race->hitcount, 0);97atomic_store_relaxed(&race->addcount, 1);98if (desc) {99int i = 0;100for (; i < kMaxDescLen - 1 && desc[i]; i++)101race->desc[i] = desc[i];102race->desc[i] = 0;103}104race->prev = list;105race->next = list->next;106race->next->prev = race;107list->next = race;108}109110static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {111for (ExpectRace *race = list->next; race != list; race = race->next) {112uptr maxbegin = max(race->addr, addr);113uptr minend = min(race->addr + race->size, addr + size);114if (maxbegin < minend)115return race;116}117return 0;118}119120static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {121ExpectRace *race = FindRace(list, addr, size);122if (race == 0)123return false;124DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",125race->desc, race->addr, (int)race->size, race->file, race->line);126atomic_fetch_add(&race->hitcount, 1, memory_order_relaxed);127return true;128}129130static void InitList(ExpectRace *list) {131list->next = list;132list->prev = list;133}134135void InitializeDynamicAnnotations() {136dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;137InitList(&dyn_ann_ctx->benign);138}139140bool IsExpectedReport(uptr addr, uptr size) {141ReadLock lock(&dyn_ann_ctx->mtx);142return CheckContains(&dyn_ann_ctx->benign, addr, size);143}144} // namespace __tsan145146using namespace __tsan;147148extern "C" {149void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {150SCOPED_ANNOTATION(AnnotateHappensBefore);151Release(thr, pc, addr);152}153154void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {155SCOPED_ANNOTATION(AnnotateHappensAfter);156Acquire(thr, pc, addr);157}158159void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {160}161162void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {163}164165void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {166}167168void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,169uptr lock) {170}171172void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {173SCOPED_ANNOTATION(AnnotateRWLockCreate);174MutexCreate(thr, pc, m, MutexFlagWriteReentrant);175}176177void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {178SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);179MutexCreate(thr, pc, m, MutexFlagWriteReentrant | MutexFlagLinkerInit);180}181182void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {183SCOPED_ANNOTATION(AnnotateRWLockDestroy);184MutexDestroy(thr, pc, m);185}186187void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,188uptr is_w) {189SCOPED_ANNOTATION(AnnotateRWLockAcquired);190if (is_w)191MutexPostLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);192else193MutexPostReadLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);194}195196void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,197uptr is_w) {198SCOPED_ANNOTATION(AnnotateRWLockReleased);199if (is_w)200MutexUnlock(thr, pc, m);201else202MutexReadUnlock(thr, pc, m);203}204205void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {206}207208void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {209}210211void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,212uptr size) {213}214215void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {216}217218void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {219}220221void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(222char *f, int l, int enable) {223}224225void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(226char *f, int l, uptr mu) {227}228229void INTERFACE_ATTRIBUTE AnnotatePCQGet(230char *f, int l, uptr pcq) {231}232233void INTERFACE_ATTRIBUTE AnnotatePCQPut(234char *f, int l, uptr pcq) {235}236237void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(238char *f, int l, uptr pcq) {239}240241void INTERFACE_ATTRIBUTE AnnotatePCQCreate(242char *f, int l, uptr pcq) {243}244245void INTERFACE_ATTRIBUTE AnnotateExpectRace(246char *f, int l, uptr mem, char *desc) {247}248249static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {250Lock lock(&dyn_ann_ctx->mtx);251AddExpectRace(&dyn_ann_ctx->benign,252f, l, mem, size, desc);253DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);254}255256void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(257char *f, int l, uptr mem, uptr size, char *desc) {258SCOPED_ANNOTATION(AnnotateBenignRaceSized);259BenignRaceImpl(f, l, mem, size, desc);260}261262void INTERFACE_ATTRIBUTE AnnotateBenignRace(263char *f, int l, uptr mem, char *desc) {264SCOPED_ANNOTATION(AnnotateBenignRace);265BenignRaceImpl(f, l, mem, 1, desc);266}267268void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {269SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);270ThreadIgnoreBegin(thr, pc);271}272273void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {274SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);275ThreadIgnoreEnd(thr);276}277278void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {279SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);280ThreadIgnoreBegin(thr, pc);281}282283void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {284SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);285ThreadIgnoreEnd(thr);286}287288void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {289SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);290ThreadIgnoreSyncBegin(thr, pc);291}292293void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {294SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);295ThreadIgnoreSyncEnd(thr);296}297298void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(299char *f, int l, uptr addr, uptr size) {300}301302void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(303char *f, int l, uptr addr, uptr size) {304}305306void INTERFACE_ATTRIBUTE AnnotateThreadName(307char *f, int l, char *name) {308SCOPED_ANNOTATION(AnnotateThreadName);309ThreadSetName(thr, name);310}311312// We deliberately omit the implementation of WTFAnnotateHappensBefore() and313// WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate314// atomic operations, which should be handled by ThreadSanitizer correctly.315void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {316}317318void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {319}320321void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(322char *f, int l, uptr mem, uptr sz, char *desc) {323SCOPED_ANNOTATION(AnnotateBenignRaceSized);324BenignRaceImpl(f, l, mem, sz, desc);325}326327int INTERFACE_ATTRIBUTE RunningOnValgrind() {328return flags()->running_on_valgrind;329}330331double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {332return 10.0;333}334335const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {336if (internal_strcmp(query, "pure_happens_before") == 0)337return "1";338else339return "0";340}341342void INTERFACE_ATTRIBUTE343AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}344void INTERFACE_ATTRIBUTE345AnnotateMemoryIsUninitialized(char *f, int l, uptr mem, uptr sz) {}346347// Note: the parameter is called flagz, because flags is already taken348// by the global function that returns flags.349INTERFACE_ATTRIBUTE350void __tsan_mutex_create(void *m, unsigned flagz) {351SCOPED_ANNOTATION(__tsan_mutex_create);352MutexCreate(thr, pc, (uptr)m, flagz & MutexCreationFlagMask);353}354355INTERFACE_ATTRIBUTE356void __tsan_mutex_destroy(void *m, unsigned flagz) {357SCOPED_ANNOTATION(__tsan_mutex_destroy);358MutexDestroy(thr, pc, (uptr)m, flagz);359}360361INTERFACE_ATTRIBUTE362void __tsan_mutex_pre_lock(void *m, unsigned flagz) {363SCOPED_ANNOTATION(__tsan_mutex_pre_lock);364if (!(flagz & MutexFlagTryLock)) {365if (flagz & MutexFlagReadLock)366MutexPreReadLock(thr, pc, (uptr)m);367else368MutexPreLock(thr, pc, (uptr)m);369}370ThreadIgnoreBegin(thr, 0);371ThreadIgnoreSyncBegin(thr, 0);372}373374INTERFACE_ATTRIBUTE375void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) {376SCOPED_ANNOTATION(__tsan_mutex_post_lock);377ThreadIgnoreSyncEnd(thr);378ThreadIgnoreEnd(thr);379if (!(flagz & MutexFlagTryLockFailed)) {380if (flagz & MutexFlagReadLock)381MutexPostReadLock(thr, pc, (uptr)m, flagz);382else383MutexPostLock(thr, pc, (uptr)m, flagz, rec);384}385}386387INTERFACE_ATTRIBUTE388int __tsan_mutex_pre_unlock(void *m, unsigned flagz) {389SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock, 0);390int ret = 0;391if (flagz & MutexFlagReadLock) {392CHECK(!(flagz & MutexFlagRecursiveUnlock));393MutexReadUnlock(thr, pc, (uptr)m);394} else {395ret = MutexUnlock(thr, pc, (uptr)m, flagz);396}397ThreadIgnoreBegin(thr, 0);398ThreadIgnoreSyncBegin(thr, 0);399return ret;400}401402INTERFACE_ATTRIBUTE403void __tsan_mutex_post_unlock(void *m, unsigned flagz) {404SCOPED_ANNOTATION(__tsan_mutex_post_unlock);405ThreadIgnoreSyncEnd(thr);406ThreadIgnoreEnd(thr);407}408409INTERFACE_ATTRIBUTE410void __tsan_mutex_pre_signal(void *addr, unsigned flagz) {411SCOPED_ANNOTATION(__tsan_mutex_pre_signal);412ThreadIgnoreBegin(thr, 0);413ThreadIgnoreSyncBegin(thr, 0);414}415416INTERFACE_ATTRIBUTE417void __tsan_mutex_post_signal(void *addr, unsigned flagz) {418SCOPED_ANNOTATION(__tsan_mutex_post_signal);419ThreadIgnoreSyncEnd(thr);420ThreadIgnoreEnd(thr);421}422423INTERFACE_ATTRIBUTE424void __tsan_mutex_pre_divert(void *addr, unsigned flagz) {425SCOPED_ANNOTATION(__tsan_mutex_pre_divert);426// Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.427ThreadIgnoreSyncEnd(thr);428ThreadIgnoreEnd(thr);429}430431INTERFACE_ATTRIBUTE432void __tsan_mutex_post_divert(void *addr, unsigned flagz) {433SCOPED_ANNOTATION(__tsan_mutex_post_divert);434ThreadIgnoreBegin(thr, 0);435ThreadIgnoreSyncBegin(thr, 0);436}437438static void ReportMutexHeldWrongContext(ThreadState *thr, uptr pc) {439ThreadRegistryLock l(&ctx->thread_registry);440ScopedReport rep(ReportTypeMutexHeldWrongContext);441for (uptr i = 0; i < thr->mset.Size(); ++i) {442MutexSet::Desc desc = thr->mset.Get(i);443rep.AddMutex(desc.addr, desc.stack_id);444}445VarSizeStackTrace trace;446ObtainCurrentStack(thr, pc, &trace);447rep.AddStack(trace, true);448OutputReport(thr, rep);449}450451INTERFACE_ATTRIBUTE452void __tsan_check_no_mutexes_held() {453SCOPED_ANNOTATION(__tsan_check_no_mutexes_held);454if (thr->mset.Size() == 0) {455return;456}457ReportMutexHeldWrongContext(thr, pc);458}459} // extern "C"460461462