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