1 //===--------- Definition of the AddressSanitizer class ---------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares the AddressSanitizer class which is a port of the legacy 10 // AddressSanitizer pass to use the new PassManager infrastructure. 11 // 12 //===----------------------------------------------------------------------===// 13 #ifndef LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZER_H 14 #define LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZER_H 15 16 #include "llvm/IR/Function.h" 17 #include "llvm/IR/Module.h" 18 #include "llvm/IR/PassManager.h" 19 #include "llvm/Pass.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 32 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. 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. 62 bool invalidate(Module &, const PreservedAnalyses &, 63 ModuleAnalysisManager::Invalidator &) { 64 return false; 65 } 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 struct AddressSanitizerOptions { 94 bool CompileKernel = false; 95 bool Recover = false; 96 bool UseAfterScope = false; 97 AsanDetectStackUseAfterReturnMode UseAfterReturn = 98 AsanDetectStackUseAfterReturnMode::Runtime; 99 }; 100 101 /// Public interface to the address sanitizer pass for instrumenting code to 102 /// check for various memory errors at runtime. 103 /// 104 /// The sanitizer itself is a function pass that works by inserting various 105 /// calls to the ASan runtime library functions. The runtime library essentially 106 /// replaces malloc() and free() with custom implementations that allow regions 107 /// surrounding requested memory to be checked for invalid accesses. 108 class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> { 109 public: 110 AddressSanitizerPass(const AddressSanitizerOptions &Options) 111 : Options(Options){}; 112 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 113 void printPipeline(raw_ostream &OS, 114 function_ref<StringRef(StringRef)> MapClassName2PassName); 115 static bool isRequired() { return true; } 116 117 private: 118 AddressSanitizerOptions Options; 119 }; 120 121 /// Public interface to the address sanitizer module pass for instrumenting code 122 /// to check for various memory errors. 123 /// 124 /// This adds 'asan.module_ctor' to 'llvm.global_ctors'. This pass may also 125 /// run intependently of the function address sanitizer. 126 class ModuleAddressSanitizerPass 127 : public PassInfoMixin<ModuleAddressSanitizerPass> { 128 public: 129 ModuleAddressSanitizerPass( 130 const AddressSanitizerOptions &Options, bool UseGlobalGC = true, 131 bool UseOdrIndicator = false, 132 AsanDtorKind DestructorKind = AsanDtorKind::Global); 133 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); 134 void printPipeline(raw_ostream &OS, 135 function_ref<StringRef(StringRef)> MapClassName2PassName); 136 static bool isRequired() { return true; } 137 138 private: 139 AddressSanitizerOptions Options; 140 bool UseGlobalGC; 141 bool UseOdrIndicator; 142 AsanDtorKind DestructorKind; 143 }; 144 145 // Insert AddressSanitizer (address basic correctness checking) instrumentation 146 FunctionPass *createAddressSanitizerFunctionPass( 147 bool CompileKernel = false, bool Recover = false, 148 bool UseAfterScope = false, 149 AsanDetectStackUseAfterReturnMode UseAfterReturn = 150 AsanDetectStackUseAfterReturnMode::Runtime); 151 ModulePass *createModuleAddressSanitizerLegacyPassPass( 152 bool CompileKernel = false, bool Recover = false, bool UseGlobalsGC = true, 153 bool UseOdrIndicator = true, 154 AsanDtorKind DestructorKind = AsanDtorKind::Global); 155 156 struct ASanAccessInfo { 157 const int32_t Packed; 158 const uint8_t AccessSizeIndex; 159 const bool IsWrite; 160 const bool CompileKernel; 161 162 explicit ASanAccessInfo(int32_t Packed); 163 ASanAccessInfo(bool IsWrite, bool CompileKernel, uint8_t AccessSizeIndex); 164 }; 165 166 } // namespace llvm 167 168 #endif 169