blob: 3e4827b9f0f3af89172a048f0c7a51e97a0ee243 [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"
23#include "lldb/Core/StreamString.h"
Greg Claytond1719722010-10-05 03:13:51 +000024#include "lldb/Core/ValueObjectConstResult.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000025#include "lldb/Expression/ClangExpressionDeclMap.h"
26#include "lldb/Expression/ClangExpressionParser.h"
27#include "lldb/Expression/ClangFunction.h"
28#include "lldb/Expression/ASTResultSynthesizer.h"
29#include "lldb/Expression/ClangUserExpression.h"
30#include "lldb/Host/Host.h"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000031#include "lldb/Symbol/VariableList.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000032#include "lldb/Target/ExecutionContext.h"
Greg Clayton0baa3942010-11-04 01:54:29 +000033#include "lldb/Target/Process.h"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000034#include "lldb/Target/StackFrame.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000035#include "lldb/Target/Target.h"
36
37using namespace lldb_private;
38
Sean Callanan77e93942010-10-29 00:29:03 +000039ClangUserExpression::ClangUserExpression (const char *expr,
40 const char *expr_prefix) :
Sean Callanan65dafa82010-08-27 01:01:44 +000041 m_expr_text(expr),
Johnny Chenb4c0f022010-10-29 20:19:44 +000042 m_expr_prefix(expr_prefix ? expr_prefix : ""),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000043 m_transformed_text(),
44 m_jit_addr(LLDB_INVALID_ADDRESS),
45 m_cplusplus(false),
46 m_objectivec(false),
Sean Callanana91dd992010-11-19 02:52:21 +000047 m_needs_object_ptr(false),
48 m_desired_type(NULL, NULL)
Sean Callanan65dafa82010-08-27 01:01:44 +000049{
Sean Callanan65dafa82010-08-27 01:01:44 +000050}
51
Sean Callanan830a9032010-08-27 23:31:21 +000052ClangUserExpression::~ClangUserExpression ()
53{
54}
55
Sean Callanan65dafa82010-08-27 01:01:44 +000056clang::ASTConsumer *
57ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
58{
Sean Callanana91dd992010-11-19 02:52:21 +000059 return new ASTResultSynthesizer(passthrough,
60 m_desired_type);
Sean Callanan65dafa82010-08-27 01:01:44 +000061}
62
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000063void
64ClangUserExpression::ScanContext(ExecutionContext &exe_ctx)
65{
66 if (!exe_ctx.frame)
67 return;
68
69 VariableList *vars = exe_ctx.frame->GetVariableList(false);
70
71 if (!vars)
72 return;
73
74 if (vars->FindVariable(ConstString("this")).get())
75 m_cplusplus = true;
76 else if (vars->FindVariable(ConstString("self")).get())
77 m_objectivec = true;
78}
79
Sean Callanan550f2762010-10-22 23:25:16 +000080// This is a really nasty hack, meant to fix Objective-C expressions of the form
81// (int)[myArray count]. Right now, because the type information for count is
82// not available, [myArray count] returns id, which can't be directly cast to
83// int without causing a clang error.
84static void
85ApplyObjcCastHack(std::string &expr)
86{
87#define OBJC_CAST_HACK_FROM "(int)["
88#define OBJC_CAST_HACK_TO "(int)(long long)["
89
90 size_t from_offset;
91
92 while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
93 expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
94
95#undef OBJC_CAST_HACK_TO
96#undef OBJC_CAST_HACK_FROM
97}
98
Sean Callanan30892372010-10-24 20:45:49 +000099// Another hack, meant to allow use of unichar despite it not being available in
100// the type information. Although we could special-case it in type lookup,
101// hopefully we'll figure out a way to #include the same environment as is
102// present in the original source file rather than try to hack specific type
103// definitions in as needed.
104static void
105ApplyUnicharHack(std::string &expr)
106{
107#define UNICHAR_HACK_FROM "unichar"
108#define UNICHAR_HACK_TO "unsigned short"
109
110 size_t from_offset;
111
112 while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
113 expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
114
115#undef UNICHAR_HACK_TO
116#undef UNICHAR_HACK_FROM
117}
118
Sean Callanan550f2762010-10-22 23:25:16 +0000119bool
Sean Callanana91dd992010-11-19 02:52:21 +0000120ClangUserExpression::Parse (Stream &error_stream,
121 ExecutionContext &exe_ctx,
122 TypeFromUser desired_type)
Sean Callanan65dafa82010-08-27 01:01:44 +0000123{
Greg Claytone005f2c2010-11-06 01:53:30 +0000124 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan65dafa82010-08-27 01:01:44 +0000125
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000126 ScanContext(exe_ctx);
127
128 StreamString m_transformed_stream;
129
130 ////////////////////////////////////
131 // Generate the expression
132 //
Sean Callanan550f2762010-10-22 23:25:16 +0000133
134 ApplyObjcCastHack(m_expr_text);
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000135 //ApplyUnicharHack(m_expr_text);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000136
137 if (m_cplusplus)
138 {
Sean Callanan77e93942010-10-29 00:29:03 +0000139 m_transformed_stream.Printf("%s \n"
140 "typedef unsigned short unichar; \n"
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000141 "void \n"
Sean Callanan550f2762010-10-22 23:25:16 +0000142 "$__lldb_class::%s(void *$__lldb_arg) \n"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000143 "{ \n"
144 " %s; \n"
145 "} \n",
Sean Callanan77e93942010-10-29 00:29:03 +0000146 m_expr_prefix.c_str(),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000147 FunctionName(),
148 m_expr_text.c_str());
149
150 m_needs_object_ptr = true;
151 }
152 else
153 {
Sean Callanan77e93942010-10-29 00:29:03 +0000154 m_transformed_stream.Printf("%s \n"
155 "typedef unsigned short unichar;\n"
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000156 "void \n"
Sean Callanan550f2762010-10-22 23:25:16 +0000157 "%s(void *$__lldb_arg) \n"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000158 "{ \n"
159 " %s; \n"
160 "} \n",
Sean Callanan77e93942010-10-29 00:29:03 +0000161 m_expr_prefix.c_str(),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000162 FunctionName(),
163 m_expr_text.c_str());
164 }
165
166 m_transformed_text = m_transformed_stream.GetData();
167
168
169 if (log)
170 log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
171
Sean Callanan65dafa82010-08-27 01:01:44 +0000172 ////////////////////////////////////
173 // Set up the target and compiler
174 //
175
176 Target *target = exe_ctx.target;
177
178 if (!target)
179 {
180 error_stream.PutCString ("error: invalid target\n");
181 return false;
182 }
183
184 ConstString target_triple;
185
186 target->GetTargetTriple (target_triple);
187
188 if (!target_triple)
189 target_triple = Host::GetTargetTriple ();
190
191 if (!target_triple)
192 {
193 error_stream.PutCString ("error: invalid target triple\n");
194 return false;
195 }
196
197 //////////////////////////
198 // Parse the expression
199 //
200
Sean Callanana91dd992010-11-19 02:52:21 +0000201 m_desired_type = desired_type;
202
Sean Callanan65dafa82010-08-27 01:01:44 +0000203 m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));
204
205 ClangExpressionParser parser(target_triple.GetCString(), *this);
206
207 unsigned num_errors = parser.Parse (error_stream);
208
209 if (num_errors)
210 {
211 error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
212 return false;
213 }
214
215 ///////////////////////////////////////////////
216 // Convert the output of the parser to DWARF
217 //
218
219 m_dwarf_opcodes.reset(new StreamString);
220 m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost);
221 m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
222
223 m_local_variables.reset(new ClangExpressionVariableStore());
224
225 Error dwarf_error = parser.MakeDWARF ();
226
227 if (dwarf_error.Success())
228 {
229 if (log)
230 log->Printf("Code can be interpreted.");
231
232 return true;
233 }
234
235 //////////////////////////////////
236 // JIT the output of the parser
237 //
238
239 m_dwarf_opcodes.reset();
240
Sean Callanan830a9032010-08-27 23:31:21 +0000241 lldb::addr_t jit_end;
242
243 Error jit_error = parser.MakeJIT (m_jit_addr, jit_end, exe_ctx);
Sean Callanan65dafa82010-08-27 01:01:44 +0000244
245 if (jit_error.Success())
246 {
Sean Callanan65dafa82010-08-27 01:01:44 +0000247 return true;
248 }
249 else
250 {
251 error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
252 return false;
253 }
254}
255
256bool
Jim Inghamd1686902010-10-14 23:45:03 +0000257ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
Sean Callananab06af92010-10-19 23:57:21 +0000258 ExecutionContext &exe_ctx,
259 lldb::addr_t &struct_address,
260 lldb::addr_t &object_ptr)
Sean Callanan65dafa82010-08-27 01:01:44 +0000261{
Greg Claytone005f2c2010-11-06 01:53:30 +0000262 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan65dafa82010-08-27 01:01:44 +0000263
Jim Inghamd1686902010-10-14 23:45:03 +0000264 if (m_jit_addr != LLDB_INVALID_ADDRESS)
Sean Callanan65dafa82010-08-27 01:01:44 +0000265 {
Sean Callanan65dafa82010-08-27 01:01:44 +0000266
267 Error materialize_error;
268
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000269
270 if (m_needs_object_ptr && !(m_expr_decl_map->GetObjectPointer(object_ptr, &exe_ctx, materialize_error)))
271 {
272 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
273 return false;
274 }
275
Sean Callanan65dafa82010-08-27 01:01:44 +0000276 if (!m_expr_decl_map->Materialize(&exe_ctx, struct_address, materialize_error))
277 {
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000278 error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
Sean Callanan65dafa82010-08-27 01:01:44 +0000279 return false;
280 }
281
282 if (log)
283 {
284 log->Printf("Function address : 0x%llx", (uint64_t)m_jit_addr);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000285
286 if (m_needs_object_ptr)
287 log->Printf("Object pointer : 0x%llx", (uint64_t)object_ptr);
288
Sean Callanan65dafa82010-08-27 01:01:44 +0000289 log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);
290
291 StreamString args;
292
293 Error dump_error;
294
Sean Callanane8a59a82010-09-13 21:34:21 +0000295 if (struct_address)
Sean Callanan65dafa82010-08-27 01:01:44 +0000296 {
Sean Callanane8a59a82010-09-13 21:34:21 +0000297 if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
298 {
299 log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
300 }
301 else
302 {
303 log->Printf("Structure contents:\n%s", args.GetData());
304 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000305 }
306 }
Jim Inghamd1686902010-10-14 23:45:03 +0000307 }
308 return true;
309}
310
311ThreadPlan *
312ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
313 ExecutionContext &exe_ctx)
314{
315 lldb::addr_t struct_address;
316
317 lldb::addr_t object_ptr = NULL;
318
319 PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr);
320
321 return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
322 m_jit_addr,
323 struct_address,
324 error_stream,
325 true,
326 true,
327 (m_needs_object_ptr ? &object_ptr : NULL));
328}
329
330bool
331ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
332 ExecutionContext &exe_ctx,
333 ClangExpressionVariable *&result)
334{
335 Error expr_error;
336
337 if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
338 {
339 error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
340 return false;
341 }
342 return true;
343}
344
345bool
346ClangUserExpression::Execute (Stream &error_stream,
347 ExecutionContext &exe_ctx,
Jim Inghamea9d4262010-11-05 19:25:48 +0000348 bool discard_on_error,
Jim Inghamd1686902010-10-14 23:45:03 +0000349 ClangExpressionVariable *&result)
350{
351 if (m_dwarf_opcodes.get())
352 {
353 // TODO execute the JITted opcodes
354
355 error_stream.Printf("We don't currently support executing DWARF expressions");
356
357 return false;
358 }
359 else if (m_jit_addr != LLDB_INVALID_ADDRESS)
360 {
361 lldb::addr_t struct_address;
362
363 lldb::addr_t object_ptr = NULL;
364
365 PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr);
Sean Callanan65dafa82010-08-27 01:01:44 +0000366
Jim Inghamea9d4262010-11-05 19:25:48 +0000367 const bool stop_others = true;
368 const bool try_all_threads = true;
Sean Callanan65dafa82010-08-27 01:01:44 +0000369 ClangFunction::ExecutionResults execution_result =
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000370 ClangFunction::ExecuteFunction (exe_ctx,
371 m_jit_addr,
372 struct_address,
Jim Inghamea9d4262010-11-05 19:25:48 +0000373 stop_others,
374 try_all_threads,
375 discard_on_error,
Sean Callanan0027cec2010-10-07 18:17:31 +0000376 10000000,
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000377 error_stream,
378 (m_needs_object_ptr ? &object_ptr : NULL));
Sean Callanan65dafa82010-08-27 01:01:44 +0000379
380 if (execution_result != ClangFunction::eExecutionCompleted)
381 {
382 const char *result_name;
383
384 switch (execution_result)
385 {
386 case ClangFunction::eExecutionCompleted:
387 result_name = "eExecutionCompleted";
388 break;
389 case ClangFunction::eExecutionDiscarded:
390 result_name = "eExecutionDiscarded";
391 break;
392 case ClangFunction::eExecutionInterrupted:
393 result_name = "eExecutionInterrupted";
394 break;
395 case ClangFunction::eExecutionSetupError:
396 result_name = "eExecutionSetupError";
397 break;
398 case ClangFunction::eExecutionTimedOut:
399 result_name = "eExecutionTimedOut";
400 break;
401 }
402
403 error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
404 return false;
405 }
406
Jim Inghamd1686902010-10-14 23:45:03 +0000407 return FinalizeJITExecution (error_stream, exe_ctx, result);
Sean Callanan65dafa82010-08-27 01:01:44 +0000408 }
409 else
410 {
Johnny Chencb395442010-11-10 19:02:11 +0000411 error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present");
Sean Callanan65dafa82010-08-27 01:01:44 +0000412 return false;
413 }
414}
415
416StreamString &
417ClangUserExpression::DwarfOpcodeStream ()
418{
419 if (!m_dwarf_opcodes.get())
420 m_dwarf_opcodes.reset(new StreamString());
421
422 return *m_dwarf_opcodes.get();
423}
Greg Clayton377e0b42010-10-05 00:31:29 +0000424
Greg Claytond1719722010-10-05 03:13:51 +0000425lldb::ValueObjectSP
Sean Callanan77e93942010-10-29 00:29:03 +0000426ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
Jim Inghamea9d4262010-11-05 19:25:48 +0000427 bool discard_on_error,
Sean Callanan77e93942010-10-29 00:29:03 +0000428 const char *expr_cstr,
429 const char *expr_prefix)
Greg Clayton377e0b42010-10-05 00:31:29 +0000430{
431 Error error;
Greg Claytond1719722010-10-05 03:13:51 +0000432 lldb::ValueObjectSP result_valobj_sp;
Greg Clayton0baa3942010-11-04 01:54:29 +0000433
434 if (exe_ctx.process == NULL)
435 return result_valobj_sp;
436
437 if (!exe_ctx.process->GetDynamicCheckers())
438 {
439 DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
440
441 StreamString install_errors;
442
443 if (!dynamic_checkers->Install(install_errors, exe_ctx))
Sean Callananf7731452010-11-05 00:57:06 +0000444 {
445 if (install_errors.GetString().empty())
446 error.SetErrorString ("couldn't install checkers, unknown error");
447 else
448 error.SetErrorString (install_errors.GetString().c_str());
449
450 result_valobj_sp.reset (new ValueObjectConstResult (error));
Greg Clayton0baa3942010-11-04 01:54:29 +0000451 return result_valobj_sp;
Sean Callananf7731452010-11-05 00:57:06 +0000452 }
453
Greg Clayton0baa3942010-11-04 01:54:29 +0000454 exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
455 }
456
Sean Callanan77e93942010-10-29 00:29:03 +0000457 ClangUserExpression user_expression (expr_cstr, expr_prefix);
Greg Clayton377e0b42010-10-05 00:31:29 +0000458
459 StreamString error_stream;
460
Sean Callanana91dd992010-11-19 02:52:21 +0000461 if (!user_expression.Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL)))
Greg Clayton377e0b42010-10-05 00:31:29 +0000462 {
463 if (error_stream.GetString().empty())
464 error.SetErrorString ("expression failed to parse, unknown error");
465 else
466 error.SetErrorString (error_stream.GetString().c_str());
467 }
468 else
469 {
470 ClangExpressionVariable *expr_result = NULL;
471
472 error_stream.GetString().clear();
473
Jim Inghamea9d4262010-11-05 19:25:48 +0000474 if (!user_expression.Execute (error_stream, exe_ctx, discard_on_error, expr_result))
Greg Clayton377e0b42010-10-05 00:31:29 +0000475 {
476 if (error_stream.GetString().empty())
477 error.SetErrorString ("expression failed to execute, unknown error");
478 else
479 error.SetErrorString (error_stream.GetString().c_str());
480 }
481 else
482 {
483 // TODO: seems weird to get a pointer to a result object back from
484 // a function. Do we own it? Feels like we do, but from looking at the
485 // code we don't. Might be best to make this a reference and state
486 // explicitly that we don't own it when we get a reference back from
487 // the execute?
488 if (expr_result)
489 {
490 result_valobj_sp = expr_result->GetExpressionResult (&exe_ctx);
491 }
492 else
493 {
Sean Callanan44820ec2010-10-19 20:15:00 +0000494 error.SetErrorString ("Expression did not return a result");
Greg Clayton377e0b42010-10-05 00:31:29 +0000495 }
496 }
497 }
Sean Callanan44820ec2010-10-19 20:15:00 +0000498
Greg Claytond1719722010-10-05 03:13:51 +0000499 if (result_valobj_sp.get() == NULL)
500 result_valobj_sp.reset (new ValueObjectConstResult (error));
501
502 return result_valobj_sp;
Johnny Chenb4c0f022010-10-29 20:19:44 +0000503}