1 //===-- UserExpression.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include <stdio.h>
11 #if HAVE_SYS_TYPES_H
12 #  include <sys/types.h>
13 #endif
14 
15 #include <cstdlib>
16 #include <string>
17 #include <map>
18 
19 #include "lldb/Core/ConstString.h"
20 #include "lldb/Core/Log.h"
21 #include "lldb/Core/Module.h"
22 #include "lldb/Core/StreamFile.h"
23 #include "lldb/Core/StreamString.h"
24 #include "lldb/Core/ValueObjectConstResult.h"
25 #include "lldb/Expression/ExpressionSourceCode.h"
26 #include "lldb/Expression/IRExecutionUnit.h"
27 #include "lldb/Expression/IRInterpreter.h"
28 #include "lldb/Expression/Materializer.h"
29 #include "lldb/Expression/UserExpression.h"
30 #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
31 #include "lldb/Host/HostInfo.h"
32 #include "lldb/Symbol/Block.h"
33 #include "lldb/Symbol/Function.h"
34 #include "lldb/Symbol/ObjectFile.h"
35 #include "lldb/Symbol/SymbolVendor.h"
36 #include "lldb/Symbol/Type.h"
37 #include "lldb/Symbol/TypeSystem.h"
38 #include "lldb/Symbol/VariableList.h"
39 #include "lldb/Target/ExecutionContext.h"
40 #include "lldb/Target/Process.h"
41 #include "lldb/Target/StackFrame.h"
42 #include "lldb/Target/Target.h"
43 #include "lldb/Target/ThreadPlan.h"
44 #include "lldb/Target/ThreadPlanCallUserExpression.h"
45 
46 using namespace lldb_private;
47 
48 UserExpression::UserExpression (ExecutionContextScope &exe_scope,
49                                 const char *expr,
50                                 const char *expr_prefix,
51                                 lldb::LanguageType language,
52                                 ResultType desired_type,
53                                 const EvaluateExpressionOptions &options) :
54       Expression(exe_scope),
55       m_expr_text(expr),
56       m_expr_prefix(expr_prefix ? expr_prefix : ""),
57       m_language(language),
58       m_desired_type(desired_type),
59       m_options (options)
60 {
61 }
62 
63 UserExpression::~UserExpression ()
64 {
65 }
66 
67 void
68 UserExpression::InstallContext (ExecutionContext &exe_ctx)
69 {
70     m_jit_process_wp = exe_ctx.GetProcessSP();
71 
72     lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
73 
74     if (frame_sp)
75         m_address = frame_sp->GetFrameCodeAddress();
76 }
77 
78 bool
79 UserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
80                                           lldb::TargetSP &target_sp,
81                                           lldb::ProcessSP &process_sp,
82                                           lldb::StackFrameSP &frame_sp)
83 {
84     lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
85     process_sp = exe_ctx.GetProcessSP();
86 
87     if (process_sp != expected_process_sp)
88         return false;
89 
90     process_sp = exe_ctx.GetProcessSP();
91     target_sp = exe_ctx.GetTargetSP();
92     frame_sp = exe_ctx.GetFrameSP();
93 
94     if (m_address.IsValid())
95     {
96         if (!frame_sp)
97             return false;
98         else
99             return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get()));
100     }
101 
102     return true;
103 }
104 
105 bool
106 UserExpression::MatchesContext (ExecutionContext &exe_ctx)
107 {
108     lldb::TargetSP target_sp;
109     lldb::ProcessSP process_sp;
110     lldb::StackFrameSP frame_sp;
111 
112     return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
113 }
114 
115 lldb::addr_t
116 UserExpression::GetObjectPointer (lldb::StackFrameSP frame_sp,
117                   ConstString &object_name,
118                   Error &err)
119 {
120     err.Clear();
121 
122     if (!frame_sp)
123     {
124         err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
125         return LLDB_INVALID_ADDRESS;
126     }
127 
128     lldb::VariableSP var_sp;
129     lldb::ValueObjectSP valobj_sp;
130 
131     valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
132                                                             lldb::eNoDynamicValues,
133                                                             StackFrame::eExpressionPathOptionCheckPtrVsMember |
134                                                             StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
135                                                             StackFrame::eExpressionPathOptionsNoSyntheticChildren |
136                                                             StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
137                                                             var_sp,
138                                                             err);
139 
140     if (!err.Success() || !valobj_sp.get())
141         return LLDB_INVALID_ADDRESS;
142 
143     lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
144 
145     if (ret == LLDB_INVALID_ADDRESS)
146     {
147         err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
148         return LLDB_INVALID_ADDRESS;
149     }
150 
151     return ret;
152 }
153 
154 lldb::ExpressionResults
155 UserExpression::Evaluate (ExecutionContext &exe_ctx,
156                                const EvaluateExpressionOptions& options,
157                                const char *expr_cstr,
158                                const char *expr_prefix,
159                                lldb::ValueObjectSP &result_valobj_sp,
160                                Error &error,
161                                uint32_t line_offset,
162                                lldb::ModuleSP *jit_module_sp_ptr)
163 {
164     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
165 
166     lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
167     lldb::LanguageType language = options.GetLanguage();
168     const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
169     lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
170 
171     Target *target = exe_ctx.GetTargetPtr();
172     if (!target)
173     {
174         if (log)
175             log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
176         return lldb::eExpressionSetupError;
177     }
178 
179     Process *process = exe_ctx.GetProcessPtr();
180 
181     if (process == NULL || process->GetState() != lldb::eStateStopped)
182     {
183         if (execution_policy == eExecutionPolicyAlways)
184         {
185             if (log)
186                 log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
187 
188             error.SetErrorString ("expression needed to run but couldn't");
189 
190             return execution_results;
191         }
192     }
193 
194     if (process == NULL || !process->CanJIT())
195         execution_policy = eExecutionPolicyNever;
196 
197     const char *full_prefix = NULL;
198     const char *option_prefix = options.GetPrefix();
199     std::string full_prefix_storage;
200     if (expr_prefix && option_prefix)
201     {
202         full_prefix_storage.assign(expr_prefix);
203         full_prefix_storage.append(option_prefix);
204         if (!full_prefix_storage.empty())
205             full_prefix = full_prefix_storage.c_str();
206     }
207     else if (expr_prefix)
208         full_prefix = expr_prefix;
209     else
210         full_prefix = option_prefix;
211 
212     // If the language was not specified in the expression command,
213     // set it to the language in the target's properties if
214     // specified, else default to the langage for the frame.
215     if (language == lldb::eLanguageTypeUnknown)
216     {
217         if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
218             language = target->GetLanguage();
219         else if (StackFrame *frame = exe_ctx.GetFramePtr())
220             language = frame->GetLanguage();
221     }
222 
223     lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
224                                                                                     full_prefix,
225                                                                                     language,
226                                                                                     desired_type,
227                                                                                     options,
228                                                                                     error));
229     if (error.Fail())
230     {
231         if (log)
232             log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
233         return lldb::eExpressionSetupError;
234     }
235 
236     StreamString error_stream;
237 
238     if (log)
239         log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
240 
241     const bool keep_expression_in_memory = true;
242     const bool generate_debug_info = options.GetGenerateDebugInfo();
243 
244     if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
245     {
246         error.SetErrorString ("expression interrupted by callback before parse");
247         result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
248         return lldb::eExpressionInterrupted;
249     }
250 
251     if (!user_expression_sp->Parse (error_stream,
252                                     exe_ctx,
253                                     execution_policy,
254                                     keep_expression_in_memory,
255                                     generate_debug_info))
256     {
257         execution_results = lldb::eExpressionParseError;
258         if (error_stream.GetString().empty())
259             error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
260         else
261             error.SetExpressionError (execution_results, error_stream.GetString().c_str());
262     }
263     else
264     {
265         // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
266         if (jit_module_sp_ptr)
267             *jit_module_sp_ptr = user_expression_sp->GetJITModule();
268 
269         lldb::ExpressionVariableSP expr_result;
270 
271         if (execution_policy == eExecutionPolicyNever &&
272             !user_expression_sp->CanInterpret())
273         {
274             if (log)
275                 log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
276 
277             if (error_stream.GetString().empty())
278                 error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
279         }
280         else
281         {
282             if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
283             {
284                 error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
285                 result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
286                 return lldb::eExpressionInterrupted;
287             }
288 
289             error_stream.GetString().clear();
290 
291             if (log)
292                 log->Printf("== [UserExpression::Evaluate] Executing expression ==");
293 
294             execution_results = user_expression_sp->Execute (error_stream,
295                                                              exe_ctx,
296                                                              options,
297                                                              user_expression_sp,
298                                                              expr_result);
299 
300             if (options.GetResultIsInternal() && expr_result && process)
301             {
302                 process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result);
303             }
304 
305             if (execution_results != lldb::eExpressionCompleted)
306             {
307                 if (log)
308                     log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");
309 
310                 if (error_stream.GetString().empty())
311                     error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
312                 else
313                     error.SetExpressionError (execution_results, error_stream.GetString().c_str());
314             }
315             else
316             {
317                 if (expr_result)
318                 {
319                     result_valobj_sp = expr_result->GetValueObject();
320 
321                     if (log)
322                         log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
323                                     result_valobj_sp->GetValueAsCString());
324                 }
325                 else
326                 {
327                     if (log)
328                         log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");
329 
330                     error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
331                 }
332             }
333         }
334     }
335 
336     if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
337     {
338         error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
339         return lldb::eExpressionInterrupted;
340     }
341 
342     if (result_valobj_sp.get() == NULL)
343     {
344         result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
345     }
346 
347     return execution_results;
348 }
349