blob: 9cd84894854fb8f54f6955e0e67be740b3be2443 [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),
56 m_const_result ()
Sean Callanan65dafa82010-08-27 01:01:44 +000057{
Sean Callanan65dafa82010-08-27 01:01:44 +000058}
59
Sean Callanan830a9032010-08-27 23:31:21 +000060ClangUserExpression::~ClangUserExpression ()
61{
62}
63
Sean Callanan65dafa82010-08-27 01:01:44 +000064clang::ASTConsumer *
65ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
66{
Sean Callanana91dd992010-11-19 02:52:21 +000067 return new ASTResultSynthesizer(passthrough,
68 m_desired_type);
Sean Callanan65dafa82010-08-27 01:01:44 +000069}
70
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000071void
72ClangUserExpression::ScanContext(ExecutionContext &exe_ctx)
73{
Sean Callananc617a4c2011-08-05 23:43:37 +000074 if (!exe_ctx.frame)
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000075 return;
76
Sean Callananc617a4c2011-08-05 23:43:37 +000077 SymbolContext sym_ctx = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextFunction);
Sean Callanane8e55572010-12-01 21:35:54 +000078
Sean Callananc617a4c2011-08-05 23:43:37 +000079 if (!sym_ctx.function)
80 return;
81
82 clang::DeclContext *decl_context;
83
84 if (sym_ctx.block && sym_ctx.block->GetInlinedFunctionInfo())
85 decl_context = sym_ctx.block->GetClangDeclContextForInlinedFunction();
86 else
87 decl_context = sym_ctx.function->GetClangDeclContext();
88
89 if (!decl_context)
90 return;
91
92 if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context))
Sean Callanane8e55572010-12-01 21:35:54 +000093 {
Sean Callananc617a4c2011-08-05 23:43:37 +000094 if (method_decl->isInstance())
Sean Callanane8e55572010-12-01 21:35:54 +000095 {
Sean Callananc617a4c2011-08-05 23:43:37 +000096 m_cplusplus = true;
Sean Callanane8e55572010-12-01 21:35:54 +000097
Sean Callananc617a4c2011-08-05 23:43:37 +000098 do {
99 clang::QualType this_type = method_decl->getThisType(decl_context->getParentASTContext());
100
101 const clang::PointerType *this_pointer_type = llvm::dyn_cast<clang::PointerType>(this_type.getTypePtr());
102
103 if (!this_pointer_type)
104 break;
105
106 clang::QualType this_pointee_type = this_pointer_type->getPointeeType();
107 } while (0);
Sean Callanane8e55572010-12-01 21:35:54 +0000108 }
109 }
Sean Callananc617a4c2011-08-05 23:43:37 +0000110 else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context))
Sean Callanane8e55572010-12-01 21:35:54 +0000111 {
Sean Callananc617a4c2011-08-05 23:43:37 +0000112 if (method_decl->isInstanceMethod())
113 m_objectivec = true;
Sean Callanane8e55572010-12-01 21:35:54 +0000114 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000115}
116
Sean Callanan550f2762010-10-22 23:25:16 +0000117// This is a really nasty hack, meant to fix Objective-C expressions of the form
118// (int)[myArray count]. Right now, because the type information for count is
119// not available, [myArray count] returns id, which can't be directly cast to
120// int without causing a clang error.
121static void
122ApplyObjcCastHack(std::string &expr)
123{
124#define OBJC_CAST_HACK_FROM "(int)["
125#define OBJC_CAST_HACK_TO "(int)(long long)["
126
127 size_t from_offset;
128
129 while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
130 expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
131
132#undef OBJC_CAST_HACK_TO
133#undef OBJC_CAST_HACK_FROM
134}
135
Sean Callanan30892372010-10-24 20:45:49 +0000136// Another hack, meant to allow use of unichar despite it not being available in
137// the type information. Although we could special-case it in type lookup,
138// hopefully we'll figure out a way to #include the same environment as is
139// present in the original source file rather than try to hack specific type
140// definitions in as needed.
141static void
142ApplyUnicharHack(std::string &expr)
143{
144#define UNICHAR_HACK_FROM "unichar"
145#define UNICHAR_HACK_TO "unsigned short"
146
147 size_t from_offset;
148
149 while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
150 expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
151
152#undef UNICHAR_HACK_TO
153#undef UNICHAR_HACK_FROM
154}
155
Sean Callanan550f2762010-10-22 23:25:16 +0000156bool
Sean Callanana91dd992010-11-19 02:52:21 +0000157ClangUserExpression::Parse (Stream &error_stream,
158 ExecutionContext &exe_ctx,
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000159 TypeFromUser desired_type,
Sean Callanan696cf5f2011-05-07 01:06:41 +0000160 bool keep_result_in_memory)
Sean Callanan65dafa82010-08-27 01:01:44 +0000161{
Greg Claytone005f2c2010-11-06 01:53:30 +0000162 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan65dafa82010-08-27 01:01:44 +0000163
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000164 ScanContext(exe_ctx);
165
166 StreamString m_transformed_stream;
167
168 ////////////////////////////////////
169 // Generate the expression
170 //
Sean Callanan550f2762010-10-22 23:25:16 +0000171
172 ApplyObjcCastHack(m_expr_text);
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000173 //ApplyUnicharHack(m_expr_text);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000174
175 if (m_cplusplus)
176 {
Sean Callanan77e93942010-10-29 00:29:03 +0000177 m_transformed_stream.Printf("%s \n"
178 "typedef unsigned short unichar; \n"
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000179 "void \n"
Sean Callanane8e55572010-12-01 21:35:54 +0000180 "$__lldb_class::%s(void *$__lldb_arg) %s\n"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000181 "{ \n"
182 " %s; \n"
183 "} \n",
Sean Callanan77e93942010-10-29 00:29:03 +0000184 m_expr_prefix.c_str(),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000185 FunctionName(),
Sean Callanane8e55572010-12-01 21:35:54 +0000186 (m_const_object ? "const" : ""),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000187 m_expr_text.c_str());
188
189 m_needs_object_ptr = true;
190 }
Enrico Granata4c3fb4b2011-07-19 18:03:25 +0000191 else if (m_objectivec)
Sean Callanan3aa7da52010-12-13 22:46:15 +0000192 {
193 const char *function_name = FunctionName();
194
195 m_transformed_stream.Printf("%s \n"
Greg Claytonc5157ec2010-12-17 02:26:24 +0000196 "typedef unsigned short unichar; \n"
Sean Callanan3aa7da52010-12-13 22:46:15 +0000197 "@interface $__lldb_objc_class ($__lldb_category) \n"
198 "-(void)%s:(void *)$__lldb_arg; \n"
199 "@end \n"
200 "@implementation $__lldb_objc_class ($__lldb_category) \n"
201 "-(void)%s:(void *)$__lldb_arg \n"
202 "{ \n"
203 " %s; \n"
204 "} \n"
205 "@end \n",
206 m_expr_prefix.c_str(),
207 function_name,
208 function_name,
209 m_expr_text.c_str());
210
211 m_needs_object_ptr = true;
212 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000213 else
214 {
Sean Callanan77e93942010-10-29 00:29:03 +0000215 m_transformed_stream.Printf("%s \n"
216 "typedef unsigned short unichar;\n"
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000217 "void \n"
Sean Callanan550f2762010-10-22 23:25:16 +0000218 "%s(void *$__lldb_arg) \n"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000219 "{ \n"
220 " %s; \n"
221 "} \n",
Sean Callanan77e93942010-10-29 00:29:03 +0000222 m_expr_prefix.c_str(),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000223 FunctionName(),
224 m_expr_text.c_str());
225 }
226
227 m_transformed_text = m_transformed_stream.GetData();
228
229
230 if (log)
231 log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
232
Sean Callanan65dafa82010-08-27 01:01:44 +0000233 ////////////////////////////////////
234 // Set up the target and compiler
235 //
236
237 Target *target = exe_ctx.target;
238
239 if (!target)
240 {
241 error_stream.PutCString ("error: invalid target\n");
242 return false;
243 }
244
Sean Callanan65dafa82010-08-27 01:01:44 +0000245 //////////////////////////
246 // Parse the expression
247 //
248
Sean Callanana91dd992010-11-19 02:52:21 +0000249 m_desired_type = desired_type;
250
Sean Callanan6a925532011-01-13 08:53:35 +0000251 m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
Sean Callananaa301c42010-12-03 01:38:59 +0000252
Sean Callanan166ba102011-08-01 18:18:33 +0000253 if (!m_expr_decl_map->WillParse(exe_ctx))
254 {
255 error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
256 return false;
257 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000258
Greg Clayton395fc332011-02-15 21:59:32 +0000259 ClangExpressionParser parser(exe_ctx.process, *this);
Sean Callanan65dafa82010-08-27 01:01:44 +0000260
261 unsigned num_errors = parser.Parse (error_stream);
262
263 if (num_errors)
264 {
265 error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
Sean Callananaa301c42010-12-03 01:38:59 +0000266
267 m_expr_decl_map->DidParse();
268
Sean Callanan65dafa82010-08-27 01:01:44 +0000269 return false;
270 }
271
272 ///////////////////////////////////////////////
273 // Convert the output of the parser to DWARF
274 //
275
276 m_dwarf_opcodes.reset(new StreamString);
Greg Claytoncd548032011-02-01 01:31:41 +0000277 m_dwarf_opcodes->SetByteOrder (lldb::endian::InlHostByteOrder());
Sean Callanan65dafa82010-08-27 01:01:44 +0000278 m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
279
Greg Clayton427f2902010-12-14 02:59:59 +0000280 m_local_variables.reset(new ClangExpressionVariableList());
Sean Callanan65dafa82010-08-27 01:01:44 +0000281
282 Error dwarf_error = parser.MakeDWARF ();
283
284 if (dwarf_error.Success())
285 {
286 if (log)
287 log->Printf("Code can be interpreted.");
288
Sean Callananaa301c42010-12-03 01:38:59 +0000289 m_expr_decl_map->DidParse();
290
Sean Callanan65dafa82010-08-27 01:01:44 +0000291 return true;
292 }
293
294 //////////////////////////////////
295 // JIT the output of the parser
296 //
297
298 m_dwarf_opcodes.reset();
299
Sean Callananc0492742011-05-23 21:40:23 +0000300 m_data_allocator.reset(new ProcessDataAllocator(*exe_ctx.process));
301
302 Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_data_allocator.get(), m_const_result, true);
303
304 if (log)
305 {
306 StreamString dump_string;
307 m_data_allocator->Dump(dump_string);
308
309 log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str());
310 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000311
Sean Callananaa301c42010-12-03 01:38:59 +0000312 m_expr_decl_map->DidParse();
313
Sean Callanan65dafa82010-08-27 01:01:44 +0000314 if (jit_error.Success())
315 {
Greg Claytond0882d02011-01-19 23:00:49 +0000316 if (exe_ctx.process && m_jit_alloc != LLDB_INVALID_ADDRESS)
317 m_jit_process_sp = exe_ctx.process->GetSP();
Sean Callanan65dafa82010-08-27 01:01:44 +0000318 return true;
319 }
320 else
321 {
Greg Clayton30581972011-05-17 03:51:29 +0000322 const char *error_cstr = jit_error.AsCString();
323 if (error_cstr && error_cstr[0])
324 error_stream.Printf ("error: %s\n", error_cstr);
325 else
326 error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
Sean Callanan65dafa82010-08-27 01:01:44 +0000327 return false;
328 }
329}
330
331bool
Jim Inghamd1686902010-10-14 23:45:03 +0000332ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
Sean Callananab06af92010-10-19 23:57:21 +0000333 ExecutionContext &exe_ctx,
334 lldb::addr_t &struct_address,
Sean Callanan047923c2010-12-14 00:42:36 +0000335 lldb::addr_t &object_ptr,
336 lldb::addr_t &cmd_ptr)
Sean Callanan65dafa82010-08-27 01:01:44 +0000337{
Greg Claytone005f2c2010-11-06 01:53:30 +0000338 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan65dafa82010-08-27 01:01:44 +0000339
Greg Claytond0882d02011-01-19 23:00:49 +0000340 if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
Sean Callanan65dafa82010-08-27 01:01:44 +0000341 {
Sean Callanan65dafa82010-08-27 01:01:44 +0000342 Error materialize_error;
343
Sean Callanan3aa7da52010-12-13 22:46:15 +0000344 if (m_needs_object_ptr)
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000345 {
Sean Callanan3aa7da52010-12-13 22:46:15 +0000346 ConstString object_name;
347
348 if (m_cplusplus)
349 {
350 object_name.SetCString("this");
351 }
352 else if (m_objectivec)
353 {
354 object_name.SetCString("self");
355 }
356 else
357 {
358 error_stream.Printf("Need object pointer but don't know the language\n");
359 return false;
360 }
361
362 if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, exe_ctx, materialize_error)))
363 {
364 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
365 return false;
366 }
Sean Callanan047923c2010-12-14 00:42:36 +0000367
368 if (m_objectivec)
369 {
370 ConstString cmd_name("_cmd");
371
372 if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, exe_ctx, materialize_error, true)))
373 {
374 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
375 return false;
376 }
377 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000378 }
379
Sean Callananaa301c42010-12-03 01:38:59 +0000380 if (!m_expr_decl_map->Materialize(exe_ctx, struct_address, materialize_error))
Sean Callanan65dafa82010-08-27 01:01:44 +0000381 {
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000382 error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
Sean Callanan65dafa82010-08-27 01:01:44 +0000383 return false;
384 }
Greg Claytonc71899e2011-01-18 19:36:39 +0000385
386#if 0
387 // jingham: look here
388 StreamFile logfile ("/tmp/exprs.txt", "a");
Greg Claytond0882d02011-01-19 23:00:49 +0000389 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 +0000390#endif
Sean Callanan65dafa82010-08-27 01:01:44 +0000391
392 if (log)
393 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000394 log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --");
Sean Callanan33711022010-12-07 10:00:20 +0000395
Greg Claytond0882d02011-01-19 23:00:49 +0000396 log->Printf(" Function address : 0x%llx", (uint64_t)m_jit_start_addr);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000397
398 if (m_needs_object_ptr)
Sean Callanan33711022010-12-07 10:00:20 +0000399 log->Printf(" Object pointer : 0x%llx", (uint64_t)object_ptr);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000400
Sean Callanan33711022010-12-07 10:00:20 +0000401 log->Printf(" Structure address : 0x%llx", (uint64_t)struct_address);
Sean Callanan65dafa82010-08-27 01:01:44 +0000402
403 StreamString args;
404
405 Error dump_error;
406
Sean Callanane8a59a82010-09-13 21:34:21 +0000407 if (struct_address)
Sean Callanan65dafa82010-08-27 01:01:44 +0000408 {
Sean Callananaa301c42010-12-03 01:38:59 +0000409 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
Sean Callanane8a59a82010-09-13 21:34:21 +0000410 {
Sean Callanan33711022010-12-07 10:00:20 +0000411 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
Sean Callanane8a59a82010-09-13 21:34:21 +0000412 }
413 else
414 {
Sean Callanan33711022010-12-07 10:00:20 +0000415 log->Printf(" Structure contents:\n%s", args.GetData());
Sean Callanane8a59a82010-09-13 21:34:21 +0000416 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000417 }
418 }
Jim Inghamd1686902010-10-14 23:45:03 +0000419 }
420 return true;
421}
422
423ThreadPlan *
424ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
Sean Callanan6a925532011-01-13 08:53:35 +0000425 ExecutionContext &exe_ctx)
Jim Inghamd1686902010-10-14 23:45:03 +0000426{
427 lldb::addr_t struct_address;
428
Johnny Chen2bc9eb32011-07-19 19:48:13 +0000429 lldb::addr_t object_ptr = 0;
430 lldb::addr_t cmd_ptr = 0;
Jim Inghamd1686902010-10-14 23:45:03 +0000431
Sean Callanan047923c2010-12-14 00:42:36 +0000432 PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
Jim Inghamd1686902010-10-14 23:45:03 +0000433
Jim Ingham360f53f2010-11-30 02:22:11 +0000434 // FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
435 // ClangUserExpression resources before the thread plan finishes execution in the target. But because we are
Sean Callanan3aa7da52010-12-13 22:46:15 +0000436 // forcing unwind_on_error to be true here, in practical terms that can't happen.
437
Jim Inghamd1686902010-10-14 23:45:03 +0000438 return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
Greg Claytond0882d02011-01-19 23:00:49 +0000439 m_jit_start_addr,
Sean Callanana65b5272010-12-01 01:28:23 +0000440 struct_address,
441 error_stream,
442 true,
443 true,
Sean Callanan3aa7da52010-12-13 22:46:15 +0000444 (m_needs_object_ptr ? &object_ptr : NULL),
445 (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
Jim Inghamd1686902010-10-14 23:45:03 +0000446}
447
448bool
449ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
450 ExecutionContext &exe_ctx,
Sean Callanan0ddf8062011-05-09 22:04:36 +0000451 lldb::ClangExpressionVariableSP &result,
452 lldb::addr_t function_stack_pointer)
Jim Inghamd1686902010-10-14 23:45:03 +0000453{
454 Error expr_error;
455
Sean Callanan33711022010-12-07 10:00:20 +0000456 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
457
458 if (log)
459 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000460 log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
Sean Callanan33711022010-12-07 10:00:20 +0000461
462 StreamString args;
463
464 Error dump_error;
465
466 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
467 {
468 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
469 }
470 else
471 {
472 log->Printf(" Structure contents:\n%s", args.GetData());
473 }
474 }
Sean Callanan0ddf8062011-05-09 22:04:36 +0000475
476 lldb::addr_t function_stack_bottom = function_stack_pointer - Host::GetPageSize();
477
Sean Callanan33711022010-12-07 10:00:20 +0000478
Sean Callanan0ddf8062011-05-09 22:04:36 +0000479 if (!m_expr_decl_map->Dematerialize(exe_ctx, result, function_stack_pointer, function_stack_bottom, expr_error))
Jim Inghamd1686902010-10-14 23:45:03 +0000480 {
481 error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
482 return false;
483 }
484 return true;
485}
486
Greg Claytonb3448432011-03-24 21:19:54 +0000487ExecutionResults
Jim Inghamd1686902010-10-14 23:45:03 +0000488ClangUserExpression::Execute (Stream &error_stream,
489 ExecutionContext &exe_ctx,
Jim Inghamea9d4262010-11-05 19:25:48 +0000490 bool discard_on_error,
Jim Ingham360f53f2010-11-30 02:22:11 +0000491 ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
Greg Clayton427f2902010-12-14 02:59:59 +0000492 lldb::ClangExpressionVariableSP &result)
Jim Inghamd1686902010-10-14 23:45:03 +0000493{
Jim Ingham7812e012011-01-18 22:20:08 +0000494 // The expression log is quite verbose, and if you're just tracking the execution of the
495 // expression, it's quite convenient to have these logs come out with the STEP log as well.
496 lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
Sean Callanan33711022010-12-07 10:00:20 +0000497
Jim Inghamd1686902010-10-14 23:45:03 +0000498 if (m_dwarf_opcodes.get())
499 {
500 // TODO execute the JITted opcodes
501
502 error_stream.Printf("We don't currently support executing DWARF expressions");
503
Greg Claytonb3448432011-03-24 21:19:54 +0000504 return eExecutionSetupError;
Jim Inghamd1686902010-10-14 23:45:03 +0000505 }
Greg Claytond0882d02011-01-19 23:00:49 +0000506 else if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
Jim Inghamd1686902010-10-14 23:45:03 +0000507 {
508 lldb::addr_t struct_address;
509
Johnny Chen2bc9eb32011-07-19 19:48:13 +0000510 lldb::addr_t object_ptr = 0;
511 lldb::addr_t cmd_ptr = 0;
Jim Inghamd1686902010-10-14 23:45:03 +0000512
Sean Callanan047923c2010-12-14 00:42:36 +0000513 if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
Greg Claytonb3448432011-03-24 21:19:54 +0000514 return eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000515
Jim Inghamea9d4262010-11-05 19:25:48 +0000516 const bool stop_others = true;
517 const bool try_all_threads = true;
Sean Callanan65dafa82010-08-27 01:01:44 +0000518
Greg Claytond0882d02011-01-19 23:00:49 +0000519 Address wrapper_address (NULL, m_jit_start_addr);
Sean Callanan3aa7da52010-12-13 22:46:15 +0000520 lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (*(exe_ctx.thread),
521 wrapper_address,
522 struct_address,
523 stop_others,
524 discard_on_error,
525 (m_needs_object_ptr ? &object_ptr : NULL),
526 ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
527 shared_ptr_to_me));
528
Jim Ingham360f53f2010-11-30 02:22:11 +0000529 if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL))
Greg Claytonb3448432011-03-24 21:19:54 +0000530 return eExecutionSetupError;
Sean Callanan0ddf8062011-05-09 22:04:36 +0000531
532 lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
Jim Ingham360f53f2010-11-30 02:22:11 +0000533
Jim Ingham5ab7fba2011-05-17 22:24:54 +0000534 call_plan_sp->SetPrivate(true);
Jim Ingham360f53f2010-11-30 02:22:11 +0000535
Greg Clayton61468e82011-01-19 07:54:15 +0000536 uint32_t single_thread_timeout_usec = 500000;
Sean Callanan33711022010-12-07 10:00:20 +0000537
538 if (log)
Sean Callanan94d255f2010-12-07 22:55:01 +0000539 log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
Sean Callanan33711022010-12-07 10:00:20 +0000540
Greg Claytonb3448432011-03-24 21:19:54 +0000541 ExecutionResults execution_result = exe_ctx.process->RunThreadPlan (exe_ctx,
Sean Callanan0ddf8062011-05-09 22:04:36 +0000542 call_plan_sp,
543 stop_others,
544 try_all_threads,
545 discard_on_error,
546 single_thread_timeout_usec,
547 error_stream);
Sean Callanan33711022010-12-07 10:00:20 +0000548
549 if (log)
Sean Callanan94d255f2010-12-07 22:55:01 +0000550 log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
Jim Ingham360f53f2010-11-30 02:22:11 +0000551
Greg Claytonb3448432011-03-24 21:19:54 +0000552 if (execution_result == eExecutionInterrupted)
Sean Callanan65dafa82010-08-27 01:01:44 +0000553 {
Jim Ingham2370a972011-05-17 01:10:11 +0000554 const char *error_desc = NULL;
555
556 if (call_plan_sp)
557 {
558 lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
559 if (real_stop_info_sp)
560 error_desc = real_stop_info_sp->GetDescription();
561 }
562 if (error_desc)
563 error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
Jim Ingham360f53f2010-11-30 02:22:11 +0000564 else
Jim Ingham2370a972011-05-17 01:10:11 +0000565 error_stream.Printf ("Execution was interrupted.", error_desc);
566
567 if (discard_on_error)
568 error_stream.Printf ("\nThe process has been returned to the state before execution.");
569 else
570 error_stream.Printf ("\nThe process has been left at the point where it was interrupted.");
Jim Ingham360f53f2010-11-30 02:22:11 +0000571
572 return execution_result;
573 }
Greg Claytonb3448432011-03-24 21:19:54 +0000574 else if (execution_result != eExecutionCompleted)
Jim Ingham360f53f2010-11-30 02:22:11 +0000575 {
576 error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
577 return execution_result;
Sean Callanan65dafa82010-08-27 01:01:44 +0000578 }
579
Sean Callanan0ddf8062011-05-09 22:04:36 +0000580 if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_pointer))
Greg Claytonb3448432011-03-24 21:19:54 +0000581 return eExecutionCompleted;
Jim Ingham360f53f2010-11-30 02:22:11 +0000582 else
Greg Claytonb3448432011-03-24 21:19:54 +0000583 return eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000584 }
585 else
586 {
Johnny Chencb395442010-11-10 19:02:11 +0000587 error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present");
Greg Claytonb3448432011-03-24 21:19:54 +0000588 return eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000589 }
590}
591
592StreamString &
593ClangUserExpression::DwarfOpcodeStream ()
594{
595 if (!m_dwarf_opcodes.get())
596 m_dwarf_opcodes.reset(new StreamString());
597
598 return *m_dwarf_opcodes.get();
599}
Greg Clayton377e0b42010-10-05 00:31:29 +0000600
Greg Claytonb3448432011-03-24 21:19:54 +0000601ExecutionResults
Sean Callanan77e93942010-10-29 00:29:03 +0000602ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
Jim Inghamea9d4262010-11-05 19:25:48 +0000603 bool discard_on_error,
Sean Callanan77e93942010-10-29 00:29:03 +0000604 const char *expr_cstr,
Jim Ingham360f53f2010-11-30 02:22:11 +0000605 const char *expr_prefix,
606 lldb::ValueObjectSP &result_valobj_sp)
Greg Clayton377e0b42010-10-05 00:31:29 +0000607{
Jim Inghamec07c0d2011-08-09 00:00:49 +0000608 Error error;
609 return EvaluateWithError (exe_ctx, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error);
610}
611
612ExecutionResults
613ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
614 bool discard_on_error,
615 const char *expr_cstr,
616 const char *expr_prefix,
617 lldb::ValueObjectSP &result_valobj_sp,
618 Error &error)
619{
Jim Ingham7812e012011-01-18 22:20:08 +0000620 lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
Sean Callanan94d255f2010-12-07 22:55:01 +0000621
Greg Claytonb3448432011-03-24 21:19:54 +0000622 ExecutionResults execution_results = eExecutionSetupError;
Greg Clayton0baa3942010-11-04 01:54:29 +0000623
Jim Inghame6bd1422011-06-20 17:32:44 +0000624 if (exe_ctx.process == NULL || exe_ctx.process->GetState() != lldb::eStateStopped)
Jim Ingham360f53f2010-11-30 02:22:11 +0000625 {
Greg Claytonfe1b47d2011-06-24 22:31:10 +0000626 error.SetErrorString ("must have a stopped process to evaluate expressions.");
Jim Ingham360f53f2010-11-30 02:22:11 +0000627
Jim Ingham47da8102011-04-22 23:53:53 +0000628 result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
Greg Claytonb3448432011-03-24 21:19:54 +0000629 return eExecutionSetupError;
Jim Ingham360f53f2010-11-30 02:22:11 +0000630 }
631
Greg Clayton0baa3942010-11-04 01:54:29 +0000632 if (!exe_ctx.process->GetDynamicCheckers())
633 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000634 if (log)
635 log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers ==");
636
Greg Clayton0baa3942010-11-04 01:54:29 +0000637 DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
638
639 StreamString install_errors;
640
641 if (!dynamic_checkers->Install(install_errors, exe_ctx))
Sean Callananf7731452010-11-05 00:57:06 +0000642 {
643 if (install_errors.GetString().empty())
644 error.SetErrorString ("couldn't install checkers, unknown error");
645 else
646 error.SetErrorString (install_errors.GetString().c_str());
647
Jim Ingham47da8102011-04-22 23:53:53 +0000648 result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
Greg Claytonb3448432011-03-24 21:19:54 +0000649 return eExecutionSetupError;
Sean Callananf7731452010-11-05 00:57:06 +0000650 }
651
Greg Clayton0baa3942010-11-04 01:54:29 +0000652 exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
Sean Callanan94d255f2010-12-07 22:55:01 +0000653
654 if (log)
655 log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
Greg Clayton0baa3942010-11-04 01:54:29 +0000656 }
657
Jim Ingham360f53f2010-11-30 02:22:11 +0000658 ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix));
659
Greg Clayton377e0b42010-10-05 00:31:29 +0000660 StreamString error_stream;
Sean Callanan696cf5f2011-05-07 01:06:41 +0000661
Sean Callanan94d255f2010-12-07 22:55:01 +0000662 if (log)
663 log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
664
Sean Callanan696cf5f2011-05-07 01:06:41 +0000665 if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), true))
Greg Clayton377e0b42010-10-05 00:31:29 +0000666 {
667 if (error_stream.GetString().empty())
668 error.SetErrorString ("expression failed to parse, unknown error");
669 else
670 error.SetErrorString (error_stream.GetString().c_str());
671 }
672 else
673 {
Greg Clayton427f2902010-12-14 02:59:59 +0000674 lldb::ClangExpressionVariableSP expr_result;
Greg Clayton377e0b42010-10-05 00:31:29 +0000675
Sean Callanan696cf5f2011-05-07 01:06:41 +0000676 if (user_expression_sp->m_const_result.get())
Greg Clayton377e0b42010-10-05 00:31:29 +0000677 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000678 if (log)
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000679 log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
Sean Callanan94d255f2010-12-07 22:55:01 +0000680
Sean Callanan696cf5f2011-05-07 01:06:41 +0000681 result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
Jim Inghamec07c0d2011-08-09 00:00:49 +0000682 execution_results = eExecutionCompleted;
Greg Clayton377e0b42010-10-05 00:31:29 +0000683 }
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000684 else
685 {
686 error_stream.GetString().clear();
687
688 if (log)
689 log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
690
691 execution_results = user_expression_sp->Execute (error_stream,
692 exe_ctx,
Sean Callanan6a925532011-01-13 08:53:35 +0000693 discard_on_error,
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000694 user_expression_sp,
695 expr_result);
696
Greg Claytonb3448432011-03-24 21:19:54 +0000697 if (execution_results != eExecutionCompleted)
Greg Clayton377e0b42010-10-05 00:31:29 +0000698 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000699 if (log)
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000700 log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
701
702 if (error_stream.GetString().empty())
703 error.SetErrorString ("expression failed to execute, unknown error");
704 else
705 error.SetErrorString (error_stream.GetString().c_str());
Greg Clayton377e0b42010-10-05 00:31:29 +0000706 }
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000707 else
Greg Clayton377e0b42010-10-05 00:31:29 +0000708 {
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000709 if (expr_result)
710 {
711 result_valobj_sp = expr_result->GetValueObject();
712
713 if (log)
Jim Inghamfa3a16a2011-03-31 00:19:25 +0000714 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString());
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000715 }
716 else
717 {
718 if (log)
719 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
720
721 error.SetErrorString ("Expression did not return a result");
722 }
Greg Clayton377e0b42010-10-05 00:31:29 +0000723 }
724 }
725 }
Sean Callanan44820ec2010-10-19 20:15:00 +0000726
Greg Claytond1719722010-10-05 03:13:51 +0000727 if (result_valobj_sp.get() == NULL)
Jim Ingham47da8102011-04-22 23:53:53 +0000728 result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
Greg Claytond1719722010-10-05 03:13:51 +0000729
Jim Ingham360f53f2010-11-30 02:22:11 +0000730 return execution_results;
Johnny Chenb4c0f022010-10-29 20:19:44 +0000731}