blob: 5ce5c1abbbe6deceea21fe022ac9efb4cd61aa07 [file] [log] [blame]
Sean Callanan65dafa82010-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 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
40using namespace lldb_private;
41
Sean Callanan77e93942010-10-29 00:29:03 +000042ClangUserExpression::ClangUserExpression (const char *expr,
43 const char *expr_prefix) :
Sean Callanan65dafa82010-08-27 01:01:44 +000044 m_expr_text(expr),
Johnny Chenb4c0f022010-10-29 20:19:44 +000045 m_expr_prefix(expr_prefix ? expr_prefix : ""),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000046 m_transformed_text(),
47 m_jit_addr(LLDB_INVALID_ADDRESS),
48 m_cplusplus(false),
49 m_objectivec(false),
Sean Callanana91dd992010-11-19 02:52:21 +000050 m_needs_object_ptr(false),
Sean Callanane8e55572010-12-01 21:35:54 +000051 m_const_object(false),
Sean Callanana91dd992010-11-19 02:52:21 +000052 m_desired_type(NULL, NULL)
Sean Callanan65dafa82010-08-27 01:01:44 +000053{
Sean Callanan65dafa82010-08-27 01:01:44 +000054}
55
Sean Callanan830a9032010-08-27 23:31:21 +000056ClangUserExpression::~ClangUserExpression ()
57{
58}
59
Sean Callanan65dafa82010-08-27 01:01:44 +000060clang::ASTConsumer *
61ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
62{
Sean Callanana91dd992010-11-19 02:52:21 +000063 return new ASTResultSynthesizer(passthrough,
64 m_desired_type);
Sean Callanan65dafa82010-08-27 01:01:44 +000065}
66
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000067void
68ClangUserExpression::ScanContext(ExecutionContext &exe_ctx)
69{
70 if (!exe_ctx.frame)
71 return;
72
73 VariableList *vars = exe_ctx.frame->GetVariableList(false);
74
75 if (!vars)
76 return;
77
Sean Callanane8e55572010-12-01 21:35:54 +000078 lldb::VariableSP this_var(vars->FindVariable(ConstString("this")));
79 lldb::VariableSP self_var(vars->FindVariable(ConstString("self")));
80
81 if (this_var.get())
82 {
83 Type *this_type = this_var->GetType();
84
85 lldb::clang_type_t pointer_target_type;
86
87 if (ClangASTContext::IsPointerType(this_type->GetClangType(),
88 &pointer_target_type))
89 {
90 TypeFromUser target_ast_type(pointer_target_type, this_type->GetClangAST());
91
92 if (target_ast_type.IsDefined())
93 m_cplusplus = true;
94
95 if (target_ast_type.IsConst())
96 m_const_object = true;
97 }
98 }
99 else if (self_var.get())
100 {
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000101 m_objectivec = true;
Sean Callanane8e55572010-12-01 21:35:54 +0000102 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000103}
104
Sean Callanan550f2762010-10-22 23:25:16 +0000105// This is a really nasty hack, meant to fix Objective-C expressions of the form
106// (int)[myArray count]. Right now, because the type information for count is
107// not available, [myArray count] returns id, which can't be directly cast to
108// int without causing a clang error.
109static void
110ApplyObjcCastHack(std::string &expr)
111{
112#define OBJC_CAST_HACK_FROM "(int)["
113#define OBJC_CAST_HACK_TO "(int)(long long)["
114
115 size_t from_offset;
116
117 while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
118 expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
119
120#undef OBJC_CAST_HACK_TO
121#undef OBJC_CAST_HACK_FROM
122}
123
Sean Callanan30892372010-10-24 20:45:49 +0000124// Another hack, meant to allow use of unichar despite it not being available in
125// the type information. Although we could special-case it in type lookup,
126// hopefully we'll figure out a way to #include the same environment as is
127// present in the original source file rather than try to hack specific type
128// definitions in as needed.
129static void
130ApplyUnicharHack(std::string &expr)
131{
132#define UNICHAR_HACK_FROM "unichar"
133#define UNICHAR_HACK_TO "unsigned short"
134
135 size_t from_offset;
136
137 while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
138 expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
139
140#undef UNICHAR_HACK_TO
141#undef UNICHAR_HACK_FROM
142}
143
Sean Callanan550f2762010-10-22 23:25:16 +0000144bool
Sean Callanana91dd992010-11-19 02:52:21 +0000145ClangUserExpression::Parse (Stream &error_stream,
146 ExecutionContext &exe_ctx,
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000147 TypeFromUser desired_type,
Sean Callanan6a925532011-01-13 08:53:35 +0000148 bool keep_result_in_memory,
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000149 lldb::ClangExpressionVariableSP *const_result)
Sean Callanan65dafa82010-08-27 01:01:44 +0000150{
Greg Claytone005f2c2010-11-06 01:53:30 +0000151 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan65dafa82010-08-27 01:01:44 +0000152
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000153 ScanContext(exe_ctx);
154
155 StreamString m_transformed_stream;
156
157 ////////////////////////////////////
158 // Generate the expression
159 //
Sean Callanan550f2762010-10-22 23:25:16 +0000160
161 ApplyObjcCastHack(m_expr_text);
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000162 //ApplyUnicharHack(m_expr_text);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000163
164 if (m_cplusplus)
165 {
Sean Callanan77e93942010-10-29 00:29:03 +0000166 m_transformed_stream.Printf("%s \n"
167 "typedef unsigned short unichar; \n"
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000168 "void \n"
Sean Callanane8e55572010-12-01 21:35:54 +0000169 "$__lldb_class::%s(void *$__lldb_arg) %s\n"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000170 "{ \n"
171 " %s; \n"
172 "} \n",
Sean Callanan77e93942010-10-29 00:29:03 +0000173 m_expr_prefix.c_str(),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000174 FunctionName(),
Sean Callanane8e55572010-12-01 21:35:54 +0000175 (m_const_object ? "const" : ""),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000176 m_expr_text.c_str());
177
178 m_needs_object_ptr = true;
179 }
Sean Callanan3aa7da52010-12-13 22:46:15 +0000180 else if(m_objectivec)
181 {
182 const char *function_name = FunctionName();
183
184 m_transformed_stream.Printf("%s \n"
Greg Claytonc5157ec2010-12-17 02:26:24 +0000185 "typedef unsigned short unichar; \n"
Sean Callanan3aa7da52010-12-13 22:46:15 +0000186 "@interface $__lldb_objc_class ($__lldb_category) \n"
187 "-(void)%s:(void *)$__lldb_arg; \n"
188 "@end \n"
189 "@implementation $__lldb_objc_class ($__lldb_category) \n"
190 "-(void)%s:(void *)$__lldb_arg \n"
191 "{ \n"
192 " %s; \n"
193 "} \n"
194 "@end \n",
195 m_expr_prefix.c_str(),
196 function_name,
197 function_name,
198 m_expr_text.c_str());
199
200 m_needs_object_ptr = true;
201 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000202 else
203 {
Sean Callanan77e93942010-10-29 00:29:03 +0000204 m_transformed_stream.Printf("%s \n"
205 "typedef unsigned short unichar;\n"
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000206 "void \n"
Sean Callanan550f2762010-10-22 23:25:16 +0000207 "%s(void *$__lldb_arg) \n"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000208 "{ \n"
209 " %s; \n"
210 "} \n",
Sean Callanan77e93942010-10-29 00:29:03 +0000211 m_expr_prefix.c_str(),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000212 FunctionName(),
213 m_expr_text.c_str());
214 }
215
216 m_transformed_text = m_transformed_stream.GetData();
217
218
219 if (log)
220 log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
221
Sean Callanan65dafa82010-08-27 01:01:44 +0000222 ////////////////////////////////////
223 // Set up the target and compiler
224 //
225
226 Target *target = exe_ctx.target;
227
228 if (!target)
229 {
230 error_stream.PutCString ("error: invalid target\n");
231 return false;
232 }
233
234 ConstString target_triple;
235
236 target->GetTargetTriple (target_triple);
237
238 if (!target_triple)
239 target_triple = Host::GetTargetTriple ();
240
241 if (!target_triple)
242 {
243 error_stream.PutCString ("error: invalid target triple\n");
244 return false;
245 }
246
247 //////////////////////////
248 // Parse the expression
249 //
250
Sean Callanana91dd992010-11-19 02:52:21 +0000251 m_desired_type = desired_type;
252
Sean Callanan6a925532011-01-13 08:53:35 +0000253 m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
Sean Callananaa301c42010-12-03 01:38:59 +0000254
255 m_expr_decl_map->WillParse(exe_ctx);
Sean Callanan65dafa82010-08-27 01:01:44 +0000256
Sean Callananc7674af2011-01-17 23:42:46 +0000257 ClangExpressionParser parser(target_triple.GetCString(), exe_ctx.process, *this);
Sean Callanan65dafa82010-08-27 01:01:44 +0000258
259 unsigned num_errors = parser.Parse (error_stream);
260
261 if (num_errors)
262 {
263 error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
Sean Callananaa301c42010-12-03 01:38:59 +0000264
265 m_expr_decl_map->DidParse();
266
Sean Callanan65dafa82010-08-27 01:01:44 +0000267 return false;
268 }
269
270 ///////////////////////////////////////////////
271 // Convert the output of the parser to DWARF
272 //
273
274 m_dwarf_opcodes.reset(new StreamString);
275 m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost);
276 m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
277
Greg Clayton427f2902010-12-14 02:59:59 +0000278 m_local_variables.reset(new ClangExpressionVariableList());
Sean Callanan65dafa82010-08-27 01:01:44 +0000279
280 Error dwarf_error = parser.MakeDWARF ();
281
282 if (dwarf_error.Success())
283 {
284 if (log)
285 log->Printf("Code can be interpreted.");
286
Sean Callananaa301c42010-12-03 01:38:59 +0000287 m_expr_decl_map->DidParse();
288
Sean Callanan65dafa82010-08-27 01:01:44 +0000289 return true;
290 }
291
292 //////////////////////////////////
293 // JIT the output of the parser
294 //
295
296 m_dwarf_opcodes.reset();
297
Sean Callanan830a9032010-08-27 23:31:21 +0000298 lldb::addr_t jit_end;
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000299
300 Error jit_error = parser.MakeJIT (m_jit_addr, jit_end, exe_ctx, const_result);
Sean Callanan65dafa82010-08-27 01:01:44 +0000301
Sean Callananaa301c42010-12-03 01:38:59 +0000302 m_expr_decl_map->DidParse();
303
Sean Callanan65dafa82010-08-27 01:01:44 +0000304 if (jit_error.Success())
305 {
Sean Callanan65dafa82010-08-27 01:01:44 +0000306 return true;
307 }
308 else
309 {
310 error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
311 return false;
312 }
313}
314
315bool
Jim Inghamd1686902010-10-14 23:45:03 +0000316ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
Sean Callananab06af92010-10-19 23:57:21 +0000317 ExecutionContext &exe_ctx,
318 lldb::addr_t &struct_address,
Sean Callanan047923c2010-12-14 00:42:36 +0000319 lldb::addr_t &object_ptr,
320 lldb::addr_t &cmd_ptr)
Sean Callanan65dafa82010-08-27 01:01:44 +0000321{
Greg Claytone005f2c2010-11-06 01:53:30 +0000322 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan65dafa82010-08-27 01:01:44 +0000323
Jim Inghamd1686902010-10-14 23:45:03 +0000324 if (m_jit_addr != LLDB_INVALID_ADDRESS)
Sean Callanan65dafa82010-08-27 01:01:44 +0000325 {
Sean Callanan65dafa82010-08-27 01:01:44 +0000326 Error materialize_error;
327
Sean Callanan3aa7da52010-12-13 22:46:15 +0000328 if (m_needs_object_ptr)
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000329 {
Sean Callanan3aa7da52010-12-13 22:46:15 +0000330 ConstString object_name;
331
332 if (m_cplusplus)
333 {
334 object_name.SetCString("this");
335 }
336 else if (m_objectivec)
337 {
338 object_name.SetCString("self");
339 }
340 else
341 {
342 error_stream.Printf("Need object pointer but don't know the language\n");
343 return false;
344 }
345
346 if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, exe_ctx, materialize_error)))
347 {
348 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
349 return false;
350 }
Sean Callanan047923c2010-12-14 00:42:36 +0000351
352 if (m_objectivec)
353 {
354 ConstString cmd_name("_cmd");
355
356 if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, exe_ctx, materialize_error, true)))
357 {
358 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
359 return false;
360 }
361 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000362 }
363
Sean Callananaa301c42010-12-03 01:38:59 +0000364 if (!m_expr_decl_map->Materialize(exe_ctx, struct_address, materialize_error))
Sean Callanan65dafa82010-08-27 01:01:44 +0000365 {
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000366 error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
Sean Callanan65dafa82010-08-27 01:01:44 +0000367 return false;
368 }
Greg Claytonc71899e2011-01-18 19:36:39 +0000369
370#if 0
371 // jingham: look here
372 StreamFile logfile ("/tmp/exprs.txt", "a");
373 logfile.Printf("0x%16.16llx: thread = 0x%4.4x, expr = '%s'\n", m_jit_addr, exe_ctx.thread ? exe_ctx.thread->GetID() : -1, m_expr_text.c_str());
374#endif
Sean Callanan65dafa82010-08-27 01:01:44 +0000375
376 if (log)
377 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000378 log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --");
Sean Callanan33711022010-12-07 10:00:20 +0000379
380 log->Printf(" Function address : 0x%llx", (uint64_t)m_jit_addr);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000381
382 if (m_needs_object_ptr)
Sean Callanan33711022010-12-07 10:00:20 +0000383 log->Printf(" Object pointer : 0x%llx", (uint64_t)object_ptr);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000384
Sean Callanan33711022010-12-07 10:00:20 +0000385 log->Printf(" Structure address : 0x%llx", (uint64_t)struct_address);
Sean Callanan65dafa82010-08-27 01:01:44 +0000386
387 StreamString args;
388
389 Error dump_error;
390
Sean Callanane8a59a82010-09-13 21:34:21 +0000391 if (struct_address)
Sean Callanan65dafa82010-08-27 01:01:44 +0000392 {
Sean Callananaa301c42010-12-03 01:38:59 +0000393 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
Sean Callanane8a59a82010-09-13 21:34:21 +0000394 {
Sean Callanan33711022010-12-07 10:00:20 +0000395 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
Sean Callanane8a59a82010-09-13 21:34:21 +0000396 }
397 else
398 {
Sean Callanan33711022010-12-07 10:00:20 +0000399 log->Printf(" Structure contents:\n%s", args.GetData());
Sean Callanane8a59a82010-09-13 21:34:21 +0000400 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000401 }
402 }
Jim Inghamd1686902010-10-14 23:45:03 +0000403 }
404 return true;
405}
406
407ThreadPlan *
408ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
Sean Callanan6a925532011-01-13 08:53:35 +0000409 ExecutionContext &exe_ctx)
Jim Inghamd1686902010-10-14 23:45:03 +0000410{
411 lldb::addr_t struct_address;
412
413 lldb::addr_t object_ptr = NULL;
Sean Callanan3aa7da52010-12-13 22:46:15 +0000414 lldb::addr_t cmd_ptr = NULL;
Jim Inghamd1686902010-10-14 23:45:03 +0000415
Sean Callanan047923c2010-12-14 00:42:36 +0000416 PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
Jim Inghamd1686902010-10-14 23:45:03 +0000417
Jim Ingham360f53f2010-11-30 02:22:11 +0000418 // FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
419 // ClangUserExpression resources before the thread plan finishes execution in the target. But because we are
Sean Callanan3aa7da52010-12-13 22:46:15 +0000420 // forcing unwind_on_error to be true here, in practical terms that can't happen.
421
Jim Inghamd1686902010-10-14 23:45:03 +0000422 return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
Sean Callanana65b5272010-12-01 01:28:23 +0000423 m_jit_addr,
424 struct_address,
425 error_stream,
426 true,
427 true,
Sean Callanan3aa7da52010-12-13 22:46:15 +0000428 (m_needs_object_ptr ? &object_ptr : NULL),
429 (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
Jim Inghamd1686902010-10-14 23:45:03 +0000430}
431
432bool
433ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
434 ExecutionContext &exe_ctx,
Greg Clayton427f2902010-12-14 02:59:59 +0000435 lldb::ClangExpressionVariableSP &result)
Jim Inghamd1686902010-10-14 23:45:03 +0000436{
437 Error expr_error;
438
Sean Callanan33711022010-12-07 10:00:20 +0000439 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
440
441 if (log)
442 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000443 log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
Sean Callanan33711022010-12-07 10:00:20 +0000444
445 StreamString args;
446
447 Error dump_error;
448
449 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
450 {
451 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
452 }
453 else
454 {
455 log->Printf(" Structure contents:\n%s", args.GetData());
456 }
457 }
458
Sean Callananaa301c42010-12-03 01:38:59 +0000459 if (!m_expr_decl_map->Dematerialize(exe_ctx, result, expr_error))
Jim Inghamd1686902010-10-14 23:45:03 +0000460 {
461 error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
462 return false;
463 }
464 return true;
465}
466
Greg Clayton427f2902010-12-14 02:59:59 +0000467lldb::ExecutionResults
Jim Inghamd1686902010-10-14 23:45:03 +0000468ClangUserExpression::Execute (Stream &error_stream,
469 ExecutionContext &exe_ctx,
Jim Inghamea9d4262010-11-05 19:25:48 +0000470 bool discard_on_error,
Sean Callanan6a925532011-01-13 08:53:35 +0000471 bool keep_in_memory,
Jim Ingham360f53f2010-11-30 02:22:11 +0000472 ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
Greg Clayton427f2902010-12-14 02:59:59 +0000473 lldb::ClangExpressionVariableSP &result)
Jim Inghamd1686902010-10-14 23:45:03 +0000474{
Jim Ingham7812e012011-01-18 22:20:08 +0000475 // The expression log is quite verbose, and if you're just tracking the execution of the
476 // expression, it's quite convenient to have these logs come out with the STEP log as well.
477 lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
Sean Callanan33711022010-12-07 10:00:20 +0000478
Jim Inghamd1686902010-10-14 23:45:03 +0000479 if (m_dwarf_opcodes.get())
480 {
481 // TODO execute the JITted opcodes
482
483 error_stream.Printf("We don't currently support executing DWARF expressions");
484
Greg Clayton427f2902010-12-14 02:59:59 +0000485 return lldb::eExecutionSetupError;
Jim Inghamd1686902010-10-14 23:45:03 +0000486 }
487 else if (m_jit_addr != LLDB_INVALID_ADDRESS)
488 {
489 lldb::addr_t struct_address;
490
491 lldb::addr_t object_ptr = NULL;
Sean Callanan3aa7da52010-12-13 22:46:15 +0000492 lldb::addr_t cmd_ptr = NULL;
Jim Inghamd1686902010-10-14 23:45:03 +0000493
Sean Callanan047923c2010-12-14 00:42:36 +0000494 if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
Greg Clayton427f2902010-12-14 02:59:59 +0000495 return lldb::eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000496
Jim Inghamea9d4262010-11-05 19:25:48 +0000497 const bool stop_others = true;
498 const bool try_all_threads = true;
Sean Callanan65dafa82010-08-27 01:01:44 +0000499
Jim Ingham360f53f2010-11-30 02:22:11 +0000500 Address wrapper_address (NULL, m_jit_addr);
Sean Callanan3aa7da52010-12-13 22:46:15 +0000501 lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (*(exe_ctx.thread),
502 wrapper_address,
503 struct_address,
504 stop_others,
505 discard_on_error,
506 (m_needs_object_ptr ? &object_ptr : NULL),
507 ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
508 shared_ptr_to_me));
509
Jim Ingham360f53f2010-11-30 02:22:11 +0000510 if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL))
Greg Clayton427f2902010-12-14 02:59:59 +0000511 return lldb::eExecutionSetupError;
Jim Ingham360f53f2010-11-30 02:22:11 +0000512
513 call_plan_sp->SetPrivate(true);
514
Greg Clayton61468e82011-01-19 07:54:15 +0000515 uint32_t single_thread_timeout_usec = 500000;
Sean Callanan33711022010-12-07 10:00:20 +0000516
517 if (log)
Sean Callanan94d255f2010-12-07 22:55:01 +0000518 log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
Sean Callanan33711022010-12-07 10:00:20 +0000519
Greg Clayton427f2902010-12-14 02:59:59 +0000520 lldb::ExecutionResults execution_result = exe_ctx.process->RunThreadPlan (exe_ctx,
521 call_plan_sp,
522 stop_others,
523 try_all_threads,
524 discard_on_error,
525 single_thread_timeout_usec,
526 error_stream);
Sean Callanan33711022010-12-07 10:00:20 +0000527
528 if (log)
Sean Callanan94d255f2010-12-07 22:55:01 +0000529 log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
Jim Ingham360f53f2010-11-30 02:22:11 +0000530
Greg Clayton427f2902010-12-14 02:59:59 +0000531 if (execution_result == lldb::eExecutionInterrupted)
Sean Callanan65dafa82010-08-27 01:01:44 +0000532 {
Jim Ingham360f53f2010-11-30 02:22:11 +0000533 if (discard_on_error)
534 error_stream.Printf ("Expression execution was interrupted. The process has been returned to the state before execution.");
535 else
536 error_stream.Printf ("Expression execution was interrupted. The process has been left at the point where it was interrupted.");
537
538 return execution_result;
539 }
Greg Clayton427f2902010-12-14 02:59:59 +0000540 else if (execution_result != lldb::eExecutionCompleted)
Jim Ingham360f53f2010-11-30 02:22:11 +0000541 {
542 error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
543 return execution_result;
Sean Callanan65dafa82010-08-27 01:01:44 +0000544 }
545
Jim Ingham360f53f2010-11-30 02:22:11 +0000546 if (FinalizeJITExecution (error_stream, exe_ctx, result))
Greg Clayton427f2902010-12-14 02:59:59 +0000547 return lldb::eExecutionCompleted;
Jim Ingham360f53f2010-11-30 02:22:11 +0000548 else
Greg Clayton427f2902010-12-14 02:59:59 +0000549 return lldb::eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000550 }
551 else
552 {
Johnny Chencb395442010-11-10 19:02:11 +0000553 error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present");
Greg Clayton427f2902010-12-14 02:59:59 +0000554 return lldb::eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000555 }
556}
557
558StreamString &
559ClangUserExpression::DwarfOpcodeStream ()
560{
561 if (!m_dwarf_opcodes.get())
562 m_dwarf_opcodes.reset(new StreamString());
563
564 return *m_dwarf_opcodes.get();
565}
Greg Clayton377e0b42010-10-05 00:31:29 +0000566
Greg Clayton427f2902010-12-14 02:59:59 +0000567lldb::ExecutionResults
Sean Callanan77e93942010-10-29 00:29:03 +0000568ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
Jim Inghamea9d4262010-11-05 19:25:48 +0000569 bool discard_on_error,
Sean Callanan6a925532011-01-13 08:53:35 +0000570 bool keep_in_memory,
Sean Callanan77e93942010-10-29 00:29:03 +0000571 const char *expr_cstr,
Jim Ingham360f53f2010-11-30 02:22:11 +0000572 const char *expr_prefix,
573 lldb::ValueObjectSP &result_valobj_sp)
Greg Clayton377e0b42010-10-05 00:31:29 +0000574{
Jim Ingham7812e012011-01-18 22:20:08 +0000575 lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
Sean Callanan94d255f2010-12-07 22:55:01 +0000576
Greg Clayton377e0b42010-10-05 00:31:29 +0000577 Error error;
Greg Clayton427f2902010-12-14 02:59:59 +0000578 lldb::ExecutionResults execution_results = lldb::eExecutionSetupError;
Greg Clayton0baa3942010-11-04 01:54:29 +0000579
580 if (exe_ctx.process == NULL)
Jim Ingham360f53f2010-11-30 02:22:11 +0000581 {
582 error.SetErrorString ("Must have a process to evaluate expressions.");
583
584 result_valobj_sp.reset (new ValueObjectConstResult (error));
Greg Clayton427f2902010-12-14 02:59:59 +0000585 return lldb::eExecutionSetupError;
Jim Ingham360f53f2010-11-30 02:22:11 +0000586 }
587
Greg Clayton0baa3942010-11-04 01:54:29 +0000588 if (!exe_ctx.process->GetDynamicCheckers())
589 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000590 if (log)
591 log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers ==");
592
Greg Clayton0baa3942010-11-04 01:54:29 +0000593 DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
594
595 StreamString install_errors;
596
597 if (!dynamic_checkers->Install(install_errors, exe_ctx))
Sean Callananf7731452010-11-05 00:57:06 +0000598 {
599 if (install_errors.GetString().empty())
600 error.SetErrorString ("couldn't install checkers, unknown error");
601 else
602 error.SetErrorString (install_errors.GetString().c_str());
603
604 result_valobj_sp.reset (new ValueObjectConstResult (error));
Greg Clayton427f2902010-12-14 02:59:59 +0000605 return lldb::eExecutionSetupError;
Sean Callananf7731452010-11-05 00:57:06 +0000606 }
607
Greg Clayton0baa3942010-11-04 01:54:29 +0000608 exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
Sean Callanan94d255f2010-12-07 22:55:01 +0000609
610 if (log)
611 log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
Greg Clayton0baa3942010-11-04 01:54:29 +0000612 }
613
Jim Ingham360f53f2010-11-30 02:22:11 +0000614 ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix));
615
Greg Clayton377e0b42010-10-05 00:31:29 +0000616 StreamString error_stream;
617
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000618 lldb::ClangExpressionVariableSP const_result;
619
Sean Callanan94d255f2010-12-07 22:55:01 +0000620 if (log)
621 log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
622
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000623 if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), &const_result))
Greg Clayton377e0b42010-10-05 00:31:29 +0000624 {
625 if (error_stream.GetString().empty())
626 error.SetErrorString ("expression failed to parse, unknown error");
627 else
628 error.SetErrorString (error_stream.GetString().c_str());
629 }
630 else
631 {
Greg Clayton427f2902010-12-14 02:59:59 +0000632 lldb::ClangExpressionVariableSP expr_result;
Greg Clayton377e0b42010-10-05 00:31:29 +0000633
Sean Callanan6a925532011-01-13 08:53:35 +0000634 if (const_result.get() && !keep_in_memory)
Greg Clayton377e0b42010-10-05 00:31:29 +0000635 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000636 if (log)
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000637 log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
Sean Callanan94d255f2010-12-07 22:55:01 +0000638
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000639 result_valobj_sp = const_result->GetValueObject();
Greg Clayton377e0b42010-10-05 00:31:29 +0000640 }
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000641 else
642 {
643 error_stream.GetString().clear();
644
645 if (log)
646 log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
647
648 execution_results = user_expression_sp->Execute (error_stream,
649 exe_ctx,
Sean Callanan6a925532011-01-13 08:53:35 +0000650 discard_on_error,
651 keep_in_memory,
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000652 user_expression_sp,
653 expr_result);
654
655 if (execution_results != lldb::eExecutionCompleted)
Greg Clayton377e0b42010-10-05 00:31:29 +0000656 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000657 if (log)
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000658 log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
659
660 if (error_stream.GetString().empty())
661 error.SetErrorString ("expression failed to execute, unknown error");
662 else
663 error.SetErrorString (error_stream.GetString().c_str());
Greg Clayton377e0b42010-10-05 00:31:29 +0000664 }
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000665 else
Greg Clayton377e0b42010-10-05 00:31:29 +0000666 {
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000667 if (expr_result)
668 {
669 result_valobj_sp = expr_result->GetValueObject();
670
671 if (log)
672 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString(exe_ctx.GetBestExecutionContextScope()));
673 }
674 else
675 {
676 if (log)
677 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
678
679 error.SetErrorString ("Expression did not return a result");
680 }
Greg Clayton377e0b42010-10-05 00:31:29 +0000681 }
682 }
683 }
Sean Callanan44820ec2010-10-19 20:15:00 +0000684
Greg Claytond1719722010-10-05 03:13:51 +0000685 if (result_valobj_sp.get() == NULL)
686 result_valobj_sp.reset (new ValueObjectConstResult (error));
687
Jim Ingham360f53f2010-11-30 02:22:11 +0000688 return execution_results;
Johnny Chenb4c0f022010-10-29 20:19:44 +0000689}