Index: include/llvm/Transforms/Utils/ModuleUtils.h =================================================================== --- include/llvm/Transforms/Utils/ModuleUtils.h +++ include/llvm/Transforms/Utils/ModuleUtils.h @@ -14,12 +14,18 @@ #ifndef LLVM_TRANSFORMS_UTILS_MODULEUTILS_H #define LLVM_TRANSFORMS_UTILS_MODULEUTILS_H +#include "llvm/ADT/ArrayRef.h" + namespace llvm { class Module; class Function; class GlobalValue; class GlobalVariable; +class Constant; +class StringRef; +class Value; +class Type; template class SmallPtrSetImpl; /// Append F to the list of global ctors of module M with the given Priority. @@ -36,6 +42,23 @@ GlobalVariable *collectUsedGlobalVariables(Module &M, SmallPtrSetImpl &Set, bool CompilerUsed); + +// Validate the result of Module::getOrInsertFunction called for an interface +// function of given sanitizer. If the instrumented module defines a function +// with the same name, their prototypes must match, otherwise +// getOrInsertFunction returns a bitcast. +Function *checkInterfaceFunction(StringRef Sanitizer, Constant *FuncOrBitcast); + +/// \brief Creates sanitizer constructor function, and calls sanitizer's init +/// function from it. +Function *createSanitizerCtor(Module &M, StringRef Sanitizer, + StringRef CtorName, StringRef InitName, + ArrayRef InitType = ArrayRef(), + ArrayRef InitArgs = ArrayRef(), + Function **InitFunctionPtr = nullptr); +Function *createSanitizerCtor(Module &M, StringRef Sanitizer, + StringRef CtorName, StringRef InitName, + Function **InitFunctionPtr); } // End llvm namespace #endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -968,18 +968,6 @@ UseCalls, Exp); } -// Validate the result of Module::getOrInsertFunction called for an interface -// function of AddressSanitizer. If the instrumented module defines a function -// with the same name, their prototypes must match, otherwise -// getOrInsertFunction returns a bitcast. -static Function *checkInterfaceFunction(Constant *FuncOrBitcast) { - if (isa(FuncOrBitcast)) return cast(FuncOrBitcast); - FuncOrBitcast->dump(); - report_fatal_error( - "trying to redefine an AddressSanitizer " - "interface function"); -} - Instruction *AddressSanitizer::generateCrashCode(Instruction *InsertBefore, Value *Addr, bool IsWrite, size_t AccessSizeIndex, @@ -1228,17 +1216,23 @@ void AddressSanitizerModule::initializeCallbacks(Module &M) { IRBuilder<> IRB(*C); // Declare our poisoning and unpoisoning functions. - AsanPoisonGlobals = checkInterfaceFunction(M.getOrInsertFunction( - kAsanPoisonGlobalsName, IRB.getVoidTy(), IntptrTy, nullptr)); + AsanPoisonGlobals = checkInterfaceFunction( + "AddressSanitizer", + M.getOrInsertFunction(kAsanPoisonGlobalsName, IRB.getVoidTy(), IntptrTy, + nullptr)); AsanPoisonGlobals->setLinkage(Function::ExternalLinkage); - AsanUnpoisonGlobals = checkInterfaceFunction(M.getOrInsertFunction( - kAsanUnpoisonGlobalsName, IRB.getVoidTy(), nullptr)); + AsanUnpoisonGlobals = checkInterfaceFunction( + "AddressSanitizer", M.getOrInsertFunction(kAsanUnpoisonGlobalsName, + IRB.getVoidTy(), nullptr)); AsanUnpoisonGlobals->setLinkage(Function::ExternalLinkage); // Declare functions that register/unregister globals. - AsanRegisterGlobals = checkInterfaceFunction(M.getOrInsertFunction( - kAsanRegisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); + AsanRegisterGlobals = checkInterfaceFunction( + "AddressSanitizer", + M.getOrInsertFunction(kAsanRegisterGlobalsName, IRB.getVoidTy(), IntptrTy, + IntptrTy, nullptr)); AsanRegisterGlobals->setLinkage(Function::ExternalLinkage); AsanUnregisterGlobals = checkInterfaceFunction( + "AddressSanitizer", M.getOrInsertFunction(kAsanUnregisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); AsanUnregisterGlobals->setLinkage(Function::ExternalLinkage); @@ -1407,46 +1401,62 @@ const std::string TypeStr = AccessIsWrite ? "store" : "load"; const std::string ExpStr = Exp ? "exp_" : ""; const Type *ExpType = Exp ? Type::getInt32Ty(*C) : nullptr; - AsanErrorCallbackSized[AccessIsWrite][Exp] = - checkInterfaceFunction(M.getOrInsertFunction( + AsanErrorCallbackSized[AccessIsWrite][Exp] = checkInterfaceFunction( + "AddressSanitizer", + M.getOrInsertFunction( kAsanReportErrorTemplate + ExpStr + TypeStr + "_n", IRB.getVoidTy(), IntptrTy, IntptrTy, ExpType, nullptr)); AsanMemoryAccessCallbackSized[AccessIsWrite][Exp] = - checkInterfaceFunction(M.getOrInsertFunction( - ClMemoryAccessCallbackPrefix + ExpStr + TypeStr + "N", - IRB.getVoidTy(), IntptrTy, IntptrTy, ExpType, nullptr)); + checkInterfaceFunction( + "AddressSanitizer", + M.getOrInsertFunction( + ClMemoryAccessCallbackPrefix + ExpStr + TypeStr + "N", + IRB.getVoidTy(), IntptrTy, IntptrTy, ExpType, nullptr)); for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes; AccessSizeIndex++) { const std::string Suffix = TypeStr + itostr(1 << AccessSizeIndex); AsanErrorCallback[AccessIsWrite][Exp][AccessSizeIndex] = - checkInterfaceFunction(M.getOrInsertFunction( - kAsanReportErrorTemplate + ExpStr + Suffix, IRB.getVoidTy(), - IntptrTy, ExpType, nullptr)); + checkInterfaceFunction( + "AddressSanitizer", + M.getOrInsertFunction( + kAsanReportErrorTemplate + ExpStr + Suffix, IRB.getVoidTy(), + IntptrTy, ExpType, nullptr)); AsanMemoryAccessCallback[AccessIsWrite][Exp][AccessSizeIndex] = - checkInterfaceFunction(M.getOrInsertFunction( - ClMemoryAccessCallbackPrefix + ExpStr + Suffix, IRB.getVoidTy(), - IntptrTy, ExpType, nullptr)); + checkInterfaceFunction( + "AddressSanitizer", + M.getOrInsertFunction( + ClMemoryAccessCallbackPrefix + ExpStr + Suffix, + IRB.getVoidTy(), IntptrTy, ExpType, nullptr)); } } } - AsanMemmove = checkInterfaceFunction(M.getOrInsertFunction( - ClMemoryAccessCallbackPrefix + "memmove", IRB.getInt8PtrTy(), - IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy, nullptr)); - AsanMemcpy = checkInterfaceFunction(M.getOrInsertFunction( - ClMemoryAccessCallbackPrefix + "memcpy", IRB.getInt8PtrTy(), - IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy, nullptr)); - AsanMemset = checkInterfaceFunction(M.getOrInsertFunction( - ClMemoryAccessCallbackPrefix + "memset", IRB.getInt8PtrTy(), - IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy, nullptr)); + AsanMemmove = checkInterfaceFunction( + "AddressSanitizer", + M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memmove", + IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), + IRB.getInt8PtrTy(), IntptrTy, nullptr)); + AsanMemcpy = checkInterfaceFunction( + "AddressSanitizer", + M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memcpy", + IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), + IRB.getInt8PtrTy(), IntptrTy, nullptr)); + AsanMemset = checkInterfaceFunction( + "AddressSanitizer", + M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "memset", + IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), + IRB.getInt32Ty(), IntptrTy, nullptr)); AsanHandleNoReturnFunc = checkInterfaceFunction( + "AddressSanitizer", M.getOrInsertFunction(kAsanHandleNoReturnName, IRB.getVoidTy(), nullptr)); - AsanPtrCmpFunction = checkInterfaceFunction(M.getOrInsertFunction( - kAsanPtrCmp, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); - AsanPtrSubFunction = checkInterfaceFunction(M.getOrInsertFunction( - kAsanPtrSub, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); + AsanPtrCmpFunction = checkInterfaceFunction( + "AddressSanitizer", M.getOrInsertFunction(kAsanPtrCmp, IRB.getVoidTy(), + IntptrTy, IntptrTy, nullptr)); + AsanPtrSubFunction = checkInterfaceFunction( + "AddressSanitizer", M.getOrInsertFunction(kAsanPtrSub, IRB.getVoidTy(), + IntptrTy, IntptrTy, nullptr)); // We insert an empty inline asm after __asan_report* to avoid callback merge. EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), StringRef(""), StringRef(""), @@ -1465,15 +1475,8 @@ TargetTriple = Triple(M.getTargetTriple()); AsanCtorFunction = - Function::Create(FunctionType::get(Type::getVoidTy(*C), false), - GlobalValue::InternalLinkage, kAsanModuleCtorName, &M); - BasicBlock *AsanCtorBB = BasicBlock::Create(*C, "", AsanCtorFunction); - // call __asan_init in the module ctor. - IRBuilder<> IRB(ReturnInst::Create(*C, AsanCtorBB)); - AsanInitFunction = checkInterfaceFunction( - M.getOrInsertFunction(kAsanInitName, IRB.getVoidTy(), nullptr)); - AsanInitFunction->setLinkage(Function::ExternalLinkage); - IRB.CreateCall(AsanInitFunction); + createSanitizerCtor(M, "AddressSanitizer", kAsanModuleCtorName, + kAsanInitName, &AsanInitFunction); Mapping = getShadowMapping(TargetTriple, LongSize); @@ -1622,16 +1625,21 @@ IRBuilder<> IRB(*C); for (int i = 0; i <= kMaxAsanStackMallocSizeClass; i++) { std::string Suffix = itostr(i); - AsanStackMallocFunc[i] = checkInterfaceFunction(M.getOrInsertFunction( - kAsanStackMallocNameTemplate + Suffix, IntptrTy, IntptrTy, nullptr)); + AsanStackMallocFunc[i] = checkInterfaceFunction( + "AddressSanitizer", + M.getOrInsertFunction(kAsanStackMallocNameTemplate + Suffix, IntptrTy, + IntptrTy, nullptr)); AsanStackFreeFunc[i] = checkInterfaceFunction( + "AddressSanitizer", M.getOrInsertFunction(kAsanStackFreeNameTemplate + Suffix, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); } AsanPoisonStackMemoryFunc = checkInterfaceFunction( + "AddressSanitizer", M.getOrInsertFunction(kAsanPoisonStackMemoryName, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); AsanUnpoisonStackMemoryFunc = checkInterfaceFunction( + "AddressSanitizer", M.getOrInsertFunction(kAsanUnpoisonStackMemoryName, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); } Index: lib/Transforms/Instrumentation/MemorySanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -191,6 +191,9 @@ cl::desc("Insert checks for constant shadow values"), cl::Hidden, cl::init(false)); +static const char *const kMsanModuleCtorName = "msan.module_ctor"; +static const char *const kMsanInitName = "__msan_init"; + namespace { // Memory map parameters used in application-to-shadow address calculation. @@ -332,6 +335,7 @@ MDNode *OriginStoreWeights; /// \brief An empty volatile inline asm that prevents callback merge. InlineAsm *EmptyAsm; + Function *MsanCtorFunction; friend struct MemorySanitizerVisitor; friend struct VarArgAMD64Helper; @@ -491,9 +495,10 @@ ColdCallWeights = MDBuilder(*C).createBranchWeights(1, 1000); OriginStoreWeights = MDBuilder(*C).createBranchWeights(1, 1000); - // Insert a call to __msan_init/__msan_track_origins into the module's CTORs. - appendToGlobalCtors(M, cast(M.getOrInsertFunction( - "__msan_init", IRB.getVoidTy(), nullptr)), 0); + MsanCtorFunction = createSanitizerCtor(M, "MemorySanitizer", + kMsanModuleCtorName, kMsanInitName); + + appendToGlobalCtors(M, MsanCtorFunction, 0); if (TrackOrigins) new GlobalVariable(M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage, @@ -2981,6 +2986,8 @@ } // namespace bool MemorySanitizer::runOnFunction(Function &F) { + if (&F == MsanCtorFunction) + return false; MemorySanitizerVisitor Visitor(F, *this); // Clear out readonly/readnone attributes. Index: lib/Transforms/Instrumentation/SanitizerCoverage.cpp =================================================================== --- lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -140,16 +140,6 @@ } // namespace -static Function *checkInterfaceFunction(Constant *FuncOrBitcast) { - if (Function *F = dyn_cast(FuncOrBitcast)) - return F; - std::string Err; - raw_string_ostream Stream(Err); - Stream << "SanitizerCoverage interface function redefined: " - << *FuncOrBitcast; - report_fatal_error(Err); -} - bool SanitizerCoverageModule::runOnModule(Module &M) { if (!CoverageLevel) return false; C = &(M.getContext()); @@ -161,25 +151,20 @@ Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); Int64Ty = IRB.getInt64Ty(); - Function *CtorFunc = - Function::Create(FunctionType::get(VoidTy, false), - GlobalValue::InternalLinkage, kSanCovModuleCtorName, &M); - ReturnInst::Create(*C, BasicBlock::Create(*C, "", CtorFunc)); - appendToGlobalCtors(M, CtorFunc, kSanCtorAndDtorPriority); - SanCovFunction = checkInterfaceFunction( + "SanitizerCoverage", M.getOrInsertFunction(kSanCovName, VoidTy, Int32PtrTy, nullptr)); SanCovWithCheckFunction = checkInterfaceFunction( + "SanitizerCoverage", M.getOrInsertFunction(kSanCovWithCheckName, VoidTy, Int32PtrTy, nullptr)); - SanCovIndirCallFunction = checkInterfaceFunction(M.getOrInsertFunction( - kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr)); - SanCovTraceCmpFunction = checkInterfaceFunction(M.getOrInsertFunction( - kSanCovTraceCmp, VoidTy, Int64Ty, Int64Ty, Int64Ty, nullptr)); + SanCovIndirCallFunction = checkInterfaceFunction( + "SanitizerCoverage", M.getOrInsertFunction(kSanCovIndirCallName, VoidTy, + IntptrTy, IntptrTy, nullptr)); + SanCovTraceCmpFunction = checkInterfaceFunction( + "SanitizerCoverage", + M.getOrInsertFunction(kSanCovTraceCmp, VoidTy, Int64Ty, Int64Ty, Int64Ty, + nullptr)); - SanCovModuleInit = checkInterfaceFunction(M.getOrInsertFunction( - kSanCovModuleInitName, Type::getVoidTy(*C), Int32PtrTy, IntptrTy, - Int8PtrTy, Int8PtrTy, nullptr)); - SanCovModuleInit->setLinkage(Function::ExternalLinkage); // We insert an empty inline asm after cov callbacks to avoid callback merge. EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), StringRef(""), StringRef(""), @@ -187,8 +172,10 @@ if (ClExperimentalTracing) { SanCovTraceEnter = checkInterfaceFunction( + "SanitizerCoverage", M.getOrInsertFunction(kSanCovTraceEnter, VoidTy, Int32PtrTy, nullptr)); SanCovTraceBB = checkInterfaceFunction( + "SanitizerCoverage", M.getOrInsertFunction(kSanCovTraceBB, VoidTy, Int32PtrTy, nullptr)); } @@ -245,15 +232,21 @@ new GlobalVariable(M, ModNameStrConst->getType(), true, GlobalValue::PrivateLinkage, ModNameStrConst); - // Call __sanitizer_cov_module_init - IRB.SetInsertPoint(CtorFunc->getEntryBlock().getTerminator()); - IRB.CreateCall4( - SanCovModuleInit, IRB.CreatePointerCast(RealGuardArray, Int32PtrTy), + ArrayRef InitArgs = { + IRB.CreatePointerCast(RealGuardArray, Int32PtrTy), ConstantInt::get(IntptrTy, N), ClUse8bitCounters ? IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy) : Constant::getNullValue(Int8PtrTy), - IRB.CreatePointerCast(ModuleName, Int8PtrTy)); + IRB.CreatePointerCast(ModuleName, Int8PtrTy)}; + + Function *CtorFunc = createSanitizerCtor( + M, "SanitizerCoverage", kSanCovModuleCtorName, kSanCovModuleInitName, + {Int32PtrTy, IntptrTy, Int8PtrTy, Int8PtrTy}, InitArgs, + &SanCovModuleInit); + + appendToGlobalCtors(M, CtorFunc, kSanCtorAndDtorPriority); + return true; } Index: lib/Transforms/Instrumentation/ThreadSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -72,6 +72,9 @@ STATISTIC(NumOmittedReadsFromVtable, "Number of vtable reads"); STATISTIC(NumOmittedNonCaptured, "Number of accesses ignored due to capturing"); +static const char *const kTsanModuleCtorName = "tsan.module_ctor"; +static const char *const kTsanInitName = "__tsan_init"; + namespace { /// ThreadSanitizer: instrument the code in module to find races. @@ -113,6 +116,7 @@ Function *TsanVptrUpdate; Function *TsanVptrLoad; Function *MemmoveFn, *MemcpyFn, *MemsetFn; + Function *TsanCtorFunction; }; } // namespace @@ -129,54 +133,58 @@ return new ThreadSanitizer(); } -static Function *checkInterfaceFunction(Constant *FuncOrBitcast) { - if (Function *F = dyn_cast(FuncOrBitcast)) - return F; - FuncOrBitcast->dump(); - report_fatal_error("ThreadSanitizer interface function redefined"); -} - void ThreadSanitizer::initializeCallbacks(Module &M) { IRBuilder<> IRB(M.getContext()); // Initialize the callbacks. - TsanFuncEntry = checkInterfaceFunction(M.getOrInsertFunction( - "__tsan_func_entry", IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr)); - TsanFuncExit = checkInterfaceFunction(M.getOrInsertFunction( - "__tsan_func_exit", IRB.getVoidTy(), nullptr)); + TsanFuncEntry = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction("__tsan_func_entry", IRB.getVoidTy(), + IRB.getInt8PtrTy(), nullptr)); + TsanFuncExit = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction("__tsan_func_exit", IRB.getVoidTy(), nullptr)); OrdTy = IRB.getInt32Ty(); for (size_t i = 0; i < kNumberOfAccessSizes; ++i) { const size_t ByteSize = 1 << i; const size_t BitSize = ByteSize * 8; SmallString<32> ReadName("__tsan_read" + itostr(ByteSize)); - TsanRead[i] = checkInterfaceFunction(M.getOrInsertFunction( - ReadName, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr)); + TsanRead[i] = checkInterfaceFunction( + "ThreadSanitizer", M.getOrInsertFunction(ReadName, IRB.getVoidTy(), + IRB.getInt8PtrTy(), nullptr)); SmallString<32> WriteName("__tsan_write" + itostr(ByteSize)); - TsanWrite[i] = checkInterfaceFunction(M.getOrInsertFunction( - WriteName, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr)); + TsanWrite[i] = checkInterfaceFunction( + "ThreadSanitizer", M.getOrInsertFunction(WriteName, IRB.getVoidTy(), + IRB.getInt8PtrTy(), nullptr)); SmallString<64> UnalignedReadName("__tsan_unaligned_read" + itostr(ByteSize)); - TsanUnalignedRead[i] = checkInterfaceFunction(M.getOrInsertFunction( - UnalignedReadName, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr)); + TsanUnalignedRead[i] = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction(UnalignedReadName, IRB.getVoidTy(), + IRB.getInt8PtrTy(), nullptr)); SmallString<64> UnalignedWriteName("__tsan_unaligned_write" + itostr(ByteSize)); - TsanUnalignedWrite[i] = checkInterfaceFunction(M.getOrInsertFunction( - UnalignedWriteName, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr)); + TsanUnalignedWrite[i] = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction(UnalignedWriteName, IRB.getVoidTy(), + IRB.getInt8PtrTy(), nullptr)); Type *Ty = Type::getIntNTy(M.getContext(), BitSize); Type *PtrTy = Ty->getPointerTo(); SmallString<32> AtomicLoadName("__tsan_atomic" + itostr(BitSize) + "_load"); - TsanAtomicLoad[i] = checkInterfaceFunction(M.getOrInsertFunction( - AtomicLoadName, Ty, PtrTy, OrdTy, nullptr)); + TsanAtomicLoad[i] = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction(AtomicLoadName, Ty, PtrTy, OrdTy, nullptr)); SmallString<32> AtomicStoreName("__tsan_atomic" + itostr(BitSize) + "_store"); - TsanAtomicStore[i] = checkInterfaceFunction(M.getOrInsertFunction( - AtomicStoreName, IRB.getVoidTy(), PtrTy, Ty, OrdTy, - nullptr)); + TsanAtomicStore[i] = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction(AtomicStoreName, IRB.getVoidTy(), PtrTy, Ty, + OrdTy, nullptr)); for (int op = AtomicRMWInst::FIRST_BINOP; op <= AtomicRMWInst::LAST_BINOP; ++op) { @@ -199,45 +207,55 @@ else continue; SmallString<32> RMWName("__tsan_atomic" + itostr(BitSize) + NamePart); - TsanAtomicRMW[op][i] = checkInterfaceFunction(M.getOrInsertFunction( - RMWName, Ty, PtrTy, Ty, OrdTy, nullptr)); + TsanAtomicRMW[op][i] = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction(RMWName, Ty, PtrTy, Ty, OrdTy, nullptr)); } SmallString<32> AtomicCASName("__tsan_atomic" + itostr(BitSize) + "_compare_exchange_val"); - TsanAtomicCAS[i] = checkInterfaceFunction(M.getOrInsertFunction( - AtomicCASName, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy, nullptr)); + TsanAtomicCAS[i] = checkInterfaceFunction( + "ThreadSanitizer", M.getOrInsertFunction(AtomicCASName, Ty, PtrTy, Ty, + Ty, OrdTy, OrdTy, nullptr)); } - TsanVptrUpdate = checkInterfaceFunction(M.getOrInsertFunction( - "__tsan_vptr_update", IRB.getVoidTy(), IRB.getInt8PtrTy(), - IRB.getInt8PtrTy(), nullptr)); - TsanVptrLoad = checkInterfaceFunction(M.getOrInsertFunction( - "__tsan_vptr_read", IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr)); - TsanAtomicThreadFence = checkInterfaceFunction(M.getOrInsertFunction( - "__tsan_atomic_thread_fence", IRB.getVoidTy(), OrdTy, nullptr)); - TsanAtomicSignalFence = checkInterfaceFunction(M.getOrInsertFunction( - "__tsan_atomic_signal_fence", IRB.getVoidTy(), OrdTy, nullptr)); + TsanVptrUpdate = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction("__tsan_vptr_update", IRB.getVoidTy(), + IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), nullptr)); + TsanVptrLoad = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction("__tsan_vptr_read", IRB.getVoidTy(), + IRB.getInt8PtrTy(), nullptr)); + TsanAtomicThreadFence = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction("__tsan_atomic_thread_fence", IRB.getVoidTy(), + OrdTy, nullptr)); + TsanAtomicSignalFence = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction("__tsan_atomic_signal_fence", IRB.getVoidTy(), + OrdTy, nullptr)); - MemmoveFn = checkInterfaceFunction(M.getOrInsertFunction( - "memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), - IRB.getInt8PtrTy(), IntptrTy, nullptr)); - MemcpyFn = checkInterfaceFunction(M.getOrInsertFunction( - "memcpy", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), - IntptrTy, nullptr)); - MemsetFn = checkInterfaceFunction(M.getOrInsertFunction( - "memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt32Ty(), - IntptrTy, nullptr)); + MemmoveFn = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction("memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), + IRB.getInt8PtrTy(), IntptrTy, nullptr)); + MemcpyFn = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction("memcpy", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), + IRB.getInt8PtrTy(), IntptrTy, nullptr)); + MemsetFn = checkInterfaceFunction( + "ThreadSanitizer", + M.getOrInsertFunction("memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), + IRB.getInt32Ty(), IntptrTy, nullptr)); } bool ThreadSanitizer::doInitialization(Module &M) { const DataLayout &DL = M.getDataLayout(); + IntptrTy = DL.getIntPtrType(M.getContext()); + TsanCtorFunction = createSanitizerCtor(M, "ThreadSanitizer", + kTsanModuleCtorName, kTsanInitName); - // Always insert a call to __tsan_init into the module's CTORs. - IRBuilder<> IRB(M.getContext()); - IntptrTy = IRB.getIntPtrTy(DL); - Value *TsanInit = M.getOrInsertFunction("__tsan_init", - IRB.getVoidTy(), nullptr); - appendToGlobalCtors(M, cast(TsanInit), 0); + appendToGlobalCtors(M, TsanCtorFunction, 0); return true; } @@ -335,6 +353,8 @@ } bool ThreadSanitizer::runOnFunction(Function &F) { + if (&F == TsanCtorFunction) + return false; initializeCallbacks(*F.getParent()); SmallVector RetVec; SmallVector AllLoadsAndStores; Index: lib/Transforms/Utils/ModuleUtils.cpp =================================================================== --- lib/Transforms/Utils/ModuleUtils.cpp +++ lib/Transforms/Utils/ModuleUtils.cpp @@ -17,6 +17,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -93,3 +94,50 @@ } return GV; } + +// Validate the result of Module::getOrInsertFunction called for an interface +// function of sanitizer. If the instrumented module defines a function +// with the same name, their prototypes must match, otherwise +// getOrInsertFunction returns a bitcast. +Function *llvm::checkInterfaceFunction(StringRef Sanitizer, + Constant *FuncOrBitcast) { + if (isa(FuncOrBitcast)) + return cast(FuncOrBitcast); + FuncOrBitcast->dump(); + std::string Err; + raw_string_ostream Stream(Err); + Stream << Sanitizer << " interface function redefined: " << *FuncOrBitcast; + report_fatal_error(Err); +} + +Function *llvm::createSanitizerCtor(Module &M, StringRef Sanitizer, + llvm::StringRef CtorName, + llvm::StringRef InitName, + llvm::ArrayRef InitType, + llvm::ArrayRef InitArgs, + llvm::Function **InitFunctionPtr) { + assert(!InitName.empty() && "Expected init function name"); + Function *Ctor = Function::Create( + FunctionType::get(Type::getVoidTy(M.getContext()), false), + GlobalValue::InternalLinkage, CtorName, &M); + BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor); + IRBuilder<> IRB(ReturnInst::Create(M.getContext(), CtorBB)); + Function *InitFunction = checkInterfaceFunction( + Sanitizer, + M.getOrInsertFunction(InitName, + FunctionType::get(IRB.getVoidTy(), InitType, false), + AttributeSet())); + InitFunction->setLinkage(Function::ExternalLinkage); + IRB.CreateCall(InitFunction, InitArgs); + if (InitFunctionPtr) + *InitFunctionPtr = InitFunction; + return Ctor; +} + +Function *llvm::createSanitizerCtor(Module &M, StringRef Sanitizer, + llvm::StringRef CtorName, + llvm::StringRef InitName, + llvm::Function **InitFunctionPtr) { + return llvm::createSanitizerCtor(M, Sanitizer, CtorName, InitName, {}, {}, + InitFunctionPtr); +}