1 //===--------- Definition of the AddressSanitizer class ---------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file declares the AddressSanitizer class which is a port of the legacy 11 // AddressSanitizer pass to use the new PassManager infrastructure. 12 // 13 //===----------------------------------------------------------------------===// 14 #ifndef LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZER_H 15 #define LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZER_H 16 17 #include "llvm/IR/Function.h" 18 #include "llvm/IR/Module.h" 19 #include "llvm/IR/PassManager.h" 20 #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h" 21 22 namespace llvm { 23 24 /// Frontend-provided metadata for source location. 25 struct LocationMetadata { 26 StringRef Filename; 27 int LineNo = 0; 28 int ColumnNo = 0; 29 30 LocationMetadata() = default; 31 emptyLocationMetadata32 bool empty() const { return Filename.empty(); } 33 void parse(MDNode *MDN); 34 }; 35 36 /// Frontend-provided metadata for global variables. 37 class GlobalsMetadata { 38 public: 39 struct Entry { 40 LocationMetadata SourceLoc; 41 StringRef Name; 42 bool IsDynInit = false; 43 bool IsExcluded = false; 44 45 Entry() = default; 46 }; 47 48 /// Create a default uninitialized GlobalsMetadata instance. 49 GlobalsMetadata() = default; 50 51 /// Create an initialized GlobalsMetadata instance. 52 GlobalsMetadata(Module &M); 53 54 /// Returns metadata entry for a given global. get(GlobalVariable * G)55 Entry get(GlobalVariable *G) const { 56 auto Pos = Entries.find(G); 57 return (Pos != Entries.end()) ? Pos->second : Entry(); 58 } 59 60 /// Handle invalidation from the pass manager. 61 /// These results are never invalidated. invalidate(Module &,const PreservedAnalyses &,ModuleAnalysisManager::Invalidator &)62 bool invalidate(Module &, const PreservedAnalyses &, 63 ModuleAnalysisManager::Invalidator &) { 64 return false; 65 } invalidate(Function &,const PreservedAnalyses &,FunctionAnalysisManager::Invalidator &)66 bool invalidate(Function &, const PreservedAnalyses &, 67 FunctionAnalysisManager::Invalidator &) { 68 return false; 69 } 70 71 private: 72 DenseMap<GlobalVariable *, Entry> Entries; 73 }; 74 75 /// The ASanGlobalsMetadataAnalysis initializes and returns a GlobalsMetadata 76 /// object. More specifically, ASan requires looking at all globals registered 77 /// in 'llvm.asan.globals' before running, which only depends on reading module 78 /// level metadata. This analysis is required to run before running the 79 /// AddressSanitizerPass since it collects that metadata. 80 /// The legacy pass manager equivalent of this is ASanGlobalsMetadataLegacyPass. 81 class ASanGlobalsMetadataAnalysis 82 : public AnalysisInfoMixin<ASanGlobalsMetadataAnalysis> { 83 public: 84 using Result = GlobalsMetadata; 85 86 Result run(Module &, ModuleAnalysisManager &); 87 88 private: 89 friend AnalysisInfoMixin<ASanGlobalsMetadataAnalysis>; 90 static AnalysisKey Key; 91 }; 92 93 /// Public interface to the address sanitizer pass for instrumenting code to 94 /// check for various memory errors at runtime. 95 /// 96 /// The sanitizer itself is a function pass that works by inserting various 97 /// calls to the ASan runtime library functions. The runtime library essentially 98 /// replaces malloc() and free() with custom implementations that allow regions 99 /// surrounding requested memory to be checked for invalid accesses. 100 class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> { 101 public: 102 explicit AddressSanitizerPass(bool CompileKernel = false, 103 bool Recover = false, 104 bool UseAfterScope = false); 105 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); isRequired()106 static bool isRequired() { return true; } 107 108 private: 109 bool CompileKernel; 110 bool Recover; 111 bool UseAfterScope; 112 }; 113 114 /// Public interface to the address sanitizer module pass for instrumenting code 115 /// to check for various memory errors. 116 /// 117 /// This adds 'asan.module_ctor' to 'llvm.global_ctors'. This pass may also 118 /// run intependently of the function address sanitizer. 119 class ModuleAddressSanitizerPass 120 : public PassInfoMixin<ModuleAddressSanitizerPass> { 121 public: 122 explicit ModuleAddressSanitizerPass( 123 bool CompileKernel = false, bool Recover = false, bool UseGlobalGC = true, 124 bool UseOdrIndicator = false, 125 AsanDtorKind DestructorKind = AsanDtorKind::Global); 126 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); isRequired()127 static bool isRequired() { return true; } 128 129 private: 130 bool CompileKernel; 131 bool Recover; 132 bool UseGlobalGC; 133 bool UseOdrIndicator; 134 AsanDtorKind DestructorKind; 135 }; 136 137 // Insert AddressSanitizer (address sanity checking) instrumentation 138 FunctionPass *createAddressSanitizerFunctionPass(bool CompileKernel = false, 139 bool Recover = false, 140 bool UseAfterScope = false); 141 ModulePass *createModuleAddressSanitizerLegacyPassPass( 142 bool CompileKernel = false, bool Recover = false, bool UseGlobalsGC = true, 143 bool UseOdrIndicator = true, 144 AsanDtorKind DestructorKind = AsanDtorKind::Global); 145 146 } // namespace llvm 147 148 #endif 149