52 #define DEBUG_TYPE "tsan" 55 "tsan-instrument-memory-accesses",
cl::init(
true),
58 "tsan-instrument-func-entry-exit",
cl::init(
true),
61 "tsan-handle-cxx-exceptions",
cl::init(
true),
62 cl::desc(
"Handle C++ exceptions (insert cleanup blocks for unwinding)"),
65 "tsan-instrument-atomics",
cl::init(
true),
68 "tsan-instrument-memintrinsics",
cl::init(
true),
71 STATISTIC(NumInstrumentedReads,
"Number of instrumented reads");
72 STATISTIC(NumInstrumentedWrites,
"Number of instrumented writes");
74 "Number of reads ignored due to following writes");
75 STATISTIC(NumAccessesWithBadSize,
"Number of accesses with bad size");
76 STATISTIC(NumInstrumentedVtableWrites,
"Number of vtable ptr writes");
77 STATISTIC(NumInstrumentedVtableReads,
"Number of vtable ptr reads");
78 STATISTIC(NumOmittedReadsFromConstantGlobals,
79 "Number of reads from constant globals");
80 STATISTIC(NumOmittedReadsFromVtable,
"Number of vtable reads");
81 STATISTIC(NumOmittedNonCaptured,
"Number of accesses ignored due to capturing");
94 bool doInitialization(
Module &M)
override;
98 void initializeCallbacks(
Module &M);
105 bool addrPointsToConstantData(
Value *Addr);
107 void InsertRuntimeIgnores(
Function &F);
130 Function *MemmoveFn, *MemcpyFn, *MemsetFn;
137 ThreadSanitizer,
"tsan",
138 "ThreadSanitizer: detects data races.",
142 ThreadSanitizer,
"tsan",
143 "ThreadSanitizer: detects data races.",
146 StringRef ThreadSanitizer::getPassName()
const {
return "ThreadSanitizer"; }
148 void ThreadSanitizer::getAnalysisUsage(
AnalysisUsage &AU)
const {
153 return new ThreadSanitizer();
156 void ThreadSanitizer::initializeCallbacks(
Module &M) {
160 Attribute::NoUnwind);
167 "__tsan_ignore_thread_begin", Attr, IRB.
getVoidTy()));
169 "__tsan_ignore_thread_end", Attr, IRB.
getVoidTy()));
170 OrdTy = IRB.getInt32Ty();
172 const unsigned ByteSize = 1U << i;
173 const unsigned BitSize = ByteSize * 8;
174 std::string ByteSizeStr =
utostr(ByteSize);
175 std::string BitSizeStr =
utostr(BitSize);
184 SmallString<64> UnalignedReadName(
"__tsan_unaligned_read" + ByteSizeStr);
185 TsanUnalignedRead[i] =
189 SmallString<64> UnalignedWriteName(
"__tsan_unaligned_write" + ByteSizeStr);
190 TsanUnalignedWrite[i] =
196 SmallString<32> AtomicLoadName(
"__tsan_atomic" + BitSizeStr +
"_load");
200 SmallString<32> AtomicStoreName(
"__tsan_atomic" + BitSizeStr +
"_store");
202 AtomicStoreName, Attr, IRB.
getVoidTy(), PtrTy, Ty, OrdTy));
206 TsanAtomicRMW[
op][i] =
nullptr;
207 const char *NamePart =
nullptr;
209 NamePart =
"_exchange";
211 NamePart =
"_fetch_add";
213 NamePart =
"_fetch_sub";
215 NamePart =
"_fetch_and";
217 NamePart =
"_fetch_or";
219 NamePart =
"_fetch_xor";
221 NamePart =
"_fetch_nand";
230 "_compare_exchange_val");
232 AtomicCASName, Attr, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy));
240 "__tsan_atomic_thread_fence", Attr, IRB.
getVoidTy(), OrdTy));
242 "__tsan_atomic_signal_fence", Attr, IRB.
getVoidTy(), OrdTy));
255 bool ThreadSanitizer::doInitialization(
Module &M) {
269 return Tag->isTBAAVtableAccess();
280 if (GV->hasSection()) {
290 if (GV->getName().startswith(
"__llvm_gcov") ||
291 GV->getName().startswith(
"__llvm_gcda"))
306 bool ThreadSanitizer::addrPointsToConstantData(
Value *Addr) {
309 Addr =
GEP->getPointerOperand();
312 if (GV->isConstant()) {
314 NumOmittedReadsFromConstantGlobals++;
317 }
else if (
LoadInst *L = dyn_cast<LoadInst>(Addr)) {
320 NumOmittedReadsFromVtable++;
339 void ThreadSanitizer::chooseInstructionsToInstrument(
349 WriteTargets.
insert(Addr);
355 if (WriteTargets.
count(Addr)) {
357 NumOmittedReadsBeforeWrite++;
360 if (addrPointsToConstantData(Addr)) {
365 Value *Addr = isa<StoreInst>(*I)
373 NumOmittedNonCaptured++;
383 if (
LoadInst *LI = dyn_cast<LoadInst>(I))
387 if (isa<AtomicRMWInst>(I))
389 if (isa<AtomicCmpXchgInst>(I))
391 if (isa<FenceInst>(I))
396 void ThreadSanitizer::InsertRuntimeIgnores(
Function &
F) {
401 AtExit->CreateCall(TsanIgnoreEnd);
408 if (&F == TsanCtorFunction)
417 bool SanitizeFunction = F.
hasFnAttribute(Attribute::SanitizeThread);
420 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
424 for (
auto &Inst : BB) {
427 else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
429 else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
430 if (
CallInst *CI = dyn_cast<CallInst>(&Inst))
432 if (isa<MemIntrinsic>(Inst))
435 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
439 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores, DL);
448 for (
auto Inst : AllLoadsAndStores) {
449 Res |= instrumentLoadOrStore(Inst, DL);
455 for (
auto Inst : AtomicAccesses) {
456 Res |= instrumentAtomic(Inst, DL);
460 for (
auto Inst : MemIntrinCalls) {
461 Res |= instrumentMemIntrinsic(Inst);
464 if (F.hasFnAttribute(
"sanitize_thread_no_checking_at_run_time")) {
465 assert(!F.hasFnAttribute(Attribute::SanitizeThread));
467 InsertRuntimeIgnores(F);
472 IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI());
473 Value *ReturnAddress = IRB.CreateCall(
476 IRB.CreateCall(TsanFuncEntry, ReturnAddress);
480 AtExit->CreateCall(TsanFuncExit, {});
487 bool ThreadSanitizer::instrumentLoadOrStore(
Instruction *
I,
490 bool IsWrite = isa<StoreInst>(*I);
491 Value *Addr = IsWrite
501 int Idx = getMemoryAccessFuncIndex(Addr, DL);
505 DEBUG(
dbgs() <<
" VPTR : " << *I <<
"\n");
506 Value *StoredValue = cast<StoreInst>(
I)->getValueOperand();
510 if (isa<VectorType>(StoredValue->
getType()))
519 NumInstrumentedVtableWrites++;
525 NumInstrumentedVtableReads++;
528 const unsigned Alignment = IsWrite
531 Type *OrigTy = cast<PointerType>(Addr->
getType())->getElementType();
533 Value *OnAccessFunc =
nullptr;
534 if (Alignment == 0 || Alignment >= 8 || (Alignment % (TypeSize / 8)) == 0)
535 OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx];
537 OnAccessFunc = IsWrite ? TsanUnalignedWrite[Idx] : TsanUnalignedRead[Idx];
539 if (IsWrite) NumInstrumentedWrites++;
540 else NumInstrumentedReads++;
569 bool ThreadSanitizer::instrumentMemIntrinsic(
Instruction *I) {
571 if (
MemSetInst *M = dyn_cast<MemSetInst>(I)) {
580 isa<MemCpyInst>(M) ? MemcpyFn : MemmoveFn,
599 if (
LoadInst *LI = dyn_cast<LoadInst>(I)) {
600 Value *Addr = LI->getPointerOperand();
601 int Idx = getMemoryAccessFuncIndex(Addr, DL);
604 const unsigned ByteSize = 1U << Idx;
605 const unsigned BitSize = ByteSize * 8;
610 Type *OrigTy = cast<PointerType>(Addr->
getType())->getElementType();
614 }
else if (
StoreInst *
SI = dyn_cast<StoreInst>(I)) {
615 Value *Addr =
SI->getPointerOperand();
616 int Idx = getMemoryAccessFuncIndex(Addr, DL);
619 const unsigned ByteSize = 1U << Idx;
620 const unsigned BitSize = ByteSize * 8;
628 }
else if (
AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I)) {
629 Value *Addr = RMWI->getPointerOperand();
630 int Idx = getMemoryAccessFuncIndex(Addr, DL);
633 Function *F = TsanAtomicRMW[RMWI->getOperation()][Idx];
636 const unsigned ByteSize = 1U << Idx;
637 const unsigned BitSize = ByteSize * 8;
646 Value *Addr = CASI->getPointerOperand();
647 int Idx = getMemoryAccessFuncIndex(Addr, DL);
650 const unsigned ByteSize = 1U << Idx;
651 const unsigned BitSize = ByteSize * 8;
666 Type *OrigOldValTy = CASI->getNewValOperand()->getType();
667 if (Ty != OrigOldValTy) {
678 }
else if (
FenceInst *FI = dyn_cast<FenceInst>(I)) {
681 TsanAtomicSignalFence : TsanAtomicThreadFence;
688 int ThreadSanitizer::getMemoryAccessFuncIndex(
Value *Addr,
691 Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType();
694 if (TypeSize != 8 && TypeSize != 16 &&
695 TypeSize != 32 && TypeSize != 64 && TypeSize != 128) {
696 NumAccessesWithBadSize++;
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void push_back(const T &Elt)
A parsed version of the target data layout string in and methods for querying it. ...
uint64_t getTypeStoreSizeInBits(Type *Ty) const
Returns the maximum number of bits that may be overwritten by storing the specified type; always a mu...
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
void ReplaceInstWithInst(BasicBlock::InstListType &BIL, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
Value * getPointerOperand(Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
LLVMContext & getContext() const
Function * checkSanitizerInterfaceFunction(Constant *FuncOrBitcast)
const Value * stripInBoundsOffsets() const
Strip off pointer casts and inbounds GEPs.
Compute iterated dominance frontiers using a linear time algorithm.
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
A Module instance is used to store all the information related to an LLVM module. ...
bool isSized(SmallPtrSetImpl< Type *> *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
An instruction for ordering other memory operations.
an instruction that atomically checks whether a specified value is in a memory location, and, if it is, stores a new value there.
This class represents a function call, abstracting a target machine's calling convention.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
This class wraps the llvm.memset intrinsic.
static bool shouldInstrumentReadWriteFromAddress(const Module *M, Value *Addr)
STATISTIC(NumFunctions, "Total number of functions")
std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
static CallInst * Create(Value *Func, ArrayRef< Value *> Args, ArrayRef< OperandBundleDef > Bundles=None, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
An instruction for reading from memory.
an instruction that atomically reads a memory location, combines it with another value, and then stores the result back.
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
static cl::opt< bool > ClInstrumentAtomics("tsan-instrument-atomics", cl::init(true), cl::desc("Instrument atomics"), cl::Hidden)
EscapeEnumerator - This is a little algorithm to find all escape points from a function so that "fina...
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool endswith(StringRef Suffix) const
Check if this string ends with the given Suffix.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
static uint32_t getAlignment(const MCSectionCOFF &Sec)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
LLVMContext & getContext() const
Get the global data context.
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool isIntegerTy() const
True if this is an instance of IntegerType.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Type * getVoidTy()
Fetch the type representing void.
AtomicOrdering
Atomic ordering for LLVM's memory model.
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Type * getType() const
All values are typed, get the type of this value.
std::string itostr(int64_t X)
bool isSwiftError() const
Return true if this value is a swifterror value.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
An instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type *> Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
const BasicBlock & getEntryBlock() const
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space...
static const size_t kNumberOfAccessSizes
static bool runOnFunction(Function &F, bool PostInlining)
initializer< Ty > init(const Ty &Val)
const Instruction * getFirstNonPHI() const
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
The instances of the Type class are immutable: once they are created, they are never changed...
std::pair< Function *, Function * > createSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type *> InitArgTypes, ArrayRef< Value *> InitArgs, StringRef VersionCheckName=StringRef())
Creates sanitizer constructor function, and calls sanitizer's init function from it.
static const char *const kTsanModuleCtorName
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Represent the analysis usage information of a pass.
FunctionPass * createThreadSanitizerPass()
FunctionPass class - This class is used to implement most global optimizations.
Value * getPointerOperand()
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Class to represent integer types.
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
static cl::opt< bool > ClInstrumentFuncEntryExit("tsan-instrument-func-entry-exit", cl::init(true), cl::desc("Instrument function entry and exit"), cl::Hidden)
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, bool StoreCaptures)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
static bool isAtomic(Instruction *I)
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Value * GetUnderlyingObject(Value *V, const DataLayout &DL, unsigned MaxLookup=6)
This method strips off any GEP address adjustments and pointer casts from the specified value...
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
This is the shared class of boolean and integer constants.
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Provides information about what library functions are available for the current target.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static ConstantInt * createOrdering(IRBuilder<> *IRB, AtomicOrdering ord)
void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
std::string utostr(uint64_t X, bool isNeg=false)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static cl::opt< bool > ClHandleCxxExceptions("tsan-handle-cxx-exceptions", cl::init(true), cl::desc("Handle C++ exceptions (insert cleanup blocks for unwinding)"), cl::Hidden)
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
This class wraps the llvm.memcpy/memmove intrinsics.
static IntegerType * getInt32Ty(LLVMContext &C)
static cl::opt< bool > ClInstrumentMemoryAccesses("tsan-instrument-memory-accesses", cl::init(true), cl::desc("Instrument memory accesses"), cl::Hidden)
void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
static cl::opt< bool > ClInstrumentMemIntrinsics("tsan-instrument-memintrinsics", cl::init(true), cl::desc("Instrument memintrinsics (memset/memcpy/memmove)"), cl::Hidden)
Synchronized with respect to signal handlers executing in the same thread.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char *const kTsanInitName
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
StringRef - Represent a constant reference to a string, i.e.
INITIALIZE_PASS_BEGIN(ThreadSanitizer, "tsan", "ThreadSanitizer: detects data races.", false, false) INITIALIZE_PASS_END(ThreadSanitizer
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static bool isVtableAccess(Instruction *I)
CallInst * CreateCall(Value *Callee, ArrayRef< Value *> Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.