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