aboutsummaryrefslogtreecommitdiff
path: root/include/lldb/Expression/UserExpression.h
blob: fca667e8ee960cc65163d4f00c8c597aa561fedc (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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
//===-- UserExpression.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_UserExpression_h_
#define liblldb_UserExpression_h_

// C Includes
// C++ Includes
#include <memory>
#include <string>
#include <vector>

// Other libraries and framework includes
// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Expression/Expression.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"

namespace lldb_private {

//----------------------------------------------------------------------
/// @class UserExpression UserExpression.h "lldb/Expression/UserExpression.h"
/// @brief Encapsulates a one-time expression for use in lldb.
///
/// LLDB uses expressions for various purposes, notably to call functions
/// and as a backend for the expr command.  UserExpression is a virtual base
/// class that encapsulates the objects needed to parse and interpret or
/// JIT an expression.  The actual parsing part will be provided by the specific
/// implementations of UserExpression - which will be vended through the
/// appropriate TypeSystem.
//----------------------------------------------------------------------
class UserExpression : public Expression {
public:
  enum { kDefaultTimeout = 500000u };

  //------------------------------------------------------------------
  /// Constructor
  ///
  /// @param[in] expr
  ///     The expression to parse.
  ///
  /// @param[in] expr_prefix
  ///     If non-nullptr, a C string containing translation-unit level
  ///     definitions to be included when the expression is parsed.
  ///
  /// @param[in] language
  ///     If not eLanguageTypeUnknown, a language to use when parsing
  ///     the expression.  Currently restricted to those languages
  ///     supported by Clang.
  ///
  /// @param[in] desired_type
  ///     If not eResultTypeAny, the type to use for the expression
  ///     result.
  //------------------------------------------------------------------
  UserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr,
                 llvm::StringRef prefix, lldb::LanguageType language,
                 ResultType desired_type,
                 const EvaluateExpressionOptions &options);

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

  //------------------------------------------------------------------
  /// Parse the expression
  ///
  /// @param[in] diagnostic_manager
  ///     A diagnostic manager to report parse errors and warnings to.
  ///
  /// @param[in] exe_ctx
  ///     The execution context to use when looking up entities that
  ///     are needed for parsing (locations of functions, types of
  ///     variables, persistent variables, etc.)
  ///
  /// @param[in] execution_policy
  ///     Determines whether interpretation is possible or mandatory.
  ///
  /// @param[in] keep_result_in_memory
  ///     True if the resulting persistent variable should reside in
  ///     target memory, if applicable.
  ///
  /// @return
  ///     True on success (no errors); false otherwise.
  //------------------------------------------------------------------
  virtual bool Parse(DiagnosticManager &diagnostic_manager,
                     ExecutionContext &exe_ctx,
                     lldb_private::ExecutionPolicy execution_policy,
                     bool keep_result_in_memory, bool generate_debug_info) = 0;

  virtual bool CanInterpret() = 0;

  bool MatchesContext(ExecutionContext &exe_ctx);

  //------------------------------------------------------------------
  /// Execute the parsed expression by callinng the derived class's
  /// DoExecute method.
  ///
  /// @param[in] diagnostic_manager
  ///     A diagnostic manager to report errors to.
  ///
  /// @param[in] exe_ctx
  ///     The execution context to use when looking up entities that
  ///     are needed for parsing (locations of variables, etc.)
  ///
  /// @param[in] options
  ///     Expression evaluation options.
  ///
  /// @param[in] shared_ptr_to_me
  ///     This is a shared pointer to this UserExpression.  This is
  ///     needed because Execute can push a thread plan that will hold onto
  ///     the UserExpression for an unbounded period of time.  So you
  ///     need to give the thread plan a reference to this object that can
  ///     keep it alive.
  ///
  /// @param[in] result
  ///     A pointer to direct at the persistent variable in which the
  ///     expression's result is stored.
  ///
  /// @return
  ///     A Process::Execution results value.
  //------------------------------------------------------------------
  lldb::ExpressionResults Execute(DiagnosticManager &diagnostic_manager,
                                  ExecutionContext &exe_ctx,
                                  const EvaluateExpressionOptions &options,
                                  lldb::UserExpressionSP &shared_ptr_to_me,
                                  lldb::ExpressionVariableSP &result);

  //------------------------------------------------------------------
  /// Apply the side effects of the function to program state.
  ///
  /// @param[in] diagnostic_manager
  ///     A diagnostic manager to report errors to.
  ///
  /// @param[in] exe_ctx
  ///     The execution context to use when looking up entities that
  ///     are needed for parsing (locations of variables, etc.)
  ///
  /// @param[in] result
  ///     A pointer to direct at the persistent variable in which the
  ///     expression's result is stored.
  ///
  /// @param[in] function_stack_pointer
  ///     A pointer to the base of the function's stack frame.  This
  ///     is used to determine whether the expression result resides in
  ///     memory that will still be valid, or whether it needs to be
  ///     treated as homeless for the purpose of future expressions.
  ///
  /// @return
  ///     A Process::Execution results value.
  //------------------------------------------------------------------
  virtual bool FinalizeJITExecution(
      DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
      lldb::ExpressionVariableSP &result,
      lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
      lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) = 0;

  //------------------------------------------------------------------
  /// Return the string that the parser should parse.
  //------------------------------------------------------------------
  const char *Text() override { return m_expr_text.c_str(); }

  //------------------------------------------------------------------
  /// Return the string that the user typed.
  //------------------------------------------------------------------
  const char *GetUserText() { return m_expr_text.c_str(); }

  //------------------------------------------------------------------
  /// Return the function name that should be used for executing the
  /// expression.  Text() should contain the definition of this
  /// function.
  //------------------------------------------------------------------
  const char *FunctionName() override { return "$__lldb_expr"; }

  //------------------------------------------------------------------
  /// Return the language that should be used when parsing.  To use
  /// the default, return eLanguageTypeUnknown.
  //------------------------------------------------------------------
  lldb::LanguageType Language() override { return m_language; }

  //------------------------------------------------------------------
  /// Return the desired result type of the function, or
  /// eResultTypeAny if indifferent.
  //------------------------------------------------------------------
  ResultType DesiredResultType() override { return m_desired_type; }

  //------------------------------------------------------------------
  /// Return true if validation code should be inserted into the
  /// expression.
  //------------------------------------------------------------------
  bool NeedsValidation() override { return true; }

  //------------------------------------------------------------------
  /// Return true if external variables in the expression should be
  /// resolved.
  //------------------------------------------------------------------
  bool NeedsVariableResolution() override { return true; }

  EvaluateExpressionOptions *GetOptions() override { return &m_options; }

  virtual lldb::ExpressionVariableSP
  GetResultAfterDematerialization(ExecutionContextScope *exe_scope) {
    return lldb::ExpressionVariableSP();
  }

  virtual lldb::ModuleSP GetJITModule() { return lldb::ModuleSP(); }

  //------------------------------------------------------------------
  /// Evaluate one expression in the scratch context of the
  /// target passed in the exe_ctx and return its result.
  ///
  /// @param[in] exe_ctx
  ///     The execution context to use when evaluating the expression.
  ///
  /// @param[in] options
  ///     Expression evaluation options.  N.B. The language in the
  ///     evaluation options will be used to determine the language used for
  ///     expression evaluation.
  ///
  /// @param[in] expr_cstr
  ///     A C string containing the expression to be evaluated.
  ///
  /// @param[in] expr_prefix
  ///     If non-nullptr, a C string containing translation-unit level
  ///     definitions to be included when the expression is parsed.
  ///
  /// @param[in,out] result_valobj_sp
  ///      If execution is successful, the result valobj is placed here.
  ///
  /// @param[out] error
  ///     Filled in with an error in case the expression evaluation
  ///     fails to parse, run, or evaluated.
  ///
  /// @param[in] line_offset
  ///     The offset of the first line of the expression from the "beginning" of
  ///     a virtual source file used for error reporting and debug info.
  ///
  /// @param[out] fixed_expression
  ///     If non-nullptr, the fixed expression is copied into the provided
  ///     string.
  ///
  /// @param[out] jit_module_sp_ptr
  ///     If non-nullptr, used to persist the generated IR module.
  ///
  /// @result
  ///      A Process::ExpressionResults value.  eExpressionCompleted for
  ///      success.
  //------------------------------------------------------------------
  static lldb::ExpressionResults
  Evaluate(ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options,
           llvm::StringRef expr_cstr, llvm::StringRef expr_prefix,
           lldb::ValueObjectSP &result_valobj_sp, Error &error,
           uint32_t line_offset = 0, std::string *fixed_expression = nullptr,
           lldb::ModuleSP *jit_module_sp_ptr = nullptr);

  static const Error::ValueType kNoResult =
      0x1001; ///< ValueObject::GetError() returns this if there is no result
              ///from the expression.

  const char *GetFixedText() {
    if (m_fixed_text.empty())
      return nullptr;
    return m_fixed_text.c_str();
  }

protected:
  virtual lldb::ExpressionResults
  DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
            const EvaluateExpressionOptions &options,
            lldb::UserExpressionSP &shared_ptr_to_me,
            lldb::ExpressionVariableSP &result) = 0;

  static lldb::addr_t GetObjectPointer(lldb::StackFrameSP frame_sp,
                                       ConstString &object_name, Error &err);

  //------------------------------------------------------------------
  /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the
  /// environment.
  //------------------------------------------------------------------

  void InstallContext(ExecutionContext &exe_ctx);

  bool LockAndCheckContext(ExecutionContext &exe_ctx, lldb::TargetSP &target_sp,
                           lldb::ProcessSP &process_sp,
                           lldb::StackFrameSP &frame_sp);

  Address m_address;       ///< The address the process is stopped in.
  std::string m_expr_text; ///< The text of the expression, as typed by the user
  std::string m_expr_prefix; ///< The text of the translation-level definitions,
                             ///as provided by the user
  std::string m_fixed_text; ///< The text of the expression with fix-its applied
                            ///- this won't be set if the fixed text doesn't
                            ///parse.
  lldb::LanguageType m_language; ///< The language to use when parsing
                                 ///(eLanguageTypeUnknown means use defaults)
  ResultType m_desired_type; ///< The type to coerce the expression's result to.
                             ///If eResultTypeAny, inferred from the expression.
  EvaluateExpressionOptions
      m_options; ///< Additional options provided by the user.
};

} // namespace lldb_private

#endif // liblldb_UserExpression_h_