blob: 8c1c7bf3040ee3517c342babca643f625ce962ea [file] [log] [blame]
Ryan Brown998c8a1c12015-11-02 19:30:40 +00001//===-- 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
41using namespace lldb_private;
42
Jim Ingham19a63fc2015-11-03 02:11:24 +000043LLVMUserExpression::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),
Ryan Brown998c8a1c12015-11-02 19:30:40 +000050 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
68LLVMUserExpression::~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
78lldb::ExpressionResults
79LLVMUserExpression::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
245bool
246LLVMUserExpression::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
282bool
283LLVMUserExpression::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 m_materialized_address = m_execution_unit_sp->Malloc(
306 m_materializer_ap->GetStructByteSize(), m_materializer_ap->GetStructAlignment(),
307 lldb::ePermissionsReadable | lldb::ePermissionsWritable, policy, alloc_error);
308
309 if (!alloc_error.Success())
310 {
311 error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
312 return false;
313 }
314 }
315
316 struct_address = m_materialized_address;
317
318 if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
319 {
320 Error alloc_error;
321
322 const size_t stack_frame_size = 512 * 1024;
323
324 m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size, 8,
325 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
326 IRMemoryMap::eAllocationPolicyHostOnly, alloc_error);
327
328 m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
329
330 if (!alloc_error.Success())
331 {
332 error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
333 return false;
334 }
335 }
336
337 Error materialize_error;
338
339 m_dematerializer_sp =
340 m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
341
342 if (!materialize_error.Success())
343 {
344 error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
345 return false;
346 }
347 }
348 return true;
349}
350
351lldb::ModuleSP
352LLVMUserExpression::GetJITModule()
353{
354 if (m_execution_unit_sp)
355 return m_execution_unit_sp->GetJITModule();
356 return lldb::ModuleSP();
357}