aboutsummaryrefslogtreecommitdiff
path: root/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h
blob: 3781253d26947a35e52333878da818b101606d70 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//===--------- 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_ADDRESSSANITIZER_H
#define LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZER_H

#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.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 IsExcluded = false;

    Entry() = default;
  };

  /// Create a default uninitialized GlobalsMetadata instance.
  GlobalsMetadata() = default;

  /// Create an initialized GlobalsMetadata instance.
  GlobalsMetadata(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();
  }

  /// Handle invalidation from the pass manager.
  /// These results are never invalidated.
  bool invalidate(Module &, const PreservedAnalyses &,
                  ModuleAnalysisManager::Invalidator &) {
    return false;
  }
  bool invalidate(Function &, const PreservedAnalyses &,
                  FunctionAnalysisManager::Invalidator &) {
    return false;
  }

private:
  DenseMap<GlobalVariable *, Entry> Entries;
};

/// The ASanGlobalsMetadataAnalysis initializes and returns a GlobalsMetadata
/// object. More specifically, ASan requires looking at all globals registered
/// in 'llvm.asan.globals' before running, which only depends on reading module
/// level metadata. This analysis is required to run before running the
/// AddressSanitizerPass since it collects that metadata.
/// The legacy pass manager equivalent of this is ASanGlobalsMetadataLegacyPass.
class ASanGlobalsMetadataAnalysis
    : public AnalysisInfoMixin<ASanGlobalsMetadataAnalysis> {
public:
  using Result = GlobalsMetadata;

  Result run(Module &, ModuleAnalysisManager &);

private:
  friend AnalysisInfoMixin<ASanGlobalsMetadataAnalysis>;
  static AnalysisKey Key;
};

/// Public interface to the address sanitizer pass for instrumenting code to
/// check for various memory errors at runtime.
///
/// The sanitizer itself is a function pass that works by inserting various
/// calls to the ASan runtime library functions. The runtime library essentially
/// replaces malloc() and free() with custom implementations that allow regions
/// surrounding requested memory to be checked for invalid accesses.
class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> {
public:
  explicit AddressSanitizerPass(
      bool CompileKernel = false, bool Recover = false,
      bool UseAfterScope = false,
      AsanDetectStackUseAfterReturnMode UseAfterReturn =
          AsanDetectStackUseAfterReturnMode::Runtime);
  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
  static bool isRequired() { return true; }

private:
  bool CompileKernel;
  bool Recover;
  bool UseAfterScope;
  AsanDetectStackUseAfterReturnMode UseAfterReturn;
};

/// Public interface to the address sanitizer module pass for instrumenting code
/// to check for various memory errors.
///
/// This adds 'asan.module_ctor' to 'llvm.global_ctors'. This pass may also
/// run intependently of the function address sanitizer.
class ModuleAddressSanitizerPass
    : public PassInfoMixin<ModuleAddressSanitizerPass> {
public:
  explicit ModuleAddressSanitizerPass(
      bool CompileKernel = false, bool Recover = false, bool UseGlobalGC = true,
      bool UseOdrIndicator = false,
      AsanDtorKind DestructorKind = AsanDtorKind::Global);
  PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
  static bool isRequired() { return true; }

private:
  bool CompileKernel;
  bool Recover;
  bool UseGlobalGC;
  bool UseOdrIndicator;
  AsanDtorKind DestructorKind;
};

// Insert AddressSanitizer (address sanity checking) instrumentation
FunctionPass *createAddressSanitizerFunctionPass(
    bool CompileKernel = false, bool Recover = false,
    bool UseAfterScope = false,
    AsanDetectStackUseAfterReturnMode UseAfterReturn =
        AsanDetectStackUseAfterReturnMode::Runtime);
ModulePass *createModuleAddressSanitizerLegacyPassPass(
    bool CompileKernel = false, bool Recover = false, bool UseGlobalsGC = true,
    bool UseOdrIndicator = true,
    AsanDtorKind DestructorKind = AsanDtorKind::Global);

} // namespace llvm

#endif