aboutsummaryrefslogtreecommitdiff
path: root/lldb/include/lldb/Expression/UserExpression.h
blob: 3874a60e06f091f3a72470504c12001f3298b8fd (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
//===-- UserExpression.h ----------------------------------------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_EXPRESSION_USEREXPRESSION_H
#define LLDB_EXPRESSION_USEREXPRESSION_H

#include <memory>
#include <string>
#include <vector>

#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"
/// 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 {
  /// LLVM RTTI support.
  static char ID;

public:
  bool isA(const void *ClassID) const override { return ClassID == &ID; }
  static bool classof(const Expression *obj) { return obj->isA(&ID); }

  enum { kDefaultTimeout = 500000u };

  /// Constructor
  ///
  /// \param[in] expr
  ///     The expression to parse.
  ///
  /// \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;

  /// Attempts to find possible command line completions for the given
  /// (possible incomplete) user expression.
  ///
  /// \param[in] exe_ctx
  ///     The execution context to use when looking up entities that
  ///     are needed for parsing and completing (locations of functions, types
  ///     of variables, persistent variables, etc.)
  ///
  /// \param[out] request
  ///     The completion request to fill out. The completion should be a string
  ///     that would complete the current token at the cursor position.
  ///     Note that the string in the list replaces the current token
  ///     in the command line.
  ///
  /// \param[in] complete_pos
  ///     The position of the cursor inside the user expression string.
  ///     The completion process starts on the token that the cursor is in.
  ///
  /// \return
  ///     True if we added any completion results to the output;
  ///     false otherwise.
  virtual bool Complete(ExecutionContext &exe_ctx, CompletionRequest &request,
                        unsigned complete_pos) {
    return false;
  }

  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_bottom
  ///     A pointer to the bottom 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.
  ///
  /// \param[in] function_stack_top
  ///     A pointer to the top 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() const 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();
  }

  /// 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[out] fixed_expression
  ///     If non-nullptr, the fixed expression is copied into the provided
  ///     string.
  ///
  /// \param[in] ctx_obj
  ///     If specified, then the expression will be evaluated in the context of
  ///     this object. It means that the context object's address will be
  ///     treated as `this` for the expression (the expression will be
  ///     evaluated as if it was inside of a method of the context object's
  ///     class, and its `this` parameter were pointing to the context object).
  ///     The parameter makes sense for class and union types only.
  ///     Currently there is a limitation: the context object must be located
  ///     in the debuggee process' memory (and have the load address).
  ///
  /// \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, Status &error,
           std::string *fixed_expression = nullptr,
           ValueObject *ctx_obj = nullptr);

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

  llvm::StringRef GetFixedText() {
    return m_fixed_text;
  }

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, Status &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 // LLDB_EXPRESSION_USEREXPRESSION_H