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/StreamFile.h"
18 #include "lldb/Core/ValueObjectConstResult.h"
19 #include "lldb/Expression/DiagnosticManager.h"
20 #include "lldb/Expression/ExpressionVariable.h"
21 #include "lldb/Expression/IRExecutionUnit.h"
22 #include "lldb/Expression/IRInterpreter.h"
23 #include "lldb/Expression/Materializer.h"
24 #include "lldb/Expression/UserExpression.h"
25 #include "lldb/Host/HostInfo.h"
26 #include "lldb/Symbol/Block.h"
27 #include "lldb/Symbol/Function.h"
28 #include "lldb/Symbol/ObjectFile.h"
29 #include "lldb/Symbol/SymbolVendor.h"
30 #include "lldb/Symbol/Type.h"
31 #include "lldb/Symbol/TypeSystem.h"
32 #include "lldb/Symbol/VariableList.h"
33 #include "lldb/Target/ExecutionContext.h"
34 #include "lldb/Target/Process.h"
35 #include "lldb/Target/StackFrame.h"
36 #include "lldb/Target/Target.h"
37 #include "lldb/Target/ThreadPlan.h"
38 #include "lldb/Target/ThreadPlanCallUserExpression.h"
39 #include "lldb/Utility/ConstString.h"
40 #include "lldb/Utility/LLDBLog.h"
41 #include "lldb/Utility/Log.h"
42 #include "lldb/Utility/State.h"
43 #include "lldb/Utility/StreamString.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                                lldb::LanguageType language,
52                                ResultType desired_type,
53                                const EvaluateExpressionOptions &options)
54     : Expression(exe_scope), m_expr_text(std::string(expr)),
55       m_expr_prefix(std::string(prefix)), m_language(language),
56       m_desired_type(desired_type), m_options(options) {}
57 
58 UserExpression::~UserExpression() = default;
59 
60 void UserExpression::InstallContext(ExecutionContext &exe_ctx) {
61   m_jit_process_wp = exe_ctx.GetProcessSP();
62 
63   lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
64 
65   if (frame_sp)
66     m_address = frame_sp->GetFrameCodeAddress();
67 }
68 
69 bool UserExpression::LockAndCheckContext(ExecutionContext &exe_ctx,
70                                          lldb::TargetSP &target_sp,
71                                          lldb::ProcessSP &process_sp,
72                                          lldb::StackFrameSP &frame_sp) {
73   lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
74   process_sp = exe_ctx.GetProcessSP();
75 
76   if (process_sp != expected_process_sp)
77     return false;
78 
79   process_sp = exe_ctx.GetProcessSP();
80   target_sp = exe_ctx.GetTargetSP();
81   frame_sp = exe_ctx.GetFrameSP();
82 
83   if (m_address.IsValid()) {
84     if (!frame_sp)
85       return false;
86     return (Address::CompareLoadAddress(m_address,
87                                         frame_sp->GetFrameCodeAddress(),
88                                         target_sp.get()) == 0);
89   }
90 
91   return true;
92 }
93 
94 bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) {
95   lldb::TargetSP target_sp;
96   lldb::ProcessSP process_sp;
97   lldb::StackFrameSP frame_sp;
98 
99   return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
100 }
101 
102 lldb::ValueObjectSP UserExpression::GetObjectPointerValueObject(
103     lldb::StackFrameSP frame_sp, ConstString const &object_name, Status &err) {
104   err.Clear();
105 
106   if (!frame_sp) {
107     err.SetErrorStringWithFormat(
108         "Couldn't load '%s' because the context is incomplete",
109         object_name.AsCString());
110     return {};
111   }
112 
113   lldb::VariableSP var_sp;
114   lldb::ValueObjectSP valobj_sp;
115 
116   return frame_sp->GetValueForVariableExpressionPath(
117       object_name.GetStringRef(), lldb::eNoDynamicValues,
118       StackFrame::eExpressionPathOptionCheckPtrVsMember |
119           StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
120           StackFrame::eExpressionPathOptionsNoSyntheticChildren |
121           StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
122       var_sp, err);
123 }
124 
125 lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp,
126                                               ConstString &object_name,
127                                               Status &err) {
128   auto valobj_sp =
129       GetObjectPointerValueObject(std::move(frame_sp), object_name, err);
130 
131   if (!err.Success() || !valobj_sp.get())
132     return LLDB_INVALID_ADDRESS;
133 
134   lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
135 
136   if (ret == LLDB_INVALID_ADDRESS) {
137     err.SetErrorStringWithFormat(
138         "Couldn't load '%s' because its value couldn't be evaluated",
139         object_name.AsCString());
140     return LLDB_INVALID_ADDRESS;
141   }
142 
143   return ret;
144 }
145 
146 lldb::ExpressionResults
147 UserExpression::Evaluate(ExecutionContext &exe_ctx,
148                          const EvaluateExpressionOptions &options,
149                          llvm::StringRef expr, llvm::StringRef prefix,
150                          lldb::ValueObjectSP &result_valobj_sp, Status &error,
151                          std::string *fixed_expression, ValueObject *ctx_obj) {
152   Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));
153 
154   if (ctx_obj) {
155     static unsigned const ctx_type_mask = lldb::TypeFlags::eTypeIsClass |
156                                           lldb::TypeFlags::eTypeIsStructUnion |
157                                           lldb::TypeFlags::eTypeIsReference;
158     if (!(ctx_obj->GetTypeInfo() & ctx_type_mask)) {
159       LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of "
160                     "an invalid type, can't run expressions.");
161       error.SetErrorString("a context object of an invalid type passed");
162       return lldb::eExpressionSetupError;
163     }
164   }
165 
166   if (ctx_obj && ctx_obj->GetTypeInfo() & lldb::TypeFlags::eTypeIsReference) {
167     Status error;
168     lldb::ValueObjectSP deref_ctx_sp = ctx_obj->Dereference(error);
169     if (!error.Success()) {
170       LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of "
171                     "a reference type that can't be dereferenced, can't run "
172                     "expressions.");
173       error.SetErrorString(
174           "passed context object of an reference type cannot be deferenced");
175       return lldb::eExpressionSetupError;
176     }
177 
178     ctx_obj = deref_ctx_sp.get();
179   }
180 
181   lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
182   lldb::LanguageType language = options.GetLanguage();
183   const ResultType desired_type = options.DoesCoerceToId()
184                                       ? UserExpression::eResultTypeId
185                                       : UserExpression::eResultTypeAny;
186   lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
187 
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     error.SetErrorString("expression passed a null target");
193     return lldb::eExpressionSetupError;
194   }
195 
196   Process *process = exe_ctx.GetProcessPtr();
197 
198   if (process == nullptr && execution_policy == eExecutionPolicyAlways) {
199     LLDB_LOG(log, "== [UserExpression::Evaluate] No process, but the policy is "
200                   "eExecutionPolicyAlways");
201 
202     error.SetErrorString("expression needed to run but couldn't: no process");
203 
204     return execution_results;
205   }
206 
207   // Since we might need to allocate memory, we need to be stopped to run
208   // an expression.
209   if (process != nullptr && process->GetState() != lldb::eStateStopped) {
210     error.SetErrorStringWithFormatv(
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 execution_results;
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 == lldb::eLanguageTypeUnknown) {
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   lldb::UserExpressionSP user_expression_sp(
256       target->GetUserExpressionForLanguage(expr, full_prefix, language,
257                                            desired_type, options, ctx_obj,
258                                            error));
259   if (error.Fail()) {
260     LLDB_LOG(log, "== [UserExpression::Evaluate] Getting expression: {0} ==",
261              error.AsCString());
262     return lldb::eExpressionSetupError;
263   }
264 
265   LLDB_LOG(log, "== [UserExpression::Evaluate] Parsing expression {0} ==",
266            expr.str());
267 
268   const bool keep_expression_in_memory = true;
269   const bool generate_debug_info = options.GetGenerateDebugInfo();
270 
271   if (options.InvokeCancelCallback(lldb::eExpressionEvaluationParse)) {
272     error.SetErrorString("expression interrupted by callback before parse");
273     result_valobj_sp = ValueObjectConstResult::Create(
274         exe_ctx.GetBestExecutionContextScope(), error);
275     return lldb::eExpressionInterrupted;
276   }
277 
278   DiagnosticManager diagnostic_manager;
279 
280   bool parse_success =
281       user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy,
282                                 keep_expression_in_memory, generate_debug_info);
283 
284   // Calculate the fixed expression always, since we need it for errors.
285   std::string tmp_fixed_expression;
286   if (fixed_expression == nullptr)
287     fixed_expression = &tmp_fixed_expression;
288 
289   *fixed_expression = user_expression_sp->GetFixedText().str();
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         DiagnosticManager fixed_diagnostic_manager;
307         parse_success = fixed_expression_sp->Parse(
308             fixed_diagnostic_manager, exe_ctx, execution_policy,
309             keep_expression_in_memory, generate_debug_info);
310         if (parse_success) {
311           diagnostic_manager.Clear();
312           user_expression_sp = fixed_expression_sp;
313           break;
314         } else {
315           // The fixed expression also didn't parse. Let's check for any new
316           // Fix-Its we could try.
317           if (!fixed_expression_sp->GetFixedText().empty()) {
318             *fixed_expression = fixed_expression_sp->GetFixedText().str();
319           } else {
320             // Fixed expression didn't compile without a fixit, don't retry and
321             // don't tell the user about it.
322             fixed_expression->clear();
323             break;
324           }
325         }
326       }
327     }
328 
329     if (!parse_success) {
330       std::string msg;
331       {
332         llvm::raw_string_ostream os(msg);
333         if (!diagnostic_manager.Diagnostics().empty())
334           os << diagnostic_manager.GetString();
335         else
336           os << "expression failed to parse (no further compiler diagnostics)";
337         if (target->GetEnableNotifyAboutFixIts() && fixed_expression &&
338             !fixed_expression->empty())
339           os << "\nfixed expression suggested:\n  " << *fixed_expression;
340       }
341       error.SetExpressionError(execution_results, msg.c_str());
342     }
343   }
344 
345   if (parse_success) {
346     lldb::ExpressionVariableSP expr_result;
347 
348     if (execution_policy == eExecutionPolicyNever &&
349         !user_expression_sp->CanInterpret()) {
350       LLDB_LOG(log, "== [UserExpression::Evaluate] Expression may not run, but "
351                     "is not constant ==");
352 
353       if (!diagnostic_manager.Diagnostics().size())
354         error.SetExpressionError(lldb::eExpressionSetupError,
355                                  "expression needed to run but couldn't");
356     } else if (execution_policy == eExecutionPolicyTopLevel) {
357       error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
358       return lldb::eExpressionCompleted;
359     } else {
360       if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) {
361         error.SetExpressionError(
362             lldb::eExpressionInterrupted,
363             "expression interrupted by callback before execution");
364         result_valobj_sp = ValueObjectConstResult::Create(
365             exe_ctx.GetBestExecutionContextScope(), error);
366         return lldb::eExpressionInterrupted;
367       }
368 
369       diagnostic_manager.Clear();
370 
371       LLDB_LOG(log, "== [UserExpression::Evaluate] Executing expression ==");
372 
373       execution_results =
374           user_expression_sp->Execute(diagnostic_manager, exe_ctx, options,
375                                       user_expression_sp, expr_result);
376 
377       if (execution_results != lldb::eExpressionCompleted) {
378         LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
379                       "abnormally ==");
380 
381         if (!diagnostic_manager.Diagnostics().size())
382           error.SetExpressionError(
383               execution_results, "expression failed to execute, unknown error");
384         else
385           error.SetExpressionError(execution_results,
386                                    diagnostic_manager.GetString().c_str());
387       } else {
388         if (expr_result) {
389           result_valobj_sp = expr_result->GetValueObject();
390           result_valobj_sp->SetPreferredDisplayLanguage(language);
391 
392           LLDB_LOG(log,
393                    "== [UserExpression::Evaluate] Execution completed "
394                    "normally with result {0} ==",
395                    result_valobj_sp->GetValueAsCString());
396         } else {
397           LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
398                         "normally with no result ==");
399 
400           error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
401         }
402       }
403     }
404   }
405 
406   if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) {
407     error.SetExpressionError(
408         lldb::eExpressionInterrupted,
409         "expression interrupted by callback after complete");
410     return lldb::eExpressionInterrupted;
411   }
412 
413   if (result_valobj_sp.get() == nullptr) {
414     result_valobj_sp = ValueObjectConstResult::Create(
415         exe_ctx.GetBestExecutionContextScope(), error);
416   }
417 
418   return execution_results;
419 }
420 
421 lldb::ExpressionResults
422 UserExpression::Execute(DiagnosticManager &diagnostic_manager,
423                         ExecutionContext &exe_ctx,
424                         const EvaluateExpressionOptions &options,
425                         lldb::UserExpressionSP &shared_ptr_to_me,
426                         lldb::ExpressionVariableSP &result_var) {
427   lldb::ExpressionResults expr_result = DoExecute(
428       diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
429   Target *target = exe_ctx.GetTargetPtr();
430   if (options.GetSuppressPersistentResult() && result_var && target) {
431     if (auto *persistent_state =
432             target->GetPersistentExpressionStateForLanguage(m_language))
433       persistent_state->RemovePersistentVariable(result_var);
434   }
435   return expr_result;
436 }
437