diff options
Diffstat (limited to 'lib/Transforms/Instrumentation/SanitizerCoverage.cpp')
-rw-r--r-- | lib/Transforms/Instrumentation/SanitizerCoverage.cpp | 81 |
1 files changed, 52 insertions, 29 deletions
diff --git a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index a4dd48c8dd6a..0ba8d5765e8c 100644 --- a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -29,6 +29,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" @@ -211,8 +212,8 @@ private: bool IsLeafFunc = true); Function *CreateInitCallsForSections(Module &M, const char *InitFunctionName, Type *Ty, const char *Section); - std::pair<GlobalVariable *, GlobalVariable *> - CreateSecStartEnd(Module &M, const char *Section, Type *Ty); + std::pair<Value *, Value *> CreateSecStartEnd(Module &M, const char *Section, + Type *Ty); void SetNoSanitizeMetadata(Instruction *I) { I->setMetadata(I->getModule()->getMDKindID("nosanitize"), @@ -234,6 +235,7 @@ private: Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, *Int16Ty, *Int8Ty, *Int8PtrTy; Module *CurModule; + std::string CurModuleUniqueId; Triple TargetTriple; LLVMContext *C; const DataLayout *DL; @@ -249,7 +251,7 @@ private: } // namespace -std::pair<GlobalVariable *, GlobalVariable *> +std::pair<Value *, Value *> SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section, Type *Ty) { GlobalVariable *SecStart = @@ -260,22 +262,28 @@ SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section, new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr, getSectionEnd(Section)); SecEnd->setVisibility(GlobalValue::HiddenVisibility); - - return std::make_pair(SecStart, SecEnd); + IRBuilder<> IRB(M.getContext()); + Value *SecEndPtr = IRB.CreatePointerCast(SecEnd, Ty); + if (!TargetTriple.isOSBinFormatCOFF()) + return std::make_pair(IRB.CreatePointerCast(SecStart, Ty), SecEndPtr); + + // Account for the fact that on windows-msvc __start_* symbols actually + // point to a uint64_t before the start of the array. + auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy); + auto GEP = IRB.CreateGEP(SecStartI8Ptr, + ConstantInt::get(IntptrTy, sizeof(uint64_t))); + return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEndPtr); } - Function *SanitizerCoverageModule::CreateInitCallsForSections( Module &M, const char *InitFunctionName, Type *Ty, const char *Section) { - IRBuilder<> IRB(M.getContext()); auto SecStartEnd = CreateSecStartEnd(M, Section, Ty); auto SecStart = SecStartEnd.first; auto SecEnd = SecStartEnd.second; Function *CtorFunc; std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( - M, SanCovModuleCtorName, InitFunctionName, {Ty, Ty}, - {IRB.CreatePointerCast(SecStart, Ty), IRB.CreatePointerCast(SecEnd, Ty)}); + M, SanCovModuleCtorName, InitFunctionName, {Ty, Ty}, {SecStart, SecEnd}); if (TargetTriple.supportsCOMDAT()) { // Use comdat to dedup CtorFunc. @@ -284,6 +292,17 @@ Function *SanitizerCoverageModule::CreateInitCallsForSections( } else { appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority); } + + if (TargetTriple.isOSBinFormatCOFF()) { + // In COFF files, if the contructors are set as COMDAT (they are because + // COFF supports COMDAT) and the linker flag /OPT:REF (strip unreferenced + // functions and data) is used, the constructors get stripped. To prevent + // this, give the constructors weak ODR linkage and ensure the linker knows + // to include the sancov constructor. This way the linker can deduplicate + // the constructors but always leave one copy. + CtorFunc->setLinkage(GlobalValue::WeakODRLinkage); + appendToUsed(M, CtorFunc); + } return CtorFunc; } @@ -293,6 +312,7 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { C = &(M.getContext()); DL = &M.getDataLayout(); CurModule = &M; + CurModuleUniqueId = getUniqueModuleId(CurModule); TargetTriple = Triple(M.getTargetTriple()); FunctionGuardArray = nullptr; Function8bitCounterArray = nullptr; @@ -397,9 +417,7 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { Function *InitFunction = declareSanitizerInitFunction( M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy}); IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); - IRBCtor.CreateCall(InitFunction, - {IRB.CreatePointerCast(SecStartEnd.first, IntptrPtrTy), - IRB.CreatePointerCast(SecStartEnd.second, IntptrPtrTy)}); + IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); } // We don't reference these arrays directly in any of our runtime functions, // so we need to prevent them from being dead stripped. @@ -549,11 +567,19 @@ GlobalVariable *SanitizerCoverageModule::CreateFunctionLocalArrayInSection( auto Array = new GlobalVariable( *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, Constant::getNullValue(ArrayTy), "__sancov_gen_"); - if (auto Comdat = F.getComdat()) - Array->setComdat(Comdat); + + if (TargetTriple.supportsCOMDAT() && !F.isInterposable()) + if (auto Comdat = + GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) + Array->setComdat(Comdat); Array->setSection(getSectionName(Section)); Array->setAlignment(Ty->isPointerTy() ? DL->getPointerSize() : Ty->getPrimitiveSizeInBits() / 8); + GlobalsToAppendToUsed.push_back(Array); + GlobalsToAppendToCompilerUsed.push_back(Array); + MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F)); + Array->addMetadata(LLVMContext::MD_associated, *MD); + return Array; } @@ -587,24 +613,16 @@ SanitizerCoverageModule::CreatePCArray(Function &F, void SanitizerCoverageModule::CreateFunctionLocalArrays( Function &F, ArrayRef<BasicBlock *> AllBlocks) { - if (Options.TracePCGuard) { + if (Options.TracePCGuard) FunctionGuardArray = CreateFunctionLocalArrayInSection( AllBlocks.size(), F, Int32Ty, SanCovGuardsSectionName); - GlobalsToAppendToUsed.push_back(FunctionGuardArray); - } - if (Options.Inline8bitCounters) { + + if (Options.Inline8bitCounters) Function8bitCounterArray = CreateFunctionLocalArrayInSection( AllBlocks.size(), F, Int8Ty, SanCovCountersSectionName); - GlobalsToAppendToCompilerUsed.push_back(Function8bitCounterArray); - MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F)); - Function8bitCounterArray->addMetadata(LLVMContext::MD_associated, *MD); - } - if (Options.PCTable) { + + if (Options.PCTable) FunctionPCsArray = CreatePCArray(F, AllBlocks); - GlobalsToAppendToCompilerUsed.push_back(FunctionPCsArray); - MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F)); - FunctionPCsArray->addMetadata(LLVMContext::MD_associated, *MD); - } } bool SanitizerCoverageModule::InjectCoverage(Function &F, @@ -806,8 +824,13 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, std::string SanitizerCoverageModule::getSectionName(const std::string &Section) const { - if (TargetTriple.getObjectFormat() == Triple::COFF) - return ".SCOV$M"; + if (TargetTriple.isOSBinFormatCOFF()) { + if (Section == SanCovCountersSectionName) + return ".SCOV$CM"; + if (Section == SanCovPCsSectionName) + return ".SCOVP$M"; + return ".SCOV$GM"; // For SanCovGuardsSectionName. + } if (TargetTriple.isOSBinFormatMachO()) return "__DATA,__" + Section; return "__" + Section; |