53 #define DEBUG_TYPE "tsan" 56 "tsan-instrument-memory-accesses",
cl::init(
true),
59 "tsan-instrument-func-entry-exit",
cl::init(
true),
62 "tsan-handle-cxx-exceptions",
cl::init(
true),
63 cl::desc(
"Handle C++ exceptions (insert cleanup blocks for unwinding)"),
66 "tsan-instrument-atomics",
cl::init(
true),
69 "tsan-instrument-memintrinsics",
cl::init(
true),
72 STATISTIC(NumInstrumentedReads,
"Number of instrumented reads");
73 STATISTIC(NumInstrumentedWrites,
"Number of instrumented writes");
75 "Number of reads ignored due to following writes");
76 STATISTIC(NumAccessesWithBadSize,
"Number of accesses with bad size");
77 STATISTIC(NumInstrumentedVtableWrites,
"Number of vtable ptr writes");
78 STATISTIC(NumInstrumentedVtableReads,
"Number of vtable ptr reads");
79 STATISTIC(NumOmittedReadsFromConstantGlobals,
80 "Number of reads from constant globals");
81 STATISTIC(NumOmittedReadsFromVtable,
"Number of vtable reads");
82 STATISTIC(NumOmittedNonCaptured,
"Number of accesses ignored due to capturing");
95 struct ThreadSanitizer {
96 ThreadSanitizer(
Module &M);
100 void initializeCallbacks(
Module &M);
107 bool addrPointsToConstantData(
Value *Addr);
109 void InsertRuntimeIgnores(
Function &F);
132 Function *MemmoveFn, *MemcpyFn, *MemsetFn;
141 bool doInitialization(
Module &M)
override;
158 "ThreadSanitizer: detects data races.",
false,
false)
161 "ThreadSanitizer: detects data races.",
false, false)
163 StringRef ThreadSanitizerLegacyPass::getPassName()
const {
164 return "ThreadSanitizerLegacyPass";
167 void ThreadSanitizerLegacyPass::getAnalysisUsage(
AnalysisUsage &AU)
const {
171 bool ThreadSanitizerLegacyPass::doInitialization(
Module &M) {
177 auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
178 TSan->sanitizeFunction(F, TLI);
183 return new ThreadSanitizerLegacyPass();
186 void ThreadSanitizer::initializeCallbacks(
Module &M) {
197 "__tsan_ignore_thread_begin", Attr, IRB.
getVoidTy()));
199 "__tsan_ignore_thread_end", Attr, IRB.
getVoidTy()));
200 OrdTy = IRB.getInt32Ty();
202 const unsigned ByteSize = 1U << i;
203 const unsigned BitSize = ByteSize * 8;
204 std::string ByteSizeStr =
utostr(ByteSize);
205 std::string BitSizeStr =
utostr(BitSize);
214 SmallString<64> UnalignedReadName(
"__tsan_unaligned_read" + ByteSizeStr);
215 TsanUnalignedRead[i] =
219 SmallString<64> UnalignedWriteName(
"__tsan_unaligned_write" + ByteSizeStr);
220 TsanUnalignedWrite[i] =
226 SmallString<32> AtomicLoadName(
"__tsan_atomic" + BitSizeStr +
"_load");
230 SmallString<32> AtomicStoreName(
"__tsan_atomic" + BitSizeStr +
"_store");
232 AtomicStoreName, Attr, IRB.
getVoidTy(), PtrTy, Ty, OrdTy));
236 TsanAtomicRMW[
op][i] =
nullptr;
237 const char *NamePart =
nullptr;
239 NamePart =
"_exchange";
241 NamePart =
"_fetch_add";
243 NamePart =
"_fetch_sub";
245 NamePart =
"_fetch_and";
247 NamePart =
"_fetch_or";
249 NamePart =
"_fetch_xor";
251 NamePart =
"_fetch_nand";
260 "_compare_exchange_val");
262 AtomicCASName, Attr, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy));
270 "__tsan_atomic_thread_fence", Attr, IRB.
getVoidTy(), OrdTy));
272 "__tsan_atomic_signal_fence", Attr, IRB.
getVoidTy(), OrdTy));
285 ThreadSanitizer::ThreadSanitizer(
Module &M) {
288 std::tie(TsanCtorFunction, std::ignore) =
299 return Tag->isTBAAVtableAccess();
310 if (GV->hasSection()) {
320 if (GV->getName().startswith(
"__llvm_gcov") ||
321 GV->getName().startswith(
"__llvm_gcda"))
336 bool ThreadSanitizer::addrPointsToConstantData(
Value *Addr) {
339 Addr =
GEP->getPointerOperand();
342 if (GV->isConstant()) {
344 NumOmittedReadsFromConstantGlobals++;
347 }
else if (
LoadInst *L = dyn_cast<LoadInst>(Addr)) {
350 NumOmittedReadsFromVtable++;
369 void ThreadSanitizer::chooseInstructionsToInstrument(
379 WriteTargets.
insert(Addr);
385 if (WriteTargets.
count(Addr)) {
387 NumOmittedReadsBeforeWrite++;
390 if (addrPointsToConstantData(Addr)) {
395 Value *Addr = isa<StoreInst>(*I)
403 NumOmittedNonCaptured++;
413 if (
LoadInst *LI = dyn_cast<LoadInst>(I))
417 if (isa<AtomicRMWInst>(I))
419 if (isa<AtomicCmpXchgInst>(I))
421 if (isa<FenceInst>(I))
426 void ThreadSanitizer::InsertRuntimeIgnores(
Function &F) {
431 AtExit->CreateCall(TsanIgnoreEnd);
435 bool ThreadSanitizer::sanitizeFunction(
Function &F,
439 if (&F == TsanCtorFunction)
453 for (
auto &Inst : BB) {
456 else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
458 else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
459 if (
CallInst *CI = dyn_cast<CallInst>(&Inst))
461 if (isa<MemIntrinsic>(Inst))
464 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
468 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores, DL);
477 for (
auto Inst : AllLoadsAndStores) {
478 Res |= instrumentLoadOrStore(Inst, DL);
484 for (
auto Inst : AtomicAccesses) {
485 Res |= instrumentAtomic(Inst, DL);
489 for (
auto Inst : MemIntrinCalls) {
490 Res |= instrumentMemIntrinsic(Inst);
493 if (F.hasFnAttribute(
"sanitize_thread_no_checking_at_run_time")) {
496 InsertRuntimeIgnores(F);
501 IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI());
502 Value *ReturnAddress = IRB.CreateCall(
505 IRB.CreateCall(TsanFuncEntry, ReturnAddress);
509 AtExit->CreateCall(TsanFuncExit, {});
516 bool ThreadSanitizer::instrumentLoadOrStore(
Instruction *
I,
519 bool IsWrite = isa<StoreInst>(*I);
520 Value *Addr = IsWrite
530 int Idx = getMemoryAccessFuncIndex(Addr, DL);
535 Value *StoredValue = cast<StoreInst>(
I)->getValueOperand();
539 if (isa<VectorType>(StoredValue->
getType()))
548 NumInstrumentedVtableWrites++;
554 NumInstrumentedVtableReads++;
557 const unsigned Alignment = IsWrite
560 Type *OrigTy = cast<PointerType>(Addr->
getType())->getElementType();
562 Value *OnAccessFunc =
nullptr;
563 if (Alignment == 0 || Alignment >= 8 || (Alignment % (TypeSize / 8)) == 0)
564 OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx];
566 OnAccessFunc = IsWrite ? TsanUnalignedWrite[Idx] : TsanUnalignedRead[Idx];
568 if (IsWrite) NumInstrumentedWrites++;
569 else NumInstrumentedReads++;
598 bool ThreadSanitizer::instrumentMemIntrinsic(
Instruction *I) {
600 if (
MemSetInst *M = dyn_cast<MemSetInst>(I)) {
609 isa<MemCpyInst>(M) ? MemcpyFn : MemmoveFn,
628 if (
LoadInst *LI = dyn_cast<LoadInst>(I)) {
629 Value *Addr = LI->getPointerOperand();
630 int Idx = getMemoryAccessFuncIndex(Addr, DL);
633 const unsigned ByteSize = 1U << Idx;
634 const unsigned BitSize = ByteSize * 8;
639 Type *OrigTy = cast<PointerType>(Addr->
getType())->getElementType();
643 }
else if (
StoreInst *
SI = dyn_cast<StoreInst>(I)) {
644 Value *Addr =
SI->getPointerOperand();
645 int Idx = getMemoryAccessFuncIndex(Addr, DL);
648 const unsigned ByteSize = 1U << Idx;
649 const unsigned BitSize = ByteSize * 8;
657 }
else if (
AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I)) {
658 Value *Addr = RMWI->getPointerOperand();
659 int Idx = getMemoryAccessFuncIndex(Addr, DL);
662 Function *F = TsanAtomicRMW[RMWI->getOperation()][Idx];
665 const unsigned ByteSize = 1U << Idx;
666 const unsigned BitSize = ByteSize * 8;
675 Value *Addr = CASI->getPointerOperand();
676 int Idx = getMemoryAccessFuncIndex(Addr, DL);
679 const unsigned ByteSize = 1U << Idx;
680 const unsigned BitSize = ByteSize * 8;
695 Type *OrigOldValTy = CASI->getNewValOperand()->getType();
696 if (Ty != OrigOldValTy) {
707 }
else if (
FenceInst *FI = dyn_cast<FenceInst>(I)) {
710 TsanAtomicSignalFence : TsanAtomicThreadFence;
717 int ThreadSanitizer::getMemoryAccessFuncIndex(
Value *Addr,
720 Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType();
723 if (TypeSize != 8 && TypeSize != 16 &&
724 TypeSize != 32 && TypeSize != 64 && TypeSize != 128) {
725 NumAccessesWithBadSize++;
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
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.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents lattice values for constants.
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.
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.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
void push_back(const T &Elt)
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.
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.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
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.
A set of analyses that are preserved following a run of a transformation pass.
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...
static const char *const kTsanModuleCtorName
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Value * getPointerOperand()
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Class to represent integer types.
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 PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
static cl::opt< bool > ClInstrumentFuncEntryExit("tsan-instrument-func-entry-exit", cl::init(true), cl::desc("Instrument function entry and exit"), cl::Hidden)
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.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
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)
INITIALIZE_PASS_BEGIN(ThreadSanitizerLegacyPass, "tsan", "ThreadSanitizer: detects data races.", false, false) INITIALIZE_PASS_END(ThreadSanitizerLegacyPass
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="")
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
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...
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value *> Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
static cl::opt< bool > ClInstrumentMemIntrinsics("tsan-instrument-memintrinsics", cl::init(true), cl::desc("Instrument memintrinsics (memset/memcpy/memmove)"), cl::Hidden)
Analysis pass providing the TargetLibraryInfo.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char *const kTsanInitName
FunctionPass * createThreadSanitizerLegacyPassPass()
Synchronized with respect to signal handlers executing in the same thread.
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.
A container for analyses that lazily runs them and caches their results.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
std::pair< Function *, Function * > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type *> InitArgTypes, ArrayRef< Value *> InitArgs, function_ref< void(Function *, Function *)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef())
Creates sanitizer constructor function lazily.
static bool isVtableAccess(Instruction *I)
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, bool StoreCaptures, unsigned MaxUsesToExplore=DefaultMaxUsesToExplore)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...