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 
268151c032cSJim Ingham     m_dematerializer_sp->Dematerialize(dematerialize_error, result, 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 
276151c032cSJim Ingham     if (result)
277151c032cSJim Ingham         result->TransferAddress();
278151c032cSJim Ingham 
279151c032cSJim Ingham     m_dematerializer_sp.reset();
280151c032cSJim Ingham 
281151c032cSJim Ingham     return true;
282151c032cSJim Ingham }
283151c032cSJim Ingham 
284151c032cSJim Ingham lldb::ExpressionResults
285151c032cSJim Ingham UserExpression::Execute (Stream &error_stream,
286151c032cSJim Ingham                               ExecutionContext &exe_ctx,
287151c032cSJim Ingham                               const EvaluateExpressionOptions& options,
288151c032cSJim Ingham                               lldb::UserExpressionSP &shared_ptr_to_me,
289151c032cSJim Ingham                               lldb::ExpressionVariableSP &result)
290151c032cSJim Ingham {
291151c032cSJim Ingham     // The expression log is quite verbose, and if you're just tracking the execution of the
292151c032cSJim Ingham     // expression, it's quite convenient to have these logs come out with the STEP log as well.
293151c032cSJim Ingham     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
294151c032cSJim Ingham 
295151c032cSJim Ingham     if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
296151c032cSJim Ingham     {
297151c032cSJim Ingham         lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
298151c032cSJim Ingham 
299151c032cSJim Ingham         if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address))
300151c032cSJim Ingham         {
301151c032cSJim Ingham             error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
302151c032cSJim Ingham             return lldb::eExpressionSetupError;
303151c032cSJim Ingham         }
304151c032cSJim Ingham 
305151c032cSJim Ingham         lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
306151c032cSJim Ingham         lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
307151c032cSJim Ingham 
308151c032cSJim Ingham         if (m_can_interpret)
309151c032cSJim Ingham         {
310151c032cSJim Ingham             llvm::Module *module = m_execution_unit_sp->GetModule();
311151c032cSJim Ingham             llvm::Function *function = m_execution_unit_sp->GetFunction();
312151c032cSJim Ingham 
313151c032cSJim Ingham             if (!module || !function)
314151c032cSJim Ingham             {
315151c032cSJim Ingham                 error_stream.Printf("Supposed to interpret, but nothing is there");
316151c032cSJim Ingham                 return lldb::eExpressionSetupError;
317151c032cSJim Ingham             }
318151c032cSJim Ingham 
319151c032cSJim Ingham             Error interpreter_error;
320151c032cSJim Ingham 
321151c032cSJim Ingham             std::vector<lldb::addr_t> args;
322151c032cSJim Ingham 
323151c032cSJim Ingham             if (!AddInitialArguments(exe_ctx, args, error_stream))
324151c032cSJim Ingham             {
325151c032cSJim Ingham                 error_stream.Printf ("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__);
326151c032cSJim Ingham                 return lldb::eExpressionSetupError;
327151c032cSJim Ingham             }
328151c032cSJim Ingham 
329151c032cSJim Ingham             args.push_back(struct_address);
330151c032cSJim Ingham 
331151c032cSJim Ingham             function_stack_bottom = m_stack_frame_bottom;
332151c032cSJim Ingham             function_stack_top = m_stack_frame_top;
333151c032cSJim Ingham 
334151c032cSJim Ingham             IRInterpreter::Interpret (*module,
335151c032cSJim Ingham                                       *function,
336151c032cSJim Ingham                                       args,
337151c032cSJim Ingham                                       *m_execution_unit_sp.get(),
338151c032cSJim Ingham                                       interpreter_error,
339151c032cSJim Ingham                                       function_stack_bottom,
340151c032cSJim Ingham                                       function_stack_top,
341151c032cSJim Ingham                                       exe_ctx);
342151c032cSJim Ingham 
343151c032cSJim Ingham             if (!interpreter_error.Success())
344151c032cSJim Ingham             {
345151c032cSJim Ingham                 error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
346151c032cSJim Ingham                 return lldb::eExpressionDiscarded;
347151c032cSJim Ingham             }
348151c032cSJim Ingham         }
349151c032cSJim Ingham         else
350151c032cSJim Ingham         {
351151c032cSJim Ingham             if (!exe_ctx.HasThreadScope())
352151c032cSJim Ingham             {
353151c032cSJim Ingham                 error_stream.Printf("UserExpression::Execute called with no thread selected.");
354151c032cSJim Ingham                 return lldb::eExpressionSetupError;
355151c032cSJim Ingham             }
356151c032cSJim Ingham 
357151c032cSJim Ingham             Address wrapper_address (m_jit_start_addr);
358151c032cSJim Ingham 
359151c032cSJim Ingham             std::vector<lldb::addr_t> args;
360151c032cSJim Ingham 
361151c032cSJim Ingham             if (!AddInitialArguments(exe_ctx, args, error_stream))
362151c032cSJim Ingham             {
363151c032cSJim Ingham                 error_stream.Printf ("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__);
364151c032cSJim Ingham                 return lldb::eExpressionSetupError;
365151c032cSJim Ingham             }
366151c032cSJim Ingham 
367151c032cSJim Ingham             args.push_back(struct_address);
368151c032cSJim Ingham 
369151c032cSJim Ingham             lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
370151c032cSJim Ingham                                                                               wrapper_address,
371151c032cSJim Ingham                                                                               args,
372151c032cSJim Ingham                                                                               options,
373151c032cSJim Ingham                                                                               shared_ptr_to_me));
374151c032cSJim Ingham 
375151c032cSJim Ingham             if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
376151c032cSJim Ingham                 return lldb::eExpressionSetupError;
377151c032cSJim Ingham 
378151c032cSJim Ingham             ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
379151c032cSJim Ingham 
380151c032cSJim Ingham             lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
381151c032cSJim Ingham 
382151c032cSJim Ingham             function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
383151c032cSJim Ingham             function_stack_top = function_stack_pointer;
384151c032cSJim Ingham 
385151c032cSJim Ingham             if (log)
386151c032cSJim Ingham                 log->Printf("-- [UserExpression::Execute] Execution of expression begins --");
387151c032cSJim Ingham 
388151c032cSJim Ingham             if (exe_ctx.GetProcessPtr())
389151c032cSJim Ingham                 exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
390151c032cSJim Ingham 
391151c032cSJim Ingham             lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
392151c032cSJim Ingham                                                                                        call_plan_sp,
393151c032cSJim Ingham                                                                                        options,
394151c032cSJim Ingham                                                                                        error_stream);
395151c032cSJim Ingham 
396151c032cSJim Ingham             if (exe_ctx.GetProcessPtr())
397151c032cSJim Ingham                 exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
398151c032cSJim Ingham 
399151c032cSJim Ingham             if (log)
400151c032cSJim Ingham                 log->Printf("-- [UserExpression::Execute] Execution of expression completed --");
401151c032cSJim Ingham 
402151c032cSJim Ingham             if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
403151c032cSJim Ingham             {
404151c032cSJim Ingham                 const char *error_desc = NULL;
405151c032cSJim Ingham 
406151c032cSJim Ingham                 if (call_plan_sp)
407151c032cSJim Ingham                 {
408151c032cSJim Ingham                     lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
409151c032cSJim Ingham                     if (real_stop_info_sp)
410151c032cSJim Ingham                         error_desc = real_stop_info_sp->GetDescription();
411151c032cSJim Ingham                 }
412151c032cSJim Ingham                 if (error_desc)
413151c032cSJim Ingham                     error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
414151c032cSJim Ingham                 else
415151c032cSJim Ingham                     error_stream.PutCString ("Execution was interrupted.");
416151c032cSJim Ingham 
417151c032cSJim Ingham                 if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError())
418151c032cSJim Ingham                     || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
419151c032cSJim Ingham                     error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
420151c032cSJim Ingham                 else
421151c032cSJim Ingham                 {
422151c032cSJim Ingham                     if (execution_result == lldb::eExpressionHitBreakpoint)
423151c032cSJim Ingham                         user_expression_plan->TransferExpressionOwnership();
424151c032cSJim Ingham                     error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, "
425151c032cSJim Ingham                                              "use \"thread return -x\" to return to the state before expression evaluation.");
426151c032cSJim Ingham                 }
427151c032cSJim Ingham 
428151c032cSJim Ingham                 return execution_result;
429151c032cSJim Ingham             }
430151c032cSJim Ingham             else if (execution_result == lldb::eExpressionStoppedForDebug)
431151c032cSJim Ingham             {
432151c032cSJim Ingham                     error_stream.PutCString ("Execution was halted at the first instruction of the expression "
433151c032cSJim Ingham                                              "function because \"debug\" was requested.\n"
434151c032cSJim Ingham                                              "Use \"thread return -x\" to return to the state before expression evaluation.");
435151c032cSJim Ingham                     return execution_result;
436151c032cSJim Ingham             }
437151c032cSJim Ingham             else if (execution_result != lldb::eExpressionCompleted)
438151c032cSJim Ingham             {
439151c032cSJim Ingham                 error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
440151c032cSJim Ingham                 return execution_result;
441151c032cSJim Ingham             }
442151c032cSJim Ingham         }
443151c032cSJim Ingham 
444151c032cSJim Ingham         if  (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
445151c032cSJim Ingham         {
446151c032cSJim Ingham             return lldb::eExpressionCompleted;
447151c032cSJim Ingham         }
448151c032cSJim Ingham         else
449151c032cSJim Ingham         {
450151c032cSJim Ingham             return lldb::eExpressionResultUnavailable;
451151c032cSJim Ingham         }
452151c032cSJim Ingham     }
453151c032cSJim Ingham     else
454151c032cSJim Ingham     {
455151c032cSJim Ingham         error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
456151c032cSJim Ingham         return lldb::eExpressionSetupError;
457151c032cSJim Ingham     }
458151c032cSJim Ingham }
459151c032cSJim Ingham 
460151c032cSJim Ingham lldb::ExpressionResults
461151c032cSJim Ingham UserExpression::Evaluate (ExecutionContext &exe_ctx,
462151c032cSJim Ingham                                const EvaluateExpressionOptions& options,
463151c032cSJim Ingham                                const char *expr_cstr,
464151c032cSJim Ingham                                const char *expr_prefix,
465151c032cSJim Ingham                                lldb::ValueObjectSP &result_valobj_sp,
466151c032cSJim Ingham                                Error &error)
467151c032cSJim Ingham {
468151c032cSJim Ingham     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
469151c032cSJim Ingham 
470151c032cSJim Ingham     lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
471151c032cSJim Ingham     const lldb::LanguageType language = options.GetLanguage();
472151c032cSJim Ingham     const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
473151c032cSJim Ingham     lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
474151c032cSJim Ingham 
475151c032cSJim Ingham     Target *target = exe_ctx.GetTargetPtr();
476151c032cSJim Ingham     if (!target)
477151c032cSJim Ingham     {
478151c032cSJim Ingham         if (log)
479151c032cSJim Ingham             log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
480151c032cSJim Ingham         return lldb::eExpressionSetupError;
481151c032cSJim Ingham     }
482151c032cSJim Ingham 
483151c032cSJim Ingham     Process *process = exe_ctx.GetProcessPtr();
484151c032cSJim Ingham 
485151c032cSJim Ingham     if (process == NULL || process->GetState() != lldb::eStateStopped)
486151c032cSJim Ingham     {
487151c032cSJim Ingham         if (execution_policy == eExecutionPolicyAlways)
488151c032cSJim Ingham         {
489151c032cSJim Ingham             if (log)
490151c032cSJim Ingham                 log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
491151c032cSJim Ingham 
492151c032cSJim Ingham             error.SetErrorString ("expression needed to run but couldn't");
493151c032cSJim Ingham 
494151c032cSJim Ingham             return execution_results;
495151c032cSJim Ingham         }
496151c032cSJim Ingham     }
497151c032cSJim Ingham 
498151c032cSJim Ingham     if (process == NULL || !process->CanJIT())
499151c032cSJim Ingham         execution_policy = eExecutionPolicyNever;
500151c032cSJim Ingham 
501151c032cSJim Ingham     const char *full_prefix = NULL;
502151c032cSJim Ingham     const char *option_prefix = options.GetPrefix();
503151c032cSJim Ingham     std::string full_prefix_storage;
504151c032cSJim Ingham     if (expr_prefix && option_prefix)
505151c032cSJim Ingham     {
506151c032cSJim Ingham         full_prefix_storage.assign(expr_prefix);
507151c032cSJim Ingham         full_prefix_storage.append(option_prefix);
508151c032cSJim Ingham         if (!full_prefix_storage.empty())
509151c032cSJim Ingham             full_prefix = full_prefix_storage.c_str();
510151c032cSJim Ingham     }
511151c032cSJim Ingham     else if (expr_prefix)
512151c032cSJim Ingham         full_prefix = expr_prefix;
513151c032cSJim Ingham     else
514151c032cSJim Ingham         full_prefix = option_prefix;
515151c032cSJim Ingham 
516151c032cSJim Ingham     lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
517151c032cSJim Ingham                                                                                     full_prefix,
518151c032cSJim Ingham                                                                                     language,
519151c032cSJim Ingham                                                                                     desired_type,
520151c032cSJim Ingham                                                                                     error));
521151c032cSJim Ingham     if (error.Fail())
522151c032cSJim Ingham     {
523151c032cSJim Ingham         if (log)
524151c032cSJim Ingham             log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
525151c032cSJim Ingham         return lldb::eExpressionSetupError;
526151c032cSJim Ingham     }
527151c032cSJim Ingham 
528151c032cSJim Ingham     StreamString error_stream;
529151c032cSJim Ingham 
530151c032cSJim Ingham     if (log)
531151c032cSJim Ingham         log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
532151c032cSJim Ingham 
533151c032cSJim Ingham     const bool keep_expression_in_memory = true;
534151c032cSJim Ingham     const bool generate_debug_info = options.GetGenerateDebugInfo();
535151c032cSJim Ingham 
536151c032cSJim Ingham     if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
537151c032cSJim Ingham     {
538151c032cSJim Ingham         error.SetErrorString ("expression interrupted by callback before parse");
539151c032cSJim Ingham         result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
540151c032cSJim Ingham         return lldb::eExpressionInterrupted;
541151c032cSJim Ingham     }
542151c032cSJim Ingham 
543151c032cSJim Ingham     if (!user_expression_sp->Parse (error_stream,
544151c032cSJim Ingham                                     exe_ctx,
545151c032cSJim Ingham                                     execution_policy,
546151c032cSJim Ingham                                     keep_expression_in_memory,
547151c032cSJim Ingham                                     generate_debug_info))
548151c032cSJim Ingham     {
549151c032cSJim Ingham         execution_results = lldb::eExpressionParseError;
550151c032cSJim Ingham         if (error_stream.GetString().empty())
551151c032cSJim Ingham             error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
552151c032cSJim Ingham         else
553151c032cSJim Ingham             error.SetExpressionError (execution_results, error_stream.GetString().c_str());
554151c032cSJim Ingham     }
555151c032cSJim Ingham     else
556151c032cSJim Ingham     {
557151c032cSJim Ingham         lldb::ExpressionVariableSP expr_result;
558151c032cSJim Ingham 
559151c032cSJim Ingham         if (execution_policy == eExecutionPolicyNever &&
560151c032cSJim Ingham             !user_expression_sp->CanInterpret())
561151c032cSJim Ingham         {
562151c032cSJim Ingham             if (log)
563151c032cSJim Ingham                 log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
564151c032cSJim Ingham 
565151c032cSJim Ingham             if (error_stream.GetString().empty())
566151c032cSJim Ingham                 error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
567151c032cSJim Ingham         }
568151c032cSJim Ingham         else
569151c032cSJim Ingham         {
570151c032cSJim Ingham             if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
571151c032cSJim Ingham             {
572151c032cSJim Ingham                 error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
573151c032cSJim Ingham                 result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
574151c032cSJim Ingham                 return lldb::eExpressionInterrupted;
575151c032cSJim Ingham             }
576151c032cSJim Ingham 
577151c032cSJim Ingham             error_stream.GetString().clear();
578151c032cSJim Ingham 
579151c032cSJim Ingham             if (log)
580151c032cSJim Ingham                 log->Printf("== [UserExpression::Evaluate] Executing expression ==");
581151c032cSJim Ingham 
582151c032cSJim Ingham             execution_results = user_expression_sp->Execute (error_stream,
583151c032cSJim Ingham                                                              exe_ctx,
584151c032cSJim Ingham                                                              options,
585151c032cSJim Ingham                                                              user_expression_sp,
586151c032cSJim Ingham                                                              expr_result);
587151c032cSJim Ingham 
588151c032cSJim Ingham             if (options.GetResultIsInternal() && expr_result && process)
589151c032cSJim Ingham             {
590*b92bd753SSean Callanan                 process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result);
591151c032cSJim Ingham             }
592151c032cSJim Ingham 
593151c032cSJim Ingham             if (execution_results != lldb::eExpressionCompleted)
594151c032cSJim Ingham             {
595151c032cSJim Ingham                 if (log)
596151c032cSJim Ingham                     log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");
597151c032cSJim Ingham 
598151c032cSJim Ingham                 if (error_stream.GetString().empty())
599151c032cSJim Ingham                     error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
600151c032cSJim Ingham                 else
601151c032cSJim Ingham                     error.SetExpressionError (execution_results, error_stream.GetString().c_str());
602151c032cSJim Ingham             }
603151c032cSJim Ingham             else
604151c032cSJim Ingham             {
605151c032cSJim Ingham                 if (expr_result)
606151c032cSJim Ingham                 {
607151c032cSJim Ingham                     result_valobj_sp = expr_result->GetValueObject();
608151c032cSJim Ingham 
609151c032cSJim Ingham                     if (log)
610151c032cSJim Ingham                         log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
611151c032cSJim Ingham                                     result_valobj_sp->GetValueAsCString());
612151c032cSJim Ingham                 }
613151c032cSJim Ingham                 else
614151c032cSJim Ingham                 {
615151c032cSJim Ingham                     if (log)
616151c032cSJim Ingham                         log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");
617151c032cSJim Ingham 
618151c032cSJim Ingham                     error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
619151c032cSJim Ingham                 }
620151c032cSJim Ingham             }
621151c032cSJim Ingham         }
622151c032cSJim Ingham     }
623151c032cSJim Ingham 
624151c032cSJim Ingham     if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
625151c032cSJim Ingham     {
626151c032cSJim Ingham         error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
627151c032cSJim Ingham         return lldb::eExpressionInterrupted;
628151c032cSJim Ingham     }
629151c032cSJim Ingham 
630151c032cSJim Ingham     if (result_valobj_sp.get() == NULL)
631151c032cSJim Ingham     {
632151c032cSJim Ingham         result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
633151c032cSJim Ingham     }
634151c032cSJim Ingham 
635151c032cSJim Ingham     return execution_results;
636151c032cSJim Ingham }
637