reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    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
  315
//===-- 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 liblldb_UserExpression_h_
#define liblldb_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 {
public:
  /// LLVM-style RTTI support.
  static bool classof(const Expression *E) {
    return E->getKind() == eKindUserExpression;
  }
  
  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,
                 ExpressionKind kind);

  /// 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_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[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.
  ///
  /// \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,
           lldb::ModuleSP *jit_module_sp_ptr = nullptr,
           ValueObject *ctx_obj = nullptr);

  static const Status::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, 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 // liblldb_UserExpression_h_