blob: 3e3d9d44f613c4e95ef99f5c8831b69db28b5d46 [file] [log] [blame]
Sean Callananc0492742011-05-23 21:40:23 +00001//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
Sean Callanan65dafa82010-08-27 01:01:44 +00002//
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 Claytonc71899e2011-01-18 19:36:39 +000023#include "lldb/Core/StreamFile.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000024#include "lldb/Core/StreamString.h"
Greg Claytond1719722010-10-05 03:13:51 +000025#include "lldb/Core/ValueObjectConstResult.h"
Sean Callanan05a5a1b2010-12-16 03:17:46 +000026#include "lldb/Expression/ASTResultSynthesizer.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000027#include "lldb/Expression/ClangExpressionDeclMap.h"
28#include "lldb/Expression/ClangExpressionParser.h"
29#include "lldb/Expression/ClangFunction.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000030#include "lldb/Expression/ClangUserExpression.h"
31#include "lldb/Host/Host.h"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000032#include "lldb/Symbol/VariableList.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000033#include "lldb/Target/ExecutionContext.h"
Greg Clayton0baa3942010-11-04 01:54:29 +000034#include "lldb/Target/Process.h"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000035#include "lldb/Target/StackFrame.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000036#include "lldb/Target/Target.h"
Jim Ingham360f53f2010-11-30 02:22:11 +000037#include "lldb/Target/ThreadPlan.h"
38#include "lldb/Target/ThreadPlanCallUserExpression.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000039
Sean Callananc617a4c2011-08-05 23:43:37 +000040#include "clang/AST/DeclCXX.h"
41#include "clang/AST/DeclObjC.h"
42
Sean Callanan65dafa82010-08-27 01:01:44 +000043using namespace lldb_private;
44
Sean Callanan77e93942010-10-29 00:29:03 +000045ClangUserExpression::ClangUserExpression (const char *expr,
46 const char *expr_prefix) :
Greg Claytond0882d02011-01-19 23:00:49 +000047 ClangExpression (),
48 m_expr_text (expr),
49 m_expr_prefix (expr_prefix ? expr_prefix : ""),
50 m_transformed_text (),
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000051 m_desired_type (NULL, NULL),
Greg Claytond0882d02011-01-19 23:00:49 +000052 m_cplusplus (false),
53 m_objectivec (false),
54 m_needs_object_ptr (false),
Sean Callanan696cf5f2011-05-07 01:06:41 +000055 m_const_object (false),
Sean Callanan47dc4572011-09-15 02:13:07 +000056 m_evaluated_statically (false),
Sean Callanan24312442011-08-23 21:20:51 +000057 m_const_result (),
58 m_target (NULL)
Sean Callanan65dafa82010-08-27 01:01:44 +000059{
Sean Callanan65dafa82010-08-27 01:01:44 +000060}
61
Sean Callanan830a9032010-08-27 23:31:21 +000062ClangUserExpression::~ClangUserExpression ()
63{
64}
65
Sean Callanan65dafa82010-08-27 01:01:44 +000066clang::ASTConsumer *
67ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
Sean Callanan036fa902011-08-24 22:18:12 +000068{
Sean Callanan24312442011-08-23 21:20:51 +000069 ClangASTContext *clang_ast_context = m_target->GetScratchClangASTContext();
70
71 if (!clang_ast_context)
72 return NULL;
73
Sean Callanana91dd992010-11-19 02:52:21 +000074 return new ASTResultSynthesizer(passthrough,
Sean Callanan24312442011-08-23 21:20:51 +000075 m_desired_type,
76 *m_target->GetScratchClangASTContext()->getASTContext(),
77 m_target->GetPersistentVariables());
Sean Callanan65dafa82010-08-27 01:01:44 +000078}
79
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000080void
81ClangUserExpression::ScanContext(ExecutionContext &exe_ctx)
82{
Greg Clayton144188b2011-09-12 23:21:58 +000083 m_target = exe_ctx.target;
84
Sean Callananc617a4c2011-08-05 23:43:37 +000085 if (!exe_ctx.frame)
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000086 return;
87
Sean Callananc617a4c2011-08-05 23:43:37 +000088 SymbolContext sym_ctx = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextFunction);
Sean Callanane8e55572010-12-01 21:35:54 +000089
Sean Callananc617a4c2011-08-05 23:43:37 +000090 if (!sym_ctx.function)
91 return;
92
93 clang::DeclContext *decl_context;
94
95 if (sym_ctx.block && sym_ctx.block->GetInlinedFunctionInfo())
96 decl_context = sym_ctx.block->GetClangDeclContextForInlinedFunction();
97 else
98 decl_context = sym_ctx.function->GetClangDeclContext();
99
100 if (!decl_context)
101 return;
Sean Callanan036fa902011-08-24 22:18:12 +0000102
Sean Callananc617a4c2011-08-05 23:43:37 +0000103 if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context))
Sean Callanane8e55572010-12-01 21:35:54 +0000104 {
Sean Callananc617a4c2011-08-05 23:43:37 +0000105 if (method_decl->isInstance())
Sean Callanane8e55572010-12-01 21:35:54 +0000106 {
Sean Callananc617a4c2011-08-05 23:43:37 +0000107 m_cplusplus = true;
Sean Callanane8e55572010-12-01 21:35:54 +0000108
Sean Callananc617a4c2011-08-05 23:43:37 +0000109 do {
110 clang::QualType this_type = method_decl->getThisType(decl_context->getParentASTContext());
111
112 const clang::PointerType *this_pointer_type = llvm::dyn_cast<clang::PointerType>(this_type.getTypePtr());
113
114 if (!this_pointer_type)
115 break;
116
117 clang::QualType this_pointee_type = this_pointer_type->getPointeeType();
118 } while (0);
Sean Callanane8e55572010-12-01 21:35:54 +0000119 }
120 }
Sean Callananc617a4c2011-08-05 23:43:37 +0000121 else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context))
Sean Callanane8e55572010-12-01 21:35:54 +0000122 {
Sean Callananc617a4c2011-08-05 23:43:37 +0000123 if (method_decl->isInstanceMethod())
124 m_objectivec = true;
Sean Callanane8e55572010-12-01 21:35:54 +0000125 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000126}
127
Sean Callanan550f2762010-10-22 23:25:16 +0000128// This is a really nasty hack, meant to fix Objective-C expressions of the form
129// (int)[myArray count]. Right now, because the type information for count is
130// not available, [myArray count] returns id, which can't be directly cast to
131// int without causing a clang error.
132static void
133ApplyObjcCastHack(std::string &expr)
134{
135#define OBJC_CAST_HACK_FROM "(int)["
136#define OBJC_CAST_HACK_TO "(int)(long long)["
137
138 size_t from_offset;
139
140 while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
141 expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
142
143#undef OBJC_CAST_HACK_TO
144#undef OBJC_CAST_HACK_FROM
145}
146
Sean Callanan30892372010-10-24 20:45:49 +0000147// Another hack, meant to allow use of unichar despite it not being available in
148// the type information. Although we could special-case it in type lookup,
149// hopefully we'll figure out a way to #include the same environment as is
150// present in the original source file rather than try to hack specific type
151// definitions in as needed.
152static void
153ApplyUnicharHack(std::string &expr)
154{
155#define UNICHAR_HACK_FROM "unichar"
156#define UNICHAR_HACK_TO "unsigned short"
157
158 size_t from_offset;
159
160 while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
161 expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
162
163#undef UNICHAR_HACK_TO
164#undef UNICHAR_HACK_FROM
165}
166
Sean Callanan550f2762010-10-22 23:25:16 +0000167bool
Sean Callanana91dd992010-11-19 02:52:21 +0000168ClangUserExpression::Parse (Stream &error_stream,
169 ExecutionContext &exe_ctx,
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000170 TypeFromUser desired_type,
Sean Callanan47dc4572011-09-15 02:13:07 +0000171 lldb_private::ExecutionPolicy execution_policy,
Sean Callanan696cf5f2011-05-07 01:06:41 +0000172 bool keep_result_in_memory)
Sean Callanan65dafa82010-08-27 01:01:44 +0000173{
Greg Claytone005f2c2010-11-06 01:53:30 +0000174 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan65dafa82010-08-27 01:01:44 +0000175
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000176 ScanContext(exe_ctx);
177
178 StreamString m_transformed_stream;
179
180 ////////////////////////////////////
181 // Generate the expression
182 //
Sean Callanan550f2762010-10-22 23:25:16 +0000183
184 ApplyObjcCastHack(m_expr_text);
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000185 //ApplyUnicharHack(m_expr_text);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000186
187 if (m_cplusplus)
188 {
Sean Callanan77e93942010-10-29 00:29:03 +0000189 m_transformed_stream.Printf("%s \n"
190 "typedef unsigned short unichar; \n"
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000191 "void \n"
Sean Callanane8e55572010-12-01 21:35:54 +0000192 "$__lldb_class::%s(void *$__lldb_arg) %s\n"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000193 "{ \n"
194 " %s; \n"
195 "} \n",
Sean Callanan77e93942010-10-29 00:29:03 +0000196 m_expr_prefix.c_str(),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000197 FunctionName(),
Sean Callanane8e55572010-12-01 21:35:54 +0000198 (m_const_object ? "const" : ""),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000199 m_expr_text.c_str());
200
201 m_needs_object_ptr = true;
202 }
Enrico Granata4c3fb4b2011-07-19 18:03:25 +0000203 else if (m_objectivec)
Sean Callanan3aa7da52010-12-13 22:46:15 +0000204 {
205 const char *function_name = FunctionName();
206
207 m_transformed_stream.Printf("%s \n"
Greg Claytonc5157ec2010-12-17 02:26:24 +0000208 "typedef unsigned short unichar; \n"
Sean Callanan3aa7da52010-12-13 22:46:15 +0000209 "@interface $__lldb_objc_class ($__lldb_category) \n"
210 "-(void)%s:(void *)$__lldb_arg; \n"
211 "@end \n"
212 "@implementation $__lldb_objc_class ($__lldb_category) \n"
213 "-(void)%s:(void *)$__lldb_arg \n"
214 "{ \n"
215 " %s; \n"
216 "} \n"
217 "@end \n",
218 m_expr_prefix.c_str(),
219 function_name,
220 function_name,
221 m_expr_text.c_str());
222
223 m_needs_object_ptr = true;
224 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000225 else
226 {
Sean Callanan77e93942010-10-29 00:29:03 +0000227 m_transformed_stream.Printf("%s \n"
228 "typedef unsigned short unichar;\n"
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000229 "void \n"
Sean Callanan550f2762010-10-22 23:25:16 +0000230 "%s(void *$__lldb_arg) \n"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000231 "{ \n"
232 " %s; \n"
233 "} \n",
Sean Callanan77e93942010-10-29 00:29:03 +0000234 m_expr_prefix.c_str(),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000235 FunctionName(),
236 m_expr_text.c_str());
237 }
238
239 m_transformed_text = m_transformed_stream.GetData();
240
241
242 if (log)
243 log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
244
Sean Callanan65dafa82010-08-27 01:01:44 +0000245 ////////////////////////////////////
246 // Set up the target and compiler
247 //
248
249 Target *target = exe_ctx.target;
250
251 if (!target)
252 {
253 error_stream.PutCString ("error: invalid target\n");
254 return false;
255 }
256
Sean Callanan65dafa82010-08-27 01:01:44 +0000257 //////////////////////////
258 // Parse the expression
259 //
260
Sean Callanana91dd992010-11-19 02:52:21 +0000261 m_desired_type = desired_type;
262
Sean Callanan6a925532011-01-13 08:53:35 +0000263 m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
Sean Callananaa301c42010-12-03 01:38:59 +0000264
Sean Callanan166ba102011-08-01 18:18:33 +0000265 if (!m_expr_decl_map->WillParse(exe_ctx))
266 {
267 error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
268 return false;
269 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000270
Greg Clayton395fc332011-02-15 21:59:32 +0000271 ClangExpressionParser parser(exe_ctx.process, *this);
Sean Callanan65dafa82010-08-27 01:01:44 +0000272
273 unsigned num_errors = parser.Parse (error_stream);
274
275 if (num_errors)
276 {
277 error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
Sean Callananaa301c42010-12-03 01:38:59 +0000278
279 m_expr_decl_map->DidParse();
280
Sean Callanan65dafa82010-08-27 01:01:44 +0000281 return false;
282 }
283
Sean Callanan47dc4572011-09-15 02:13:07 +0000284 //////////////////////////////////////////////////////////////////////////////////////////
285 // Prepare the output of the parser for execution, evaluating it statically if possible
Sean Callanan65dafa82010-08-27 01:01:44 +0000286 //
Sean Callanan65dafa82010-08-27 01:01:44 +0000287
Sean Callanan47dc4572011-09-15 02:13:07 +0000288 if (execution_policy != eExecutionPolicyNever && exe_ctx.process)
289 m_data_allocator.reset(new ProcessDataAllocator(*exe_ctx.process));
Sean Callanan65dafa82010-08-27 01:01:44 +0000290
Sean Callanan47dc4572011-09-15 02:13:07 +0000291 Error jit_error = parser.PrepareForExecution (m_jit_alloc,
292 m_jit_start_addr,
293 m_jit_end_addr,
294 exe_ctx,
295 m_data_allocator.get(),
296 m_evaluated_statically,
297 m_const_result,
298 execution_policy);
Sean Callanan65dafa82010-08-27 01:01:44 +0000299
Sean Callanan47dc4572011-09-15 02:13:07 +0000300 if (log && m_data_allocator.get())
Sean Callananc0492742011-05-23 21:40:23 +0000301 {
302 StreamString dump_string;
303 m_data_allocator->Dump(dump_string);
304
305 log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str());
306 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000307
Sean Callananaa301c42010-12-03 01:38:59 +0000308 m_expr_decl_map->DidParse();
309
Sean Callanan65dafa82010-08-27 01:01:44 +0000310 if (jit_error.Success())
311 {
Greg Claytond0882d02011-01-19 23:00:49 +0000312 if (exe_ctx.process && m_jit_alloc != LLDB_INVALID_ADDRESS)
313 m_jit_process_sp = exe_ctx.process->GetSP();
Sean Callanan65dafa82010-08-27 01:01:44 +0000314 return true;
315 }
316 else
317 {
Greg Clayton30581972011-05-17 03:51:29 +0000318 const char *error_cstr = jit_error.AsCString();
319 if (error_cstr && error_cstr[0])
320 error_stream.Printf ("error: %s\n", error_cstr);
321 else
322 error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
Sean Callanan65dafa82010-08-27 01:01:44 +0000323 return false;
324 }
325}
326
327bool
Jim Inghamd1686902010-10-14 23:45:03 +0000328ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
Sean Callananab06af92010-10-19 23:57:21 +0000329 ExecutionContext &exe_ctx,
330 lldb::addr_t &struct_address,
Sean Callanan047923c2010-12-14 00:42:36 +0000331 lldb::addr_t &object_ptr,
332 lldb::addr_t &cmd_ptr)
Sean Callanan65dafa82010-08-27 01:01:44 +0000333{
Greg Claytone005f2c2010-11-06 01:53:30 +0000334 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan65dafa82010-08-27 01:01:44 +0000335
Greg Claytond0882d02011-01-19 23:00:49 +0000336 if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
Sean Callanan65dafa82010-08-27 01:01:44 +0000337 {
Sean Callanan65dafa82010-08-27 01:01:44 +0000338 Error materialize_error;
339
Sean Callanan3aa7da52010-12-13 22:46:15 +0000340 if (m_needs_object_ptr)
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000341 {
Sean Callanan3aa7da52010-12-13 22:46:15 +0000342 ConstString object_name;
343
344 if (m_cplusplus)
345 {
346 object_name.SetCString("this");
347 }
348 else if (m_objectivec)
349 {
350 object_name.SetCString("self");
351 }
352 else
353 {
354 error_stream.Printf("Need object pointer but don't know the language\n");
355 return false;
356 }
357
358 if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, exe_ctx, materialize_error)))
359 {
360 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
361 return false;
362 }
Sean Callanan047923c2010-12-14 00:42:36 +0000363
364 if (m_objectivec)
365 {
366 ConstString cmd_name("_cmd");
367
368 if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, exe_ctx, materialize_error, true)))
369 {
370 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
371 return false;
372 }
373 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000374 }
375
Sean Callananaa301c42010-12-03 01:38:59 +0000376 if (!m_expr_decl_map->Materialize(exe_ctx, struct_address, materialize_error))
Sean Callanan65dafa82010-08-27 01:01:44 +0000377 {
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000378 error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
Sean Callanan65dafa82010-08-27 01:01:44 +0000379 return false;
380 }
Greg Claytonc71899e2011-01-18 19:36:39 +0000381
382#if 0
383 // jingham: look here
384 StreamFile logfile ("/tmp/exprs.txt", "a");
Greg Claytond0882d02011-01-19 23:00:49 +0000385 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 Claytonc71899e2011-01-18 19:36:39 +0000386#endif
Sean Callanan65dafa82010-08-27 01:01:44 +0000387
388 if (log)
389 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000390 log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --");
Sean Callanan33711022010-12-07 10:00:20 +0000391
Greg Claytond0882d02011-01-19 23:00:49 +0000392 log->Printf(" Function address : 0x%llx", (uint64_t)m_jit_start_addr);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000393
394 if (m_needs_object_ptr)
Sean Callanan33711022010-12-07 10:00:20 +0000395 log->Printf(" Object pointer : 0x%llx", (uint64_t)object_ptr);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000396
Sean Callanan33711022010-12-07 10:00:20 +0000397 log->Printf(" Structure address : 0x%llx", (uint64_t)struct_address);
Sean Callanan65dafa82010-08-27 01:01:44 +0000398
399 StreamString args;
400
401 Error dump_error;
402
Sean Callanane8a59a82010-09-13 21:34:21 +0000403 if (struct_address)
Sean Callanan65dafa82010-08-27 01:01:44 +0000404 {
Sean Callananaa301c42010-12-03 01:38:59 +0000405 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
Sean Callanane8a59a82010-09-13 21:34:21 +0000406 {
Sean Callanan33711022010-12-07 10:00:20 +0000407 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
Sean Callanane8a59a82010-09-13 21:34:21 +0000408 }
409 else
410 {
Sean Callanan33711022010-12-07 10:00:20 +0000411 log->Printf(" Structure contents:\n%s", args.GetData());
Sean Callanane8a59a82010-09-13 21:34:21 +0000412 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000413 }
414 }
Jim Inghamd1686902010-10-14 23:45:03 +0000415 }
416 return true;
417}
418
419ThreadPlan *
420ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
Sean Callanan6a925532011-01-13 08:53:35 +0000421 ExecutionContext &exe_ctx)
Jim Inghamd1686902010-10-14 23:45:03 +0000422{
423 lldb::addr_t struct_address;
424
Johnny Chen2bc9eb32011-07-19 19:48:13 +0000425 lldb::addr_t object_ptr = 0;
426 lldb::addr_t cmd_ptr = 0;
Jim Inghamd1686902010-10-14 23:45:03 +0000427
Sean Callanan047923c2010-12-14 00:42:36 +0000428 PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
Jim Inghamd1686902010-10-14 23:45:03 +0000429
Jim Ingham360f53f2010-11-30 02:22:11 +0000430 // FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
431 // ClangUserExpression resources before the thread plan finishes execution in the target. But because we are
Sean Callanan3aa7da52010-12-13 22:46:15 +0000432 // forcing unwind_on_error to be true here, in practical terms that can't happen.
433
Jim Inghamd1686902010-10-14 23:45:03 +0000434 return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
Greg Claytond0882d02011-01-19 23:00:49 +0000435 m_jit_start_addr,
Sean Callanana65b5272010-12-01 01:28:23 +0000436 struct_address,
437 error_stream,
438 true,
439 true,
Sean Callanan3aa7da52010-12-13 22:46:15 +0000440 (m_needs_object_ptr ? &object_ptr : NULL),
441 (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
Jim Inghamd1686902010-10-14 23:45:03 +0000442}
443
444bool
445ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
446 ExecutionContext &exe_ctx,
Sean Callanan0ddf8062011-05-09 22:04:36 +0000447 lldb::ClangExpressionVariableSP &result,
448 lldb::addr_t function_stack_pointer)
Jim Inghamd1686902010-10-14 23:45:03 +0000449{
450 Error expr_error;
451
Sean Callanan33711022010-12-07 10:00:20 +0000452 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
453
454 if (log)
455 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000456 log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
Sean Callanan33711022010-12-07 10:00:20 +0000457
458 StreamString args;
459
460 Error dump_error;
461
462 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
463 {
464 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
465 }
466 else
467 {
468 log->Printf(" Structure contents:\n%s", args.GetData());
469 }
470 }
Sean Callanan0ddf8062011-05-09 22:04:36 +0000471
472 lldb::addr_t function_stack_bottom = function_stack_pointer - Host::GetPageSize();
473
Sean Callanan33711022010-12-07 10:00:20 +0000474
Sean Callanan0ddf8062011-05-09 22:04:36 +0000475 if (!m_expr_decl_map->Dematerialize(exe_ctx, result, function_stack_pointer, function_stack_bottom, expr_error))
Jim Inghamd1686902010-10-14 23:45:03 +0000476 {
477 error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
478 return false;
479 }
480 return true;
481}
482
Greg Claytonb3448432011-03-24 21:19:54 +0000483ExecutionResults
Jim Inghamd1686902010-10-14 23:45:03 +0000484ClangUserExpression::Execute (Stream &error_stream,
485 ExecutionContext &exe_ctx,
Jim Inghamea9d4262010-11-05 19:25:48 +0000486 bool discard_on_error,
Jim Ingham360f53f2010-11-30 02:22:11 +0000487 ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
Greg Clayton427f2902010-12-14 02:59:59 +0000488 lldb::ClangExpressionVariableSP &result)
Jim Inghamd1686902010-10-14 23:45:03 +0000489{
Jim Ingham7812e012011-01-18 22:20:08 +0000490 // The expression log is quite verbose, and if you're just tracking the execution of the
491 // expression, it's quite convenient to have these logs come out with the STEP log as well.
492 lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
Sean Callanan33711022010-12-07 10:00:20 +0000493
Sean Callanan47dc4572011-09-15 02:13:07 +0000494 if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
Jim Inghamd1686902010-10-14 23:45:03 +0000495 {
496 lldb::addr_t struct_address;
497
Johnny Chen2bc9eb32011-07-19 19:48:13 +0000498 lldb::addr_t object_ptr = 0;
499 lldb::addr_t cmd_ptr = 0;
Jim Inghamd1686902010-10-14 23:45:03 +0000500
Sean Callanan047923c2010-12-14 00:42:36 +0000501 if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
Greg Claytonb3448432011-03-24 21:19:54 +0000502 return eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000503
Jim Inghamea9d4262010-11-05 19:25:48 +0000504 const bool stop_others = true;
505 const bool try_all_threads = true;
Sean Callanan65dafa82010-08-27 01:01:44 +0000506
Greg Claytond0882d02011-01-19 23:00:49 +0000507 Address wrapper_address (NULL, m_jit_start_addr);
Sean Callanan3aa7da52010-12-13 22:46:15 +0000508 lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (*(exe_ctx.thread),
509 wrapper_address,
510 struct_address,
511 stop_others,
512 discard_on_error,
513 (m_needs_object_ptr ? &object_ptr : NULL),
514 ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
515 shared_ptr_to_me));
516
Jim Ingham360f53f2010-11-30 02:22:11 +0000517 if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL))
Greg Claytonb3448432011-03-24 21:19:54 +0000518 return eExecutionSetupError;
Sean Callanan0ddf8062011-05-09 22:04:36 +0000519
520 lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
Jim Ingham360f53f2010-11-30 02:22:11 +0000521
Jim Ingham5ab7fba2011-05-17 22:24:54 +0000522 call_plan_sp->SetPrivate(true);
Jim Ingham360f53f2010-11-30 02:22:11 +0000523
Greg Clayton61468e82011-01-19 07:54:15 +0000524 uint32_t single_thread_timeout_usec = 500000;
Sean Callanan33711022010-12-07 10:00:20 +0000525
526 if (log)
Sean Callanan94d255f2010-12-07 22:55:01 +0000527 log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
Sean Callanan33711022010-12-07 10:00:20 +0000528
Greg Claytonb3448432011-03-24 21:19:54 +0000529 ExecutionResults execution_result = exe_ctx.process->RunThreadPlan (exe_ctx,
Sean Callanan0ddf8062011-05-09 22:04:36 +0000530 call_plan_sp,
531 stop_others,
532 try_all_threads,
533 discard_on_error,
534 single_thread_timeout_usec,
535 error_stream);
Sean Callanan33711022010-12-07 10:00:20 +0000536
537 if (log)
Sean Callanan94d255f2010-12-07 22:55:01 +0000538 log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
Jim Ingham360f53f2010-11-30 02:22:11 +0000539
Greg Claytonb3448432011-03-24 21:19:54 +0000540 if (execution_result == eExecutionInterrupted)
Sean Callanan65dafa82010-08-27 01:01:44 +0000541 {
Jim Ingham2370a972011-05-17 01:10:11 +0000542 const char *error_desc = NULL;
543
544 if (call_plan_sp)
545 {
546 lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
547 if (real_stop_info_sp)
548 error_desc = real_stop_info_sp->GetDescription();
549 }
550 if (error_desc)
551 error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
Jim Ingham360f53f2010-11-30 02:22:11 +0000552 else
Jim Ingham2370a972011-05-17 01:10:11 +0000553 error_stream.Printf ("Execution was interrupted.", error_desc);
554
555 if (discard_on_error)
556 error_stream.Printf ("\nThe process has been returned to the state before execution.");
557 else
558 error_stream.Printf ("\nThe process has been left at the point where it was interrupted.");
Jim Ingham360f53f2010-11-30 02:22:11 +0000559
560 return execution_result;
561 }
Greg Claytonb3448432011-03-24 21:19:54 +0000562 else if (execution_result != eExecutionCompleted)
Jim Ingham360f53f2010-11-30 02:22:11 +0000563 {
564 error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
565 return execution_result;
Sean Callanan65dafa82010-08-27 01:01:44 +0000566 }
567
Sean Callanan0ddf8062011-05-09 22:04:36 +0000568 if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_pointer))
Greg Claytonb3448432011-03-24 21:19:54 +0000569 return eExecutionCompleted;
Jim Ingham360f53f2010-11-30 02:22:11 +0000570 else
Greg Claytonb3448432011-03-24 21:19:54 +0000571 return eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000572 }
573 else
574 {
Sean Callanan47dc4572011-09-15 02:13:07 +0000575 error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
Greg Claytonb3448432011-03-24 21:19:54 +0000576 return eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000577 }
578}
579
Greg Claytonb3448432011-03-24 21:19:54 +0000580ExecutionResults
Sean Callanan47dc4572011-09-15 02:13:07 +0000581ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
582 lldb_private::ExecutionPolicy execution_policy,
Jim Inghamea9d4262010-11-05 19:25:48 +0000583 bool discard_on_error,
Sean Callanan77e93942010-10-29 00:29:03 +0000584 const char *expr_cstr,
Jim Ingham360f53f2010-11-30 02:22:11 +0000585 const char *expr_prefix,
586 lldb::ValueObjectSP &result_valobj_sp)
Greg Clayton377e0b42010-10-05 00:31:29 +0000587{
Jim Inghamec07c0d2011-08-09 00:00:49 +0000588 Error error;
Sean Callanan47dc4572011-09-15 02:13:07 +0000589 return EvaluateWithError (exe_ctx, execution_policy, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error);
Jim Inghamec07c0d2011-08-09 00:00:49 +0000590}
591
592ExecutionResults
Sean Callanan47dc4572011-09-15 02:13:07 +0000593ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
594 lldb_private::ExecutionPolicy execution_policy,
595 bool discard_on_error,
596 const char *expr_cstr,
597 const char *expr_prefix,
598 lldb::ValueObjectSP &result_valobj_sp,
599 Error &error)
Jim Inghamec07c0d2011-08-09 00:00:49 +0000600{
Jim Ingham7812e012011-01-18 22:20:08 +0000601 lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
Sean Callanan94d255f2010-12-07 22:55:01 +0000602
Greg Claytonb3448432011-03-24 21:19:54 +0000603 ExecutionResults execution_results = eExecutionSetupError;
Greg Clayton0baa3942010-11-04 01:54:29 +0000604
Jim Inghame6bd1422011-06-20 17:32:44 +0000605 if (exe_ctx.process == NULL || exe_ctx.process->GetState() != lldb::eStateStopped)
Jim Ingham360f53f2010-11-30 02:22:11 +0000606 {
Sean Callanan47dc4572011-09-15 02:13:07 +0000607 if (execution_policy == eExecutionPolicyAlways)
608 {
609 if (log)
610 log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
Jim Ingham360f53f2010-11-30 02:22:11 +0000611
Sean Callanan47dc4572011-09-15 02:13:07 +0000612 error.SetErrorString ("expression needed to run but couldn't");
613
614 return execution_results;
615 }
Jim Ingham360f53f2010-11-30 02:22:11 +0000616 }
Sean Callananf7649bb2011-09-15 17:43:00 +0000617
618 if (exe_ctx.process == NULL)
619 execution_policy = eExecutionPolicyNever;
Sean Callanan47dc4572011-09-15 02:13:07 +0000620
621 if (execution_policy != eExecutionPolicyNever && !exe_ctx.process->GetDynamicCheckers())
Greg Clayton0baa3942010-11-04 01:54:29 +0000622 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000623 if (log)
624 log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers ==");
625
Greg Clayton0baa3942010-11-04 01:54:29 +0000626 DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
627
628 StreamString install_errors;
629
630 if (!dynamic_checkers->Install(install_errors, exe_ctx))
Sean Callananf7731452010-11-05 00:57:06 +0000631 {
632 if (install_errors.GetString().empty())
633 error.SetErrorString ("couldn't install checkers, unknown error");
634 else
635 error.SetErrorString (install_errors.GetString().c_str());
636
Jim Ingham47da8102011-04-22 23:53:53 +0000637 result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
Greg Claytonb3448432011-03-24 21:19:54 +0000638 return eExecutionSetupError;
Sean Callananf7731452010-11-05 00:57:06 +0000639 }
640
Greg Clayton0baa3942010-11-04 01:54:29 +0000641 exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
Sean Callanan94d255f2010-12-07 22:55:01 +0000642
643 if (log)
644 log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
Greg Clayton0baa3942010-11-04 01:54:29 +0000645 }
646
Jim Ingham360f53f2010-11-30 02:22:11 +0000647 ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix));
648
Greg Clayton377e0b42010-10-05 00:31:29 +0000649 StreamString error_stream;
Sean Callanan696cf5f2011-05-07 01:06:41 +0000650
Sean Callanan94d255f2010-12-07 22:55:01 +0000651 if (log)
652 log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
653
Sean Callanan47dc4572011-09-15 02:13:07 +0000654 const bool keep_expression_in_memory = true;
655
656 if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), execution_policy, keep_expression_in_memory))
Greg Clayton377e0b42010-10-05 00:31:29 +0000657 {
658 if (error_stream.GetString().empty())
659 error.SetErrorString ("expression failed to parse, unknown error");
660 else
661 error.SetErrorString (error_stream.GetString().c_str());
662 }
663 else
664 {
Greg Clayton427f2902010-12-14 02:59:59 +0000665 lldb::ClangExpressionVariableSP expr_result;
Greg Clayton377e0b42010-10-05 00:31:29 +0000666
Sean Callanan47dc4572011-09-15 02:13:07 +0000667 if (user_expression_sp->EvaluatedStatically())
Greg Clayton377e0b42010-10-05 00:31:29 +0000668 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000669 if (log)
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000670 log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
Sean Callanan94d255f2010-12-07 22:55:01 +0000671
Sean Callanan47dc4572011-09-15 02:13:07 +0000672 if (user_expression_sp->m_const_result)
673 result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
674 else
675 error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
676
Jim Inghamec07c0d2011-08-09 00:00:49 +0000677 execution_results = eExecutionCompleted;
Greg Clayton377e0b42010-10-05 00:31:29 +0000678 }
Sean Callanan47dc4572011-09-15 02:13:07 +0000679 else if (execution_policy == eExecutionPolicyNever)
680 {
681 if (log)
682 log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
683
684 if (error_stream.GetString().empty())
685 error.SetErrorString ("expression needed to run but couldn't");
686 }
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000687 else
688 {
689 error_stream.GetString().clear();
690
691 if (log)
692 log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
693
694 execution_results = user_expression_sp->Execute (error_stream,
695 exe_ctx,
Sean Callanan6a925532011-01-13 08:53:35 +0000696 discard_on_error,
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000697 user_expression_sp,
698 expr_result);
699
Greg Claytonb3448432011-03-24 21:19:54 +0000700 if (execution_results != eExecutionCompleted)
Greg Clayton377e0b42010-10-05 00:31:29 +0000701 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000702 if (log)
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000703 log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
704
705 if (error_stream.GetString().empty())
706 error.SetErrorString ("expression failed to execute, unknown error");
707 else
708 error.SetErrorString (error_stream.GetString().c_str());
Greg Clayton377e0b42010-10-05 00:31:29 +0000709 }
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000710 else
Greg Clayton377e0b42010-10-05 00:31:29 +0000711 {
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000712 if (expr_result)
713 {
714 result_valobj_sp = expr_result->GetValueObject();
715
716 if (log)
Jim Inghamfa3a16a2011-03-31 00:19:25 +0000717 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString());
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000718 }
719 else
720 {
721 if (log)
722 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
723
Sean Callanan24312442011-08-23 21:20:51 +0000724 error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000725 }
Greg Clayton377e0b42010-10-05 00:31:29 +0000726 }
727 }
728 }
Sean Callanan44820ec2010-10-19 20:15:00 +0000729
Greg Claytond1719722010-10-05 03:13:51 +0000730 if (result_valobj_sp.get() == NULL)
Jim Ingham47da8102011-04-22 23:53:53 +0000731 result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
Greg Claytond1719722010-10-05 03:13:51 +0000732
Jim Ingham360f53f2010-11-30 02:22:11 +0000733 return execution_results;
Johnny Chenb4c0f022010-10-29 20:19:44 +0000734}