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