1 //===-- LLVMUserExpression.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 
10 #include "lldb/Expression/LLVMUserExpression.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/StreamFile.h"
13 #include "lldb/Core/ValueObjectConstResult.h"
14 #include "lldb/Expression/DiagnosticManager.h"
15 #include "lldb/Expression/ExpressionSourceCode.h"
16 #include "lldb/Expression/IRExecutionUnit.h"
17 #include "lldb/Expression/IRInterpreter.h"
18 #include "lldb/Expression/Materializer.h"
19 #include "lldb/Host/HostInfo.h"
20 #include "lldb/Symbol/Block.h"
21 #include "lldb/Symbol/ClangASTContext.h"
22 #include "lldb/Symbol/ClangExternalASTSourceCommon.h"
23 #include "lldb/Symbol/Function.h"
24 #include "lldb/Symbol/ObjectFile.h"
25 #include "lldb/Symbol/SymbolVendor.h"
26 #include "lldb/Symbol/Type.h"
27 #include "lldb/Symbol/VariableList.h"
28 #include "lldb/Target/ExecutionContext.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/StackFrame.h"
31 #include "lldb/Target/Target.h"
32 #include "lldb/Target/ThreadPlan.h"
33 #include "lldb/Target/ThreadPlanCallUserExpression.h"
34 #include "lldb/Utility/ConstString.h"
35 #include "lldb/Utility/Log.h"
36 #include "lldb/Utility/StreamString.h"
37 
38 using namespace lldb_private;
39 
40 LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope,
41                                        llvm::StringRef expr,
42                                        llvm::StringRef prefix,
43                                        lldb::LanguageType language,
44                                        ResultType desired_type,
45                                        const EvaluateExpressionOptions &options)
46     : UserExpression(exe_scope, expr, prefix, language, desired_type, options),
47       m_stack_frame_bottom(LLDB_INVALID_ADDRESS),
48       m_stack_frame_top(LLDB_INVALID_ADDRESS),
49       m_allow_cxx(false),
50       m_allow_objc(false),
51       m_transformed_text(),
52       m_execution_unit_sp(), m_materializer_ap(), m_jit_module_wp(),
53       m_enforce_valid_object(true), m_in_cplusplus_method(false),
54       m_in_objectivec_method(false), m_in_static_method(false),
55       m_needs_object_ptr(false), m_target(NULL), m_can_interpret(false),
56       m_materialized_address(LLDB_INVALID_ADDRESS) {}
57 
58 LLVMUserExpression::~LLVMUserExpression() {
59   if (m_target) {
60     lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
61     if (jit_module_sp)
62       m_target->GetImages().Remove(jit_module_sp);
63   }
64 }
65 
66 lldb::ExpressionResults
67 LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
68                               ExecutionContext &exe_ctx,
69                               const EvaluateExpressionOptions &options,
70                               lldb::UserExpressionSP &shared_ptr_to_me,
71                               lldb::ExpressionVariableSP &result) {
72   // The expression log is quite verbose, and if you're just tracking the
73   // execution of the expression, it's quite convenient to have these logs come
74   // out with the STEP log as well.
75   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
76                                                   LIBLLDB_LOG_STEP));
77 
78   if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) {
79     lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
80 
81     if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx,
82                                        struct_address)) {
83       diagnostic_manager.Printf(
84           eDiagnosticSeverityError,
85           "errored out in %s, couldn't PrepareToExecuteJITExpression",
86           __FUNCTION__);
87       return lldb::eExpressionSetupError;
88     }
89 
90     lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
91     lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
92 
93     if (m_can_interpret) {
94       llvm::Module *module = m_execution_unit_sp->GetModule();
95       llvm::Function *function = m_execution_unit_sp->GetFunction();
96 
97       if (!module || !function) {
98         diagnostic_manager.PutString(
99             eDiagnosticSeverityError,
100             "supposed to interpret, but nothing is there");
101         return lldb::eExpressionSetupError;
102       }
103 
104       Status interpreter_error;
105 
106       std::vector<lldb::addr_t> args;
107 
108       if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
109         diagnostic_manager.Printf(eDiagnosticSeverityError,
110                                   "errored out in %s, couldn't AddArguments",
111                                   __FUNCTION__);
112         return lldb::eExpressionSetupError;
113       }
114 
115       function_stack_bottom = m_stack_frame_bottom;
116       function_stack_top = m_stack_frame_top;
117 
118       IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp,
119                                interpreter_error, function_stack_bottom,
120                                function_stack_top, exe_ctx);
121 
122       if (!interpreter_error.Success()) {
123         diagnostic_manager.Printf(eDiagnosticSeverityError,
124                                   "supposed to interpret, but failed: %s",
125                                   interpreter_error.AsCString());
126         return lldb::eExpressionDiscarded;
127       }
128     } else {
129       if (!exe_ctx.HasThreadScope()) {
130         diagnostic_manager.Printf(eDiagnosticSeverityError,
131                                   "%s called with no thread selected",
132                                   __FUNCTION__);
133         return lldb::eExpressionSetupError;
134       }
135 
136       Address wrapper_address(m_jit_start_addr);
137 
138       std::vector<lldb::addr_t> args;
139 
140       if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
141         diagnostic_manager.Printf(eDiagnosticSeverityError,
142                                   "errored out in %s, couldn't AddArguments",
143                                   __FUNCTION__);
144         return lldb::eExpressionSetupError;
145       }
146 
147       lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(
148           exe_ctx.GetThreadRef(), wrapper_address, args, options,
149           shared_ptr_to_me));
150 
151       StreamString ss;
152       if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
153         diagnostic_manager.PutString(eDiagnosticSeverityError, ss.GetString());
154         return lldb::eExpressionSetupError;
155       }
156 
157       ThreadPlanCallUserExpression *user_expression_plan =
158           static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
159 
160       lldb::addr_t function_stack_pointer =
161           user_expression_plan->GetFunctionStackPointer();
162 
163       function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
164       function_stack_top = function_stack_pointer;
165 
166       if (log)
167         log->Printf(
168             "-- [UserExpression::Execute] Execution of expression begins --");
169 
170       if (exe_ctx.GetProcessPtr())
171         exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
172 
173       lldb::ExpressionResults execution_result =
174           exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options,
175                                                 diagnostic_manager);
176 
177       if (exe_ctx.GetProcessPtr())
178         exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
179 
180       if (log)
181         log->Printf("-- [UserExpression::Execute] Execution of expression "
182                     "completed --");
183 
184       if (execution_result == lldb::eExpressionInterrupted ||
185           execution_result == lldb::eExpressionHitBreakpoint) {
186         const char *error_desc = NULL;
187 
188         if (call_plan_sp) {
189           lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
190           if (real_stop_info_sp)
191             error_desc = real_stop_info_sp->GetDescription();
192         }
193         if (error_desc)
194           diagnostic_manager.Printf(eDiagnosticSeverityError,
195                                     "Execution was interrupted, reason: %s.",
196                                     error_desc);
197         else
198           diagnostic_manager.PutString(eDiagnosticSeverityError,
199                                        "Execution was interrupted.");
200 
201         if ((execution_result == lldb::eExpressionInterrupted &&
202              options.DoesUnwindOnError()) ||
203             (execution_result == lldb::eExpressionHitBreakpoint &&
204              options.DoesIgnoreBreakpoints()))
205           diagnostic_manager.AppendMessageToDiagnostic(
206               "The process has been returned to the state before expression "
207               "evaluation.");
208         else {
209           if (execution_result == lldb::eExpressionHitBreakpoint)
210             user_expression_plan->TransferExpressionOwnership();
211           diagnostic_manager.AppendMessageToDiagnostic(
212               "The process has been left at the point where it was "
213               "interrupted, "
214               "use \"thread return -x\" to return to the state before "
215               "expression evaluation.");
216         }
217 
218         return execution_result;
219       } else if (execution_result == lldb::eExpressionStoppedForDebug) {
220         diagnostic_manager.PutString(
221             eDiagnosticSeverityRemark,
222             "Execution was halted at the first instruction of the expression "
223             "function because \"debug\" was requested.\n"
224             "Use \"thread return -x\" to return to the state before expression "
225             "evaluation.");
226         return execution_result;
227       } else if (execution_result != lldb::eExpressionCompleted) {
228         diagnostic_manager.Printf(
229             eDiagnosticSeverityError,
230             "Couldn't execute function; result was %s",
231             Process::ExecutionResultAsCString(execution_result));
232         return execution_result;
233       }
234     }
235 
236     if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result,
237                              function_stack_bottom, function_stack_top)) {
238       return lldb::eExpressionCompleted;
239     } else {
240       return lldb::eExpressionResultUnavailable;
241     }
242   } else {
243     diagnostic_manager.PutString(
244         eDiagnosticSeverityError,
245         "Expression can't be run, because there is no JIT compiled function");
246     return lldb::eExpressionSetupError;
247   }
248 }
249 
250 bool LLVMUserExpression::FinalizeJITExecution(
251     DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
252     lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom,
253     lldb::addr_t function_stack_top) {
254   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
255 
256   if (log)
257     log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing "
258                 "after execution --");
259 
260   if (!m_dematerializer_sp) {
261     diagnostic_manager.Printf(eDiagnosticSeverityError,
262                               "Couldn't apply expression side effects : no "
263                               "dematerializer is present");
264     return false;
265   }
266 
267   Status dematerialize_error;
268 
269   m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom,
270                                      function_stack_top);
271 
272   if (!dematerialize_error.Success()) {
273     diagnostic_manager.Printf(eDiagnosticSeverityError,
274                               "Couldn't apply expression side effects : %s",
275                               dematerialize_error.AsCString("unknown error"));
276     return false;
277   }
278 
279   result =
280       GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope());
281 
282   if (result)
283     result->TransferAddress();
284 
285   m_dematerializer_sp.reset();
286 
287   return true;
288 }
289 
290 bool LLVMUserExpression::PrepareToExecuteJITExpression(
291     DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
292     lldb::addr_t &struct_address) {
293   lldb::TargetSP target;
294   lldb::ProcessSP process;
295   lldb::StackFrameSP frame;
296 
297   if (!LockAndCheckContext(exe_ctx, target, process, frame)) {
298     diagnostic_manager.PutString(
299         eDiagnosticSeverityError,
300         "The context has changed before we could JIT the expression!");
301     return false;
302   }
303 
304   if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) {
305     if (m_materialized_address == LLDB_INVALID_ADDRESS) {
306       Status alloc_error;
307 
308       IRMemoryMap::AllocationPolicy policy =
309           m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly
310                           : IRMemoryMap::eAllocationPolicyMirror;
311 
312       const bool zero_memory = false;
313 
314       m_materialized_address = m_execution_unit_sp->Malloc(
315           m_materializer_ap->GetStructByteSize(),
316           m_materializer_ap->GetStructAlignment(),
317           lldb::ePermissionsReadable | lldb::ePermissionsWritable, policy,
318           zero_memory, alloc_error);
319 
320       if (!alloc_error.Success()) {
321         diagnostic_manager.Printf(
322             eDiagnosticSeverityError,
323             "Couldn't allocate space for materialized struct: %s",
324             alloc_error.AsCString());
325         return false;
326       }
327     }
328 
329     struct_address = m_materialized_address;
330 
331     if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) {
332       Status alloc_error;
333 
334       const size_t stack_frame_size = 512 * 1024;
335 
336       const bool zero_memory = false;
337 
338       m_stack_frame_bottom = m_execution_unit_sp->Malloc(
339           stack_frame_size, 8,
340           lldb::ePermissionsReadable | lldb::ePermissionsWritable,
341           IRMemoryMap::eAllocationPolicyHostOnly, zero_memory, alloc_error);
342 
343       m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
344 
345       if (!alloc_error.Success()) {
346         diagnostic_manager.Printf(
347             eDiagnosticSeverityError,
348             "Couldn't allocate space for the stack frame: %s",
349             alloc_error.AsCString());
350         return false;
351       }
352     }
353 
354     Status materialize_error;
355 
356     m_dematerializer_sp = m_materializer_ap->Materialize(
357         frame, *m_execution_unit_sp, struct_address, materialize_error);
358 
359     if (!materialize_error.Success()) {
360       diagnostic_manager.Printf(eDiagnosticSeverityError,
361                                 "Couldn't materialize: %s",
362                                 materialize_error.AsCString());
363       return false;
364     }
365   }
366   return true;
367 }
368 
369 lldb::ModuleSP LLVMUserExpression::GetJITModule() {
370   if (m_execution_unit_sp)
371     return m_execution_unit_sp->GetJITModule();
372   return lldb::ModuleSP();
373 }
374