Index: llvm/include/llvm/InitializePasses.h =================================================================== --- llvm/include/llvm/InitializePasses.h +++ llvm/include/llvm/InitializePasses.h @@ -65,8 +65,9 @@ void initializeAAResultsWrapperPassPass(PassRegistry&); void initializeADCELegacyPassPass(PassRegistry&); void initializeAddDiscriminatorsLegacyPassPass(PassRegistry&); -void initializeAddressSanitizerModulePass(PassRegistry&); -void initializeAddressSanitizerPass(PassRegistry&); +void initializeAddressSanitizerModuleLegacyPassPass(PassRegistry &); +void initializeAddressSanitizerParamsLegacyPassPass(PassRegistry &); +void initializeAddressSanitizerLegacyPassPass(PassRegistry &); void initializeAggressiveInstCombinerLegacyPassPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlignmentFromAssumptionsPass(PassRegistry&); Index: llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerPass.h =================================================================== --- /dev/null +++ llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerPass.h @@ -0,0 +1,158 @@ +//===--------- 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_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZERPASS_H +#define LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZERPASS_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// Frontend-provided metadata for source location. +struct LocationMetadata { + StringRef Filename; + int LineNo = 0; + int ColumnNo = 0; + + LocationMetadata() = default; + + bool empty() const { return Filename.empty(); } + void parse(MDNode *MDN); +}; + +/// Frontend-provided metadata for global variables. +class GlobalsMetadata { +public: + struct Entry { + LocationMetadata SourceLoc; + StringRef Name; + bool IsDynInit = false; + bool IsBlacklisted = false; + + Entry() = default; + }; + + GlobalsMetadata() = default; + + void reset() { + inited_ = false; + Entries.clear(); + } + + void init(Module &M); + + /// Returns metadata entry for a given global. + Entry get(GlobalVariable *G) const { + auto Pos = Entries.find(G); + return (Pos != Entries.end()) ? Pos->second : Entry(); + } + +private: + bool inited_ = false; + DenseMap Entries; +}; + +/// This struct defines the shadow mapping using the rule: +/// shadow = (mem >> Scale) ADD-or-OR Offset. +/// If InGlobal is true, then +/// extern char __asan_shadow[]; +/// shadow = (mem >> Scale) + &__asan_shadow +struct ShadowMapping { + int Scale; + uint64_t Offset; + bool OrShadowOffset; + bool InGlobal; +}; + +struct AddressSanitizerParams { + GlobalsMetadata GlobalsMD; + LLVMContext *C; + int LongSize; + Type *IntptrTy; + Triple TargetTriple; + ShadowMapping Mapping; + bool CompileKernel; + + AddressSanitizerParams(bool CompileKernel); + void Initialize(Module &M); + +private: + bool Inited = false; +}; + +/// Helper class which holds a reference to an underlying AddressSanitizerParams +/// so we do not need to copy it so many times. +class AddressSanitizerParamsWrapper { +public: + AddressSanitizerParamsWrapper(AddressSanitizerParams &Params) + : Params(Params) {} + + AddressSanitizerParams &getParams() { return Params; } + +private: + AddressSanitizerParams Params; +}; + +class AddressSanitizerParamsAnalysis + : public AnalysisInfoMixin { +public: + using Result = AddressSanitizerParamsWrapper; + + AddressSanitizerParamsAnalysis(bool CompileKernel = false) + : Params(CompileKernel) {} + Result run(Module &, ModuleAnalysisManager &); + Result run(Function &, FunctionAnalysisManager &); + +private: + friend AnalysisInfoMixin; + static AnalysisKey Key; + + AddressSanitizerParams Params; +}; + +/// Public interface to the address sanitizer pass for instrumenting code to +/// check for various memory bugs. +class AddressSanitizerPass : public PassInfoMixin { +public: + explicit AddressSanitizerPass(bool CompileKernel = false, + bool Recover = false, + bool UseAfterScope = false); + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + +private: + bool CompileKernel; + bool Recover; + bool UseAfterScope; +}; + +class AddressSanitizerModulePass + : public PassInfoMixin { +public: + explicit AddressSanitizerModulePass(bool CompileKernel = false, + bool Recover = false, + bool UseGlobalGC = true, + bool UseOdrIndicator = false); + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + +private: + bool CompileKernel; + bool Recover; + bool UseGlobalGC; + bool UseOdrIndicator; +}; + +} // namespace llvm + +#endif Index: llvm/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/lib/Passes/PassBuilder.cpp +++ llvm/lib/Passes/PassBuilder.cpp @@ -89,6 +89,7 @@ #include "llvm/Transforms/IPO/WholeProgramDevirt.h" #include "llvm/Transforms/InstCombine/InstCombine.h" #include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/Instrumentation/AddressSanitizerPass.h" #include "llvm/Transforms/Instrumentation/BoundsChecking.h" #include "llvm/Transforms/Instrumentation/CGProfile.h" #include "llvm/Transforms/Instrumentation/ControlHeightReduction.h" Index: llvm/lib/Passes/PassRegistry.def =================================================================== --- llvm/lib/Passes/PassRegistry.def +++ llvm/lib/Passes/PassRegistry.def @@ -28,6 +28,7 @@ MODULE_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) MODULE_ANALYSIS("verify", VerifierAnalysis()) MODULE_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC)) +MODULE_ANALYSIS("asan-params", AddressSanitizerParamsAnalysis(false)) #ifndef MODULE_ALIAS_ANALYSIS #define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ @@ -82,6 +83,7 @@ MODULE_PASS("synthetic-counts-propagation", SyntheticCountsPropagation()) MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass(nullptr, nullptr)) MODULE_PASS("verify", VerifierPass()) +MODULE_PASS("asan-module", AddressSanitizerModulePass(false, false, true, false)) #undef MODULE_PASS #ifndef CGSCC_ANALYSIS @@ -129,6 +131,7 @@ TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis()) FUNCTION_ANALYSIS("verify", VerifierAnalysis()) FUNCTION_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC)) +FUNCTION_ANALYSIS("asan-params", AddressSanitizerParamsAnalysis(false)) #ifndef FUNCTION_ALIAS_ANALYSIS #define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ @@ -233,6 +236,7 @@ FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass()) FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass()) FUNCTION_PASS("msan", MemorySanitizerPass()) +FUNCTION_PASS("asan", AddressSanitizerPass(false, false, false)) #undef FUNCTION_PASS #ifndef LOOP_ANALYSIS Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -25,7 +25,6 @@ #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/Argument.h" @@ -70,8 +69,10 @@ #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/Instrumentation/AddressSanitizerPass.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 @@ -391,103 +392,6 @@ STATISTIC(NumOptimizedAccessesToStackVar, "Number of optimized accesses to stack vars"); -namespace { - -/// Frontend-provided metadata for source location. -struct LocationMetadata { - StringRef Filename; - int LineNo = 0; - int ColumnNo = 0; - - LocationMetadata() = default; - - bool empty() const { return Filename.empty(); } - - void parse(MDNode *MDN) { - assert(MDN->getNumOperands() == 3); - MDString *DIFilename = cast(MDN->getOperand(0)); - Filename = DIFilename->getString(); - LineNo = - mdconst::extract(MDN->getOperand(1))->getLimitedValue(); - ColumnNo = - mdconst::extract(MDN->getOperand(2))->getLimitedValue(); - } -}; - -/// Frontend-provided metadata for global variables. -class GlobalsMetadata { -public: - struct Entry { - LocationMetadata SourceLoc; - StringRef Name; - bool IsDynInit = false; - bool IsBlacklisted = false; - - Entry() = default; - }; - - GlobalsMetadata() = default; - - void reset() { - inited_ = false; - Entries.clear(); - } - - void init(Module &M) { - assert(!inited_); - inited_ = true; - NamedMDNode *Globals = M.getNamedMetadata("llvm.asan.globals"); - if (!Globals) return; - for (auto MDN : Globals->operands()) { - // Metadata node contains the global and the fields of "Entry". - assert(MDN->getNumOperands() == 5); - auto *V = mdconst::extract_or_null(MDN->getOperand(0)); - // The optimizer may optimize away a global entirely. - if (!V) continue; - auto *StrippedV = V->stripPointerCasts(); - auto *GV = dyn_cast(StrippedV); - if (!GV) continue; - // We can already have an entry for GV if it was merged with another - // global. - Entry &E = Entries[GV]; - if (auto *Loc = cast_or_null(MDN->getOperand(1))) - E.SourceLoc.parse(Loc); - if (auto *Name = cast_or_null(MDN->getOperand(2))) - E.Name = Name->getString(); - ConstantInt *IsDynInit = - mdconst::extract(MDN->getOperand(3)); - E.IsDynInit |= IsDynInit->isOne(); - ConstantInt *IsBlacklisted = - mdconst::extract(MDN->getOperand(4)); - E.IsBlacklisted |= IsBlacklisted->isOne(); - } - } - - /// Returns metadata entry for a given global. - Entry get(GlobalVariable *G) const { - auto Pos = Entries.find(G); - return (Pos != Entries.end()) ? Pos->second : Entry(); - } - -private: - bool inited_ = false; - DenseMap Entries; -}; - -/// This struct defines the shadow mapping using the rule: -/// shadow = (mem >> Scale) ADD-or-OR Offset. -/// If InGlobal is true, then -/// extern char __asan_shadow[]; -/// shadow = (mem >> Scale) + &__asan_shadow -struct ShadowMapping { - int Scale; - uint64_t Offset; - bool OrShadowOffset; - bool InGlobal; -}; - -} // end anonymous namespace - static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize, bool IsKasan) { bool IsAndroid = TargetTriple.isAndroid(); @@ -607,27 +511,54 @@ namespace { -/// AddressSanitizer: instrument the code in module to find memory bugs. -struct AddressSanitizer : public FunctionPass { - // Pass identification, replacement for typeid +bool ShouldCompileKernel(bool CompileKernel) { + return ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan : CompileKernel; +} + +/// Module analysis for getting various metadata about the module. +class AddressSanitizerParamsLegacyPass : public ModulePass { +public: static char ID; - explicit AddressSanitizer(bool CompileKernel = false, bool Recover = false, - bool UseAfterScope = false) - : FunctionPass(ID), UseAfterScope(UseAfterScope || ClUseAfterScope) { - this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; - this->CompileKernel = ClEnableKasan.getNumOccurrences() > 0 ? - ClEnableKasan : CompileKernel; - initializeAddressSanitizerPass(*PassRegistry::getPassRegistry()); + AddressSanitizerParamsLegacyPass(bool CompileKernel = false) + : ModulePass(ID), Params(CompileKernel) { + initializeAddressSanitizerParamsLegacyPassPass( + *PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) override { + Params.Initialize(M); + return false; } StringRef getPassName() const override { - return "AddressSanitizerFunctionPass"; + return "AddressSanitizerParamsLegacyPass"; } void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); - AU.addRequired(); + AU.setPreservesAll(); + } + + AddressSanitizerParams &getParams() { return Params; } + +private: + AddressSanitizerParams Params; +}; + +char AddressSanitizerParamsLegacyPass::ID = 0; + +/// AddressSanitizer: instrument the code in module to find memory bugs. +struct AddressSanitizer { + explicit AddressSanitizer(AddressSanitizerParams ¶ms, + bool CompileKernel = false, bool Recover = false, + bool UseAfterScope = false) + : C(params.C), TargetTriple(params.TargetTriple), + LongSize(params.LongSize), + UseAfterScope(UseAfterScope || ClUseAfterScope), + IntptrTy(params.IntptrTy), Mapping(params.Mapping), + GlobalsMD(params.GlobalsMD) { + this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; + this->CompileKernel = ShouldCompileKernel(CompileKernel); } uint64_t getAllocaSizeInBytes(const AllocaInst &AI) const { @@ -672,14 +603,10 @@ Value *SizeArgument, uint32_t Exp); void instrumentMemIntrinsic(MemIntrinsic *MI); Value *memToShadow(Value *Shadow, IRBuilder<> &IRB); - bool runOnFunction(Function &F) override; + bool instrument(Function &F, const TargetLibraryInfo *TLI); bool maybeInsertAsanInitAtFunctionEntry(Function &F); void maybeInsertDynamicShadowAtFunctionEntry(Function &F); void markEscapedLocalAllocas(Function &F); - bool doInitialization(Module &M) override; - bool doFinalization(Module &M) override; - - DominatorTree &getDominatorTree() const { return *DT; } private: friend struct FunctionStackPoisoner; @@ -715,7 +642,6 @@ bool UseAfterScope; Type *IntptrTy; ShadowMapping Mapping; - DominatorTree *DT; Function *AsanHandleNoReturnFunc; Function *AsanPtrCmpFunction, *AsanPtrSubFunction; Constant *AsanShadowGlobal; @@ -735,16 +661,51 @@ DenseMap ProcessedAllocas; }; -class AddressSanitizerModule : public ModulePass { +class AddressSanitizerLegacyPass : public FunctionPass { public: - // Pass identification, replacement for typeid static char ID; - explicit AddressSanitizerModule(bool CompileKernel = false, + explicit AddressSanitizerLegacyPass(bool CompileKernel = false, + bool Recover = false, + bool UseAfterScope = false) + : FunctionPass(ID), CompileKernel(CompileKernel), Recover(Recover), + UseAfterScope(UseAfterScope) { + initializeAddressSanitizerLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + StringRef getPassName() const override { + return "AddressSanitizerFunctionPass"; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + AU.addRequired(); + } + + bool runOnFunction(Function &F) override { + AddressSanitizerParams ¶ms = + getAnalysis().getParams(); + const TargetLibraryInfo *TLI = + &getAnalysis().getTLI(); + AddressSanitizer ASan(params, CompileKernel, Recover, UseAfterScope); + return ASan.instrument(F, TLI); + } + +private: + bool CompileKernel; + bool Recover; + bool UseAfterScope; +}; + +class AddressSanitizerModule { +public: + explicit AddressSanitizerModule(AddressSanitizerParams ¶ms, + bool CompileKernel = false, bool Recover = false, bool UseGlobalsGC = true, bool UseOdrIndicator = false) - : ModulePass(ID), UseGlobalsGC(UseGlobalsGC && ClUseGlobalsGC), + : GlobalsMD(params.GlobalsMD), + UseGlobalsGC(UseGlobalsGC && ClUseGlobalsGC), // Enable aliases as they should have no downside with ODR indicators. UsePrivateAlias(UseOdrIndicator || ClUsePrivateAlias), UseOdrIndicator(UseOdrIndicator || ClUseOdrIndicator), @@ -755,14 +716,14 @@ // argument is designed as workaround. Therefore, disable both // ClWithComdat and ClUseGlobalsGC unless the frontend says it's ok to // do globals-gc. - UseCtorComdat(UseGlobalsGC && ClWithComdat) { + UseCtorComdat(UseGlobalsGC && ClWithComdat), IntptrTy(params.IntptrTy), + C(params.C), TargetTriple(params.TargetTriple), + Mapping(params.Mapping) { this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; - this->CompileKernel = - ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan : CompileKernel; + this->CompileKernel = ShouldCompileKernel(CompileKernel); } - bool runOnModule(Module &M) override; - StringRef getPassName() const override { return "AddressSanitizerModule"; } + bool instrument(Module &); private: void initializeCallbacks(Module &M); @@ -823,6 +784,41 @@ Function *AsanDtorFunction = nullptr; }; +class AddressSanitizerModuleLegacyPass : public ModulePass { +public: + static char ID; + + explicit AddressSanitizerModuleLegacyPass(bool CompileKernel = false, + bool Recover = false, + bool UseGlobalGC = true, + bool UseOdrIndicator = false) + : ModulePass(ID), CompileKernel(CompileKernel), Recover(Recover), + UseGlobalGC(UseGlobalGC), UseOdrIndicator(UseOdrIndicator) { + initializeAddressSanitizerModuleLegacyPassPass( + *PassRegistry::getPassRegistry()); + } + + StringRef getPassName() const override { return "AddressSanitizerModule"; } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + } + + bool runOnModule(Module &M) override { + AddressSanitizerParams ¶ms = + getAnalysis().getParams(); + AddressSanitizerModule ASanModule(params, CompileKernel, Recover, + UseGlobalGC, UseOdrIndicator); + return ASanModule.instrument(M); + } + +private: + bool CompileKernel; + bool Recover; + bool UseGlobalGC; + bool UseOdrIndicator; +}; + // Stack poisoning does not play well with exception handling. // When an exception is thrown, we essentially bypass the code // that unpoisones the stack. This is why the run-time library has @@ -876,13 +872,9 @@ std::unique_ptr EmptyInlineAsm; FunctionStackPoisoner(Function &F, AddressSanitizer &ASan) - : F(F), - ASan(ASan), - DIB(*F.getParent(), /*AllowUnresolved*/ false), - C(ASan.C), - IntptrTy(ASan.IntptrTy), - IntptrPtrTy(PointerType::get(IntptrTy, 0)), - Mapping(ASan.Mapping), + : F(F), ASan(ASan), DIB(*F.getParent(), /*AllowUnresolved*/ false), + C(ASan.C), IntptrTy(ASan.IntptrTy), + IntptrPtrTy(PointerType::get(IntptrTy, 0)), Mapping(ASan.Mapping), StackAlignment(1 << Mapping.Scale), EmptyInlineAsm(CallInst::Create(ASan.EmptyAsm)) {} @@ -1042,13 +1034,6 @@ // ---------------------- Helpers. void initializeCallbacks(Module &M); - bool doesDominateAllExits(const Instruction *I) const { - for (auto Ret : RetVec) { - if (!ASan.getDominatorTree().dominates(I, Ret)) return false; - } - return true; - } - /// Finds alloca where the value comes from. AllocaInst *findAllocaForValue(Value *V); @@ -1074,16 +1059,130 @@ } // end anonymous namespace -char AddressSanitizer::ID = 0; +void LocationMetadata::parse(MDNode *MDN) { + assert(MDN->getNumOperands() == 3); + MDString *DIFilename = cast(MDN->getOperand(0)); + Filename = DIFilename->getString(); + LineNo = mdconst::extract(MDN->getOperand(1))->getLimitedValue(); + ColumnNo = + mdconst::extract(MDN->getOperand(2))->getLimitedValue(); +} + +void GlobalsMetadata::init(Module &M) { + assert(!inited_); + inited_ = true; + NamedMDNode *Globals = M.getNamedMetadata("llvm.asan.globals"); + if (!Globals) + return; + for (auto MDN : Globals->operands()) { + // Metadata node contains the global and the fields of "Entry". + assert(MDN->getNumOperands() == 5); + auto *V = mdconst::extract_or_null(MDN->getOperand(0)); + // The optimizer may optimize away a global entirely. + if (!V) + continue; + auto *StrippedV = V->stripPointerCasts(); + auto *GV = dyn_cast(StrippedV); + if (!GV) + continue; + // We can already have an entry for GV if it was merged with another + // global. + Entry &E = Entries[GV]; + if (auto *Loc = cast_or_null(MDN->getOperand(1))) + E.SourceLoc.parse(Loc); + if (auto *Name = cast_or_null(MDN->getOperand(2))) + E.Name = Name->getString(); + ConstantInt *IsDynInit = mdconst::extract(MDN->getOperand(3)); + E.IsDynInit |= IsDynInit->isOne(); + ConstantInt *IsBlacklisted = + mdconst::extract(MDN->getOperand(4)); + E.IsBlacklisted |= IsBlacklisted->isOne(); + } +} + +AddressSanitizerParams::AddressSanitizerParams(bool CompileKernel) + : CompileKernel(ShouldCompileKernel(CompileKernel)) {} + +void AddressSanitizerParams::Initialize(Module &M) { + // Only need to initialize once. This covers the case in which we compile + // with either -compile-twice with llc or -run-twice with opt. + if (!Inited) { + // 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); + Inited = true; + } +} + +AnalysisKey AddressSanitizerParamsAnalysis::Key; + +AddressSanitizerParamsWrapper +AddressSanitizerParamsAnalysis::run(Module &M, ModuleAnalysisManager &AM) { + Params.Initialize(M); + return AddressSanitizerParamsWrapper(Params); +} + +AddressSanitizerParamsWrapper +AddressSanitizerParamsAnalysis::run(Function &F, FunctionAnalysisManager &AM) { + Params.Initialize(*F.getParent()); + return AddressSanitizerParamsWrapper(Params); +} + +AddressSanitizerPass::AddressSanitizerPass(bool CompileKernel, bool Recover, + bool UseAfterScope) + : CompileKernel(CompileKernel), Recover(Recover), + UseAfterScope(UseAfterScope) {} + +PreservedAnalyses AddressSanitizerPass::run(Function &F, + AnalysisManager &AM) { + AddressSanitizerParams ¶ms = + AM.getResult(F).getParams(); + const TargetLibraryInfo *TLI = &AM.getResult(F); + AddressSanitizer Sanitizer(params, CompileKernel, Recover, UseAfterScope); + if (Sanitizer.instrument(F, TLI)) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); +} + +AddressSanitizerModulePass::AddressSanitizerModulePass(bool CompileKernel, + bool Recover, + bool UseGlobalGC, + bool UseOdrIndicator) + : CompileKernel(CompileKernel), Recover(Recover), UseGlobalGC(UseGlobalGC), + UseOdrIndicator(UseOdrIndicator) {} + +PreservedAnalyses AddressSanitizerModulePass::run(Module &M, + AnalysisManager &AM) { + AddressSanitizerParams ¶ms = + AM.getResult(M).getParams(); + AddressSanitizerModule Sanitizer(params, CompileKernel, Recover, UseGlobalGC, + UseOdrIndicator); + if (Sanitizer.instrument(M)) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); +} + +INITIALIZE_PASS( + AddressSanitizerParamsLegacyPass, "asan-params", + "AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false, + true); + +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(AddressSanitizerParamsLegacyPass) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) INITIALIZE_PASS_END( - AddressSanitizer, "asan", + AddressSanitizerLegacyPass, "asan", "AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false, false) @@ -1091,13 +1190,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) @@ -1107,8 +1206,8 @@ bool UseGlobalsGC, bool UseOdrIndicator) { assert(!CompileKernel || Recover); - return new AddressSanitizerModule(CompileKernel, Recover, UseGlobalsGC, - UseOdrIndicator); + return new AddressSanitizerModuleLegacyPass(CompileKernel, Recover, + UseGlobalsGC, UseOdrIndicator); } static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { @@ -2072,7 +2171,6 @@ // asan constructor is comdat-compatible. bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M, bool *CtorComdat) { *CtorComdat = false; - GlobalsMD.init(M); SmallVector GlobalsToChange; @@ -2281,12 +2379,7 @@ return Version; } -bool AddressSanitizerModule::runOnModule(Module &M) { - C = &(M.getContext()); - int LongSize = M.getDataLayout().getPointerSizeInBits(); - IntptrTy = Type::getIntNTy(*C, LongSize); - TargetTriple = Triple(M.getTargetTriple()); - Mapping = getShadowMapping(TargetTriple, LongSize, CompileKernel); +bool AddressSanitizerModule::instrument(Module &M) { initializeCallbacks(M); if (CompileKernel) @@ -2400,25 +2493,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. @@ -2492,7 +2566,7 @@ } } -bool AddressSanitizer::runOnFunction(Function &F) { +bool AddressSanitizer::instrument(Function &F, 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; @@ -2511,7 +2585,6 @@ LLVM_DEBUG(dbgs() << "ASAN instrumenting:\n" << F << "\n"); initializeCallbacks(*F.getParent()); - DT = &getAnalysis().getDomTree(); FunctionStateRAII CleanupObj(this); @@ -2532,8 +2605,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: llvm/lib/Transforms/Instrumentation/Instrumentation.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/Instrumentation.cpp +++ llvm/lib/Transforms/Instrumentation/Instrumentation.cpp @@ -101,8 +101,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: llvm/test/Instrumentation/AddressSanitizer/basic.ll =================================================================== --- llvm/test/Instrumentation/AddressSanitizer/basic.ll +++ llvm/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"