xref: /llvm-project/lldb/source/Expression/UserExpression.cpp (revision 3fcc302af34f648fb7a56557b6a504fcbf49a115)
1 //===-- UserExpression.cpp ------------------------------------------------===//
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 <cstdio>
10 #include <sys/types.h>
11 
12 #include <cstdlib>
13 #include <map>
14 #include <string>
15 
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/Progress.h"
18 #include "lldb/Expression/DiagnosticManager.h"
19 #include "lldb/Expression/ExpressionVariable.h"
20 #include "lldb/Expression/IRExecutionUnit.h"
21 #include "lldb/Expression/IRInterpreter.h"
22 #include "lldb/Expression/Materializer.h"
23 #include "lldb/Expression/UserExpression.h"
24 #include "lldb/Host/HostInfo.h"
25 #include "lldb/Symbol/Block.h"
26 #include "lldb/Symbol/Function.h"
27 #include "lldb/Symbol/ObjectFile.h"
28 #include "lldb/Symbol/SymbolVendor.h"
29 #include "lldb/Symbol/Type.h"
30 #include "lldb/Symbol/TypeSystem.h"
31 #include "lldb/Symbol/VariableList.h"
32 #include "lldb/Target/ExecutionContext.h"
33 #include "lldb/Target/Process.h"
34 #include "lldb/Target/StackFrame.h"
35 #include "lldb/Target/Target.h"
36 #include "lldb/Target/ThreadPlan.h"
37 #include "lldb/Target/ThreadPlanCallUserExpression.h"
38 #include "lldb/Utility/LLDBLog.h"
39 #include "lldb/Utility/Log.h"
40 #include "lldb/Utility/State.h"
41 #include "lldb/Utility/StreamString.h"
42 #include "lldb/ValueObject/ValueObjectConstResult.h"
43 #include "llvm/BinaryFormat/Dwarf.h"
44 
45 using namespace lldb_private;
46 
47 char UserExpression::ID;
48 
49 UserExpression::UserExpression(ExecutionContextScope &exe_scope,
50                                llvm::StringRef expr, llvm::StringRef prefix,
51                                SourceLanguage language, ResultType desired_type,
52                                const EvaluateExpressionOptions &options)
53     : Expression(exe_scope), m_expr_text(std::string(expr)),
54       m_expr_prefix(std::string(prefix)), m_language(language),
55       m_desired_type(desired_type), m_options(options) {}
56 
57 UserExpression::~UserExpression() = default;
58 
59 void UserExpression::InstallContext(ExecutionContext &exe_ctx) {
60   m_jit_process_wp = exe_ctx.GetProcessSP();
61 
62   lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
63 
64   if (frame_sp)
65     m_address = frame_sp->GetFrameCodeAddress();
66 }
67 
68 bool UserExpression::LockAndCheckContext(ExecutionContext &exe_ctx,
69                                          lldb::TargetSP &target_sp,
70                                          lldb::ProcessSP &process_sp,
71                                          lldb::StackFrameSP &frame_sp) {
72   lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
73   process_sp = exe_ctx.GetProcessSP();
74 
75   if (process_sp != expected_process_sp)
76     return false;
77 
78   process_sp = exe_ctx.GetProcessSP();
79   target_sp = exe_ctx.GetTargetSP();
80   frame_sp = exe_ctx.GetFrameSP();
81 
82   if (m_address.IsValid()) {
83     if (!frame_sp)
84       return false;
85     return (Address::CompareLoadAddress(m_address,
86                                         frame_sp->GetFrameCodeAddress(),
87                                         target_sp.get()) == 0);
88   }
89 
90   return true;
91 }
92 
93 bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) {
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::ValueObjectSP UserExpression::GetObjectPointerValueObject(
102     lldb::StackFrameSP frame_sp, llvm::StringRef object_name, Status &err) {
103   err.Clear();
104 
105   if (!frame_sp) {
106     err = Status::FromErrorStringWithFormatv(
107         "Couldn't load '{0}' because the context is incomplete", object_name);
108     return {};
109   }
110 
111   lldb::VariableSP var_sp;
112   lldb::ValueObjectSP valobj_sp;
113 
114   return frame_sp->GetValueForVariableExpressionPath(
115       object_name, lldb::eNoDynamicValues,
116       StackFrame::eExpressionPathOptionCheckPtrVsMember |
117           StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
118           StackFrame::eExpressionPathOptionsNoSyntheticChildren |
119           StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
120       var_sp, err);
121 }
122 
123 lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp,
124                                               llvm::StringRef object_name,
125                                               Status &err) {
126   auto valobj_sp =
127       GetObjectPointerValueObject(std::move(frame_sp), object_name, err);
128 
129   if (!err.Success() || !valobj_sp.get())
130     return LLDB_INVALID_ADDRESS;
131 
132   lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
133 
134   if (ret == LLDB_INVALID_ADDRESS) {
135     err = Status::FromErrorStringWithFormatv(
136         "Couldn't load '{0}' because its value couldn't be evaluated",
137         object_name);
138     return LLDB_INVALID_ADDRESS;
139   }
140 
141   return ret;
142 }
143 
144 lldb::ExpressionResults
145 UserExpression::Evaluate(ExecutionContext &exe_ctx,
146                          const EvaluateExpressionOptions &options,
147                          llvm::StringRef expr, llvm::StringRef prefix,
148                          lldb::ValueObjectSP &result_valobj_sp,
149                          std::string *fixed_expression, ValueObject *ctx_obj) {
150   Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));
151   auto set_error = [&](Status error) {
152     result_valobj_sp = ValueObjectConstResult::Create(
153         exe_ctx.GetBestExecutionContextScope(), std::move(error));
154   };
155 
156   if (ctx_obj) {
157     static unsigned const ctx_type_mask = lldb::TypeFlags::eTypeIsClass |
158                                           lldb::TypeFlags::eTypeIsStructUnion |
159                                           lldb::TypeFlags::eTypeIsReference;
160     if (!(ctx_obj->GetTypeInfo() & ctx_type_mask)) {
161       LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of "
162                     "an invalid type, can't run expressions.");
163       set_error(Status("a context object of an invalid type passed"));
164       return lldb::eExpressionSetupError;
165     }
166   }
167 
168   if (ctx_obj && ctx_obj->GetTypeInfo() & lldb::TypeFlags::eTypeIsReference) {
169     Status error;
170     lldb::ValueObjectSP deref_ctx_sp = ctx_obj->Dereference(error);
171     if (!error.Success()) {
172       LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of "
173                     "a reference type that can't be dereferenced, can't run "
174                     "expressions.");
175       set_error(Status(
176           "passed context object of an reference type cannot be deferenced"));
177       return lldb::eExpressionSetupError;
178     }
179 
180     ctx_obj = deref_ctx_sp.get();
181   }
182 
183   lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
184   SourceLanguage language = options.GetLanguage();
185   const ResultType desired_type = options.DoesCoerceToId()
186                                       ? UserExpression::eResultTypeId
187                                       : UserExpression::eResultTypeAny;
188   Target *target = exe_ctx.GetTargetPtr();
189   if (!target) {
190     LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a NULL target, can't "
191                   "run expressions.");
192     set_error(Status("expression passed a null target"));
193     return lldb::eExpressionSetupError;
194   }
195 
196   Process *process = exe_ctx.GetProcessPtr();
197 
198   if (!process && execution_policy == eExecutionPolicyAlways) {
199     LLDB_LOG(log, "== [UserExpression::Evaluate] No process, but the policy is "
200                   "eExecutionPolicyAlways");
201 
202     set_error(Status("expression needed to run but couldn't: no process"));
203 
204     return lldb::eExpressionSetupError;
205   }
206 
207   // Since we might need to allocate memory, we need to be stopped to run
208   // an expression.
209   if (process && process->GetState() != lldb::eStateStopped) {
210     set_error(Status::FromErrorStringWithFormatv(
211         "unable to evaluate expression while the process is {0}: the process "
212         "must be stopped because the expression might require allocating "
213         "memory.",
214         StateAsCString(process->GetState())));
215     return lldb::eExpressionSetupError;
216   }
217 
218   // Explicitly force the IR interpreter to evaluate the expression when the
219   // there is no process that supports running the expression for us. Don't
220   // change the execution policy if we have the special top-level policy that
221   // doesn't contain any expression and there is nothing to interpret.
222   if (execution_policy != eExecutionPolicyTopLevel &&
223       (process == nullptr || !process->CanJIT()))
224     execution_policy = eExecutionPolicyNever;
225 
226   // We need to set the expression execution thread here, turns out parse can
227   // call functions in the process of looking up symbols, which will escape the
228   // context set by exe_ctx passed to Execute.
229   lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
230   ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(
231       thread_sp);
232 
233   llvm::StringRef full_prefix;
234   llvm::StringRef option_prefix(options.GetPrefix());
235   std::string full_prefix_storage;
236   if (!prefix.empty() && !option_prefix.empty()) {
237     full_prefix_storage = std::string(prefix);
238     full_prefix_storage.append(std::string(option_prefix));
239     full_prefix = full_prefix_storage;
240   } else if (!prefix.empty())
241     full_prefix = prefix;
242   else
243     full_prefix = option_prefix;
244 
245   // If the language was not specified in the expression command, set it to the
246   // language in the target's properties if specified, else default to the
247   // langage for the frame.
248   if (!language) {
249     if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
250       language = target->GetLanguage();
251     else if (StackFrame *frame = exe_ctx.GetFramePtr())
252       language = frame->GetLanguage();
253   }
254 
255   Status error;
256   lldb::UserExpressionSP user_expression_sp(
257       target->GetUserExpressionForLanguage(
258           expr, full_prefix, language, desired_type, options, ctx_obj, error));
259   if (error.Fail() || !user_expression_sp) {
260     LLDB_LOG(log, "== [UserExpression::Evaluate] Getting expression: {0} ==",
261              error.AsCString());
262     set_error(std::move(error));
263     return lldb::eExpressionSetupError;
264   }
265 
266   LLDB_LOG(log, "== [UserExpression::Evaluate] Parsing expression {0} ==",
267            expr.str());
268 
269   const bool keep_expression_in_memory = true;
270   const bool generate_debug_info = options.GetGenerateDebugInfo();
271 
272   if (options.InvokeCancelCallback(lldb::eExpressionEvaluationParse)) {
273     set_error(Status("expression interrupted by callback before parse"));
274     return lldb::eExpressionInterrupted;
275   }
276 
277   DiagnosticManager diagnostic_manager;
278 
279   bool parse_success =
280       user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy,
281                                 keep_expression_in_memory, generate_debug_info);
282 
283   // Calculate the fixed expression always, since we need it for errors.
284   std::string tmp_fixed_expression;
285   if (fixed_expression == nullptr)
286     fixed_expression = &tmp_fixed_expression;
287 
288   *fixed_expression = user_expression_sp->GetFixedText().str();
289   lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
290 
291   // If there is a fixed expression, try to parse it:
292   if (!parse_success) {
293     // Delete the expression that failed to parse before attempting to parse
294     // the next expression.
295     user_expression_sp.reset();
296 
297     execution_results = lldb::eExpressionParseError;
298     if (!fixed_expression->empty() && options.GetAutoApplyFixIts()) {
299       const uint64_t max_fix_retries = options.GetRetriesWithFixIts();
300       for (uint64_t i = 0; i < max_fix_retries; ++i) {
301         // Try parsing the fixed expression.
302         lldb::UserExpressionSP fixed_expression_sp(
303             target->GetUserExpressionForLanguage(
304                 fixed_expression->c_str(), full_prefix, language, desired_type,
305                 options, ctx_obj, error));
306         if (!fixed_expression_sp)
307           break;
308         DiagnosticManager fixed_diagnostic_manager;
309         parse_success = fixed_expression_sp->Parse(
310             fixed_diagnostic_manager, exe_ctx, execution_policy,
311             keep_expression_in_memory, generate_debug_info);
312         if (parse_success) {
313           diagnostic_manager.Clear();
314           user_expression_sp = fixed_expression_sp;
315           break;
316         }
317         // The fixed expression also didn't parse. Let's check for any new
318         // fixits we could try.
319         if (!fixed_expression_sp->GetFixedText().empty()) {
320           *fixed_expression = fixed_expression_sp->GetFixedText().str();
321         } else {
322           // Fixed expression didn't compile without a fixit, don't retry and
323           // don't tell the user about it.
324           fixed_expression->clear();
325           break;
326         }
327       }
328     }
329 
330     if (!parse_success) {
331       if (target->GetEnableNotifyAboutFixIts() && fixed_expression &&
332           !fixed_expression->empty()) {
333         std::string fixit =
334             "fixed expression suggested:\n  " + *fixed_expression;
335         diagnostic_manager.AddDiagnostic(fixit, lldb::eSeverityInfo,
336                                          eDiagnosticOriginLLDB);
337       }
338       if (diagnostic_manager.Diagnostics().empty())
339         error = Status::FromError(llvm::make_error<ExpressionError>(
340             execution_results,
341             "expression failed to parse (no further compiler diagnostics)"));
342       else
343         error =
344             Status::FromError(diagnostic_manager.GetAsError(execution_results));
345     }
346   }
347 
348   if (parse_success) {
349     lldb::ExpressionVariableSP expr_result;
350 
351     if (execution_policy == eExecutionPolicyNever &&
352         !user_expression_sp->CanInterpret()) {
353       LLDB_LOG(log, "== [UserExpression::Evaluate] Expression may not run, but "
354                     "is not constant ==");
355 
356       if (diagnostic_manager.Diagnostics().empty())
357         error = Status::FromError(llvm::make_error<ExpressionError>(
358             lldb::eExpressionSetupError,
359             "expression needed to run but couldn't"));
360     } else if (execution_policy == eExecutionPolicyTopLevel) {
361       set_error(Status(UserExpression::kNoResult, lldb::eErrorTypeGeneric));
362       return lldb::eExpressionCompleted;
363     } else {
364       if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) {
365         set_error(Status::FromError(llvm::make_error<ExpressionError>(
366             lldb::eExpressionInterrupted,
367             "expression interrupted by callback before execution")));
368         return lldb::eExpressionInterrupted;
369       }
370 
371       diagnostic_manager.Clear();
372 
373       LLDB_LOG(log, "== [UserExpression::Evaluate] Executing expression ==");
374 
375       execution_results =
376           user_expression_sp->Execute(diagnostic_manager, exe_ctx, options,
377                                       user_expression_sp, expr_result);
378 
379       if (execution_results != lldb::eExpressionCompleted) {
380         LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
381                       "abnormally ==");
382 
383         if (diagnostic_manager.Diagnostics().empty())
384           error = Status::FromError(llvm::make_error<ExpressionError>(
385               execution_results,
386               "expression failed to execute, unknown error"));
387         else
388           error = Status::FromError(
389               diagnostic_manager.GetAsError(execution_results));
390       } else {
391         if (expr_result) {
392           result_valobj_sp = expr_result->GetValueObject();
393           result_valobj_sp->SetPreferredDisplayLanguage(
394               language.AsLanguageType());
395 
396           LLDB_LOG(log,
397                    "== [UserExpression::Evaluate] Execution completed "
398                    "normally with result {0} ==",
399                    result_valobj_sp->GetValueAsCString());
400         } else {
401           LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
402                         "normally with no result ==");
403 
404           error = Status(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
405         }
406       }
407     }
408   }
409 
410   if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) {
411     set_error(Status::FromError(llvm::make_error<ExpressionError>(
412         lldb::eExpressionInterrupted,
413         "expression interrupted by callback after complete")));
414     return lldb::eExpressionInterrupted;
415   }
416 
417   if (error.Fail())
418     set_error(std::move(error));
419   return execution_results;
420 }
421 
422 lldb::ExpressionResults
423 UserExpression::Execute(DiagnosticManager &diagnostic_manager,
424                         ExecutionContext &exe_ctx,
425                         const EvaluateExpressionOptions &options,
426                         lldb::UserExpressionSP &shared_ptr_to_me,
427                         lldb::ExpressionVariableSP &result_var) {
428   Debugger *debugger =
429       exe_ctx.GetTargetPtr() ? &exe_ctx.GetTargetPtr()->GetDebugger() : nullptr;
430   std::string details;
431   if (m_options.IsForUtilityExpr())
432     details = "LLDB utility";
433   else if (m_expr_text.size() > 15)
434     details = m_expr_text.substr(0, 14) + "…";
435   else
436     details = m_expr_text;
437 
438   Progress progress("Running expression", details, {}, debugger);
439 
440   lldb::ExpressionResults expr_result = DoExecute(
441       diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
442   Target *target = exe_ctx.GetTargetPtr();
443   if (options.GetSuppressPersistentResult() && result_var && target) {
444     if (auto *persistent_state =
445             target->GetPersistentExpressionStateForLanguage(
446                 m_language.AsLanguageType()))
447       persistent_state->RemovePersistentVariable(result_var);
448   }
449   return expr_result;
450 }
451