summaryrefslogtreecommitdiff
path: root/include/lldb/Expression/IRDynamicChecks.h
blob: f31c03cfb9efa5ce70400d7e3775e5a9bfbdb226 (plain)
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
//===-- IRDynamicChecks.h ---------------------------------------------*- C++
//-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_IRDynamicChecks_h_
#define liblldb_IRDynamicChecks_h_

#include "lldb/lldb-types.h"
#include "llvm/Pass.h"

namespace llvm {
class BasicBlock;
class CallInst;
class Constant;
class Function;
class Instruction;
class Module;
class DataLayout;
class Value;
}

namespace lldb_private {

class ClangExpressionDeclMap;
class ExecutionContext;
class Stream;

//----------------------------------------------------------------------
/// @class DynamicCheckerFunctions IRDynamicChecks.h
/// "lldb/Expression/IRDynamicChecks.h" Encapsulates dynamic check functions
/// used by expressions.
///
/// Each of the utility functions encapsulated in this class is responsible
/// for validating some data that an expression is about to use.  Examples
/// are:
///
/// a = *b;     // check that b is a valid pointer [b init];   // check that b
/// is a valid object to send "init" to
///
/// The class installs each checker function into the target process and makes
/// it available to IRDynamicChecks to use.
//----------------------------------------------------------------------
class DynamicCheckerFunctions {
public:
  //------------------------------------------------------------------
  /// Constructor
  //------------------------------------------------------------------
  DynamicCheckerFunctions();

  //------------------------------------------------------------------
  /// Destructor
  //------------------------------------------------------------------
  ~DynamicCheckerFunctions();

  //------------------------------------------------------------------
  /// Install the utility functions into a process.  This binds the instance
  /// of DynamicCheckerFunctions to that process.
  ///
  /// @param[in] diagnostic_manager
  ///     A diagnostic manager to report errors to.
  ///
  /// @param[in] exe_ctx
  ///     The execution context to install the functions into.
  ///
  /// @return
  ///     True on success; false on failure, or if the functions have
  ///     already been installed.
  //------------------------------------------------------------------
  bool Install(DiagnosticManager &diagnostic_manager,
               ExecutionContext &exe_ctx);

  bool DoCheckersExplainStop(lldb::addr_t addr, Stream &message);

  std::unique_ptr<UtilityFunction> m_valid_pointer_check;
  std::unique_ptr<UtilityFunction> m_objc_object_check;
};

//----------------------------------------------------------------------
/// @class IRDynamicChecks IRDynamicChecks.h
/// "lldb/Expression/IRDynamicChecks.h" Adds dynamic checks to a user-entered
/// expression to reduce its likelihood of crashing
///
/// When an IR function is executed in the target process, it may cause
/// crashes or hangs by dereferencing NULL pointers, trying to call
/// Objective-C methods on objects that do not respond to them, and so forth.
///
/// IRDynamicChecks adds calls to the functions in DynamicCheckerFunctions to
/// appropriate locations in an expression's IR.
//----------------------------------------------------------------------
class IRDynamicChecks : public llvm::ModulePass {
public:
  //------------------------------------------------------------------
  /// Constructor
  ///
  /// @param[in] checker_functions
  ///     The checker functions for the target process.
  ///
  /// @param[in] func_name
  ///     The name of the function to prepare for execution in the target.
  ///
  /// @param[in] decl_map
  ///     The mapping used to look up entities in the target process. In
  ///     this case, used to find objc_msgSend
  //------------------------------------------------------------------
  IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
                  const char *func_name = "$__lldb_expr");

  //------------------------------------------------------------------
  /// Destructor
  //------------------------------------------------------------------
  ~IRDynamicChecks() override;

  //------------------------------------------------------------------
  /// Run this IR transformer on a single module
  ///
  /// @param[in] M
  ///     The module to run on.  This module is searched for the function
  ///     $__lldb_expr, and that function is passed to the passes one by
  ///     one.
  ///
  /// @return
  ///     True on success; false otherwise
  //------------------------------------------------------------------
  bool runOnModule(llvm::Module &M) override;

  //------------------------------------------------------------------
  /// Interface stub
  //------------------------------------------------------------------
  void assignPassManager(
      llvm::PMStack &PMS,
      llvm::PassManagerType T = llvm::PMT_ModulePassManager) override;

  //------------------------------------------------------------------
  /// Returns PMT_ModulePassManager
  //------------------------------------------------------------------
  llvm::PassManagerType getPotentialPassManagerType() const override;

private:
  //------------------------------------------------------------------
  /// A basic block-level pass to find all pointer dereferences and
  /// validate them before use.
  //------------------------------------------------------------------

  //------------------------------------------------------------------
  /// The top-level pass implementation
  ///
  /// @param[in] M
  ///     The module currently being processed.
  ///
  /// @param[in] BB
  ///     The basic block currently being processed.
  ///
  /// @return
  ///     True on success; false otherwise
  //------------------------------------------------------------------
  bool FindDataLoads(llvm::Module &M, llvm::BasicBlock &BB);

  std::string m_func_name; ///< The name of the function to add checks to
  DynamicCheckerFunctions
      &m_checker_functions; ///< The checker functions for the process
};

} // namespace lldb_private

#endif // liblldb_IRDynamicChecks_h_