Index: include/llvm/IR/AddressSanitizerPass.h =================================================================== --- /dev/null +++ include/llvm/IR/AddressSanitizerPass.h @@ -0,0 +1,52 @@ +//===--------- Definition of the AddressSanitizer class ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the AddressSanitizer class which is a port of the legacy +// AddressSanitizer pass to use the new PassManager infrastructure. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_IR_ADDRESSSANITIZERNEWPASS_H +#define LLVM_IR_ADDRESSSANITIZERNEWPASS_H + +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" + +namespace llvm { + +class AddressSanitizerPass : public PassInfoMixin { +public: + explicit AddressSanitizerPass(bool CompileKernel = false, + bool Recover = false, + bool UseAfterScope = false); + PreservedAnalyses run(Function &F, AnalysisManager &AM); + +private: + bool CompileKernel; + bool Recover; + bool UseAfterScope; +}; + +class AddressSanitizerModulePass + : public PassInfoMixin { +public: + explicit AddressSanitizerModulePass(bool CompileKernel = false, + bool Recover = false, + bool UseAfterScope = true); + PreservedAnalyses run(Module &M, AnalysisManager &AM); + +private: + bool CompileKernel; + bool Recover; + bool UseAfterScope; +}; + +} // namespace llvm + +#endif Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -65,8 +65,8 @@ void initializeAAResultsWrapperPassPass(PassRegistry&); void initializeADCELegacyPassPass(PassRegistry&); void initializeAddDiscriminatorsLegacyPassPass(PassRegistry&); -void initializeAddressSanitizerModulePass(PassRegistry&); -void initializeAddressSanitizerPass(PassRegistry&); +void initializeAddressSanitizerModuleLegacyPassPass(PassRegistry &); +void initializeAddressSanitizerLegacyPassPass(PassRegistry &); void initializeAggressiveInstCombinerLegacyPassPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlignmentFromAssumptionsPass(PassRegistry&); Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -53,6 +53,7 @@ #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/CodeGen/PreISelIntrinsicLowering.h" #include "llvm/CodeGen/UnreachableBlockElim.h" +#include "llvm/IR/AddressSanitizerPass.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/PassManager.h" Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -40,6 +40,7 @@ #define MODULE_PASS(NAME, CREATE_PASS) #endif MODULE_PASS("always-inline", AlwaysInlinerPass()) +MODULE_PASS("asan-module", AddressSanitizerModulePass()) MODULE_PASS("called-value-propagation", CalledValuePropagationPass()) MODULE_PASS("cg-profile", CGProfilePass()) MODULE_PASS("constmerge", ConstantMergePass()) @@ -147,6 +148,7 @@ FUNCTION_PASS("add-discriminators", AddDiscriminatorsPass()) FUNCTION_PASS("aggressive-instcombine", AggressiveInstCombinePass()) FUNCTION_PASS("alignment-from-assumptions", AlignmentFromAssumptionsPass()) +FUNCTION_PASS("asan", AddressSanitizerPass()) FUNCTION_PASS("bdce", BDCEPass()) FUNCTION_PASS("bounds-checking", BoundsCheckingPass()) FUNCTION_PASS("break-crit-edges", BreakCriticalEdgesPass()) Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -25,9 +25,9 @@ #include "llvm/ADT/Twine.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/IR/AddressSanitizerPass.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" @@ -72,6 +72,7 @@ #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Utils/ASanStackFrameLayout.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" #include @@ -597,26 +598,21 @@ namespace { /// AddressSanitizer: instrument the code in module to find memory bugs. -struct AddressSanitizer : public FunctionPass { - // Pass identification, replacement for typeid - static char ID; - - explicit AddressSanitizer(bool CompileKernel = false, bool Recover = false, - bool UseAfterScope = false) - : FunctionPass(ID), UseAfterScope(UseAfterScope || ClUseAfterScope) { +struct AddressSanitizer { + explicit AddressSanitizer(Module &M, bool CompileKernel = false, + bool Recover = false, bool UseAfterScope = false) + : UseAfterScope(UseAfterScope || ClUseAfterScope) { this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; this->CompileKernel = ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan : CompileKernel; - initializeAddressSanitizerPass(*PassRegistry::getPassRegistry()); - } - - StringRef getPassName() const override { - return "AddressSanitizerFunctionPass"; - } - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); - AU.addRequired(); + // Initialize the private fields. No one has accessed them before. + GlobalsMD.init(M); + C = &(M.getContext()); + LongSize = M.getDataLayout().getPointerSizeInBits(); + IntptrTy = Type::getIntNTy(*C, LongSize); + TargetTriple = Triple(M.getTargetTriple()); + Mapping = getShadowMapping(TargetTriple, LongSize, CompileKernel); } uint64_t getAllocaSizeInBytes(const AllocaInst &AI) const { @@ -661,12 +657,13 @@ Value *SizeArgument, uint32_t Exp); void instrumentMemIntrinsic(MemIntrinsic *MI); Value *memToShadow(Value *Shadow, IRBuilder<> &IRB); - bool runOnFunction(Function &F) override; bool maybeInsertAsanInitAtFunctionEntry(Function &F); void maybeInsertDynamicShadowAtFunctionEntry(Function &F); void markEscapedLocalAllocas(Function &F); - bool doInitialization(Module &M) override; - bool doFinalization(Module &M) override; + + /// Return true if the function changed. + bool instrument(Function &F, DominatorTree *DTree, + const TargetLibraryInfo *TLI); DominatorTree &getDominatorTree() const { return *DT; } @@ -724,16 +721,12 @@ DenseMap ProcessedAllocas; }; -class AddressSanitizerModule : public ModulePass { +class AddressSanitizerModule { public: - // Pass identification, replacement for typeid - static char ID; - explicit AddressSanitizerModule(bool CompileKernel = false, bool Recover = false, bool UseGlobalsGC = true) - : ModulePass(ID), - UseGlobalsGC(UseGlobalsGC && ClUseGlobalsGC), + : UseGlobalsGC(UseGlobalsGC && ClUseGlobalsGC), // Not a typo: ClWithComdat is almost completely pointless without // ClUseGlobalsGC (because then it only works on modules without // globals, which are rare); it is a prerequisite for ClUseGlobalsGC; @@ -742,14 +735,12 @@ // ClWithComdat and ClUseGlobalsGC unless the frontend says it's ok to // do globals-gc. UseCtorComdat(UseGlobalsGC && ClWithComdat) { - this->Recover = ClRecover.getNumOccurrences() > 0 ? - ClRecover : Recover; - this->CompileKernel = ClEnableKasan.getNumOccurrences() > 0 ? - ClEnableKasan : CompileKernel; - } + this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; + this->CompileKernel = + ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan : CompileKernel; + } - bool runOnModule(Module &M) override; - StringRef getPassName() const override { return "AddressSanitizerModule"; } + bool instrument(Module &M); private: void initializeCallbacks(Module &M); @@ -1057,18 +1048,106 @@ Instruction *ThenTerm, Value *ValueIfFalse); }; +class AddressSanitizerLegacyPass : public FunctionPass { +public: + static char ID; + + explicit AddressSanitizerLegacyPass(bool CompileKernel = false, + bool Recover = false, + bool UseAfterScope = false) + : FunctionPass(ID), CompileKernel(CompileKernel), Recover(Recover), + UseAfterScope(UseAfterScope) {} + + StringRef getPassName() const override { + return "AddressSanitizerFunctionPass"; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + AU.addRequired(); + } + + bool runOnFunction(Function &F) override { + DominatorTree *DTree = + &getAnalysis().getDomTree(); + const TargetLibraryInfo *TLI = + &getAnalysis().getTLI(); + AddressSanitizer Sanitizer(*F.getParent(), CompileKernel, Recover, + UseAfterScope); + return Sanitizer.instrument(F, DTree, TLI); + } + +private: + bool CompileKernel; + bool Recover; + bool UseAfterScope; +}; + +class AddressSanitizerModuleLegacyPass : public ModulePass { +public: + static char ID; + + explicit AddressSanitizerModuleLegacyPass(bool CompileKernel = false, + bool Recover = false, + bool UseAfterScope = true) + : ModulePass(ID), CompileKernel(CompileKernel), Recover(Recover), + UseAfterScope(UseAfterScope) {} + + StringRef getPassName() const override { return "AddressSanitizerModule"; } + + bool runOnModule(Module &M) override { + AddressSanitizerModule Sanitizer(CompileKernel, Recover, UseAfterScope); + return Sanitizer.instrument(M); + } + +private: + bool CompileKernel; + bool Recover; + bool UseAfterScope; +}; + } // end anonymous namespace -char AddressSanitizer::ID = 0; +AddressSanitizerPass::AddressSanitizerPass(bool CompileKernel, bool Recover, + bool UseAfterScope) + : CompileKernel(CompileKernel), Recover(Recover), + UseAfterScope(UseAfterScope) {} + +AddressSanitizerModulePass::AddressSanitizerModulePass(bool CompileKernel, + bool Recover, + bool UseAfterScope) + : CompileKernel(CompileKernel), Recover(Recover), + UseAfterScope(UseAfterScope) {} + +PreservedAnalyses AddressSanitizerPass::run(Function &F, + AnalysisManager &AM) { + DominatorTree *DT = &AM.getResult(F); + const TargetLibraryInfo *TLI = &AM.getResult(F); + AddressSanitizer Sanitizer(*F.getParent(), CompileKernel, Recover, + UseAfterScope); + if (Sanitizer.instrument(F, DT, TLI)) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); +} + +PreservedAnalyses AddressSanitizerModulePass::run(Module &M, + AnalysisManager &AM) { + AddressSanitizerModule Sanitizer(CompileKernel, Recover, UseAfterScope); + if (Sanitizer.instrument(M)) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); +} + +char AddressSanitizerLegacyPass::ID = 0; INITIALIZE_PASS_BEGIN( - AddressSanitizer, "asan", + AddressSanitizerLegacyPass, "asan", "AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false, false) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) INITIALIZE_PASS_END( - AddressSanitizer, "asan", + AddressSanitizerLegacyPass, "asan", "AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false, false) @@ -1076,13 +1155,13 @@ bool Recover, bool UseAfterScope) { assert(!CompileKernel || Recover); - return new AddressSanitizer(CompileKernel, Recover, UseAfterScope); + return new AddressSanitizerLegacyPass(CompileKernel, Recover, UseAfterScope); } -char AddressSanitizerModule::ID = 0; +char AddressSanitizerModuleLegacyPass::ID = 0; INITIALIZE_PASS( - AddressSanitizerModule, "asan-module", + AddressSanitizerModuleLegacyPass, "asan-module", "AddressSanitizer: detects use-after-free and out-of-bounds bugs." "ModulePass", false, false) @@ -1091,7 +1170,8 @@ bool Recover, bool UseGlobalsGC) { assert(!CompileKernel || Recover); - return new AddressSanitizerModule(CompileKernel, Recover, UseGlobalsGC); + return new AddressSanitizerModuleLegacyPass(CompileKernel, Recover, + UseGlobalsGC); } static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { @@ -2268,7 +2348,7 @@ return Version; } -bool AddressSanitizerModule::runOnModule(Module &M) { +bool AddressSanitizerModule::instrument(Module &M) { C = &(M.getContext()); int LongSize = M.getDataLayout().getPointerSizeInBits(); IntptrTy = Type::getIntNTy(*C, LongSize); @@ -2387,25 +2467,6 @@ ArrayType::get(IRB.getInt8Ty(), 0)); } -// virtual -bool AddressSanitizer::doInitialization(Module &M) { - // Initialize the private fields. No one has accessed them before. - GlobalsMD.init(M); - - C = &(M.getContext()); - LongSize = M.getDataLayout().getPointerSizeInBits(); - IntptrTy = Type::getIntNTy(*C, LongSize); - TargetTriple = Triple(M.getTargetTriple()); - - Mapping = getShadowMapping(TargetTriple, LongSize, CompileKernel); - return true; -} - -bool AddressSanitizer::doFinalization(Module &M) { - GlobalsMD.reset(); - return false; -} - bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) { // For each NSObject descendant having a +load method, this method is invoked // by the ObjC runtime before any of the static constructors is called. @@ -2479,7 +2540,8 @@ } } -bool AddressSanitizer::runOnFunction(Function &F) { +bool AddressSanitizer::instrument(Function &F, DominatorTree *DTree, + const TargetLibraryInfo *TLI) { if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return false; if (!ClDebugFunc.empty() && ClDebugFunc == F.getName()) return false; if (F.getName().startswith("__asan_")) return false; @@ -2498,7 +2560,7 @@ LLVM_DEBUG(dbgs() << "ASAN instrumenting:\n" << F << "\n"); initializeCallbacks(*F.getParent()); - DT = &getAnalysis().getDomTree(); + DT = DTree; FunctionStateRAII CleanupObj(this); @@ -2519,8 +2581,6 @@ bool IsWrite; unsigned Alignment; uint64_t TypeSize; - const TargetLibraryInfo *TLI = - &getAnalysis().getTLI(); // Fill the set of memory operations to instrument. for (auto &BB : F) { Index: lib/Transforms/Instrumentation/Instrumentation.cpp =================================================================== --- lib/Transforms/Instrumentation/Instrumentation.cpp +++ lib/Transforms/Instrumentation/Instrumentation.cpp @@ -56,8 +56,8 @@ /// initializeInstrumentation - Initialize all passes in the TransformUtils /// library. void llvm::initializeInstrumentation(PassRegistry &Registry) { - initializeAddressSanitizerPass(Registry); - initializeAddressSanitizerModulePass(Registry); + initializeAddressSanitizerLegacyPassPass(Registry); + initializeAddressSanitizerModuleLegacyPassPass(Registry); initializeBoundsCheckingLegacyPassPass(Registry); initializeControlHeightReductionLegacyPassPass(Registry); initializeGCOVProfilerLegacyPassPass(Registry); Index: test/Instrumentation/AddressSanitizer/basic.ll =================================================================== --- test/Instrumentation/AddressSanitizer/basic.ll +++ test/Instrumentation/AddressSanitizer/basic.ll @@ -1,7 +1,9 @@ ; Test basic address sanitizer instrumentation. ; ; RUN: opt < %s -asan -asan-module -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -passes='function(asan),module(asan-module)' -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s ; RUN: opt < %s -asan -asan-module -asan-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s +; RUN: opt < %s -passes='function(asan),module(asan-module)' -asan-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %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"