LLDB  mainline
UserExpression.cpp
Go to the documentation of this file.
1 //===-- UserExpression.cpp ---------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <stdio.h>
10 #if HAVE_SYS_TYPES_H
11 #include <sys/types.h>
12 #endif
13 
14 #include <cstdlib>
15 #include <map>
16 #include <string>
17 
19 #include "lldb/Core/Module.h"
20 #include "lldb/Core/StreamFile.h"
27 #include "lldb/Host/HostInfo.h"
28 #include "lldb/Symbol/Block.h"
29 #include "lldb/Symbol/Function.h"
30 #include "lldb/Symbol/ObjectFile.h"
32 #include "lldb/Symbol/Type.h"
33 #include "lldb/Symbol/TypeSystem.h"
36 #include "lldb/Target/Process.h"
37 #include "lldb/Target/StackFrame.h"
38 #include "lldb/Target/Target.h"
39 #include "lldb/Target/ThreadPlan.h"
42 #include "lldb/Utility/Log.h"
44 
45 using namespace lldb_private;
46 
48  llvm::StringRef expr, llvm::StringRef prefix,
49  lldb::LanguageType language,
50  ResultType desired_type,
51  const EvaluateExpressionOptions &options,
52  ExpressionKind kind)
53  : Expression(exe_scope, kind), m_expr_text(expr), m_expr_prefix(prefix),
54  m_language(language), m_desired_type(desired_type), m_options(options) {}
55 
57 
59  m_jit_process_wp = exe_ctx.GetProcessSP();
60 
61  lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
62 
63  if (frame_sp)
64  m_address = frame_sp->GetFrameCodeAddress();
65 }
66 
68  lldb::TargetSP &target_sp,
69  lldb::ProcessSP &process_sp,
70  lldb::StackFrameSP &frame_sp) {
71  lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
72  process_sp = exe_ctx.GetProcessSP();
73 
74  if (process_sp != expected_process_sp)
75  return false;
76 
77  process_sp = exe_ctx.GetProcessSP();
78  target_sp = exe_ctx.GetTargetSP();
79  frame_sp = exe_ctx.GetFrameSP();
80 
81  if (m_address.IsValid()) {
82  if (!frame_sp)
83  return false;
84  else
86  frame_sp->GetFrameCodeAddress(),
87  target_sp.get()));
88  }
89 
90  return true;
91 }
92 
94  lldb::TargetSP target_sp;
95  lldb::ProcessSP process_sp;
96  lldb::StackFrameSP frame_sp;
97 
98  return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
99 }
100 
101 lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp,
102  ConstString &object_name,
103  Status &err) {
104  err.Clear();
105 
106  if (!frame_sp) {
108  "Couldn't load '%s' because the context is incomplete",
109  object_name.AsCString());
110  return LLDB_INVALID_ADDRESS;
111  }
112 
113  lldb::VariableSP var_sp;
114  lldb::ValueObjectSP valobj_sp;
115 
116  valobj_sp = frame_sp->GetValueForVariableExpressionPath(
117  object_name.AsCString(), lldb::eNoDynamicValues,
122  var_sp, err);
123 
124  if (!err.Success() || !valobj_sp.get())
125  return LLDB_INVALID_ADDRESS;
126 
127  lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
128 
129  if (ret == LLDB_INVALID_ADDRESS) {
131  "Couldn't load '%s' because its value couldn't be evaluated",
132  object_name.AsCString());
133  return LLDB_INVALID_ADDRESS;
134  }
135 
136  return ret;
137 }
138 
140  ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options,
141  llvm::StringRef expr, llvm::StringRef prefix,
142  lldb::ValueObjectSP &result_valobj_sp, Status &error,
143  std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr,
144  ValueObject *ctx_obj) {
147 
148  if (ctx_obj) {
149  static unsigned const ctx_type_mask =
150  lldb::TypeFlags::eTypeIsClass | lldb::TypeFlags::eTypeIsStructUnion;
151  if (!(ctx_obj->GetTypeInfo() & ctx_type_mask)) {
152  LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of "
153  "an invalid type, can't run expressions.");
154  error.SetErrorString("a context object of an invalid type passed");
156  }
157  }
158 
159  lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
160  lldb::LanguageType language = options.GetLanguage();
161  const ResultType desired_type = options.DoesCoerceToId()
165 
166  Target *target = exe_ctx.GetTargetPtr();
167  if (!target) {
168  if (log)
169  log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't "
170  "run expressions.");
171  error.SetErrorString("expression passed a null target");
173  }
174 
175  Process *process = exe_ctx.GetProcessPtr();
176 
177  if (process == NULL || process->GetState() != lldb::eStateStopped) {
178  if (execution_policy == eExecutionPolicyAlways) {
179  if (log)
180  log->Printf("== [UserExpression::Evaluate] Expression may not run, but "
181  "is not constant ==");
182 
183  error.SetErrorString("expression needed to run but couldn't");
184 
185  return execution_results;
186  }
187  }
188 
189  if (process == NULL || !process->CanJIT())
190  execution_policy = eExecutionPolicyNever;
191 
192  // We need to set the expression execution thread here, turns out parse can
193  // call functions in the process of looking up symbols, which will escape the
194  // context set by exe_ctx passed to Execute.
195  lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
196  ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(
197  thread_sp);
198 
199  llvm::StringRef full_prefix;
200  llvm::StringRef option_prefix(options.GetPrefix());
201  std::string full_prefix_storage;
202  if (!prefix.empty() && !option_prefix.empty()) {
203  full_prefix_storage = prefix;
204  full_prefix_storage.append(option_prefix);
205  full_prefix = full_prefix_storage;
206  } else if (!prefix.empty())
207  full_prefix = prefix;
208  else
209  full_prefix = option_prefix;
210 
211  // If the language was not specified in the expression command, set it to the
212  // language in the target's properties if specified, else default to the
213  // langage for the frame.
214  if (language == lldb::eLanguageTypeUnknown) {
215  if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
216  language = target->GetLanguage();
217  else if (StackFrame *frame = exe_ctx.GetFramePtr())
218  language = frame->GetLanguage();
219  }
220 
221  lldb::UserExpressionSP user_expression_sp(
222  target->GetUserExpressionForLanguage(expr, full_prefix, language,
223  desired_type, options, ctx_obj,
224  error));
225  if (error.Fail()) {
226  if (log)
227  log->Printf("== [UserExpression::Evaluate] Getting expression: %s ==",
228  error.AsCString());
230  }
231 
232  if (log)
233  log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==",
234  expr.str().c_str());
235 
236  const bool keep_expression_in_memory = true;
237  const bool generate_debug_info = options.GetGenerateDebugInfo();
238 
240  error.SetErrorString("expression interrupted by callback before parse");
241  result_valobj_sp = ValueObjectConstResult::Create(
242  exe_ctx.GetBestExecutionContextScope(), error);
244  }
245 
246  DiagnosticManager diagnostic_manager;
247 
248  bool parse_success =
249  user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy,
250  keep_expression_in_memory, generate_debug_info);
251 
252  // Calculate the fixed expression always, since we need it for errors.
253  std::string tmp_fixed_expression;
254  if (fixed_expression == nullptr)
255  fixed_expression = &tmp_fixed_expression;
256 
257  const char *fixed_text = user_expression_sp->GetFixedText();
258  if (fixed_text != nullptr)
259  fixed_expression->append(fixed_text);
260 
261  // If there is a fixed expression, try to parse it:
262  if (!parse_success) {
263  execution_results = lldb::eExpressionParseError;
264  if (fixed_expression && !fixed_expression->empty() &&
265  options.GetAutoApplyFixIts()) {
266  lldb::UserExpressionSP fixed_expression_sp(
267  target->GetUserExpressionForLanguage(fixed_expression->c_str(),
268  full_prefix, language,
269  desired_type, options, ctx_obj,
270  error));
271  DiagnosticManager fixed_diagnostic_manager;
272  parse_success = fixed_expression_sp->Parse(
273  fixed_diagnostic_manager, exe_ctx, execution_policy,
274  keep_expression_in_memory, generate_debug_info);
275  if (parse_success) {
276  diagnostic_manager.Clear();
277  user_expression_sp = fixed_expression_sp;
278  } else {
279  // If the fixed expression failed to parse, don't tell the user about,
280  // that won't help.
281  fixed_expression->clear();
282  }
283  }
284 
285  if (!parse_success) {
286  if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) {
288  execution_results,
289  "expression failed to parse, fixed expression suggested:\n %s",
290  fixed_expression->c_str());
291  } else {
292  if (!diagnostic_manager.Diagnostics().size())
293  error.SetExpressionError(execution_results,
294  "expression failed to parse, unknown error");
295  else
296  error.SetExpressionError(execution_results,
297  diagnostic_manager.GetString().c_str());
298  }
299  }
300  }
301 
302  if (parse_success) {
303  // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module
304  // if one was created
305  if (jit_module_sp_ptr)
306  *jit_module_sp_ptr = user_expression_sp->GetJITModule();
307 
308  lldb::ExpressionVariableSP expr_result;
309 
310  if (execution_policy == eExecutionPolicyNever &&
311  !user_expression_sp->CanInterpret()) {
312  if (log)
313  log->Printf("== [UserExpression::Evaluate] Expression may not run, but "
314  "is not constant ==");
315 
316  if (!diagnostic_manager.Diagnostics().size())
318  "expression needed to run but couldn't");
319  } else if (execution_policy == eExecutionPolicyTopLevel) {
322  } else {
324  error.SetExpressionError(
326  "expression interrupted by callback before execution");
327  result_valobj_sp = ValueObjectConstResult::Create(
328  exe_ctx.GetBestExecutionContextScope(), error);
330  }
331 
332  diagnostic_manager.Clear();
333 
334  if (log)
335  log->Printf("== [UserExpression::Evaluate] Executing expression ==");
336 
337  execution_results =
338  user_expression_sp->Execute(diagnostic_manager, exe_ctx, options,
339  user_expression_sp, expr_result);
340 
341  if (execution_results != lldb::eExpressionCompleted) {
342  if (log)
343  log->Printf("== [UserExpression::Evaluate] Execution completed "
344  "abnormally ==");
345 
346  if (!diagnostic_manager.Diagnostics().size())
347  error.SetExpressionError(
348  execution_results, "expression failed to execute, unknown error");
349  else
350  error.SetExpressionError(execution_results,
351  diagnostic_manager.GetString().c_str());
352  } else {
353  if (expr_result) {
354  result_valobj_sp = expr_result->GetValueObject();
355 
356  if (log)
357  log->Printf("== [UserExpression::Evaluate] Execution completed "
358  "normally with result %s ==",
359  result_valobj_sp->GetValueAsCString());
360  } else {
361  if (log)
362  log->Printf("== [UserExpression::Evaluate] Execution completed "
363  "normally with no result ==");
364 
366  }
367  }
368  }
369  }
370 
372  error.SetExpressionError(
374  "expression interrupted by callback after complete");
376  }
377 
378  if (result_valobj_sp.get() == NULL) {
379  result_valobj_sp = ValueObjectConstResult::Create(
380  exe_ctx.GetBestExecutionContextScope(), error);
381  }
382 
383  return execution_results;
384 }
385 
388  ExecutionContext &exe_ctx,
389  const EvaluateExpressionOptions &options,
390  lldb::UserExpressionSP &shared_ptr_to_me,
391  lldb::ExpressionVariableSP &result_var) {
392  lldb::ExpressionResults expr_result = DoExecute(
393  diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
394  Target *target = exe_ctx.GetTargetPtr();
395  if (options.GetResultIsInternal() && result_var && target) {
397  ->RemovePersistentVariable(result_var);
398  }
399  return expr_result;
400 }
const lldb::ThreadSP & GetThreadSP() const
Get accessor to get the thread shared pointer.
ExpressionKind
Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
Definition: Expression.h:36
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:224
virtual uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr)
UserExpression * GetUserExpressionForLanguage(llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, Expression::ResultType desired_type, const EvaluateExpressionOptions &options, ValueObject *ctx_obj, Status &error)
Definition: Target.cpp:2217
bool MatchesContext(ExecutionContext &exe_ctx)
const lldb::TargetSP & GetTargetSP() const
Get accessor to get the target shared pointer.
int SetExpressionErrorWithFormat(lldb::ExpressionResults, const char *format,...) __attribute__((format(printf
Definition: Status.cpp:198
Address m_address
The address the process is stopped in.
lldb::StateType GetState()
Get accessor for the current process state.
Definition: Process.cpp:1347
static lldb::addr_t GetObjectPointer(lldb::StackFrameSP frame_sp, ConstString &object_name, Status &err)
static int CompareLoadAddress(const Address &lhs, const Address &rhs, Target *target)
Definition: Address.cpp:892
Encapsulates a single expression for use in lldb.
Definition: Expression.h:33
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Process or thread is stopped and can be examined.
#define LLDB_LOG(log,...)
Definition: Log.h:209
void SetExpressionError(lldb::ExpressionResults, const char *mssg)
Definition: Status.cpp:191
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
Target * GetTargetPtr() const
Returns a pointer to the target object.
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
LanguageType
Programming language type.
void Clear()
Clear the object state.
Definition: Status.cpp:167
const lldb::StackFrameSP & GetFrameSP() const
Get accessor to get the frame shared pointer.
std::string GetString(char separator='\n')
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
A plug-in interface definition class for debugging a process.
Definition: Process.h:353
Process * GetProcessPtr() const
Returns a pointer to the process object.
lldb::ProcessWP m_jit_process_wp
Expression&#39;s always have to have a target...
Definition: Expression.h:101
UserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options, ExpressionKind kind)
Constructor.
bool Success() const
Test for success condition.
Definition: Status.cpp:287
static const Status::ValueType kNoResult
ValueObject::GetError() returns this if there is no result from the expression.
const lldb::ProcessSP & GetProcessSP() const
Get accessor to get the process shared pointer.
Generic errors that can be any value.
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:343
lldb::LanguageType GetLanguage() const
Definition: Target.h:264
bool InvokeCancelCallback(lldb::ExpressionEvaluationPhase phase) const
Definition: Target.h:353
void InstallContext(ExecutionContext &exe_ctx)
Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment.
uint64_t addr_t
Definition: lldb-types.h:83
A uniqued constant string class.
Definition: ConstString.h:38
Unknown or invalid language value.
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
bool LockAndCheckContext(ExecutionContext &exe_ctx, lldb::TargetSP &target_sp, lldb::ProcessSP &process_sp, lldb::StackFrameSP &frame_sp)
int void SetError(ValueType err, lldb::ErrorType type)
Set accesssor with an error value and type.
Definition: Status.cpp:216
Log * GetLogIfAnyCategoriesSet(uint32_t mask)
Definition: Logging.cpp:61
bool GetEnableNotifyAboutFixIts() const
Definition: Target.cpp:3920
virtual lldb::ExpressionResults DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result)=0
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
bool CanJIT()
Determines whether executing JIT-compiled code in this process is possible.
Definition: Process.cpp:2377
#define LIBLLDB_LOG_EXPRESSIONS
Definition: Logging.h:22
virtual void RemovePersistentVariable(lldb::ExpressionVariableSP variable)=0
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size, lldb::addr_t address=LLDB_INVALID_ADDRESS)
const DiagnosticList & Diagnostics()
lldb::ExpressionResults Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result)
Execute the parsed expression by callinng the derived class&#39;s DoExecute method.
ExecutionContextScope * GetBestExecutionContextScope() const
const char * GetPrefix() const
Definition: Target.h:270
#define LIBLLDB_LOG_STEP
Definition: Logging.h:21
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
ExecutionPolicy
Expression execution policies.
lldb::LanguageType GetLanguage() const
Definition: Target.cpp:3986
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)
Evaluate one expression in the scratch context of the target passed in the exe_ctx and return its res...
lldb::LanguageType m_language
The language to use when parsing (eLanguageTypeUnknown means use defaults)
PersistentExpressionState * GetPersistentExpressionStateForLanguage(lldb::LanguageType language)
Definition: Target.cpp:2206
This base class provides an interface to stack frames.
Definition: StackFrame.h:40
An error handling class.
Definition: Status.h:44
ExecutionPolicy GetExecutionPolicy() const
Definition: Target.h:258
~UserExpression() override
Destructor.