aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm14/include/llvm/Transforms/Instrumentation/AddressSanitizer.h
blob: 3264fc0605eb222574065dc71aa8beb494b8f55f (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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#pragma once

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

//===--------- Definition of the AddressSanitizer class ---------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// 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/Pass.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;
};

struct AddressSanitizerOptions {
  bool CompileKernel = false;
  bool Recover = false;
  bool UseAfterScope = false;
  AsanDetectStackUseAfterReturnMode UseAfterReturn =
      AsanDetectStackUseAfterReturnMode::Runtime;
};

/// 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:
  AddressSanitizerPass(const AddressSanitizerOptions &Options)
      : Options(Options){};
  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
  void printPipeline(raw_ostream &OS,
                     function_ref<StringRef(StringRef)> MapClassName2PassName);
  static bool isRequired() { return true; }

private:
  AddressSanitizerOptions Options;
};

/// 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:
  ModuleAddressSanitizerPass(
      const AddressSanitizerOptions &Options, bool UseGlobalGC = true,
      bool UseOdrIndicator = false,
      AsanDtorKind DestructorKind = AsanDtorKind::Global);
  PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
  void printPipeline(raw_ostream &OS,
                     function_ref<StringRef(StringRef)> MapClassName2PassName);
  static bool isRequired() { return true; }

private:
  AddressSanitizerOptions Options;
  bool UseGlobalGC;
  bool UseOdrIndicator;
  AsanDtorKind DestructorKind;
};

// Insert AddressSanitizer (address basic correctness 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);

struct ASanAccessInfo {
  const int32_t Packed;
  const uint8_t AccessSizeIndex;
  const bool IsWrite;
  const bool CompileKernel;

  explicit ASanAccessInfo(int32_t Packed);
  ASanAccessInfo(bool IsWrite, bool CompileKernel, uint8_t AccessSizeIndex);
};

} // namespace llvm

#endif

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif