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