From: Leonard Chan Date: Thu, 11 Jul 2019 22:35:40 +0000 (+0000) Subject: [NewPM] Port Sancov X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3f54675197e7ae20d67b303f6e250c06e84e7e95;p=llvm [NewPM] Port Sancov This patch contains a port of SanitizerCoverage to the new pass manager. This one's a bit hefty. Changes: - Split SanitizerCoverageModule into 2 SanitizerCoverage for passing over functions and ModuleSanitizerCoverage for passing over modules. - ModuleSanitizerCoverage exists for adding 2 module level calls to initialization functions but only if there's a function that was instrumented by sancov. - Added legacy and new PM wrapper classes that own instances of the 2 new classes. - Update llvm tests and add clang tests. Differential Revision: https://reviews.llvm.org/D62888 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365838 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 164d0be2855..031df1f00e8 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -360,7 +360,9 @@ void initializeSROALegacyPassPass(PassRegistry&); void initializeSafeStackLegacyPassPass(PassRegistry&); void initializeSafepointIRVerifierPass(PassRegistry&); void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&); -void initializeSanitizerCoverageModulePass(PassRegistry&); +void initializeSanitizerCoverageFunctionCheckLegacyPassPass(PassRegistry &); +void initializeSanitizerCoverageLegacyPassPass(PassRegistry &); +void initializeModuleSanitizerCoverageLegacyPassPass(PassRegistry &); void initializeScalarEvolutionWrapperPassPass(PassRegistry&); void initializeScalarizeMaskedMemIntrinPass(PassRegistry&); void initializeScalarizerLegacyPassPass(PassRegistry&); diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 8b70d2926ae..fcad1e11895 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -181,10 +181,6 @@ struct SanitizerCoverageOptions { SanitizerCoverageOptions() = default; }; -// Insert SanitizerCoverage instrumentation. -ModulePass *createSanitizerCoverageModulePass( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()); - /// Calculate what to divide by to scale counts. /// /// Given the maximum count, calculate a divisor that will scale all the diff --git a/include/llvm/Transforms/Instrumentation/SanitizerCoverage.h b/include/llvm/Transforms/Instrumentation/SanitizerCoverage.h new file mode 100644 index 00000000000..bdc79b1a452 --- /dev/null +++ b/include/llvm/Transforms/Instrumentation/SanitizerCoverage.h @@ -0,0 +1,62 @@ +//===--------- Definition of the SanitizerCoverage class --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the SanitizerCoverage class which is a port of the legacy +// SanitizerCoverage pass to use the new PassManager infrastructure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERCOVERAGE_H +#define LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERCOVERAGE_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Instrumentation.h" + +namespace llvm { + +/// This is the SanitizerCoverage pass used in the new pass manager. The +/// pass instruments functions for coverage. +class SanitizerCoveragePass : public PassInfoMixin { +public: + explicit SanitizerCoveragePass( + SanitizerCoverageOptions Options = SanitizerCoverageOptions()) + : Options(Options) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + +private: + SanitizerCoverageOptions Options; +}; + +/// This is the ModuleSanitizerCoverage pass used in the new pass manager. This +/// adds initialization calls to the module for trace PC guards and 8bit +/// counters if they are requested. +class ModuleSanitizerCoveragePass + : public PassInfoMixin { +public: + explicit ModuleSanitizerCoveragePass( + SanitizerCoverageOptions Options = SanitizerCoverageOptions()) + : Options(Options) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + +private: + SanitizerCoverageOptions Options; +}; + +// Insert SanitizerCoverage instrumentation. +FunctionPass *createSanitizerCoverageLegacyPassPass( + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()); +ModulePass *createModuleSanitizerCoverageLegacyPassPass( + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()); + +} // namespace llvm + +#endif diff --git a/lib/Passes/PassBuilder.cpp b/lib/Passes/PassBuilder.cpp index e2b2a2b2526..eef94bf9012 100644 --- a/lib/Passes/PassBuilder.cpp +++ b/lib/Passes/PassBuilder.cpp @@ -101,6 +101,7 @@ #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" #include "llvm/Transforms/Instrumentation/PoisonChecking.h" +#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/Scalar/ADCE.h" #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h" @@ -143,8 +144,8 @@ #include "llvm/Transforms/Scalar/LowerWidenableCondition.h" #include "llvm/Transforms/Scalar/MakeGuardsExplicit.h" #include "llvm/Transforms/Scalar/MemCpyOptimizer.h" -#include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h" #include "llvm/Transforms/Scalar/MergeICmps.h" +#include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h" #include "llvm/Transforms/Scalar/NaryReassociate.h" #include "llvm/Transforms/Scalar/NewGVN.h" #include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h" diff --git a/lib/Passes/PassRegistry.def b/lib/Passes/PassRegistry.def index e785558d5a7..b1b2304af8d 100644 --- a/lib/Passes/PassRegistry.def +++ b/lib/Passes/PassRegistry.def @@ -86,6 +86,7 @@ MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass(nullptr, nullptr)) MODULE_PASS("verify", VerifierPass()) MODULE_PASS("asan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/false, false, true, false)) MODULE_PASS("kasan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/true, false, true, false)) +MODULE_PASS("sancov-module", ModuleSanitizerCoveragePass()) MODULE_PASS("poison-checking", PoisonCheckingPass()) #undef MODULE_PASS @@ -245,6 +246,7 @@ FUNCTION_PASS("khwasan", HWAddressSanitizerPass(true, true)) FUNCTION_PASS("msan", MemorySanitizerPass({})) FUNCTION_PASS("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true})) FUNCTION_PASS("tsan", ThreadSanitizerPass()) +FUNCTION_PASS("sancov-func", SanitizerCoveragePass()) #undef FUNCTION_PASS #ifndef FUNCTION_PASS_WITH_PARAMS diff --git a/lib/Transforms/Instrumentation/Instrumentation.cpp b/lib/Transforms/Instrumentation/Instrumentation.cpp index f56a1bd91b8..64bf5147661 100644 --- a/lib/Transforms/Instrumentation/Instrumentation.cpp +++ b/lib/Transforms/Instrumentation/Instrumentation.cpp @@ -116,7 +116,7 @@ void llvm::initializeInstrumentation(PassRegistry &Registry) { initializeMemorySanitizerLegacyPassPass(Registry); initializeHWAddressSanitizerLegacyPassPass(Registry); initializeThreadSanitizerLegacyPassPass(Registry); - initializeSanitizerCoverageModulePass(Registry); + initializeSanitizerCoverageLegacyPassPass(Registry); initializeDataFlowSanitizerPass(Registry); } diff --git a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index ca0cb4bdbe8..47fa3863c6a 100644 --- a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/EHPersonalities.h" @@ -176,24 +177,168 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { return Options; } -class SanitizerCoverageModule : public ModulePass { +bool canInstrumentWithSancov(const Function &F) { + if (F.empty()) + return false; + if (F.getName().find(".module_ctor") != std::string::npos) + return false; // Should not instrument sanitizer init functions. + if (F.getName().startswith("__sanitizer_")) + return false; // Don't instrument __sanitizer_* callbacks. + // Don't touch available_externally functions, their actual body is elewhere. + if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) + return false; + // Don't instrument MSVC CRT configuration helpers. They may run before normal + // initialization. + if (F.getName() == "__local_stdio_printf_options" || + F.getName() == "__local_stdio_scanf_options") + return false; + if (isa(F.getEntryBlock().getTerminator())) + return false; + // Don't instrument functions using SEH for now. Splitting basic blocks like + // we do for coverage breaks WinEHPrepare. + // FIXME: Remove this when SEH no longer uses landingpad pattern matching. + if (F.hasPersonalityFn() && + isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) + return false; + return true; +} + +std::string getSectionStartImpl(const Triple &TargetTriple, + const std::string &Section) { + if (TargetTriple.isOSBinFormatMachO()) + return "\1section$start$__DATA$__" + Section; + return "__start___" + Section; +} + +std::string getSectionEndImpl(const Triple &TargetTriple, + const std::string &Section) { + if (TargetTriple.isOSBinFormatMachO()) + return "\1section$end$__DATA$__" + Section; + return "__stop___" + Section; +} + +/// This is a class for instrumenting the module to add calls to initializing +/// the trace PC guards and 8bit counter globals. This should only be done +/// though if there is at least one function that can be instrumented with +/// Sancov. +class ModuleSanitizerCoverage { +public: + ModuleSanitizerCoverage(const SanitizerCoverageOptions &Options) + : Options(OverrideFromCL(Options)) {} + + bool instrumentModule(Module &M) { + if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) + return false; + + Function *Ctor = nullptr; + LLVMContext *C = &(M.getContext()); + const DataLayout *DL = &M.getDataLayout(); + TargetTriple = Triple(M.getTargetTriple()); + IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); + Type *IntptrPtrTy = PointerType::getUnqual(IntptrTy); + IRBuilder<> IRB(*C); + Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); + Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); + Int8Ty = IRB.getInt8Ty(); + + // Check that the __sancov_lowest_stack marker does not already exist. + Constant *SanCovLowestStackConstant = + M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy); + GlobalVariable *SanCovLowestStack = + dyn_cast(SanCovLowestStackConstant); + if (!SanCovLowestStack) { + C->emitError(StringRef("'") + SanCovLowestStackName + + "' should not be declared by the user"); + return true; + } + + // We want to emit guard init calls if the module contains a function that + // we can instrument with SanitizerCoverage. We ignore any functions that + // were inserted by SanitizerCoverage and get the result from the analysis + // that checks for a valid function that the analysis may have run over. + if (!llvm::any_of( + M, [](const Function &F) { return canInstrumentWithSancov(F); })) + return false; + + // Emit the init calls. + if (Options.TracePCGuard) + Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName, + SanCovTracePCGuardInitName, Int32PtrTy, + SanCovGuardsSectionName); + if (Options.Inline8bitCounters) + Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName, + SanCov8bitCountersInitName, Int8PtrTy, + SanCovCountersSectionName); + if (Ctor && Options.PCTable) { + auto SecStartEnd = + CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy); + FunctionCallee InitFunction = declareSanitizerInitFunction( + M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy}); + IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); + IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); + } + return Ctor; + } + +private: + Function *CreateInitCallsForSections(Module &M, const char *CtorName, + const char *InitFunctionName, Type *Ty, + const char *Section); + std::pair CreateSecStartEnd(Module &M, const char *Section, + Type *Ty); + std::string getSectionStart(const std::string &Section) const { + return getSectionStartImpl(TargetTriple, Section); + } + std::string getSectionEnd(const std::string &Section) const { + return getSectionEndImpl(TargetTriple, Section); + } + + SanitizerCoverageOptions Options; + Triple TargetTriple; + Type *IntptrTy, *Int8PtrTy, *Int8Ty; +}; + +class ModuleSanitizerCoverageLegacyPass : public ModulePass { public: - SanitizerCoverageModule( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) - : ModulePass(ID), Options(OverrideFromCL(Options)) { - initializeSanitizerCoverageModulePass(*PassRegistry::getPassRegistry()); + static char ID; + + ModuleSanitizerCoverageLegacyPass( + SanitizerCoverageOptions Options = SanitizerCoverageOptions()) + : ModulePass(ID), Options(Options) { + initializeModuleSanitizerCoverageLegacyPassPass( + *PassRegistry::getPassRegistry()); } - bool runOnModule(Module &M) override; - bool runOnFunction(Function &F); - static char ID; // Pass identification, replacement for typeid - StringRef getPassName() const override { return "SanitizerCoverageModule"; } - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); - AU.addRequired(); + bool runOnModule(Module &M) override { + ModuleSanitizerCoverage ModuleSancov(Options); + return ModuleSancov.instrumentModule(M); + }; + + StringRef getPassName() const override { + return "ModuleSanitizerCoverageLegacyPass"; } private: + SanitizerCoverageOptions Options; +}; + +char ModuleSanitizerCoverageLegacyPass::ID = 0; + +class SanitizerCoverage { +public: + SanitizerCoverage(Function &F, const SanitizerCoverageOptions &Options) + : CurModule(F.getParent()), Options(OverrideFromCL(Options)) { + initializeModule(*F.getParent()); + } + + ~SanitizerCoverage() { finalizeModule(*CurModule); } + + bool instrumentFunction(Function &F, const DominatorTree *DT, + const PostDominatorTree *PDT); + +private: + void initializeModule(Module &M); + void finalizeModule(Module &M); void InjectCoverageForIndirectCalls(Function &F, ArrayRef IndirCalls); void InjectTraceForCmp(Function &F, ArrayRef CmpTraceTargets); @@ -212,11 +357,6 @@ private: void CreateFunctionLocalArrays(Function &F, ArrayRef AllBlocks); void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx, bool IsLeafFunc = true); - Function *CreateInitCallsForSections(Module &M, const char *CtorName, - const char *InitFunctionName, Type *Ty, - const char *Section); - std::pair CreateSecStartEnd(Module &M, const char *Section, - Type *Ty); void SetNoSanitizeMetadata(Instruction *I) { I->setMetadata(I->getModule()->getMDKindID("nosanitize"), @@ -252,10 +392,63 @@ private: SanitizerCoverageOptions Options; }; +class SanitizerCoverageLegacyPass : public FunctionPass { +public: + static char ID; // Pass identification, replacement for typeid + + SanitizerCoverageLegacyPass( + SanitizerCoverageOptions Options = SanitizerCoverageOptions()) + : FunctionPass(ID), Options(Options) { + initializeSanitizerCoverageLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override { + const DominatorTree *DT = + &getAnalysis().getDomTree(); + const PostDominatorTree *PDT = + &getAnalysis().getPostDomTree(); + SanitizerCoverage Sancov(F, Options); + return Sancov.instrumentFunction(F, DT, PDT); + } + + StringRef getPassName() const override { + return "SanitizerCoverageLegacyPass"; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + // Make the module sancov pass required by this pass so that it runs when + // -sancov is passed. + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + } + +private: + SanitizerCoverageOptions Options; +}; + } // namespace +PreservedAnalyses SanitizerCoveragePass::run(Function &F, + FunctionAnalysisManager &AM) { + const DominatorTree *DT = &AM.getResult(F); + const PostDominatorTree *PDT = &AM.getResult(F); + SanitizerCoverage Sancov(F, Options); + if (Sancov.instrumentFunction(F, DT, PDT)) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); +} + +PreservedAnalyses ModuleSanitizerCoveragePass::run(Module &M, + ModuleAnalysisManager &AM) { + ModuleSanitizerCoverage ModuleSancov(Options); + if (ModuleSancov.instrumentModule(M)) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); +} + std::pair -SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section, +ModuleSanitizerCoverage::CreateSecStartEnd(Module &M, const char *Section, Type *Ty) { GlobalVariable *SecStart = new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr, @@ -265,6 +458,7 @@ SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section, new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr, getSectionEnd(Section)); SecEnd->setVisibility(GlobalValue::HiddenVisibility); + IRBuilder<> IRB(M.getContext()); Value *SecEndPtr = IRB.CreatePointerCast(SecEnd, Ty); if (!TargetTriple.isOSBinFormatCOFF()) @@ -278,7 +472,7 @@ SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section, return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEndPtr); } -Function *SanitizerCoverageModule::CreateInitCallsForSections( +Function *ModuleSanitizerCoverage::CreateInitCallsForSections( Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty, const char *Section) { auto SecStartEnd = CreateSecStartEnd(M, Section, Ty); @@ -310,12 +504,11 @@ Function *SanitizerCoverageModule::CreateInitCallsForSections( return CtorFunc; } -bool SanitizerCoverageModule::runOnModule(Module &M) { +void SanitizerCoverage::initializeModule(Module &M) { if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) - return false; + return; C = &(M.getContext()); DL = &M.getDataLayout(); - CurModule = &M; CurModuleUniqueId = getUniqueModuleId(CurModule); TargetTriple = Triple(M.getTargetTriple()); FunctionGuardArray = nullptr; @@ -383,11 +576,6 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { Constant *SanCovLowestStackConstant = M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy); SanCovLowestStack = dyn_cast(SanCovLowestStackConstant); - if (!SanCovLowestStack) { - C->emitError(StringRef("'") + SanCovLowestStackName + - "' should not be declared by the user"); - return true; - } SanCovLowestStack->setThreadLocalMode( GlobalValue::ThreadLocalMode::InitialExecTLSModel); if (Options.StackDepth && !SanCovLowestStack->isDeclaration()) @@ -401,33 +589,14 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy); SanCovTracePCGuard = M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy); +} - for (auto &F : M) - runOnFunction(F); - - Function *Ctor = nullptr; - - if (FunctionGuardArray) - Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName, - SanCovTracePCGuardInitName, Int32PtrTy, - SanCovGuardsSectionName); - if (Function8bitCounterArray) - Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName, - SanCov8bitCountersInitName, Int8PtrTy, - SanCovCountersSectionName); - if (Ctor && Options.PCTable) { - auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy); - FunctionCallee InitFunction = declareSanitizerInitFunction( - M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy}); - IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); - IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); - } +void SanitizerCoverage::finalizeModule(Module &M) { // We don't reference these arrays directly in any of our runtime functions, // so we need to prevent them from being dead stripped. if (TargetTriple.isOSBinFormatMachO()) appendToUsed(M, GlobalsToAppendToUsed); appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed); - return true; } // True if block has successors and it dominates all of them. @@ -518,28 +687,11 @@ static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT, return true; } -bool SanitizerCoverageModule::runOnFunction(Function &F) { - if (F.empty()) - return false; - if (F.getName().find(".module_ctor") != std::string::npos) - return false; // Should not instrument sanitizer init functions. - if (F.getName().startswith("__sanitizer_")) - return false; // Don't instrument __sanitizer_* callbacks. - // Don't touch available_externally functions, their actual body is elewhere. - if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) - return false; - // Don't instrument MSVC CRT configuration helpers. They may run before normal - // initialization. - if (F.getName() == "__local_stdio_printf_options" || - F.getName() == "__local_stdio_scanf_options") +bool SanitizerCoverage::instrumentFunction(Function &F, const DominatorTree *DT, + const PostDominatorTree *PDT) { + if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; - if (isa(F.getEntryBlock().getTerminator())) - return false; - // Don't instrument functions using SEH for now. Splitting basic blocks like - // we do for coverage breaks WinEHPrepare. - // FIXME: Remove this when SEH no longer uses landingpad pattern matching. - if (F.hasPersonalityFn() && - isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) + if (!canInstrumentWithSancov(F)) return false; if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); @@ -550,10 +702,6 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) { SmallVector DivTraceTargets; SmallVector GepTraceTargets; - const DominatorTree *DT = - &getAnalysis(F).getDomTree(); - const PostDominatorTree *PDT = - &getAnalysis(F).getPostDomTree(); bool IsLeafFunc = true; for (auto &BB : F) { @@ -596,7 +744,7 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) { return true; } -GlobalVariable *SanitizerCoverageModule::CreateFunctionLocalArrayInSection( +GlobalVariable *SanitizerCoverage::CreateFunctionLocalArrayInSection( size_t NumElements, Function &F, Type *Ty, const char *Section) { ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); auto Array = new GlobalVariable( @@ -619,8 +767,8 @@ GlobalVariable *SanitizerCoverageModule::CreateFunctionLocalArrayInSection( } GlobalVariable * -SanitizerCoverageModule::CreatePCArray(Function &F, - ArrayRef AllBlocks) { +SanitizerCoverage::CreatePCArray(Function &F, + ArrayRef AllBlocks) { size_t N = AllBlocks.size(); assert(N); SmallVector PCs; @@ -646,7 +794,7 @@ SanitizerCoverageModule::CreatePCArray(Function &F, return PCArray; } -void SanitizerCoverageModule::CreateFunctionLocalArrays( +void SanitizerCoverage::CreateFunctionLocalArrays( Function &F, ArrayRef AllBlocks) { if (Options.TracePCGuard) FunctionGuardArray = CreateFunctionLocalArrayInSection( @@ -660,9 +808,9 @@ void SanitizerCoverageModule::CreateFunctionLocalArrays( FunctionPCsArray = CreatePCArray(F, AllBlocks); } -bool SanitizerCoverageModule::InjectCoverage(Function &F, - ArrayRef AllBlocks, - bool IsLeafFunc) { +bool SanitizerCoverage::InjectCoverage(Function &F, + ArrayRef AllBlocks, + bool IsLeafFunc) { if (AllBlocks.empty()) return false; CreateFunctionLocalArrays(F, AllBlocks); for (size_t i = 0, N = AllBlocks.size(); i < N; i++) @@ -677,7 +825,7 @@ bool SanitizerCoverageModule::InjectCoverage(Function &F, // The cache is used to speed up recording the caller-callee pairs. // The address of the caller is passed implicitly via caller PC. // CacheSize is encoded in the name of the run-time function. -void SanitizerCoverageModule::InjectCoverageForIndirectCalls( +void SanitizerCoverage::InjectCoverageForIndirectCalls( Function &F, ArrayRef IndirCalls) { if (IndirCalls.empty()) return; @@ -696,7 +844,7 @@ void SanitizerCoverageModule::InjectCoverageForIndirectCalls( // __sanitizer_cov_trace_switch(CondValue, // {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... }) -void SanitizerCoverageModule::InjectTraceForSwitch( +void SanitizerCoverage::InjectTraceForSwitch( Function &, ArrayRef SwitchTraceTargets) { for (auto I : SwitchTraceTargets) { if (SwitchInst *SI = dyn_cast(I)) { @@ -735,7 +883,7 @@ void SanitizerCoverageModule::InjectTraceForSwitch( } } -void SanitizerCoverageModule::InjectTraceForDiv( +void SanitizerCoverage::InjectTraceForDiv( Function &, ArrayRef DivTraceTargets) { for (auto BO : DivTraceTargets) { IRBuilder<> IRB(BO); @@ -753,7 +901,7 @@ void SanitizerCoverageModule::InjectTraceForDiv( } } -void SanitizerCoverageModule::InjectTraceForGep( +void SanitizerCoverage::InjectTraceForGep( Function &, ArrayRef GepTraceTargets) { for (auto GEP : GepTraceTargets) { IRBuilder<> IRB(GEP); @@ -764,7 +912,7 @@ void SanitizerCoverageModule::InjectTraceForGep( } } -void SanitizerCoverageModule::InjectTraceForCmp( +void SanitizerCoverage::InjectTraceForCmp( Function &, ArrayRef CmpTraceTargets) { for (auto I : CmpTraceTargets) { if (ICmpInst *ICMP = dyn_cast(I)) { @@ -799,9 +947,8 @@ void SanitizerCoverageModule::InjectTraceForCmp( } } -void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, - size_t Idx, - bool IsLeafFunc) { +void SanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, + size_t Idx, bool IsLeafFunc) { BasicBlock::iterator IP = BB.getFirstInsertionPt(); bool IsEntryBB = &BB == &F.getEntryBlock(); DebugLoc EntryLoc; @@ -858,7 +1005,7 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } std::string -SanitizerCoverageModule::getSectionName(const std::string &Section) const { +SanitizerCoverage::getSectionName(const std::string &Section) const { if (TargetTriple.isOSBinFormatCOFF()) { if (Section == SanCovCountersSectionName) return ".SCOV$CM"; @@ -872,32 +1019,33 @@ SanitizerCoverageModule::getSectionName(const std::string &Section) const { } std::string -SanitizerCoverageModule::getSectionStart(const std::string &Section) const { - if (TargetTriple.isOSBinFormatMachO()) - return "\1section$start$__DATA$__" + Section; - return "__start___" + Section; +SanitizerCoverage::getSectionStart(const std::string &Section) const { + return getSectionStartImpl(TargetTriple, Section); } -std::string -SanitizerCoverageModule::getSectionEnd(const std::string &Section) const { - if (TargetTriple.isOSBinFormatMachO()) - return "\1section$end$__DATA$__" + Section; - return "__stop___" + Section; +std::string SanitizerCoverage::getSectionEnd(const std::string &Section) const { + return getSectionEndImpl(TargetTriple, Section); } +INITIALIZE_PASS(ModuleSanitizerCoverageLegacyPass, "module-sancov", + "Pass for inserting sancov top-level initialization calls", + false, false) -char SanitizerCoverageModule::ID = 0; -INITIALIZE_PASS_BEGIN(SanitizerCoverageModule, "sancov", - "SanitizerCoverage: TODO." - "ModulePass", - false, false) +char SanitizerCoverageLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(SanitizerCoverageLegacyPass, "sancov", + "Pass for instrumenting coverage on functions", false, + false) +INITIALIZE_PASS_DEPENDENCY(ModuleSanitizerCoverageLegacyPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) -INITIALIZE_PASS_END(SanitizerCoverageModule, "sancov", - "SanitizerCoverage: TODO." - "ModulePass", - false, false) -ModulePass *llvm::createSanitizerCoverageModulePass( +INITIALIZE_PASS_END(SanitizerCoverageLegacyPass, "sancov", + "Pass for instrumenting coverage on functions", false, + false) +FunctionPass *llvm::createSanitizerCoverageLegacyPassPass( + const SanitizerCoverageOptions &Options) { + return new SanitizerCoverageLegacyPass(Options); +} +ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( const SanitizerCoverageOptions &Options) { - return new SanitizerCoverageModule(Options); + return new ModuleSanitizerCoverageLegacyPass(Options); } diff --git a/test/Instrumentation/SanitizerCoverage/abort-in-entry-block.ll b/test/Instrumentation/SanitizerCoverage/abort-in-entry-block.ll index 9bc8acef481..5711669240c 100644 --- a/test/Instrumentation/SanitizerCoverage/abort-in-entry-block.ll +++ b/test/Instrumentation/SanitizerCoverage/abort-in-entry-block.ll @@ -1,5 +1,6 @@ ; Checks that a function with no-return in the entry block is not instrumented. ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s ; CHECK-NOT: call void @__sanitizer_cov_trace_pc_guard target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/test/Instrumentation/SanitizerCoverage/backedge-pruning.ll b/test/Instrumentation/SanitizerCoverage/backedge-pruning.ll index 10319831127..5e9e579e171 100644 --- a/test/Instrumentation/SanitizerCoverage/backedge-pruning.ll +++ b/test/Instrumentation/SanitizerCoverage/backedge-pruning.ll @@ -1,6 +1,8 @@ ; Test -sanitizer-coverage-trace-compares=1 and how it prunes backedge compares. ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=PRUNE ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=NOPRUNE +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=PRUNE +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=NOPRUNE target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/chains.ll b/test/Instrumentation/SanitizerCoverage/chains.ll index 86b109165ee..7618267069a 100644 --- a/test/Instrumentation/SanitizerCoverage/chains.ll +++ b/test/Instrumentation/SanitizerCoverage/chains.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s define i32 @blah(i32) #0 { %2 = icmp sgt i32 %0, 1 diff --git a/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll b/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll index 0f42756fdcb..976bc77beb6 100644 --- a/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll +++ b/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll @@ -1,5 +1,6 @@ ; Test -sanitizer-coverage-trace-compares=1 API declarations on a non-x86_64 arch ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s target triple = "i386-unknown-linux-gnu" define i32 @foo() #0 { @@ -7,16 +8,16 @@ entry: ret i32 0 } -; CHECK: declare void @__sanitizer_cov_trace_pc_indir(i64) -; CHECK: declare void @__sanitizer_cov_trace_cmp1(i8, i8) -; CHECK: declare void @__sanitizer_cov_trace_cmp2(i16, i16) -; CHECK: declare void @__sanitizer_cov_trace_cmp4(i32, i32) -; CHECK: declare void @__sanitizer_cov_trace_cmp8(i64, i64) -; CHECK: declare void @__sanitizer_cov_trace_div4(i32) -; CHECK: declare void @__sanitizer_cov_trace_div8(i64) -; CHECK: declare void @__sanitizer_cov_trace_gep(i64) -; CHECK: declare void @__sanitizer_cov_trace_switch(i64, i64*) -; CHECK: declare void @__sanitizer_cov_trace_pc() -; CHECK: declare void @__sanitizer_cov_trace_pc_guard(i32*) -; CHECK: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*) +; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_indir(i64) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp1(i8, i8) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp2(i16, i16) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp4(i32, i32) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp8(i64, i64) +; CHECK-DAG: declare void @__sanitizer_cov_trace_div4(i32) +; CHECK-DAG: declare void @__sanitizer_cov_trace_div8(i64) +; CHECK-DAG: declare void @__sanitizer_cov_trace_gep(i64) +; CHECK-DAG: declare void @__sanitizer_cov_trace_switch(i64, i64*) +; CHECK-DAG: declare void @__sanitizer_cov_trace_pc() +; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard(i32*) +; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*) ; CHECK-NOT: declare diff --git a/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_64.ll b/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_64.ll index 16689f9831d..165bf744432 100644 --- a/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_64.ll +++ b/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_64.ll @@ -1,5 +1,6 @@ ; Test -sanitizer-coverage-trace-compares=1 API declarations on x86_64 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s target triple = "x86_64-unknown-linux-gnu" define i32 @foo() #0 { @@ -7,16 +8,16 @@ entry: ret i32 0 } -; CHECK: declare void @__sanitizer_cov_trace_pc_indir(i64) -; CHECK: declare void @__sanitizer_cov_trace_cmp1(i8 zeroext, i8 zeroext) -; CHECK: declare void @__sanitizer_cov_trace_cmp2(i16 zeroext, i16 zeroext) -; CHECK: declare void @__sanitizer_cov_trace_cmp4(i32 zeroext, i32 zeroext) -; CHECK: declare void @__sanitizer_cov_trace_cmp8(i64, i64) -; CHECK: declare void @__sanitizer_cov_trace_div4(i32 zeroext) -; CHECK: declare void @__sanitizer_cov_trace_div8(i64) -; CHECK: declare void @__sanitizer_cov_trace_gep(i64) -; CHECK: declare void @__sanitizer_cov_trace_switch(i64, i64*) -; CHECK: declare void @__sanitizer_cov_trace_pc() -; CHECK: declare void @__sanitizer_cov_trace_pc_guard(i32*) -; CHECK: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*) +; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_indir(i64) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp1(i8 zeroext, i8 zeroext) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp2(i16 zeroext, i16 zeroext) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp4(i32 zeroext, i32 zeroext) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp8(i64, i64) +; CHECK-DAG: declare void @__sanitizer_cov_trace_div4(i32 zeroext) +; CHECK-DAG: declare void @__sanitizer_cov_trace_div8(i64) +; CHECK-DAG: declare void @__sanitizer_cov_trace_gep(i64) +; CHECK-DAG: declare void @__sanitizer_cov_trace_switch(i64, i64*) +; CHECK-DAG: declare void @__sanitizer_cov_trace_pc() +; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard(i32*) +; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*) ; CHECK-NOT: declare diff --git a/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll b/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll index fda6f251bc8..c599806454d 100644 --- a/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll +++ b/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll @@ -1,5 +1,6 @@ ; Test -sanitizer-coverage-trace-compares=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/coff-comdat.ll b/test/Instrumentation/SanitizerCoverage/coff-comdat.ll index 61a9dcd92de..d6019cb50a4 100644 --- a/test/Instrumentation/SanitizerCoverage/coff-comdat.ll +++ b/test/Instrumentation/SanitizerCoverage/coff-comdat.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s ; Make sure we use the right comdat groups for COFF to avoid relocations ; against discarded sections. Internal linkage functions are also different from diff --git a/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-8bit-counters.ll b/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-8bit-counters.ll index d81d480009b..31a2dd39c6d 100644 --- a/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-8bit-counters.ll +++ b/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-8bit-counters.ll @@ -1,5 +1,6 @@ ; Checks that the PC and 8-bit Counter Arrays are placed in their own sections in COFF binaries. ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc19.14.26433" diff --git a/test/Instrumentation/SanitizerCoverage/coff-used-ctor.ll b/test/Instrumentation/SanitizerCoverage/coff-used-ctor.ll index fd12eed8e36..f412d2f237d 100644 --- a/test/Instrumentation/SanitizerCoverage/coff-used-ctor.ll +++ b/test/Instrumentation/SanitizerCoverage/coff-used-ctor.ll @@ -1,5 +1,6 @@ ; Checks that sancov.module_ctor is marked used. ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc19.14.26433" @@ -8,4 +9,4 @@ entry: ret void } -; CHECK: @llvm.used = appending global {{.*}} @sancov.module_ctor \ No newline at end of file +; CHECK: @llvm.used = appending global {{.*}} @sancov.module_ctor diff --git a/test/Instrumentation/SanitizerCoverage/const-cmp-tracing.ll b/test/Instrumentation/SanitizerCoverage/const-cmp-tracing.ll index b61b4eef5df..0ee1a339ee5 100644 --- a/test/Instrumentation/SanitizerCoverage/const-cmp-tracing.ll +++ b/test/Instrumentation/SanitizerCoverage/const-cmp-tracing.ll @@ -1,5 +1,6 @@ ; Test -sanitizer-coverage-trace-compares=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/coverage-dbg.ll b/test/Instrumentation/SanitizerCoverage/coverage-dbg.ll index 09e23372533..03be088bfd8 100644 --- a/test/Instrumentation/SanitizerCoverage/coverage-dbg.ll +++ b/test/Instrumentation/SanitizerCoverage/coverage-dbg.ll @@ -1,6 +1,7 @@ ; Test that coverage instrumentation does not lose debug location. ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -S | FileCheck %s ; C++ source: ; 1: struct A { diff --git a/test/Instrumentation/SanitizerCoverage/coverage.ll b/test/Instrumentation/SanitizerCoverage/coverage.ll index 7b6b5f00442..1e8c6982753 100644 --- a/test/Instrumentation/SanitizerCoverage/coverage.ll +++ b/test/Instrumentation/SanitizerCoverage/coverage.ll @@ -1,7 +1,9 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC - ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=CHECKPRUNE +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=CHECKPRUNE + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" define void @foo(i32* %a) sanitize_address { diff --git a/test/Instrumentation/SanitizerCoverage/coverage2-dbg.ll b/test/Instrumentation/SanitizerCoverage/coverage2-dbg.ll index 508657a5976..428a7d735c5 100644 --- a/test/Instrumentation/SanitizerCoverage/coverage2-dbg.ll +++ b/test/Instrumentation/SanitizerCoverage/coverage2-dbg.ll @@ -1,6 +1,7 @@ ; Test that coverage instrumentation does not lose debug location. ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=2 -S | FileCheck %s ; C++ source: ; 1: void foo(int *a) { diff --git a/test/Instrumentation/SanitizerCoverage/div-tracing.ll b/test/Instrumentation/SanitizerCoverage/div-tracing.ll index 0de2ddf68e7..e52366707b7 100644 --- a/test/Instrumentation/SanitizerCoverage/div-tracing.ll +++ b/test/Instrumentation/SanitizerCoverage/div-tracing.ll @@ -1,5 +1,6 @@ ; Test -sanitizer-coverage-trace-divs=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-divs=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-divs=1 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/gep-tracing.ll b/test/Instrumentation/SanitizerCoverage/gep-tracing.ll index ac6af4b3720..924c2fe3eb3 100644 --- a/test/Instrumentation/SanitizerCoverage/gep-tracing.ll +++ b/test/Instrumentation/SanitizerCoverage/gep-tracing.ll @@ -1,5 +1,6 @@ ; Test -sanitizer-coverage-trace-geps=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-geps=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-geps=1 -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll b/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll index 88141678b6c..d4e30aab54e 100644 --- a/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll +++ b/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll @@ -1,5 +1,6 @@ ; Test -sanitizer-coverage-inline-8bit-counters=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/interposable-symbol-nocomdat.ll b/test/Instrumentation/SanitizerCoverage/interposable-symbol-nocomdat.ll index c79a2fb5fff..e73f1516fa1 100644 --- a/test/Instrumentation/SanitizerCoverage/interposable-symbol-nocomdat.ll +++ b/test/Instrumentation/SanitizerCoverage/interposable-symbol-nocomdat.ll @@ -1,6 +1,8 @@ ; Test that interposable symbols do not get put in comdats. ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-linux-gnu -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-windows-msvc -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-linux-gnu -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-windows-msvc -S | FileCheck %s define void @Vanilla() { entry: diff --git a/test/Instrumentation/SanitizerCoverage/no-func.ll b/test/Instrumentation/SanitizerCoverage/no-func.ll index ec9e1214391..683238c33c8 100644 --- a/test/Instrumentation/SanitizerCoverage/no-func.ll +++ b/test/Instrumentation/SanitizerCoverage/no-func.ll @@ -1,6 +1,7 @@ ; Tests that we don't insert __sanitizer_cov_trace_pc_guard_init or some such ; when there is no instrumentation. ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/pc-table.ll b/test/Instrumentation/SanitizerCoverage/pc-table.ll index 888277a4c50..f8e2a3015ba 100644 --- a/test/Instrumentation/SanitizerCoverage/pc-table.ll +++ b/test/Instrumentation/SanitizerCoverage/pc-table.ll @@ -1,6 +1,8 @@ ; Test -sanitizer-coverage-pc-table=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/postdominator_check.ll b/test/Instrumentation/SanitizerCoverage/postdominator_check.ll index c50d663eff8..ebcf3b276c9 100644 --- a/test/Instrumentation/SanitizerCoverage/postdominator_check.ll +++ b/test/Instrumentation/SanitizerCoverage/postdominator_check.ll @@ -1,5 +1,7 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=CHECK_NO_PRUNE +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=CHECK_NO_PRUNE define i32 @foo(i32) #0 { %2 = icmp sgt i32 %0, 0 diff --git a/test/Instrumentation/SanitizerCoverage/seh.ll b/test/Instrumentation/SanitizerCoverage/seh.ll index 94d1a2e9acd..b45f1e02ddd 100644 --- a/test/Instrumentation/SanitizerCoverage/seh.ll +++ b/test/Instrumentation/SanitizerCoverage/seh.ll @@ -1,6 +1,9 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=0 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=0 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=2 -S | FileCheck %s target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" target triple = "i686-pc-windows-msvc18.0.0" diff --git a/test/Instrumentation/SanitizerCoverage/stack-depth-variable-declared-by-user.ll b/test/Instrumentation/SanitizerCoverage/stack-depth-variable-declared-by-user.ll index 1ad96f82a69..ff14bff1b7f 100644 --- a/test/Instrumentation/SanitizerCoverage/stack-depth-variable-declared-by-user.ll +++ b/test/Instrumentation/SanitizerCoverage/stack-depth-variable-declared-by-user.ll @@ -2,6 +2,8 @@ ; user declares `__sancov_lowest_stack` with an unexpected type. ; RUN: not opt < %s -sancov -sanitizer-coverage-level=1 \ ; RUN: -sanitizer-coverage-stack-depth -S 2>&1 | FileCheck %s +; RUN: not opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 \ +; RUN: -sanitizer-coverage-stack-depth -S 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/stack-depth.ll b/test/Instrumentation/SanitizerCoverage/stack-depth.ll index 0c6db1a922a..9deb2f04d78 100644 --- a/test/Instrumentation/SanitizerCoverage/stack-depth.ll +++ b/test/Instrumentation/SanitizerCoverage/stack-depth.ll @@ -4,6 +4,11 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 \ ; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \ ; RUN: -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 \ +; RUN: -sanitizer-coverage-stack-depth -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 \ +; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \ +; RUN: -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/switch-tracing.ll b/test/Instrumentation/SanitizerCoverage/switch-tracing.ll index debb825db1b..b109d80ff68 100644 --- a/test/Instrumentation/SanitizerCoverage/switch-tracing.ll +++ b/test/Instrumentation/SanitizerCoverage/switch-tracing.ll @@ -1,5 +1,6 @@ ; Test -sanitizer-coverage-trace-compares=1 (instrumenting a switch) ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/trace-pc-guard-comdat.ll b/test/Instrumentation/SanitizerCoverage/trace-pc-guard-comdat.ll index 970ee0d3ac2..e6633e1c3ff 100644 --- a/test/Instrumentation/SanitizerCoverage/trace-pc-guard-comdat.ll +++ b/test/Instrumentation/SanitizerCoverage/trace-pc-guard-comdat.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-8bit-counters.ll b/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-8bit-counters.ll index d5c9ff451ab..06cd192a829 100644 --- a/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-8bit-counters.ll +++ b/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-8bit-counters.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-8bit-counters -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-8bit-counters -S | FileCheck %s ; Module ctors should have stable names across modules, not something like ; @sancov.module_ctor.3 that may cause duplicate ctors after linked together. diff --git a/test/Instrumentation/SanitizerCoverage/trace-pc-guard-nocomdat.ll b/test/Instrumentation/SanitizerCoverage/trace-pc-guard-nocomdat.ll index 1fe1886975e..006c662f144 100644 --- a/test/Instrumentation/SanitizerCoverage/trace-pc-guard-nocomdat.ll +++ b/test/Instrumentation/SanitizerCoverage/trace-pc-guard-nocomdat.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-darwin10.0.0" diff --git a/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll b/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll index baf4dc1e140..012a19ba17f 100644 --- a/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll +++ b/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll @@ -2,6 +2,9 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s ; Make sure asan does not instrument __sancov_gen_ ; RUN: opt < %s -sancov -asan -asan-module -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s + +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s +; RUN: opt < %s -passes='module(require,sancov-module,asan-module),function(sancov-func,asan)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" $Foo = comdat any diff --git a/test/Instrumentation/SanitizerCoverage/tracing.ll b/test/Instrumentation/SanitizerCoverage/tracing.ll index 7bf8cf7e18e..c27fd0eac0b 100644 --- a/test/Instrumentation/SanitizerCoverage/tracing.ll +++ b/test/Instrumentation/SanitizerCoverage/tracing.ll @@ -3,6 +3,10 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_PC_GUARD ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S -mtriple=x86_64-apple-macosx | FileCheck %s --check-prefix=CHECK_PC_GUARD_DARWIN +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_PC +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_PC_GUARD +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S -mtriple=x86_64-apple-macosx | FileCheck %s --check-prefix=CHECK_PC_GUARD_DARWIN + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" define void @foo(i32* %a) sanitize_address { diff --git a/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll b/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll index ad6cd574d7e..e3e31086ccb 100644 --- a/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll +++ b/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -S -sancov -sanitizer-coverage-level=3 | FileCheck %s +; RUN: opt < %s -S -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 | FileCheck %s ; The critical edges to unreachable_bb should not be split. define i32 @foo(i32 %c, i32 %d) { diff --git a/test/Instrumentation/SanitizerCoverage/wineh.ll b/test/Instrumentation/SanitizerCoverage/wineh.ll index 87b44be5544..350242bb301 100644 --- a/test/Instrumentation/SanitizerCoverage/wineh.ll +++ b/test/Instrumentation/SanitizerCoverage/wineh.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK +; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK ; Generated from this C++ source: ; $ clang -O2 t.cpp -S -emit-llvm