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