blob: ebd385ff19eb1135826c8696d8cf2e146176ead8 [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"
24#include "lldb/Expression/ClangExpressionDeclMap.h"
25#include "lldb/Expression/ClangExpressionParser.h"
26#include "lldb/Expression/ClangFunction.h"
27#include "lldb/Expression/ASTResultSynthesizer.h"
28#include "lldb/Expression/ClangUserExpression.h"
29#include "lldb/Host/Host.h"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000030#include "lldb/Symbol/VariableList.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000031#include "lldb/Target/ExecutionContext.h"
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000032#include "lldb/Target/StackFrame.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000033#include "lldb/Target/Target.h"
34
35using namespace lldb_private;
36
37ClangUserExpression::ClangUserExpression (const char *expr) :
38 m_expr_text(expr),
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000039 m_transformed_text(),
40 m_jit_addr(LLDB_INVALID_ADDRESS),
41 m_cplusplus(false),
42 m_objectivec(false),
43 m_needs_object_ptr(false)
Sean Callanan65dafa82010-08-27 01:01:44 +000044{
Sean Callanan65dafa82010-08-27 01:01:44 +000045}
46
Sean Callanan830a9032010-08-27 23:31:21 +000047ClangUserExpression::~ClangUserExpression ()
48{
49}
50
Sean Callanan65dafa82010-08-27 01:01:44 +000051clang::ASTConsumer *
52ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
53{
54 return new ASTResultSynthesizer(passthrough);
55}
56
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000057void
58ClangUserExpression::ScanContext(ExecutionContext &exe_ctx)
59{
60 if (!exe_ctx.frame)
61 return;
62
63 VariableList *vars = exe_ctx.frame->GetVariableList(false);
64
65 if (!vars)
66 return;
67
68 if (vars->FindVariable(ConstString("this")).get())
69 m_cplusplus = true;
70 else if (vars->FindVariable(ConstString("self")).get())
71 m_objectivec = true;
72}
73
Sean Callanan65dafa82010-08-27 01:01:44 +000074bool
75ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
76{
77 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
78
Sean Callanan3c9c5eb2010-09-21 00:44:12 +000079 ScanContext(exe_ctx);
80
81 StreamString m_transformed_stream;
82
83 ////////////////////////////////////
84 // Generate the expression
85 //
86
87 if (m_cplusplus)
88 {
89 m_transformed_stream.Printf("void \n"
90 "___clang_class::%s(void *___clang_arg) \n"
91 "{ \n"
92 " %s; \n"
93 "} \n",
94 FunctionName(),
95 m_expr_text.c_str());
96
97 m_needs_object_ptr = true;
98 }
99 else
100 {
101 m_transformed_stream.Printf("void \n"
102 "%s(void *___clang_arg) \n"
103 "{ \n"
104 " %s; \n"
105 "} \n",
106 FunctionName(),
107 m_expr_text.c_str());
108 }
109
110 m_transformed_text = m_transformed_stream.GetData();
111
112
113 if (log)
114 log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
115
Sean Callanan65dafa82010-08-27 01:01:44 +0000116 ////////////////////////////////////
117 // Set up the target and compiler
118 //
119
120 Target *target = exe_ctx.target;
121
122 if (!target)
123 {
124 error_stream.PutCString ("error: invalid target\n");
125 return false;
126 }
127
128 ConstString target_triple;
129
130 target->GetTargetTriple (target_triple);
131
132 if (!target_triple)
133 target_triple = Host::GetTargetTriple ();
134
135 if (!target_triple)
136 {
137 error_stream.PutCString ("error: invalid target triple\n");
138 return false;
139 }
140
141 //////////////////////////
142 // Parse the expression
143 //
144
145 m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));
146
147 ClangExpressionParser parser(target_triple.GetCString(), *this);
148
149 unsigned num_errors = parser.Parse (error_stream);
150
151 if (num_errors)
152 {
153 error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
154 return false;
155 }
156
157 ///////////////////////////////////////////////
158 // Convert the output of the parser to DWARF
159 //
160
161 m_dwarf_opcodes.reset(new StreamString);
162 m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost);
163 m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
164
165 m_local_variables.reset(new ClangExpressionVariableStore());
166
167 Error dwarf_error = parser.MakeDWARF ();
168
169 if (dwarf_error.Success())
170 {
171 if (log)
172 log->Printf("Code can be interpreted.");
173
174 return true;
175 }
176
177 //////////////////////////////////
178 // JIT the output of the parser
179 //
180
181 m_dwarf_opcodes.reset();
182
Sean Callanan830a9032010-08-27 23:31:21 +0000183 lldb::addr_t jit_end;
184
185 Error jit_error = parser.MakeJIT (m_jit_addr, jit_end, exe_ctx);
Sean Callanan65dafa82010-08-27 01:01:44 +0000186
187 if (jit_error.Success())
188 {
189 if (log)
190 {
191 log->Printf("Code can be run in the target.");
192
193 StreamString disassembly_stream;
194
195 Error err = parser.DisassembleFunction(disassembly_stream, exe_ctx);
196
197 if (!err.Success())
198 {
199 log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
200 }
201 else
202 {
203 log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
204 }
205 }
206
207 return true;
208 }
209 else
210 {
211 error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
212 return false;
213 }
214}
215
216bool
217ClangUserExpression::Execute (Stream &error_stream,
218 ExecutionContext &exe_ctx,
219 ClangExpressionVariable *&result)
220{
221 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
222
223 if (m_dwarf_opcodes.get())
224 {
225 // TODO execute the JITted opcodes
226
227 error_stream.Printf("We don't currently support executing DWARF expressions");
228
229 return false;
230 }
231 else if (m_jit_addr != LLDB_INVALID_ADDRESS)
232 {
233 lldb::addr_t struct_address;
234
235 Error materialize_error;
236
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000237 lldb::addr_t object_ptr = NULL;
238
239 if (m_needs_object_ptr && !(m_expr_decl_map->GetObjectPointer(object_ptr, &exe_ctx, materialize_error)))
240 {
241 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
242 return false;
243 }
244
Sean Callanan65dafa82010-08-27 01:01:44 +0000245 if (!m_expr_decl_map->Materialize(&exe_ctx, struct_address, materialize_error))
246 {
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000247 error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
Sean Callanan65dafa82010-08-27 01:01:44 +0000248 return false;
249 }
250
251 if (log)
252 {
253 log->Printf("Function address : 0x%llx", (uint64_t)m_jit_addr);
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000254
255 if (m_needs_object_ptr)
256 log->Printf("Object pointer : 0x%llx", (uint64_t)object_ptr);
257
Sean Callanan65dafa82010-08-27 01:01:44 +0000258 log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);
259
260 StreamString args;
261
262 Error dump_error;
263
Sean Callanane8a59a82010-09-13 21:34:21 +0000264 if (struct_address)
Sean Callanan65dafa82010-08-27 01:01:44 +0000265 {
Sean Callanane8a59a82010-09-13 21:34:21 +0000266 if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
267 {
268 log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
269 }
270 else
271 {
272 log->Printf("Structure contents:\n%s", args.GetData());
273 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000274 }
275 }
276
277 ClangFunction::ExecutionResults execution_result =
Sean Callanan3c9c5eb2010-09-21 00:44:12 +0000278 ClangFunction::ExecuteFunction (exe_ctx,
279 m_jit_addr,
280 struct_address,
281 true,
282 true,
283 10000,
284 error_stream,
285 (m_needs_object_ptr ? &object_ptr : NULL));
Sean Callanan65dafa82010-08-27 01:01:44 +0000286
287 if (execution_result != ClangFunction::eExecutionCompleted)
288 {
289 const char *result_name;
290
291 switch (execution_result)
292 {
293 case ClangFunction::eExecutionCompleted:
294 result_name = "eExecutionCompleted";
295 break;
296 case ClangFunction::eExecutionDiscarded:
297 result_name = "eExecutionDiscarded";
298 break;
299 case ClangFunction::eExecutionInterrupted:
300 result_name = "eExecutionInterrupted";
301 break;
302 case ClangFunction::eExecutionSetupError:
303 result_name = "eExecutionSetupError";
304 break;
305 case ClangFunction::eExecutionTimedOut:
306 result_name = "eExecutionTimedOut";
307 break;
308 }
309
310 error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
311 return false;
312 }
313
314 Error expr_error;
315
316 if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
317 {
318 error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
319 return false;
320 }
321
322 return true;
323 }
324 else
325 {
326 error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function are present");
327 return false;
328 }
329}
330
331StreamString &
332ClangUserExpression::DwarfOpcodeStream ()
333{
334 if (!m_dwarf_opcodes.get())
335 m_dwarf_opcodes.reset(new StreamString());
336
337 return *m_dwarf_opcodes.get();
338}