blob: f1dd49f64dd4edf82bc4dc6718872ca7050a4d62 [file] [log] [blame]
Sean Callanan1a8d4092010-08-27 01:01:44 +00001//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
11#include <stdio.h>
12#if HAVE_SYS_TYPES_H
13# include <sys/types.h>
14#endif
15
16// C++ Includes
17#include <cstdlib>
18#include <string>
19#include <map>
20
21#include "lldb/Core/ConstString.h"
22#include "lldb/Core/Log.h"
Greg Claytonc4e411f2011-01-18 19:36:39 +000023#include "lldb/Core/StreamFile.h"
Sean Callanan1a8d4092010-08-27 01:01:44 +000024#include "lldb/Core/StreamString.h"
Greg Claytonb71f3842010-10-05 03:13:51 +000025#include "lldb/Core/ValueObjectConstResult.h"
Sean Callanane4ec90e2010-12-16 03:17:46 +000026#include "lldb/Expression/ASTResultSynthesizer.h"
Sean Callanan1a8d4092010-08-27 01:01:44 +000027#include "lldb/Expression/ClangExpressionDeclMap.h"
28#include "lldb/Expression/ClangExpressionParser.h"
29#include "lldb/Expression/ClangFunction.h"
Sean Callanan1a8d4092010-08-27 01:01:44 +000030#include "lldb/Expression/ClangUserExpression.h"
31#include "lldb/Host/Host.h"
Sean Callananfc55f5d2010-09-21 00:44:12 +000032#include "lldb/Symbol/VariableList.h"
Sean Callanan1a8d4092010-08-27 01:01:44 +000033#include "lldb/Target/ExecutionContext.h"
Greg Clayton8f343b02010-11-04 01:54:29 +000034#include "lldb/Target/Process.h"
Sean Callananfc55f5d2010-09-21 00:44:12 +000035#include "lldb/Target/StackFrame.h"
Sean Callanan1a8d4092010-08-27 01:01:44 +000036#include "lldb/Target/Target.h"
Jim Inghamf48169b2010-11-30 02:22:11 +000037#include "lldb/Target/ThreadPlan.h"
38#include "lldb/Target/ThreadPlanCallUserExpression.h"
Sean Callanan1a8d4092010-08-27 01:01:44 +000039
40using namespace lldb_private;
41
Sean Callanan322f5292010-10-29 00:29:03 +000042ClangUserExpression::ClangUserExpression (const char *expr,
43 const char *expr_prefix) :
Greg Clayton22a939a2011-01-19 23:00:49 +000044 ClangExpression (),
45 m_expr_text (expr),
46 m_expr_prefix (expr_prefix ? expr_prefix : ""),
47 m_transformed_text (),
Stephen Wilson71c21d12011-04-11 19:41:40 +000048 m_desired_type (NULL, NULL),
Greg Clayton22a939a2011-01-19 23:00:49 +000049 m_cplusplus (false),
50 m_objectivec (false),
51 m_needs_object_ptr (false),
Sean Callanan63697e52011-05-07 01:06:41 +000052 m_const_object (false),
53 m_const_result ()
Sean Callanan1a8d4092010-08-27 01:01:44 +000054{
Sean Callanan1a8d4092010-08-27 01:01:44 +000055}
56
Sean Callanane71d5532010-08-27 23:31:21 +000057ClangUserExpression::~ClangUserExpression ()
58{
59}
60
Sean Callanan1a8d4092010-08-27 01:01:44 +000061clang::ASTConsumer *
62ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
63{
Sean Callananf7c3e272010-11-19 02:52:21 +000064 return new ASTResultSynthesizer(passthrough,
65 m_desired_type);
Sean Callanan1a8d4092010-08-27 01:01:44 +000066}
67
Sean Callananfc55f5d2010-09-21 00:44:12 +000068void
69ClangUserExpression::ScanContext(ExecutionContext &exe_ctx)
70{
71 if (!exe_ctx.frame)
72 return;
73
74 VariableList *vars = exe_ctx.frame->GetVariableList(false);
75
76 if (!vars)
77 return;
78
Sean Callanan3670ba52010-12-01 21:35:54 +000079 lldb::VariableSP this_var(vars->FindVariable(ConstString("this")));
80 lldb::VariableSP self_var(vars->FindVariable(ConstString("self")));
81
82 if (this_var.get())
83 {
84 Type *this_type = this_var->GetType();
85
86 lldb::clang_type_t pointer_target_type;
87
Greg Claytonf4ecaa52011-02-16 23:00:21 +000088 if (ClangASTContext::IsPointerType(this_type->GetClangForwardType(),
Sean Callanan3670ba52010-12-01 21:35:54 +000089 &pointer_target_type))
90 {
91 TypeFromUser target_ast_type(pointer_target_type, this_type->GetClangAST());
92
Greg Claytonf4ecaa52011-02-16 23:00:21 +000093 if (ClangASTContext::IsCXXClassType(target_ast_type.GetOpaqueQualType()))
Sean Callanan9d2127a2011-01-24 08:11:45 +000094 {
Sean Callanan3670ba52010-12-01 21:35:54 +000095 m_cplusplus = true;
96
Sean Callanan9d2127a2011-01-24 08:11:45 +000097 if (target_ast_type.IsConst())
98 m_const_object = true;
99 }
Sean Callanan3670ba52010-12-01 21:35:54 +0000100 }
101 }
102 else if (self_var.get())
103 {
Sean Callananfc55f5d2010-09-21 00:44:12 +0000104 m_objectivec = true;
Sean Callanan3670ba52010-12-01 21:35:54 +0000105 }
Sean Callananfc55f5d2010-09-21 00:44:12 +0000106}
107
Sean Callanancf5498f2010-10-22 23:25:16 +0000108// This is a really nasty hack, meant to fix Objective-C expressions of the form
109// (int)[myArray count]. Right now, because the type information for count is
110// not available, [myArray count] returns id, which can't be directly cast to
111// int without causing a clang error.
112static void
113ApplyObjcCastHack(std::string &expr)
114{
115#define OBJC_CAST_HACK_FROM "(int)["
116#define OBJC_CAST_HACK_TO "(int)(long long)["
117
118 size_t from_offset;
119
120 while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
121 expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
122
123#undef OBJC_CAST_HACK_TO
124#undef OBJC_CAST_HACK_FROM
125}
126
Sean Callanan64186e72010-10-24 20:45:49 +0000127// Another hack, meant to allow use of unichar despite it not being available in
128// the type information. Although we could special-case it in type lookup,
129// hopefully we'll figure out a way to #include the same environment as is
130// present in the original source file rather than try to hack specific type
131// definitions in as needed.
132static void
133ApplyUnicharHack(std::string &expr)
134{
135#define UNICHAR_HACK_FROM "unichar"
136#define UNICHAR_HACK_TO "unsigned short"
137
138 size_t from_offset;
139
140 while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
141 expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
142
143#undef UNICHAR_HACK_TO
144#undef UNICHAR_HACK_FROM
145}
146
Sean Callanancf5498f2010-10-22 23:25:16 +0000147bool
Sean Callananf7c3e272010-11-19 02:52:21 +0000148ClangUserExpression::Parse (Stream &error_stream,
149 ExecutionContext &exe_ctx,
Sean Callanane4ec90e2010-12-16 03:17:46 +0000150 TypeFromUser desired_type,
Sean Callanan63697e52011-05-07 01:06:41 +0000151 bool keep_result_in_memory)
Sean Callanan1a8d4092010-08-27 01:01:44 +0000152{
Greg Clayton2d4edfb2010-11-06 01:53:30 +0000153 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan1a8d4092010-08-27 01:01:44 +0000154
Sean Callananfc55f5d2010-09-21 00:44:12 +0000155 ScanContext(exe_ctx);
156
157 StreamString m_transformed_stream;
158
159 ////////////////////////////////////
160 // Generate the expression
161 //
Sean Callanancf5498f2010-10-22 23:25:16 +0000162
163 ApplyObjcCastHack(m_expr_text);
Greg Clayton73b472d2010-10-27 03:32:59 +0000164 //ApplyUnicharHack(m_expr_text);
Sean Callananfc55f5d2010-09-21 00:44:12 +0000165
166 if (m_cplusplus)
167 {
Sean Callanan322f5292010-10-29 00:29:03 +0000168 m_transformed_stream.Printf("%s \n"
169 "typedef unsigned short unichar; \n"
Greg Clayton73b472d2010-10-27 03:32:59 +0000170 "void \n"
Sean Callanan3670ba52010-12-01 21:35:54 +0000171 "$__lldb_class::%s(void *$__lldb_arg) %s\n"
Sean Callananfc55f5d2010-09-21 00:44:12 +0000172 "{ \n"
173 " %s; \n"
174 "} \n",
Sean Callanan322f5292010-10-29 00:29:03 +0000175 m_expr_prefix.c_str(),
Sean Callananfc55f5d2010-09-21 00:44:12 +0000176 FunctionName(),
Sean Callanan3670ba52010-12-01 21:35:54 +0000177 (m_const_object ? "const" : ""),
Sean Callananfc55f5d2010-09-21 00:44:12 +0000178 m_expr_text.c_str());
179
180 m_needs_object_ptr = true;
181 }
Sean Callanan17827832010-12-13 22:46:15 +0000182 else if(m_objectivec)
183 {
184 const char *function_name = FunctionName();
185
186 m_transformed_stream.Printf("%s \n"
Greg Claytonf028a1f2010-12-17 02:26:24 +0000187 "typedef unsigned short unichar; \n"
Sean Callanan17827832010-12-13 22:46:15 +0000188 "@interface $__lldb_objc_class ($__lldb_category) \n"
189 "-(void)%s:(void *)$__lldb_arg; \n"
190 "@end \n"
191 "@implementation $__lldb_objc_class ($__lldb_category) \n"
192 "-(void)%s:(void *)$__lldb_arg \n"
193 "{ \n"
194 " %s; \n"
195 "} \n"
196 "@end \n",
197 m_expr_prefix.c_str(),
198 function_name,
199 function_name,
200 m_expr_text.c_str());
201
202 m_needs_object_ptr = true;
203 }
Sean Callananfc55f5d2010-09-21 00:44:12 +0000204 else
205 {
Sean Callanan322f5292010-10-29 00:29:03 +0000206 m_transformed_stream.Printf("%s \n"
207 "typedef unsigned short unichar;\n"
Greg Clayton73b472d2010-10-27 03:32:59 +0000208 "void \n"
Sean Callanancf5498f2010-10-22 23:25:16 +0000209 "%s(void *$__lldb_arg) \n"
Sean Callananfc55f5d2010-09-21 00:44:12 +0000210 "{ \n"
211 " %s; \n"
212 "} \n",
Sean Callanan322f5292010-10-29 00:29:03 +0000213 m_expr_prefix.c_str(),
Sean Callananfc55f5d2010-09-21 00:44:12 +0000214 FunctionName(),
215 m_expr_text.c_str());
216 }
217
218 m_transformed_text = m_transformed_stream.GetData();
219
220
221 if (log)
222 log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
223
Sean Callanan1a8d4092010-08-27 01:01:44 +0000224 ////////////////////////////////////
225 // Set up the target and compiler
226 //
227
228 Target *target = exe_ctx.target;
229
230 if (!target)
231 {
232 error_stream.PutCString ("error: invalid target\n");
233 return false;
234 }
235
Sean Callanan1a8d4092010-08-27 01:01:44 +0000236 //////////////////////////
237 // Parse the expression
238 //
239
Sean Callananf7c3e272010-11-19 02:52:21 +0000240 m_desired_type = desired_type;
241
Sean Callanan92adcac2011-01-13 08:53:35 +0000242 m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
Sean Callanan979f74d2010-12-03 01:38:59 +0000243
244 m_expr_decl_map->WillParse(exe_ctx);
Sean Callanan1a8d4092010-08-27 01:01:44 +0000245
Greg Clayton514487e2011-02-15 21:59:32 +0000246 ClangExpressionParser parser(exe_ctx.process, *this);
Sean Callanan1a8d4092010-08-27 01:01:44 +0000247
248 unsigned num_errors = parser.Parse (error_stream);
249
250 if (num_errors)
251 {
252 error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
Sean Callanan979f74d2010-12-03 01:38:59 +0000253
254 m_expr_decl_map->DidParse();
255
Sean Callanan1a8d4092010-08-27 01:01:44 +0000256 return false;
257 }
258
259 ///////////////////////////////////////////////
260 // Convert the output of the parser to DWARF
261 //
262
263 m_dwarf_opcodes.reset(new StreamString);
Greg Clayton7fb56d02011-02-01 01:31:41 +0000264 m_dwarf_opcodes->SetByteOrder (lldb::endian::InlHostByteOrder());
Sean Callanan1a8d4092010-08-27 01:01:44 +0000265 m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
266
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000267 m_local_variables.reset(new ClangExpressionVariableList());
Sean Callanan1a8d4092010-08-27 01:01:44 +0000268
269 Error dwarf_error = parser.MakeDWARF ();
270
271 if (dwarf_error.Success())
272 {
273 if (log)
274 log->Printf("Code can be interpreted.");
275
Sean Callanan979f74d2010-12-03 01:38:59 +0000276 m_expr_decl_map->DidParse();
277
Sean Callanan1a8d4092010-08-27 01:01:44 +0000278 return true;
279 }
280
281 //////////////////////////////////
282 // JIT the output of the parser
283 //
284
285 m_dwarf_opcodes.reset();
286
Sean Callanan63697e52011-05-07 01:06:41 +0000287 Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_const_result, true);
Sean Callanan1a8d4092010-08-27 01:01:44 +0000288
Sean Callanan979f74d2010-12-03 01:38:59 +0000289 m_expr_decl_map->DidParse();
290
Sean Callanan1a8d4092010-08-27 01:01:44 +0000291 if (jit_error.Success())
292 {
Greg Clayton22a939a2011-01-19 23:00:49 +0000293 if (exe_ctx.process && m_jit_alloc != LLDB_INVALID_ADDRESS)
294 m_jit_process_sp = exe_ctx.process->GetSP();
Sean Callanan1a8d4092010-08-27 01:01:44 +0000295 return true;
296 }
297 else
298 {
299 error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
300 return false;
301 }
302}
303
304bool
Jim Ingham36f3b362010-10-14 23:45:03 +0000305ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
Sean Callanan104a6e92010-10-19 23:57:21 +0000306 ExecutionContext &exe_ctx,
307 lldb::addr_t &struct_address,
Sean Callanan9d48e802010-12-14 00:42:36 +0000308 lldb::addr_t &object_ptr,
309 lldb::addr_t &cmd_ptr)
Sean Callanan1a8d4092010-08-27 01:01:44 +0000310{
Greg Clayton2d4edfb2010-11-06 01:53:30 +0000311 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan1a8d4092010-08-27 01:01:44 +0000312
Greg Clayton22a939a2011-01-19 23:00:49 +0000313 if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
Sean Callanan1a8d4092010-08-27 01:01:44 +0000314 {
Sean Callanan1a8d4092010-08-27 01:01:44 +0000315 Error materialize_error;
316
Sean Callanan17827832010-12-13 22:46:15 +0000317 if (m_needs_object_ptr)
Sean Callananfc55f5d2010-09-21 00:44:12 +0000318 {
Sean Callanan17827832010-12-13 22:46:15 +0000319 ConstString object_name;
320
321 if (m_cplusplus)
322 {
323 object_name.SetCString("this");
324 }
325 else if (m_objectivec)
326 {
327 object_name.SetCString("self");
328 }
329 else
330 {
331 error_stream.Printf("Need object pointer but don't know the language\n");
332 return false;
333 }
334
335 if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, exe_ctx, materialize_error)))
336 {
337 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
338 return false;
339 }
Sean Callanan9d48e802010-12-14 00:42:36 +0000340
341 if (m_objectivec)
342 {
343 ConstString cmd_name("_cmd");
344
345 if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, exe_ctx, materialize_error, true)))
346 {
347 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
348 return false;
349 }
350 }
Sean Callananfc55f5d2010-09-21 00:44:12 +0000351 }
352
Sean Callanan979f74d2010-12-03 01:38:59 +0000353 if (!m_expr_decl_map->Materialize(exe_ctx, struct_address, materialize_error))
Sean Callanan1a8d4092010-08-27 01:01:44 +0000354 {
Sean Callananfc55f5d2010-09-21 00:44:12 +0000355 error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
Sean Callanan1a8d4092010-08-27 01:01:44 +0000356 return false;
357 }
Greg Claytonc4e411f2011-01-18 19:36:39 +0000358
359#if 0
360 // jingham: look here
361 StreamFile logfile ("/tmp/exprs.txt", "a");
Greg Clayton22a939a2011-01-19 23:00:49 +0000362 logfile.Printf("0x%16.16llx: thread = 0x%4.4x, expr = '%s'\n", m_jit_start_addr, exe_ctx.thread ? exe_ctx.thread->GetID() : -1, m_expr_text.c_str());
Greg Claytonc4e411f2011-01-18 19:36:39 +0000363#endif
Sean Callanan1a8d4092010-08-27 01:01:44 +0000364
365 if (log)
366 {
Sean Callanana162eba2010-12-07 22:55:01 +0000367 log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --");
Sean Callananc673a6e2010-12-07 10:00:20 +0000368
Greg Clayton22a939a2011-01-19 23:00:49 +0000369 log->Printf(" Function address : 0x%llx", (uint64_t)m_jit_start_addr);
Sean Callananfc55f5d2010-09-21 00:44:12 +0000370
371 if (m_needs_object_ptr)
Sean Callananc673a6e2010-12-07 10:00:20 +0000372 log->Printf(" Object pointer : 0x%llx", (uint64_t)object_ptr);
Sean Callananfc55f5d2010-09-21 00:44:12 +0000373
Sean Callananc673a6e2010-12-07 10:00:20 +0000374 log->Printf(" Structure address : 0x%llx", (uint64_t)struct_address);
Sean Callanan1a8d4092010-08-27 01:01:44 +0000375
376 StreamString args;
377
378 Error dump_error;
379
Sean Callanan9e6ed532010-09-13 21:34:21 +0000380 if (struct_address)
Sean Callanan1a8d4092010-08-27 01:01:44 +0000381 {
Sean Callanan979f74d2010-12-03 01:38:59 +0000382 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
Sean Callanan9e6ed532010-09-13 21:34:21 +0000383 {
Sean Callananc673a6e2010-12-07 10:00:20 +0000384 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
Sean Callanan9e6ed532010-09-13 21:34:21 +0000385 }
386 else
387 {
Sean Callananc673a6e2010-12-07 10:00:20 +0000388 log->Printf(" Structure contents:\n%s", args.GetData());
Sean Callanan9e6ed532010-09-13 21:34:21 +0000389 }
Sean Callanan1a8d4092010-08-27 01:01:44 +0000390 }
391 }
Jim Ingham36f3b362010-10-14 23:45:03 +0000392 }
393 return true;
394}
395
396ThreadPlan *
397ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
Sean Callanan92adcac2011-01-13 08:53:35 +0000398 ExecutionContext &exe_ctx)
Jim Ingham36f3b362010-10-14 23:45:03 +0000399{
400 lldb::addr_t struct_address;
401
402 lldb::addr_t object_ptr = NULL;
Sean Callanan17827832010-12-13 22:46:15 +0000403 lldb::addr_t cmd_ptr = NULL;
Jim Ingham36f3b362010-10-14 23:45:03 +0000404
Sean Callanan9d48e802010-12-14 00:42:36 +0000405 PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
Jim Ingham36f3b362010-10-14 23:45:03 +0000406
Jim Inghamf48169b2010-11-30 02:22:11 +0000407 // FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
408 // ClangUserExpression resources before the thread plan finishes execution in the target. But because we are
Sean Callanan17827832010-12-13 22:46:15 +0000409 // forcing unwind_on_error to be true here, in practical terms that can't happen.
410
Jim Ingham36f3b362010-10-14 23:45:03 +0000411 return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
Greg Clayton22a939a2011-01-19 23:00:49 +0000412 m_jit_start_addr,
Sean Callanan1d47caf2010-12-01 01:28:23 +0000413 struct_address,
414 error_stream,
415 true,
416 true,
Sean Callanan17827832010-12-13 22:46:15 +0000417 (m_needs_object_ptr ? &object_ptr : NULL),
418 (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
Jim Ingham36f3b362010-10-14 23:45:03 +0000419}
420
421bool
422ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
423 ExecutionContext &exe_ctx,
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000424 lldb::ClangExpressionVariableSP &result)
Jim Ingham36f3b362010-10-14 23:45:03 +0000425{
426 Error expr_error;
427
Sean Callananc673a6e2010-12-07 10:00:20 +0000428 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
429
430 if (log)
431 {
Sean Callanana162eba2010-12-07 22:55:01 +0000432 log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
Sean Callananc673a6e2010-12-07 10:00:20 +0000433
434 StreamString args;
435
436 Error dump_error;
437
438 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
439 {
440 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
441 }
442 else
443 {
444 log->Printf(" Structure contents:\n%s", args.GetData());
445 }
446 }
447
Sean Callanan979f74d2010-12-03 01:38:59 +0000448 if (!m_expr_decl_map->Dematerialize(exe_ctx, result, expr_error))
Jim Ingham36f3b362010-10-14 23:45:03 +0000449 {
450 error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
451 return false;
452 }
453 return true;
454}
455
Greg Claytone0d378b2011-03-24 21:19:54 +0000456ExecutionResults
Jim Ingham36f3b362010-10-14 23:45:03 +0000457ClangUserExpression::Execute (Stream &error_stream,
458 ExecutionContext &exe_ctx,
Jim Ingham399f1ca2010-11-05 19:25:48 +0000459 bool discard_on_error,
Jim Inghamf48169b2010-11-30 02:22:11 +0000460 ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000461 lldb::ClangExpressionVariableSP &result)
Jim Ingham36f3b362010-10-14 23:45:03 +0000462{
Jim Inghamb086ff72011-01-18 22:20:08 +0000463 // The expression log is quite verbose, and if you're just tracking the execution of the
464 // expression, it's quite convenient to have these logs come out with the STEP log as well.
465 lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
Sean Callananc673a6e2010-12-07 10:00:20 +0000466
Jim Ingham36f3b362010-10-14 23:45:03 +0000467 if (m_dwarf_opcodes.get())
468 {
469 // TODO execute the JITted opcodes
470
471 error_stream.Printf("We don't currently support executing DWARF expressions");
472
Greg Claytone0d378b2011-03-24 21:19:54 +0000473 return eExecutionSetupError;
Jim Ingham36f3b362010-10-14 23:45:03 +0000474 }
Greg Clayton22a939a2011-01-19 23:00:49 +0000475 else if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
Jim Ingham36f3b362010-10-14 23:45:03 +0000476 {
477 lldb::addr_t struct_address;
478
479 lldb::addr_t object_ptr = NULL;
Sean Callanan17827832010-12-13 22:46:15 +0000480 lldb::addr_t cmd_ptr = NULL;
Jim Ingham36f3b362010-10-14 23:45:03 +0000481
Sean Callanan9d48e802010-12-14 00:42:36 +0000482 if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
Greg Claytone0d378b2011-03-24 21:19:54 +0000483 return eExecutionSetupError;
Sean Callanan1a8d4092010-08-27 01:01:44 +0000484
Jim Ingham399f1ca2010-11-05 19:25:48 +0000485 const bool stop_others = true;
486 const bool try_all_threads = true;
Sean Callanan1a8d4092010-08-27 01:01:44 +0000487
Greg Clayton22a939a2011-01-19 23:00:49 +0000488 Address wrapper_address (NULL, m_jit_start_addr);
Sean Callanan17827832010-12-13 22:46:15 +0000489 lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (*(exe_ctx.thread),
490 wrapper_address,
491 struct_address,
492 stop_others,
493 discard_on_error,
494 (m_needs_object_ptr ? &object_ptr : NULL),
495 ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
496 shared_ptr_to_me));
497
Jim Inghamf48169b2010-11-30 02:22:11 +0000498 if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL))
Greg Claytone0d378b2011-03-24 21:19:54 +0000499 return eExecutionSetupError;
Jim Inghamf48169b2010-11-30 02:22:11 +0000500
501 call_plan_sp->SetPrivate(true);
502
Greg Claytone2d4f0d2011-01-19 07:54:15 +0000503 uint32_t single_thread_timeout_usec = 500000;
Sean Callananc673a6e2010-12-07 10:00:20 +0000504
505 if (log)
Sean Callanana162eba2010-12-07 22:55:01 +0000506 log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
Sean Callananc673a6e2010-12-07 10:00:20 +0000507
Greg Claytone0d378b2011-03-24 21:19:54 +0000508 ExecutionResults execution_result = exe_ctx.process->RunThreadPlan (exe_ctx,
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000509 call_plan_sp,
510 stop_others,
511 try_all_threads,
512 discard_on_error,
513 single_thread_timeout_usec,
514 error_stream);
Sean Callananc673a6e2010-12-07 10:00:20 +0000515
516 if (log)
Sean Callanana162eba2010-12-07 22:55:01 +0000517 log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
Jim Inghamf48169b2010-11-30 02:22:11 +0000518
Greg Claytone0d378b2011-03-24 21:19:54 +0000519 if (execution_result == eExecutionInterrupted)
Sean Callanan1a8d4092010-08-27 01:01:44 +0000520 {
Jim Inghamf48169b2010-11-30 02:22:11 +0000521 if (discard_on_error)
522 error_stream.Printf ("Expression execution was interrupted. The process has been returned to the state before execution.");
523 else
524 error_stream.Printf ("Expression execution was interrupted. The process has been left at the point where it was interrupted.");
525
526 return execution_result;
527 }
Greg Claytone0d378b2011-03-24 21:19:54 +0000528 else if (execution_result != eExecutionCompleted)
Jim Inghamf48169b2010-11-30 02:22:11 +0000529 {
530 error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
531 return execution_result;
Sean Callanan1a8d4092010-08-27 01:01:44 +0000532 }
533
Jim Inghamf48169b2010-11-30 02:22:11 +0000534 if (FinalizeJITExecution (error_stream, exe_ctx, result))
Greg Claytone0d378b2011-03-24 21:19:54 +0000535 return eExecutionCompleted;
Jim Inghamf48169b2010-11-30 02:22:11 +0000536 else
Greg Claytone0d378b2011-03-24 21:19:54 +0000537 return eExecutionSetupError;
Sean Callanan1a8d4092010-08-27 01:01:44 +0000538 }
539 else
540 {
Johnny Chenfec456d2010-11-10 19:02:11 +0000541 error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present");
Greg Claytone0d378b2011-03-24 21:19:54 +0000542 return eExecutionSetupError;
Sean Callanan1a8d4092010-08-27 01:01:44 +0000543 }
544}
545
546StreamString &
547ClangUserExpression::DwarfOpcodeStream ()
548{
549 if (!m_dwarf_opcodes.get())
550 m_dwarf_opcodes.reset(new StreamString());
551
552 return *m_dwarf_opcodes.get();
553}
Greg Clayton0184f012010-10-05 00:31:29 +0000554
Greg Claytone0d378b2011-03-24 21:19:54 +0000555ExecutionResults
Sean Callanan322f5292010-10-29 00:29:03 +0000556ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
Jim Ingham399f1ca2010-11-05 19:25:48 +0000557 bool discard_on_error,
Sean Callanan322f5292010-10-29 00:29:03 +0000558 const char *expr_cstr,
Jim Inghamf48169b2010-11-30 02:22:11 +0000559 const char *expr_prefix,
560 lldb::ValueObjectSP &result_valobj_sp)
Greg Clayton0184f012010-10-05 00:31:29 +0000561{
Jim Inghamb086ff72011-01-18 22:20:08 +0000562 lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
Sean Callanana162eba2010-12-07 22:55:01 +0000563
Greg Clayton0184f012010-10-05 00:31:29 +0000564 Error error;
Greg Claytone0d378b2011-03-24 21:19:54 +0000565 ExecutionResults execution_results = eExecutionSetupError;
Greg Clayton8f343b02010-11-04 01:54:29 +0000566
567 if (exe_ctx.process == NULL)
Jim Inghamf48169b2010-11-30 02:22:11 +0000568 {
569 error.SetErrorString ("Must have a process to evaluate expressions.");
570
Jim Ingham58b59f92011-04-22 23:53:53 +0000571 result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
Greg Claytone0d378b2011-03-24 21:19:54 +0000572 return eExecutionSetupError;
Jim Inghamf48169b2010-11-30 02:22:11 +0000573 }
574
Greg Clayton8f343b02010-11-04 01:54:29 +0000575 if (!exe_ctx.process->GetDynamicCheckers())
576 {
Sean Callanana162eba2010-12-07 22:55:01 +0000577 if (log)
578 log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers ==");
579
Greg Clayton8f343b02010-11-04 01:54:29 +0000580 DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
581
582 StreamString install_errors;
583
584 if (!dynamic_checkers->Install(install_errors, exe_ctx))
Sean Callanan2a396522010-11-05 00:57:06 +0000585 {
586 if (install_errors.GetString().empty())
587 error.SetErrorString ("couldn't install checkers, unknown error");
588 else
589 error.SetErrorString (install_errors.GetString().c_str());
590
Jim Ingham58b59f92011-04-22 23:53:53 +0000591 result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
Greg Claytone0d378b2011-03-24 21:19:54 +0000592 return eExecutionSetupError;
Sean Callanan2a396522010-11-05 00:57:06 +0000593 }
594
Greg Clayton8f343b02010-11-04 01:54:29 +0000595 exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
Sean Callanana162eba2010-12-07 22:55:01 +0000596
597 if (log)
598 log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
Greg Clayton8f343b02010-11-04 01:54:29 +0000599 }
600
Jim Inghamf48169b2010-11-30 02:22:11 +0000601 ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix));
602
Greg Clayton0184f012010-10-05 00:31:29 +0000603 StreamString error_stream;
Sean Callanan63697e52011-05-07 01:06:41 +0000604
Sean Callanana162eba2010-12-07 22:55:01 +0000605 if (log)
606 log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
607
Sean Callanan63697e52011-05-07 01:06:41 +0000608 if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), true))
Greg Clayton0184f012010-10-05 00:31:29 +0000609 {
610 if (error_stream.GetString().empty())
611 error.SetErrorString ("expression failed to parse, unknown error");
612 else
613 error.SetErrorString (error_stream.GetString().c_str());
614 }
615 else
616 {
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000617 lldb::ClangExpressionVariableSP expr_result;
Greg Clayton0184f012010-10-05 00:31:29 +0000618
Sean Callanan63697e52011-05-07 01:06:41 +0000619 if (user_expression_sp->m_const_result.get())
Greg Clayton0184f012010-10-05 00:31:29 +0000620 {
Sean Callanana162eba2010-12-07 22:55:01 +0000621 if (log)
Sean Callanane4ec90e2010-12-16 03:17:46 +0000622 log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
Sean Callanana162eba2010-12-07 22:55:01 +0000623
Sean Callanan63697e52011-05-07 01:06:41 +0000624 result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
Greg Clayton0184f012010-10-05 00:31:29 +0000625 }
Sean Callanane4ec90e2010-12-16 03:17:46 +0000626 else
627 {
628 error_stream.GetString().clear();
629
630 if (log)
631 log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
632
633 execution_results = user_expression_sp->Execute (error_stream,
634 exe_ctx,
Sean Callanan92adcac2011-01-13 08:53:35 +0000635 discard_on_error,
Sean Callanane4ec90e2010-12-16 03:17:46 +0000636 user_expression_sp,
637 expr_result);
638
Greg Claytone0d378b2011-03-24 21:19:54 +0000639 if (execution_results != eExecutionCompleted)
Greg Clayton0184f012010-10-05 00:31:29 +0000640 {
Sean Callanana162eba2010-12-07 22:55:01 +0000641 if (log)
Sean Callanane4ec90e2010-12-16 03:17:46 +0000642 log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
643
644 if (error_stream.GetString().empty())
645 error.SetErrorString ("expression failed to execute, unknown error");
646 else
647 error.SetErrorString (error_stream.GetString().c_str());
Greg Clayton0184f012010-10-05 00:31:29 +0000648 }
Sean Callanane4ec90e2010-12-16 03:17:46 +0000649 else
Greg Clayton0184f012010-10-05 00:31:29 +0000650 {
Sean Callanane4ec90e2010-12-16 03:17:46 +0000651 if (expr_result)
652 {
653 result_valobj_sp = expr_result->GetValueObject();
654
655 if (log)
Jim Ingham6035b672011-03-31 00:19:25 +0000656 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString());
Sean Callanane4ec90e2010-12-16 03:17:46 +0000657 }
658 else
659 {
660 if (log)
661 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
662
663 error.SetErrorString ("Expression did not return a result");
664 }
Greg Clayton0184f012010-10-05 00:31:29 +0000665 }
666 }
667 }
Sean Callananc57f64d2010-10-19 20:15:00 +0000668
Greg Claytonb71f3842010-10-05 03:13:51 +0000669 if (result_valobj_sp.get() == NULL)
Jim Ingham58b59f92011-04-22 23:53:53 +0000670 result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
Greg Claytonb71f3842010-10-05 03:13:51 +0000671
Jim Inghamf48169b2010-11-30 02:22:11 +0000672 return execution_results;
Johnny Chendabefd02010-10-29 20:19:44 +0000673}