blob: c86a771d09cd81dc6e2dce9eaa43d35ddb715d17 [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) :
Greg Claytond0882d02011-01-19 23:00:49 +000044 ClangExpression (),
45 m_expr_text (expr),
46 m_expr_prefix (expr_prefix ? expr_prefix : ""),
47 m_transformed_text (),
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000048 m_desired_type (NULL, NULL),
Greg Claytond0882d02011-01-19 23:00:49 +000049 m_cplusplus (false),
50 m_objectivec (false),
51 m_needs_object_ptr (false),
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000052 m_const_object (false)
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
Greg Clayton04c9c7b2011-02-16 23:00:21 +000087 if (ClangASTContext::IsPointerType(this_type->GetClangForwardType(),
Sean Callanane8e55572010-12-01 21:35:54 +000088 &pointer_target_type))
89 {
90 TypeFromUser target_ast_type(pointer_target_type, this_type->GetClangAST());
91
Greg Clayton04c9c7b2011-02-16 23:00:21 +000092 if (ClangASTContext::IsCXXClassType(target_ast_type.GetOpaqueQualType()))
Sean Callanan14404f82011-01-24 08:11:45 +000093 {
Sean Callanane8e55572010-12-01 21:35:54 +000094 m_cplusplus = true;
95
Sean Callanan14404f82011-01-24 08:11:45 +000096 if (target_ast_type.IsConst())
97 m_const_object = true;
98 }
Sean Callanane8e55572010-12-01 21:35:54 +000099 }
100 }
101 else if (self_var.get())
102 {
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000103 m_objectivec = true;
Sean Callanane8e55572010-12-01 21:35:54 +0000104 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000105}
106
Sean Callanan550f2762010-10-22 23:25:16 +0000107// This is a really nasty hack, meant to fix Objective-C expressions of the form
108// (int)[myArray count]. Right now, because the type information for count is
109// not available, [myArray count] returns id, which can't be directly cast to
110// int without causing a clang error.
111static void
112ApplyObjcCastHack(std::string &expr)
113{
114#define OBJC_CAST_HACK_FROM "(int)["
115#define OBJC_CAST_HACK_TO "(int)(long long)["
116
117 size_t from_offset;
118
119 while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
120 expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
121
122#undef OBJC_CAST_HACK_TO
123#undef OBJC_CAST_HACK_FROM
124}
125
Sean Callanan30892372010-10-24 20:45:49 +0000126// Another hack, meant to allow use of unichar despite it not being available in
127// the type information. Although we could special-case it in type lookup,
128// hopefully we'll figure out a way to #include the same environment as is
129// present in the original source file rather than try to hack specific type
130// definitions in as needed.
131static void
132ApplyUnicharHack(std::string &expr)
133{
134#define UNICHAR_HACK_FROM "unichar"
135#define UNICHAR_HACK_TO "unsigned short"
136
137 size_t from_offset;
138
139 while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
140 expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
141
142#undef UNICHAR_HACK_TO
143#undef UNICHAR_HACK_FROM
144}
145
Sean Callanan550f2762010-10-22 23:25:16 +0000146bool
Sean Callanana91dd992010-11-19 02:52:21 +0000147ClangUserExpression::Parse (Stream &error_stream,
148 ExecutionContext &exe_ctx,
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000149 TypeFromUser desired_type,
Sean Callanan6a925532011-01-13 08:53:35 +0000150 bool keep_result_in_memory,
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000151 lldb::ClangExpressionVariableSP *const_result)
Sean Callanan65dafa82010-08-27 01:01:44 +0000152{
Greg Claytone005f2c2010-11-06 01:53:30 +0000153 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan65dafa82010-08-27 01:01:44 +0000154
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000155 ScanContext(exe_ctx);
156
157 StreamString m_transformed_stream;
158
159 ////////////////////////////////////
160 // Generate the expression
161 //
Sean Callanan550f2762010-10-22 23:25:16 +0000162
163 ApplyObjcCastHack(m_expr_text);
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000164 //ApplyUnicharHack(m_expr_text);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000165
166 if (m_cplusplus)
167 {
Sean Callanan77e93942010-10-29 00:29:03 +0000168 m_transformed_stream.Printf("%s \n"
169 "typedef unsigned short unichar; \n"
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000170 "void \n"
Sean Callanane8e55572010-12-01 21:35:54 +0000171 "$__lldb_class::%s(void *$__lldb_arg) %s\n"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000172 "{ \n"
173 " %s; \n"
174 "} \n",
Sean Callanan77e93942010-10-29 00:29:03 +0000175 m_expr_prefix.c_str(),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000176 FunctionName(),
Sean Callanane8e55572010-12-01 21:35:54 +0000177 (m_const_object ? "const" : ""),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000178 m_expr_text.c_str());
179
180 m_needs_object_ptr = true;
181 }
Sean Callanan3aa7da52010-12-13 22:46:15 +0000182 else if(m_objectivec)
183 {
184 const char *function_name = FunctionName();
185
186 m_transformed_stream.Printf("%s \n"
Greg Claytonc5157ec2010-12-17 02:26:24 +0000187 "typedef unsigned short unichar; \n"
Sean Callanan3aa7da52010-12-13 22:46:15 +0000188 "@interface $__lldb_objc_class ($__lldb_category) \n"
189 "-(void)%s:(void *)$__lldb_arg; \n"
190 "@end \n"
191 "@implementation $__lldb_objc_class ($__lldb_category) \n"
192 "-(void)%s:(void *)$__lldb_arg \n"
193 "{ \n"
194 " %s; \n"
195 "} \n"
196 "@end \n",
197 m_expr_prefix.c_str(),
198 function_name,
199 function_name,
200 m_expr_text.c_str());
201
202 m_needs_object_ptr = true;
203 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000204 else
205 {
Sean Callanan77e93942010-10-29 00:29:03 +0000206 m_transformed_stream.Printf("%s \n"
207 "typedef unsigned short unichar;\n"
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000208 "void \n"
Sean Callanan550f2762010-10-22 23:25:16 +0000209 "%s(void *$__lldb_arg) \n"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000210 "{ \n"
211 " %s; \n"
212 "} \n",
Sean Callanan77e93942010-10-29 00:29:03 +0000213 m_expr_prefix.c_str(),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000214 FunctionName(),
215 m_expr_text.c_str());
216 }
217
218 m_transformed_text = m_transformed_stream.GetData();
219
220
221 if (log)
222 log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
223
Sean Callanan65dafa82010-08-27 01:01:44 +0000224 ////////////////////////////////////
225 // Set up the target and compiler
226 //
227
228 Target *target = exe_ctx.target;
229
230 if (!target)
231 {
232 error_stream.PutCString ("error: invalid target\n");
233 return false;
234 }
235
Sean Callanan65dafa82010-08-27 01:01:44 +0000236 //////////////////////////
237 // Parse the expression
238 //
239
Sean Callanana91dd992010-11-19 02:52:21 +0000240 m_desired_type = desired_type;
241
Sean Callanan6a925532011-01-13 08:53:35 +0000242 m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
Sean Callananaa301c42010-12-03 01:38:59 +0000243
244 m_expr_decl_map->WillParse(exe_ctx);
Sean Callanan65dafa82010-08-27 01:01:44 +0000245
Greg Clayton395fc332011-02-15 21:59:32 +0000246 ClangExpressionParser parser(exe_ctx.process, *this);
Sean Callanan65dafa82010-08-27 01:01:44 +0000247
248 unsigned num_errors = parser.Parse (error_stream);
249
250 if (num_errors)
251 {
252 error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
Sean Callananaa301c42010-12-03 01:38:59 +0000253
254 m_expr_decl_map->DidParse();
255
Sean Callanan65dafa82010-08-27 01:01:44 +0000256 return false;
257 }
258
259 ///////////////////////////////////////////////
260 // Convert the output of the parser to DWARF
261 //
262
263 m_dwarf_opcodes.reset(new StreamString);
Greg Claytoncd548032011-02-01 01:31:41 +0000264 m_dwarf_opcodes->SetByteOrder (lldb::endian::InlHostByteOrder());
Sean Callanan65dafa82010-08-27 01:01:44 +0000265 m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
266
Greg Clayton427f2902010-12-14 02:59:59 +0000267 m_local_variables.reset(new ClangExpressionVariableList());
Sean Callanan65dafa82010-08-27 01:01:44 +0000268
269 Error dwarf_error = parser.MakeDWARF ();
270
271 if (dwarf_error.Success())
272 {
273 if (log)
274 log->Printf("Code can be interpreted.");
275
Sean Callananaa301c42010-12-03 01:38:59 +0000276 m_expr_decl_map->DidParse();
277
Sean Callanan65dafa82010-08-27 01:01:44 +0000278 return true;
279 }
280
281 //////////////////////////////////
282 // JIT the output of the parser
283 //
284
285 m_dwarf_opcodes.reset();
286
Greg Claytond0882d02011-01-19 23:00:49 +0000287 Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, const_result);
Sean Callanan65dafa82010-08-27 01:01:44 +0000288
Sean Callananaa301c42010-12-03 01:38:59 +0000289 m_expr_decl_map->DidParse();
290
Sean Callanan65dafa82010-08-27 01:01:44 +0000291 if (jit_error.Success())
292 {
Greg Claytond0882d02011-01-19 23:00:49 +0000293 if (exe_ctx.process && m_jit_alloc != LLDB_INVALID_ADDRESS)
294 m_jit_process_sp = exe_ctx.process->GetSP();
Sean Callanan65dafa82010-08-27 01:01:44 +0000295 return true;
296 }
297 else
298 {
299 error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
300 return false;
301 }
302}
303
304bool
Jim Inghamd1686902010-10-14 23:45:03 +0000305ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
Sean Callananab06af92010-10-19 23:57:21 +0000306 ExecutionContext &exe_ctx,
307 lldb::addr_t &struct_address,
Sean Callanan047923c2010-12-14 00:42:36 +0000308 lldb::addr_t &object_ptr,
309 lldb::addr_t &cmd_ptr)
Sean Callanan65dafa82010-08-27 01:01:44 +0000310{
Greg Claytone005f2c2010-11-06 01:53:30 +0000311 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan65dafa82010-08-27 01:01:44 +0000312
Greg Claytond0882d02011-01-19 23:00:49 +0000313 if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
Sean Callanan65dafa82010-08-27 01:01:44 +0000314 {
Sean Callanan65dafa82010-08-27 01:01:44 +0000315 Error materialize_error;
316
Sean Callanan3aa7da52010-12-13 22:46:15 +0000317 if (m_needs_object_ptr)
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000318 {
Sean Callanan3aa7da52010-12-13 22:46:15 +0000319 ConstString object_name;
320
321 if (m_cplusplus)
322 {
323 object_name.SetCString("this");
324 }
325 else if (m_objectivec)
326 {
327 object_name.SetCString("self");
328 }
329 else
330 {
331 error_stream.Printf("Need object pointer but don't know the language\n");
332 return false;
333 }
334
335 if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, exe_ctx, materialize_error)))
336 {
337 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
338 return false;
339 }
Sean Callanan047923c2010-12-14 00:42:36 +0000340
341 if (m_objectivec)
342 {
343 ConstString cmd_name("_cmd");
344
345 if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, exe_ctx, materialize_error, true)))
346 {
347 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
348 return false;
349 }
350 }
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000351 }
352
Sean Callananaa301c42010-12-03 01:38:59 +0000353 if (!m_expr_decl_map->Materialize(exe_ctx, struct_address, materialize_error))
Sean Callanan65dafa82010-08-27 01:01:44 +0000354 {
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000355 error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
Sean Callanan65dafa82010-08-27 01:01:44 +0000356 return false;
357 }
Greg Claytonc71899e2011-01-18 19:36:39 +0000358
359#if 0
360 // jingham: look here
361 StreamFile logfile ("/tmp/exprs.txt", "a");
Greg Claytond0882d02011-01-19 23:00:49 +0000362 logfile.Printf("0x%16.16llx: thread = 0x%4.4x, expr = '%s'\n", m_jit_start_addr, exe_ctx.thread ? exe_ctx.thread->GetID() : -1, m_expr_text.c_str());
Greg Claytonc71899e2011-01-18 19:36:39 +0000363#endif
Sean Callanan65dafa82010-08-27 01:01:44 +0000364
365 if (log)
366 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000367 log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --");
Sean Callanan33711022010-12-07 10:00:20 +0000368
Greg Claytond0882d02011-01-19 23:00:49 +0000369 log->Printf(" Function address : 0x%llx", (uint64_t)m_jit_start_addr);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000370
371 if (m_needs_object_ptr)
Sean Callanan33711022010-12-07 10:00:20 +0000372 log->Printf(" Object pointer : 0x%llx", (uint64_t)object_ptr);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000373
Sean Callanan33711022010-12-07 10:00:20 +0000374 log->Printf(" Structure address : 0x%llx", (uint64_t)struct_address);
Sean Callanan65dafa82010-08-27 01:01:44 +0000375
376 StreamString args;
377
378 Error dump_error;
379
Sean Callanane8a59a82010-09-13 21:34:21 +0000380 if (struct_address)
Sean Callanan65dafa82010-08-27 01:01:44 +0000381 {
Sean Callananaa301c42010-12-03 01:38:59 +0000382 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
Sean Callanane8a59a82010-09-13 21:34:21 +0000383 {
Sean Callanan33711022010-12-07 10:00:20 +0000384 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
Sean Callanane8a59a82010-09-13 21:34:21 +0000385 }
386 else
387 {
Sean Callanan33711022010-12-07 10:00:20 +0000388 log->Printf(" Structure contents:\n%s", args.GetData());
Sean Callanane8a59a82010-09-13 21:34:21 +0000389 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000390 }
391 }
Jim Inghamd1686902010-10-14 23:45:03 +0000392 }
393 return true;
394}
395
396ThreadPlan *
397ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
Sean Callanan6a925532011-01-13 08:53:35 +0000398 ExecutionContext &exe_ctx)
Jim Inghamd1686902010-10-14 23:45:03 +0000399{
400 lldb::addr_t struct_address;
401
402 lldb::addr_t object_ptr = NULL;
Sean Callanan3aa7da52010-12-13 22:46:15 +0000403 lldb::addr_t cmd_ptr = NULL;
Jim Inghamd1686902010-10-14 23:45:03 +0000404
Sean Callanan047923c2010-12-14 00:42:36 +0000405 PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
Jim Inghamd1686902010-10-14 23:45:03 +0000406
Jim Ingham360f53f2010-11-30 02:22:11 +0000407 // FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
408 // ClangUserExpression resources before the thread plan finishes execution in the target. But because we are
Sean Callanan3aa7da52010-12-13 22:46:15 +0000409 // forcing unwind_on_error to be true here, in practical terms that can't happen.
410
Jim Inghamd1686902010-10-14 23:45:03 +0000411 return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
Greg Claytond0882d02011-01-19 23:00:49 +0000412 m_jit_start_addr,
Sean Callanana65b5272010-12-01 01:28:23 +0000413 struct_address,
414 error_stream,
415 true,
416 true,
Sean Callanan3aa7da52010-12-13 22:46:15 +0000417 (m_needs_object_ptr ? &object_ptr : NULL),
418 (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
Jim Inghamd1686902010-10-14 23:45:03 +0000419}
420
421bool
422ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
423 ExecutionContext &exe_ctx,
Greg Clayton427f2902010-12-14 02:59:59 +0000424 lldb::ClangExpressionVariableSP &result)
Jim Inghamd1686902010-10-14 23:45:03 +0000425{
426 Error expr_error;
427
Sean Callanan33711022010-12-07 10:00:20 +0000428 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
429
430 if (log)
431 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000432 log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
Sean Callanan33711022010-12-07 10:00:20 +0000433
434 StreamString args;
435
436 Error dump_error;
437
438 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
439 {
440 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
441 }
442 else
443 {
444 log->Printf(" Structure contents:\n%s", args.GetData());
445 }
446 }
447
Sean Callananaa301c42010-12-03 01:38:59 +0000448 if (!m_expr_decl_map->Dematerialize(exe_ctx, result, expr_error))
Jim Inghamd1686902010-10-14 23:45:03 +0000449 {
450 error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
451 return false;
452 }
453 return true;
454}
455
Greg Claytonb3448432011-03-24 21:19:54 +0000456ExecutionResults
Jim Inghamd1686902010-10-14 23:45:03 +0000457ClangUserExpression::Execute (Stream &error_stream,
458 ExecutionContext &exe_ctx,
Jim Inghamea9d4262010-11-05 19:25:48 +0000459 bool discard_on_error,
Sean Callanan6a925532011-01-13 08:53:35 +0000460 bool keep_in_memory,
Jim Ingham360f53f2010-11-30 02:22:11 +0000461 ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
Greg Clayton427f2902010-12-14 02:59:59 +0000462 lldb::ClangExpressionVariableSP &result)
Jim Inghamd1686902010-10-14 23:45:03 +0000463{
Jim Ingham7812e012011-01-18 22:20:08 +0000464 // The expression log is quite verbose, and if you're just tracking the execution of the
465 // expression, it's quite convenient to have these logs come out with the STEP log as well.
466 lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
Sean Callanan33711022010-12-07 10:00:20 +0000467
Jim Inghamd1686902010-10-14 23:45:03 +0000468 if (m_dwarf_opcodes.get())
469 {
470 // TODO execute the JITted opcodes
471
472 error_stream.Printf("We don't currently support executing DWARF expressions");
473
Greg Claytonb3448432011-03-24 21:19:54 +0000474 return eExecutionSetupError;
Jim Inghamd1686902010-10-14 23:45:03 +0000475 }
Greg Claytond0882d02011-01-19 23:00:49 +0000476 else if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
Jim Inghamd1686902010-10-14 23:45:03 +0000477 {
478 lldb::addr_t struct_address;
479
480 lldb::addr_t object_ptr = NULL;
Sean Callanan3aa7da52010-12-13 22:46:15 +0000481 lldb::addr_t cmd_ptr = NULL;
Jim Inghamd1686902010-10-14 23:45:03 +0000482
Sean Callanan047923c2010-12-14 00:42:36 +0000483 if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
Greg Claytonb3448432011-03-24 21:19:54 +0000484 return eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000485
Jim Inghamea9d4262010-11-05 19:25:48 +0000486 const bool stop_others = true;
487 const bool try_all_threads = true;
Sean Callanan65dafa82010-08-27 01:01:44 +0000488
Greg Claytond0882d02011-01-19 23:00:49 +0000489 Address wrapper_address (NULL, m_jit_start_addr);
Sean Callanan3aa7da52010-12-13 22:46:15 +0000490 lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (*(exe_ctx.thread),
491 wrapper_address,
492 struct_address,
493 stop_others,
494 discard_on_error,
495 (m_needs_object_ptr ? &object_ptr : NULL),
496 ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
497 shared_ptr_to_me));
498
Jim Ingham360f53f2010-11-30 02:22:11 +0000499 if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL))
Greg Claytonb3448432011-03-24 21:19:54 +0000500 return eExecutionSetupError;
Jim Ingham360f53f2010-11-30 02:22:11 +0000501
502 call_plan_sp->SetPrivate(true);
503
Greg Clayton61468e82011-01-19 07:54:15 +0000504 uint32_t single_thread_timeout_usec = 500000;
Sean Callanan33711022010-12-07 10:00:20 +0000505
506 if (log)
Sean Callanan94d255f2010-12-07 22:55:01 +0000507 log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
Sean Callanan33711022010-12-07 10:00:20 +0000508
Greg Claytonb3448432011-03-24 21:19:54 +0000509 ExecutionResults execution_result = exe_ctx.process->RunThreadPlan (exe_ctx,
Greg Clayton427f2902010-12-14 02:59:59 +0000510 call_plan_sp,
511 stop_others,
512 try_all_threads,
513 discard_on_error,
514 single_thread_timeout_usec,
515 error_stream);
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 completed --");
Jim Ingham360f53f2010-11-30 02:22:11 +0000519
Greg Claytonb3448432011-03-24 21:19:54 +0000520 if (execution_result == eExecutionInterrupted)
Sean Callanan65dafa82010-08-27 01:01:44 +0000521 {
Jim Ingham360f53f2010-11-30 02:22:11 +0000522 if (discard_on_error)
523 error_stream.Printf ("Expression execution was interrupted. The process has been returned to the state before execution.");
524 else
525 error_stream.Printf ("Expression execution was interrupted. The process has been left at the point where it was interrupted.");
526
527 return execution_result;
528 }
Greg Claytonb3448432011-03-24 21:19:54 +0000529 else if (execution_result != eExecutionCompleted)
Jim Ingham360f53f2010-11-30 02:22:11 +0000530 {
531 error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
532 return execution_result;
Sean Callanan65dafa82010-08-27 01:01:44 +0000533 }
534
Jim Ingham360f53f2010-11-30 02:22:11 +0000535 if (FinalizeJITExecution (error_stream, exe_ctx, result))
Greg Claytonb3448432011-03-24 21:19:54 +0000536 return eExecutionCompleted;
Jim Ingham360f53f2010-11-30 02:22:11 +0000537 else
Greg Claytonb3448432011-03-24 21:19:54 +0000538 return eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000539 }
540 else
541 {
Johnny Chencb395442010-11-10 19:02:11 +0000542 error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present");
Greg Claytonb3448432011-03-24 21:19:54 +0000543 return eExecutionSetupError;
Sean Callanan65dafa82010-08-27 01:01:44 +0000544 }
545}
546
547StreamString &
548ClangUserExpression::DwarfOpcodeStream ()
549{
550 if (!m_dwarf_opcodes.get())
551 m_dwarf_opcodes.reset(new StreamString());
552
553 return *m_dwarf_opcodes.get();
554}
Greg Clayton377e0b42010-10-05 00:31:29 +0000555
Greg Claytonb3448432011-03-24 21:19:54 +0000556ExecutionResults
Sean Callanan77e93942010-10-29 00:29:03 +0000557ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
Jim Inghamea9d4262010-11-05 19:25:48 +0000558 bool discard_on_error,
Sean Callanan6a925532011-01-13 08:53:35 +0000559 bool keep_in_memory,
Sean Callanan77e93942010-10-29 00:29:03 +0000560 const char *expr_cstr,
Jim Ingham360f53f2010-11-30 02:22:11 +0000561 const char *expr_prefix,
562 lldb::ValueObjectSP &result_valobj_sp)
Greg Clayton377e0b42010-10-05 00:31:29 +0000563{
Jim Ingham7812e012011-01-18 22:20:08 +0000564 lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
Sean Callanan94d255f2010-12-07 22:55:01 +0000565
Greg Clayton377e0b42010-10-05 00:31:29 +0000566 Error error;
Greg Claytonb3448432011-03-24 21:19:54 +0000567 ExecutionResults execution_results = eExecutionSetupError;
Greg Clayton0baa3942010-11-04 01:54:29 +0000568
569 if (exe_ctx.process == NULL)
Jim Ingham360f53f2010-11-30 02:22:11 +0000570 {
571 error.SetErrorString ("Must have a process to evaluate expressions.");
572
Jim Inghamfa3a16a2011-03-31 00:19:25 +0000573 result_valobj_sp.reset (new ValueObjectConstResult (NULL, error));
Greg Claytonb3448432011-03-24 21:19:54 +0000574 return eExecutionSetupError;
Jim Ingham360f53f2010-11-30 02:22:11 +0000575 }
576
Greg Clayton0baa3942010-11-04 01:54:29 +0000577 if (!exe_ctx.process->GetDynamicCheckers())
578 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000579 if (log)
580 log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers ==");
581
Greg Clayton0baa3942010-11-04 01:54:29 +0000582 DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
583
584 StreamString install_errors;
585
586 if (!dynamic_checkers->Install(install_errors, exe_ctx))
Sean Callananf7731452010-11-05 00:57:06 +0000587 {
588 if (install_errors.GetString().empty())
589 error.SetErrorString ("couldn't install checkers, unknown error");
590 else
591 error.SetErrorString (install_errors.GetString().c_str());
592
Jim Inghamfa3a16a2011-03-31 00:19:25 +0000593 result_valobj_sp.reset (new ValueObjectConstResult (NULL, error));
Greg Claytonb3448432011-03-24 21:19:54 +0000594 return eExecutionSetupError;
Sean Callananf7731452010-11-05 00:57:06 +0000595 }
596
Greg Clayton0baa3942010-11-04 01:54:29 +0000597 exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
Sean Callanan94d255f2010-12-07 22:55:01 +0000598
599 if (log)
600 log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
Greg Clayton0baa3942010-11-04 01:54:29 +0000601 }
602
Jim Ingham360f53f2010-11-30 02:22:11 +0000603 ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix));
604
Greg Clayton377e0b42010-10-05 00:31:29 +0000605 StreamString error_stream;
606
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000607 lldb::ClangExpressionVariableSP const_result;
608
Sean Callanan94d255f2010-12-07 22:55:01 +0000609 if (log)
610 log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
611
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000612 if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), &const_result))
Greg Clayton377e0b42010-10-05 00:31:29 +0000613 {
614 if (error_stream.GetString().empty())
615 error.SetErrorString ("expression failed to parse, unknown error");
616 else
617 error.SetErrorString (error_stream.GetString().c_str());
618 }
619 else
620 {
Greg Clayton427f2902010-12-14 02:59:59 +0000621 lldb::ClangExpressionVariableSP expr_result;
Greg Clayton377e0b42010-10-05 00:31:29 +0000622
Sean Callanan6a925532011-01-13 08:53:35 +0000623 if (const_result.get() && !keep_in_memory)
Greg Clayton377e0b42010-10-05 00:31:29 +0000624 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000625 if (log)
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000626 log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
Sean Callanan94d255f2010-12-07 22:55:01 +0000627
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000628 result_valobj_sp = const_result->GetValueObject();
Greg Clayton377e0b42010-10-05 00:31:29 +0000629 }
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000630 else
631 {
632 error_stream.GetString().clear();
633
634 if (log)
635 log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
636
637 execution_results = user_expression_sp->Execute (error_stream,
638 exe_ctx,
Sean Callanan6a925532011-01-13 08:53:35 +0000639 discard_on_error,
640 keep_in_memory,
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000641 user_expression_sp,
642 expr_result);
643
Greg Claytonb3448432011-03-24 21:19:54 +0000644 if (execution_results != eExecutionCompleted)
Greg Clayton377e0b42010-10-05 00:31:29 +0000645 {
Sean Callanan94d255f2010-12-07 22:55:01 +0000646 if (log)
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000647 log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
648
649 if (error_stream.GetString().empty())
650 error.SetErrorString ("expression failed to execute, unknown error");
651 else
652 error.SetErrorString (error_stream.GetString().c_str());
Greg Clayton377e0b42010-10-05 00:31:29 +0000653 }
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000654 else
Greg Clayton377e0b42010-10-05 00:31:29 +0000655 {
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000656 if (expr_result)
657 {
658 result_valobj_sp = expr_result->GetValueObject();
659
660 if (log)
Jim Inghamfa3a16a2011-03-31 00:19:25 +0000661 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString());
Sean Callanan05a5a1b2010-12-16 03:17:46 +0000662 }
663 else
664 {
665 if (log)
666 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
667
668 error.SetErrorString ("Expression did not return a result");
669 }
Greg Clayton377e0b42010-10-05 00:31:29 +0000670 }
671 }
672 }
Sean Callanan44820ec2010-10-19 20:15:00 +0000673
Greg Claytond1719722010-10-05 03:13:51 +0000674 if (result_valobj_sp.get() == NULL)
Jim Inghamfa3a16a2011-03-31 00:19:25 +0000675 result_valobj_sp.reset (new ValueObjectConstResult (NULL, error));
Greg Claytond1719722010-10-05 03:13:51 +0000676
Jim Ingham360f53f2010-11-30 02:22:11 +0000677 return execution_results;
Johnny Chenb4c0f022010-10-29 20:19:44 +0000678}