1151c032cSJim Ingham //===-- UserExpression.cpp ---------------------------------*- C++ -*-===//
2151c032cSJim Ingham //
3151c032cSJim Ingham //                     The LLVM Compiler Infrastructure
4151c032cSJim Ingham //
5151c032cSJim Ingham // This file is distributed under the University of Illinois Open Source
6151c032cSJim Ingham // License. See LICENSE.TXT for details.
7151c032cSJim Ingham //
8151c032cSJim Ingham //===----------------------------------------------------------------------===//
9151c032cSJim Ingham 
10151c032cSJim Ingham #include <stdio.h>
11151c032cSJim Ingham #if HAVE_SYS_TYPES_H
12151c032cSJim Ingham #  include <sys/types.h>
13151c032cSJim Ingham #endif
14151c032cSJim Ingham 
15151c032cSJim Ingham #include <cstdlib>
16151c032cSJim Ingham #include <string>
17151c032cSJim Ingham #include <map>
18151c032cSJim Ingham 
19151c032cSJim Ingham #include "lldb/Core/ConstString.h"
20151c032cSJim Ingham #include "lldb/Core/Log.h"
21151c032cSJim Ingham #include "lldb/Core/Module.h"
22151c032cSJim Ingham #include "lldb/Core/StreamFile.h"
23151c032cSJim Ingham #include "lldb/Core/StreamString.h"
24151c032cSJim Ingham #include "lldb/Core/ValueObjectConstResult.h"
25151c032cSJim Ingham #include "lldb/Expression/ExpressionSourceCode.h"
26151c032cSJim Ingham #include "lldb/Expression/IRExecutionUnit.h"
27151c032cSJim Ingham #include "lldb/Expression/IRInterpreter.h"
28151c032cSJim Ingham #include "lldb/Expression/Materializer.h"
29151c032cSJim Ingham #include "lldb/Expression/UserExpression.h"
304dbb271fSSean Callanan #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
31151c032cSJim Ingham #include "lldb/Host/HostInfo.h"
32151c032cSJim Ingham #include "lldb/Symbol/Block.h"
33151c032cSJim Ingham #include "lldb/Symbol/Function.h"
34151c032cSJim Ingham #include "lldb/Symbol/ObjectFile.h"
35151c032cSJim Ingham #include "lldb/Symbol/SymbolVendor.h"
36151c032cSJim Ingham #include "lldb/Symbol/Type.h"
378f1f9a1bSSean Callanan #include "lldb/Symbol/TypeSystem.h"
38151c032cSJim Ingham #include "lldb/Symbol/VariableList.h"
39151c032cSJim Ingham #include "lldb/Target/ExecutionContext.h"
40151c032cSJim Ingham #include "lldb/Target/Process.h"
41151c032cSJim Ingham #include "lldb/Target/StackFrame.h"
42151c032cSJim Ingham #include "lldb/Target/Target.h"
43151c032cSJim Ingham #include "lldb/Target/ThreadPlan.h"
44151c032cSJim Ingham #include "lldb/Target/ThreadPlanCallUserExpression.h"
45151c032cSJim Ingham 
46151c032cSJim Ingham using namespace lldb_private;
47151c032cSJim Ingham 
48151c032cSJim Ingham UserExpression::UserExpression (ExecutionContextScope &exe_scope,
49151c032cSJim Ingham                                 const char *expr,
50151c032cSJim Ingham                                 const char *expr_prefix,
51151c032cSJim Ingham                                 lldb::LanguageType language,
52151c032cSJim Ingham                                 ResultType desired_type) :
53151c032cSJim Ingham     Expression (exe_scope),
54151c032cSJim Ingham     m_stack_frame_bottom (LLDB_INVALID_ADDRESS),
55151c032cSJim Ingham     m_stack_frame_top (LLDB_INVALID_ADDRESS),
56151c032cSJim Ingham     m_expr_text (expr),
57151c032cSJim Ingham     m_expr_prefix (expr_prefix ? expr_prefix : ""),
58151c032cSJim Ingham     m_language (language),
59151c032cSJim Ingham     m_transformed_text (),
60151c032cSJim Ingham     m_desired_type (desired_type),
61151c032cSJim Ingham     m_execution_unit_sp(),
62151c032cSJim Ingham     m_materializer_ap(),
63151c032cSJim Ingham     m_jit_module_wp(),
64151c032cSJim Ingham     m_enforce_valid_object (true),
65151c032cSJim Ingham     m_in_cplusplus_method (false),
66151c032cSJim Ingham     m_in_objectivec_method (false),
67151c032cSJim Ingham     m_in_static_method(false),
68151c032cSJim Ingham     m_needs_object_ptr (false),
69151c032cSJim Ingham     m_const_object (false),
70151c032cSJim Ingham     m_target (NULL),
71151c032cSJim Ingham     m_can_interpret (false),
72151c032cSJim Ingham     m_materialized_address (LLDB_INVALID_ADDRESS)
73151c032cSJim Ingham {
74151c032cSJim Ingham }
75151c032cSJim Ingham 
76151c032cSJim Ingham UserExpression::~UserExpression ()
77151c032cSJim Ingham {
78151c032cSJim Ingham     if (m_target)
79151c032cSJim Ingham     {
80151c032cSJim Ingham         lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
81151c032cSJim Ingham         if (jit_module_sp)
82151c032cSJim Ingham             m_target->GetImages().Remove(jit_module_sp);
83151c032cSJim Ingham     }
84151c032cSJim Ingham }
85151c032cSJim Ingham 
86151c032cSJim Ingham void
87151c032cSJim Ingham UserExpression::InstallContext (ExecutionContext &exe_ctx)
88151c032cSJim Ingham {
89151c032cSJim Ingham     m_jit_process_wp = exe_ctx.GetProcessSP();
90151c032cSJim Ingham 
91151c032cSJim Ingham     lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
92151c032cSJim Ingham 
93151c032cSJim Ingham     if (frame_sp)
94151c032cSJim Ingham         m_address = frame_sp->GetFrameCodeAddress();
95151c032cSJim Ingham }
96151c032cSJim Ingham 
97151c032cSJim Ingham bool
98151c032cSJim Ingham UserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
99151c032cSJim Ingham                                           lldb::TargetSP &target_sp,
100151c032cSJim Ingham                                           lldb::ProcessSP &process_sp,
101151c032cSJim Ingham                                           lldb::StackFrameSP &frame_sp)
102151c032cSJim Ingham {
103151c032cSJim Ingham     lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
104151c032cSJim Ingham     process_sp = exe_ctx.GetProcessSP();
105151c032cSJim Ingham 
106151c032cSJim Ingham     if (process_sp != expected_process_sp)
107151c032cSJim Ingham         return false;
108151c032cSJim Ingham 
109151c032cSJim Ingham     process_sp = exe_ctx.GetProcessSP();
110151c032cSJim Ingham     target_sp = exe_ctx.GetTargetSP();
111151c032cSJim Ingham     frame_sp = exe_ctx.GetFrameSP();
112151c032cSJim Ingham 
113151c032cSJim Ingham     if (m_address.IsValid())
114151c032cSJim Ingham     {
115151c032cSJim Ingham         if (!frame_sp)
116151c032cSJim Ingham             return false;
117151c032cSJim Ingham         else
118151c032cSJim Ingham             return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get()));
119151c032cSJim Ingham     }
120151c032cSJim Ingham 
121151c032cSJim Ingham     return true;
122151c032cSJim Ingham }
123151c032cSJim Ingham 
124151c032cSJim Ingham bool
125151c032cSJim Ingham UserExpression::MatchesContext (ExecutionContext &exe_ctx)
126151c032cSJim Ingham {
127151c032cSJim Ingham     lldb::TargetSP target_sp;
128151c032cSJim Ingham     lldb::ProcessSP process_sp;
129151c032cSJim Ingham     lldb::StackFrameSP frame_sp;
130151c032cSJim Ingham 
131151c032cSJim Ingham     return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
132151c032cSJim Ingham }
133151c032cSJim Ingham 
134151c032cSJim Ingham lldb::addr_t
135151c032cSJim Ingham UserExpression::GetObjectPointer (lldb::StackFrameSP frame_sp,
136151c032cSJim Ingham                   ConstString &object_name,
137151c032cSJim Ingham                   Error &err)
138151c032cSJim Ingham {
139151c032cSJim Ingham     err.Clear();
140151c032cSJim Ingham 
141151c032cSJim Ingham     if (!frame_sp)
142151c032cSJim Ingham     {
143151c032cSJim Ingham         err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
144151c032cSJim Ingham         return LLDB_INVALID_ADDRESS;
145151c032cSJim Ingham     }
146151c032cSJim Ingham 
147151c032cSJim Ingham     lldb::VariableSP var_sp;
148151c032cSJim Ingham     lldb::ValueObjectSP valobj_sp;
149151c032cSJim Ingham 
150151c032cSJim Ingham     valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
151151c032cSJim Ingham                                                             lldb::eNoDynamicValues,
152151c032cSJim Ingham                                                             StackFrame::eExpressionPathOptionCheckPtrVsMember |
153151c032cSJim Ingham                                                             StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
154151c032cSJim Ingham                                                             StackFrame::eExpressionPathOptionsNoSyntheticChildren |
155151c032cSJim Ingham                                                             StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
156151c032cSJim Ingham                                                             var_sp,
157151c032cSJim Ingham                                                             err);
158151c032cSJim Ingham 
159151c032cSJim Ingham     if (!err.Success() || !valobj_sp.get())
160151c032cSJim Ingham         return LLDB_INVALID_ADDRESS;
161151c032cSJim Ingham 
162151c032cSJim Ingham     lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
163151c032cSJim Ingham 
164151c032cSJim Ingham     if (ret == LLDB_INVALID_ADDRESS)
165151c032cSJim Ingham     {
166151c032cSJim Ingham         err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
167151c032cSJim Ingham         return LLDB_INVALID_ADDRESS;
168151c032cSJim Ingham     }
169151c032cSJim Ingham 
170151c032cSJim Ingham     return ret;
171151c032cSJim Ingham }
172151c032cSJim Ingham 
173151c032cSJim Ingham bool
174151c032cSJim Ingham UserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
175151c032cSJim Ingham                                                     ExecutionContext &exe_ctx,
176151c032cSJim Ingham                                                     lldb::addr_t &struct_address)
177151c032cSJim Ingham {
178151c032cSJim Ingham     lldb::TargetSP target;
179151c032cSJim Ingham     lldb::ProcessSP process;
180151c032cSJim Ingham     lldb::StackFrameSP frame;
181151c032cSJim Ingham 
182151c032cSJim Ingham     if (!LockAndCheckContext(exe_ctx,
183151c032cSJim Ingham                              target,
184151c032cSJim Ingham                              process,
185151c032cSJim Ingham                              frame))
186151c032cSJim Ingham     {
187151c032cSJim Ingham         error_stream.Printf("The context has changed before we could JIT the expression!\n");
188151c032cSJim Ingham         return false;
189151c032cSJim Ingham     }
190151c032cSJim Ingham 
191151c032cSJim Ingham     if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
192151c032cSJim Ingham     {
193151c032cSJim Ingham         if (m_materialized_address == LLDB_INVALID_ADDRESS)
194151c032cSJim Ingham         {
195151c032cSJim Ingham             Error alloc_error;
196151c032cSJim Ingham 
197151c032cSJim Ingham             IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
198151c032cSJim Ingham 
199151c032cSJim Ingham             m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
200151c032cSJim Ingham                                                                  m_materializer_ap->GetStructAlignment(),
201151c032cSJim Ingham                                                                  lldb::ePermissionsReadable | lldb::ePermissionsWritable,
202151c032cSJim Ingham                                                                  policy,
203151c032cSJim Ingham                                                                  alloc_error);
204151c032cSJim Ingham 
205151c032cSJim Ingham             if (!alloc_error.Success())
206151c032cSJim Ingham             {
207151c032cSJim Ingham                 error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
208151c032cSJim Ingham                 return false;
209151c032cSJim Ingham             }
210151c032cSJim Ingham         }
211151c032cSJim Ingham 
212151c032cSJim Ingham         struct_address = m_materialized_address;
213151c032cSJim Ingham 
214151c032cSJim Ingham         if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
215151c032cSJim Ingham         {
216151c032cSJim Ingham             Error alloc_error;
217151c032cSJim Ingham 
218151c032cSJim Ingham             const size_t stack_frame_size = 512 * 1024;
219151c032cSJim Ingham 
220151c032cSJim Ingham             m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
221151c032cSJim Ingham                                                                8,
222151c032cSJim Ingham                                                                lldb::ePermissionsReadable | lldb::ePermissionsWritable,
223151c032cSJim Ingham                                                                IRMemoryMap::eAllocationPolicyHostOnly,
224151c032cSJim Ingham                                                                alloc_error);
225151c032cSJim Ingham 
226151c032cSJim Ingham             m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
227151c032cSJim Ingham 
228151c032cSJim Ingham             if (!alloc_error.Success())
229151c032cSJim Ingham             {
230151c032cSJim Ingham                 error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
231151c032cSJim Ingham                 return false;
232151c032cSJim Ingham             }
233151c032cSJim Ingham         }
234151c032cSJim Ingham 
235151c032cSJim Ingham         Error materialize_error;
236151c032cSJim Ingham 
237151c032cSJim Ingham         m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
238151c032cSJim Ingham 
239151c032cSJim Ingham         if (!materialize_error.Success())
240151c032cSJim Ingham         {
241151c032cSJim Ingham             error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
242151c032cSJim Ingham             return false;
243151c032cSJim Ingham         }
244151c032cSJim Ingham     }
245151c032cSJim Ingham     return true;
246151c032cSJim Ingham }
247151c032cSJim Ingham 
248151c032cSJim Ingham bool
249151c032cSJim Ingham UserExpression::FinalizeJITExecution (Stream &error_stream,
250151c032cSJim Ingham                                            ExecutionContext &exe_ctx,
251151c032cSJim Ingham                                            lldb::ExpressionVariableSP &result,
252151c032cSJim Ingham                                            lldb::addr_t function_stack_bottom,
253151c032cSJim Ingham                                            lldb::addr_t function_stack_top)
254151c032cSJim Ingham {
255151c032cSJim Ingham     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
256151c032cSJim Ingham 
257151c032cSJim Ingham     if (log)
258151c032cSJim Ingham         log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing after execution --");
259151c032cSJim Ingham 
260151c032cSJim Ingham     if (!m_dematerializer_sp)
261151c032cSJim Ingham     {
262151c032cSJim Ingham         error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present");
263151c032cSJim Ingham         return false;
264151c032cSJim Ingham     }
265151c032cSJim Ingham 
266151c032cSJim Ingham     Error dematerialize_error;
267151c032cSJim Ingham 
2689fda9d21SSean Callanan     m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom, function_stack_top);
269151c032cSJim Ingham 
270151c032cSJim Ingham     if (!dematerialize_error.Success())
271151c032cSJim Ingham     {
272151c032cSJim Ingham         error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error"));
273151c032cSJim Ingham         return false;
274151c032cSJim Ingham     }
275151c032cSJim Ingham 
2769fda9d21SSean Callanan     result = GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope());
2779fda9d21SSean Callanan 
278151c032cSJim Ingham     if (result)
279151c032cSJim Ingham         result->TransferAddress();
280151c032cSJim Ingham 
281151c032cSJim Ingham     m_dematerializer_sp.reset();
282151c032cSJim Ingham 
283151c032cSJim Ingham     return true;
284151c032cSJim Ingham }
285151c032cSJim Ingham 
286151c032cSJim Ingham lldb::ExpressionResults
287151c032cSJim Ingham UserExpression::Execute (Stream &error_stream,
288151c032cSJim Ingham                               ExecutionContext &exe_ctx,
289151c032cSJim Ingham                               const EvaluateExpressionOptions& options,
290151c032cSJim Ingham                               lldb::UserExpressionSP &shared_ptr_to_me,
291151c032cSJim Ingham                               lldb::ExpressionVariableSP &result)
292151c032cSJim Ingham {
293151c032cSJim Ingham     // The expression log is quite verbose, and if you're just tracking the execution of the
294151c032cSJim Ingham     // expression, it's quite convenient to have these logs come out with the STEP log as well.
295151c032cSJim Ingham     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
296151c032cSJim Ingham 
297151c032cSJim Ingham     if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
298151c032cSJim Ingham     {
299151c032cSJim Ingham         lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
300151c032cSJim Ingham 
301151c032cSJim Ingham         if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address))
302151c032cSJim Ingham         {
303151c032cSJim Ingham             error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
304151c032cSJim Ingham             return lldb::eExpressionSetupError;
305151c032cSJim Ingham         }
306151c032cSJim Ingham 
307151c032cSJim Ingham         lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
308151c032cSJim Ingham         lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
309151c032cSJim Ingham 
310151c032cSJim Ingham         if (m_can_interpret)
311151c032cSJim Ingham         {
312151c032cSJim Ingham             llvm::Module *module = m_execution_unit_sp->GetModule();
313151c032cSJim Ingham             llvm::Function *function = m_execution_unit_sp->GetFunction();
314151c032cSJim Ingham 
315151c032cSJim Ingham             if (!module || !function)
316151c032cSJim Ingham             {
317151c032cSJim Ingham                 error_stream.Printf("Supposed to interpret, but nothing is there");
318151c032cSJim Ingham                 return lldb::eExpressionSetupError;
319151c032cSJim Ingham             }
320151c032cSJim Ingham 
321151c032cSJim Ingham             Error interpreter_error;
322151c032cSJim Ingham 
323151c032cSJim Ingham             std::vector<lldb::addr_t> args;
324151c032cSJim Ingham 
325151c032cSJim Ingham             if (!AddInitialArguments(exe_ctx, args, error_stream))
326151c032cSJim Ingham             {
327151c032cSJim Ingham                 error_stream.Printf ("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__);
328151c032cSJim Ingham                 return lldb::eExpressionSetupError;
329151c032cSJim Ingham             }
330151c032cSJim Ingham 
331151c032cSJim Ingham             args.push_back(struct_address);
332151c032cSJim Ingham 
333151c032cSJim Ingham             function_stack_bottom = m_stack_frame_bottom;
334151c032cSJim Ingham             function_stack_top = m_stack_frame_top;
335151c032cSJim Ingham 
336151c032cSJim Ingham             IRInterpreter::Interpret (*module,
337151c032cSJim Ingham                                       *function,
338151c032cSJim Ingham                                       args,
339151c032cSJim Ingham                                       *m_execution_unit_sp.get(),
340151c032cSJim Ingham                                       interpreter_error,
341151c032cSJim Ingham                                       function_stack_bottom,
342151c032cSJim Ingham                                       function_stack_top,
343151c032cSJim Ingham                                       exe_ctx);
344151c032cSJim Ingham 
345151c032cSJim Ingham             if (!interpreter_error.Success())
346151c032cSJim Ingham             {
347151c032cSJim Ingham                 error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
348151c032cSJim Ingham                 return lldb::eExpressionDiscarded;
349151c032cSJim Ingham             }
350151c032cSJim Ingham         }
351151c032cSJim Ingham         else
352151c032cSJim Ingham         {
353151c032cSJim Ingham             if (!exe_ctx.HasThreadScope())
354151c032cSJim Ingham             {
355151c032cSJim Ingham                 error_stream.Printf("UserExpression::Execute called with no thread selected.");
356151c032cSJim Ingham                 return lldb::eExpressionSetupError;
357151c032cSJim Ingham             }
358151c032cSJim Ingham 
359151c032cSJim Ingham             Address wrapper_address (m_jit_start_addr);
360151c032cSJim Ingham 
361151c032cSJim Ingham             std::vector<lldb::addr_t> args;
362151c032cSJim Ingham 
363151c032cSJim Ingham             if (!AddInitialArguments(exe_ctx, args, error_stream))
364151c032cSJim Ingham             {
365151c032cSJim Ingham                 error_stream.Printf ("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__);
366151c032cSJim Ingham                 return lldb::eExpressionSetupError;
367151c032cSJim Ingham             }
368151c032cSJim Ingham 
369151c032cSJim Ingham             args.push_back(struct_address);
370151c032cSJim Ingham 
371151c032cSJim Ingham             lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
372151c032cSJim Ingham                                                                               wrapper_address,
373151c032cSJim Ingham                                                                               args,
374151c032cSJim Ingham                                                                               options,
375151c032cSJim Ingham                                                                               shared_ptr_to_me));
376151c032cSJim Ingham 
377151c032cSJim Ingham             if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
378151c032cSJim Ingham                 return lldb::eExpressionSetupError;
379151c032cSJim Ingham 
380151c032cSJim Ingham             ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
381151c032cSJim Ingham 
382151c032cSJim Ingham             lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
383151c032cSJim Ingham 
384151c032cSJim Ingham             function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
385151c032cSJim Ingham             function_stack_top = function_stack_pointer;
386151c032cSJim Ingham 
387151c032cSJim Ingham             if (log)
388151c032cSJim Ingham                 log->Printf("-- [UserExpression::Execute] Execution of expression begins --");
389151c032cSJim Ingham 
390151c032cSJim Ingham             if (exe_ctx.GetProcessPtr())
391151c032cSJim Ingham                 exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
392151c032cSJim Ingham 
393151c032cSJim Ingham             lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
394151c032cSJim Ingham                                                                                        call_plan_sp,
395151c032cSJim Ingham                                                                                        options,
396151c032cSJim Ingham                                                                                        error_stream);
397151c032cSJim Ingham 
398151c032cSJim Ingham             if (exe_ctx.GetProcessPtr())
399151c032cSJim Ingham                 exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
400151c032cSJim Ingham 
401151c032cSJim Ingham             if (log)
402151c032cSJim Ingham                 log->Printf("-- [UserExpression::Execute] Execution of expression completed --");
403151c032cSJim Ingham 
404151c032cSJim Ingham             if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
405151c032cSJim Ingham             {
406151c032cSJim Ingham                 const char *error_desc = NULL;
407151c032cSJim Ingham 
408151c032cSJim Ingham                 if (call_plan_sp)
409151c032cSJim Ingham                 {
410151c032cSJim Ingham                     lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
411151c032cSJim Ingham                     if (real_stop_info_sp)
412151c032cSJim Ingham                         error_desc = real_stop_info_sp->GetDescription();
413151c032cSJim Ingham                 }
414151c032cSJim Ingham                 if (error_desc)
415151c032cSJim Ingham                     error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
416151c032cSJim Ingham                 else
417151c032cSJim Ingham                     error_stream.PutCString ("Execution was interrupted.");
418151c032cSJim Ingham 
419151c032cSJim Ingham                 if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError())
420151c032cSJim Ingham                     || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
421151c032cSJim Ingham                     error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
422151c032cSJim Ingham                 else
423151c032cSJim Ingham                 {
424151c032cSJim Ingham                     if (execution_result == lldb::eExpressionHitBreakpoint)
425151c032cSJim Ingham                         user_expression_plan->TransferExpressionOwnership();
426151c032cSJim Ingham                     error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, "
427151c032cSJim Ingham                                              "use \"thread return -x\" to return to the state before expression evaluation.");
428151c032cSJim Ingham                 }
429151c032cSJim Ingham 
430151c032cSJim Ingham                 return execution_result;
431151c032cSJim Ingham             }
432151c032cSJim Ingham             else if (execution_result == lldb::eExpressionStoppedForDebug)
433151c032cSJim Ingham             {
434151c032cSJim Ingham                     error_stream.PutCString ("Execution was halted at the first instruction of the expression "
435151c032cSJim Ingham                                              "function because \"debug\" was requested.\n"
436151c032cSJim Ingham                                              "Use \"thread return -x\" to return to the state before expression evaluation.");
437151c032cSJim Ingham                     return execution_result;
438151c032cSJim Ingham             }
439151c032cSJim Ingham             else if (execution_result != lldb::eExpressionCompleted)
440151c032cSJim Ingham             {
441151c032cSJim Ingham                 error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
442151c032cSJim Ingham                 return execution_result;
443151c032cSJim Ingham             }
444151c032cSJim Ingham         }
445151c032cSJim Ingham 
446151c032cSJim Ingham         if  (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
447151c032cSJim Ingham         {
448151c032cSJim Ingham             return lldb::eExpressionCompleted;
449151c032cSJim Ingham         }
450151c032cSJim Ingham         else
451151c032cSJim Ingham         {
452151c032cSJim Ingham             return lldb::eExpressionResultUnavailable;
453151c032cSJim Ingham         }
454151c032cSJim Ingham     }
455151c032cSJim Ingham     else
456151c032cSJim Ingham     {
457151c032cSJim Ingham         error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
458151c032cSJim Ingham         return lldb::eExpressionSetupError;
459151c032cSJim Ingham     }
460151c032cSJim Ingham }
461151c032cSJim Ingham 
462151c032cSJim Ingham lldb::ExpressionResults
463151c032cSJim Ingham UserExpression::Evaluate (ExecutionContext &exe_ctx,
464151c032cSJim Ingham                                const EvaluateExpressionOptions& options,
465151c032cSJim Ingham                                const char *expr_cstr,
466151c032cSJim Ingham                                const char *expr_prefix,
467151c032cSJim Ingham                                lldb::ValueObjectSP &result_valobj_sp,
468*6681041dSSean Callanan                                Error &error,
469*6681041dSSean Callanan                                uint32_t line_offset,
470*6681041dSSean Callanan                                lldb::ModuleSP *jit_module_sp_ptr)
471151c032cSJim Ingham {
472151c032cSJim Ingham     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
473151c032cSJim Ingham 
474151c032cSJim Ingham     lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
4751bbaede5SDawn Perchik     lldb::LanguageType language = options.GetLanguage();
476151c032cSJim Ingham     const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
477151c032cSJim Ingham     lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
478151c032cSJim Ingham 
479151c032cSJim Ingham     Target *target = exe_ctx.GetTargetPtr();
480151c032cSJim Ingham     if (!target)
481151c032cSJim Ingham     {
482151c032cSJim Ingham         if (log)
483151c032cSJim Ingham             log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
484151c032cSJim Ingham         return lldb::eExpressionSetupError;
485151c032cSJim Ingham     }
486151c032cSJim Ingham 
487151c032cSJim Ingham     Process *process = exe_ctx.GetProcessPtr();
488151c032cSJim Ingham 
489151c032cSJim Ingham     if (process == NULL || process->GetState() != lldb::eStateStopped)
490151c032cSJim Ingham     {
491151c032cSJim Ingham         if (execution_policy == eExecutionPolicyAlways)
492151c032cSJim Ingham         {
493151c032cSJim Ingham             if (log)
494151c032cSJim Ingham                 log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
495151c032cSJim Ingham 
496151c032cSJim Ingham             error.SetErrorString ("expression needed to run but couldn't");
497151c032cSJim Ingham 
498151c032cSJim Ingham             return execution_results;
499151c032cSJim Ingham         }
500151c032cSJim Ingham     }
501151c032cSJim Ingham 
502151c032cSJim Ingham     if (process == NULL || !process->CanJIT())
503151c032cSJim Ingham         execution_policy = eExecutionPolicyNever;
504151c032cSJim Ingham 
505151c032cSJim Ingham     const char *full_prefix = NULL;
506151c032cSJim Ingham     const char *option_prefix = options.GetPrefix();
507151c032cSJim Ingham     std::string full_prefix_storage;
508151c032cSJim Ingham     if (expr_prefix && option_prefix)
509151c032cSJim Ingham     {
510151c032cSJim Ingham         full_prefix_storage.assign(expr_prefix);
511151c032cSJim Ingham         full_prefix_storage.append(option_prefix);
512151c032cSJim Ingham         if (!full_prefix_storage.empty())
513151c032cSJim Ingham             full_prefix = full_prefix_storage.c_str();
514151c032cSJim Ingham     }
515151c032cSJim Ingham     else if (expr_prefix)
516151c032cSJim Ingham         full_prefix = expr_prefix;
517151c032cSJim Ingham     else
518151c032cSJim Ingham         full_prefix = option_prefix;
519151c032cSJim Ingham 
5201bbaede5SDawn Perchik     // If the language was not specified in the expression command,
5211bbaede5SDawn Perchik     // set it to the language in the target's properties if
5221bbaede5SDawn Perchik     // specified, else default to the langage for the frame.
5231bbaede5SDawn Perchik     if (language == lldb::eLanguageTypeUnknown)
5241bbaede5SDawn Perchik     {
5251bbaede5SDawn Perchik         if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
5261bbaede5SDawn Perchik             language = target->GetLanguage();
5271bbaede5SDawn Perchik         else if (StackFrame *frame = exe_ctx.GetFramePtr())
5281bbaede5SDawn Perchik             language = frame->GetLanguage();
5291bbaede5SDawn Perchik     }
5301bbaede5SDawn Perchik 
531151c032cSJim Ingham     lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
532151c032cSJim Ingham                                                                                     full_prefix,
533151c032cSJim Ingham                                                                                     language,
534151c032cSJim Ingham                                                                                     desired_type,
535151c032cSJim Ingham                                                                                     error));
536151c032cSJim Ingham     if (error.Fail())
537151c032cSJim Ingham     {
538151c032cSJim Ingham         if (log)
539151c032cSJim Ingham             log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
540151c032cSJim Ingham         return lldb::eExpressionSetupError;
541151c032cSJim Ingham     }
542151c032cSJim Ingham 
543151c032cSJim Ingham     StreamString error_stream;
544151c032cSJim Ingham 
545151c032cSJim Ingham     if (log)
546151c032cSJim Ingham         log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
547151c032cSJim Ingham 
548151c032cSJim Ingham     const bool keep_expression_in_memory = true;
549151c032cSJim Ingham     const bool generate_debug_info = options.GetGenerateDebugInfo();
550151c032cSJim Ingham 
551151c032cSJim Ingham     if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
552151c032cSJim Ingham     {
553151c032cSJim Ingham         error.SetErrorString ("expression interrupted by callback before parse");
554151c032cSJim Ingham         result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
555151c032cSJim Ingham         return lldb::eExpressionInterrupted;
556151c032cSJim Ingham     }
557151c032cSJim Ingham 
558151c032cSJim Ingham     if (!user_expression_sp->Parse (error_stream,
559151c032cSJim Ingham                                     exe_ctx,
560151c032cSJim Ingham                                     execution_policy,
561151c032cSJim Ingham                                     keep_expression_in_memory,
562151c032cSJim Ingham                                     generate_debug_info))
563151c032cSJim Ingham     {
564151c032cSJim Ingham         execution_results = lldb::eExpressionParseError;
565151c032cSJim Ingham         if (error_stream.GetString().empty())
566151c032cSJim Ingham             error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
567151c032cSJim Ingham         else
568151c032cSJim Ingham             error.SetExpressionError (execution_results, error_stream.GetString().c_str());
569151c032cSJim Ingham     }
570151c032cSJim Ingham     else
571151c032cSJim Ingham     {
572*6681041dSSean Callanan         // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
573*6681041dSSean Callanan         if (jit_module_sp_ptr && user_expression_sp->m_execution_unit_sp)
574*6681041dSSean Callanan             *jit_module_sp_ptr = user_expression_sp->m_execution_unit_sp->GetJITModule();
575*6681041dSSean Callanan 
576151c032cSJim Ingham         lldb::ExpressionVariableSP expr_result;
577151c032cSJim Ingham 
578151c032cSJim Ingham         if (execution_policy == eExecutionPolicyNever &&
579151c032cSJim Ingham             !user_expression_sp->CanInterpret())
580151c032cSJim Ingham         {
581151c032cSJim Ingham             if (log)
582151c032cSJim Ingham                 log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
583151c032cSJim Ingham 
584151c032cSJim Ingham             if (error_stream.GetString().empty())
585151c032cSJim Ingham                 error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
586151c032cSJim Ingham         }
587151c032cSJim Ingham         else
588151c032cSJim Ingham         {
589151c032cSJim Ingham             if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
590151c032cSJim Ingham             {
591151c032cSJim Ingham                 error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
592151c032cSJim Ingham                 result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
593151c032cSJim Ingham                 return lldb::eExpressionInterrupted;
594151c032cSJim Ingham             }
595151c032cSJim Ingham 
596151c032cSJim Ingham             error_stream.GetString().clear();
597151c032cSJim Ingham 
598151c032cSJim Ingham             if (log)
599151c032cSJim Ingham                 log->Printf("== [UserExpression::Evaluate] Executing expression ==");
600151c032cSJim Ingham 
601151c032cSJim Ingham             execution_results = user_expression_sp->Execute (error_stream,
602151c032cSJim Ingham                                                              exe_ctx,
603151c032cSJim Ingham                                                              options,
604151c032cSJim Ingham                                                              user_expression_sp,
605151c032cSJim Ingham                                                              expr_result);
606151c032cSJim Ingham 
607151c032cSJim Ingham             if (options.GetResultIsInternal() && expr_result && process)
608151c032cSJim Ingham             {
609b92bd753SSean Callanan                 process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result);
610151c032cSJim Ingham             }
611151c032cSJim Ingham 
612151c032cSJim Ingham             if (execution_results != lldb::eExpressionCompleted)
613151c032cSJim Ingham             {
614151c032cSJim Ingham                 if (log)
615151c032cSJim Ingham                     log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");
616151c032cSJim Ingham 
617151c032cSJim Ingham                 if (error_stream.GetString().empty())
618151c032cSJim Ingham                     error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
619151c032cSJim Ingham                 else
620151c032cSJim Ingham                     error.SetExpressionError (execution_results, error_stream.GetString().c_str());
621151c032cSJim Ingham             }
622151c032cSJim Ingham             else
623151c032cSJim Ingham             {
624151c032cSJim Ingham                 if (expr_result)
625151c032cSJim Ingham                 {
626151c032cSJim Ingham                     result_valobj_sp = expr_result->GetValueObject();
627151c032cSJim Ingham 
628151c032cSJim Ingham                     if (log)
629151c032cSJim Ingham                         log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
630151c032cSJim Ingham                                     result_valobj_sp->GetValueAsCString());
631151c032cSJim Ingham                 }
632151c032cSJim Ingham                 else
633151c032cSJim Ingham                 {
634151c032cSJim Ingham                     if (log)
635151c032cSJim Ingham                         log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");
636151c032cSJim Ingham 
637151c032cSJim Ingham                     error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
638151c032cSJim Ingham                 }
639151c032cSJim Ingham             }
640151c032cSJim Ingham         }
641151c032cSJim Ingham     }
642151c032cSJim Ingham 
643151c032cSJim Ingham     if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
644151c032cSJim Ingham     {
645151c032cSJim Ingham         error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
646151c032cSJim Ingham         return lldb::eExpressionInterrupted;
647151c032cSJim Ingham     }
648151c032cSJim Ingham 
649151c032cSJim Ingham     if (result_valobj_sp.get() == NULL)
650151c032cSJim Ingham     {
651151c032cSJim Ingham         result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
652151c032cSJim Ingham     }
653151c032cSJim Ingham 
654151c032cSJim Ingham     return execution_results;
655151c032cSJim Ingham }
656