blob: 38534f03730a01a577ba236b57bac6ba76793800 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectExpression.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#include "CommandObjectExpression.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Jim Ingham84cdc152010-06-15 19:49:27 +000016#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000017#include "lldb/Core/Value.h"
18#include "lldb/Core/InputReader.h"
19#include "lldb/Expression/ClangExpression.h"
20#include "lldb/Expression/ClangExpressionDeclMap.h"
21#include "lldb/Expression/ClangExpressionVariable.h"
22#include "lldb/Expression/DWARFExpression.h"
23#include "lldb/Host/Host.h"
Greg Clayton63094e02010-06-23 01:19:29 +000024#include "lldb/Core/Debugger.h"
25#include "lldb/Interpreter/CommandInterpreter.h"
Chris Lattner24943d22010-06-08 16:52:24 +000026#include "lldb/Interpreter/CommandReturnObject.h"
27#include "lldb/Symbol/ObjectFile.h"
28#include "lldb/Symbol/Variable.h"
29#include "lldb/Target/Process.h"
30#include "lldb/Target/StackFrame.h"
31#include "lldb/Target/Target.h"
32#include "llvm/ADT/StringRef.h"
33
34using namespace lldb;
35using namespace lldb_private;
36
37CommandObjectExpression::CommandOptions::CommandOptions () :
38 Options()
39{
40 // Keep only one place to reset the values to their defaults
41 ResetOptionValues();
42}
43
44
45CommandObjectExpression::CommandOptions::~CommandOptions ()
46{
47}
48
49Error
50CommandObjectExpression::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
51{
52 Error error;
53
54 char short_option = (char) m_getopt_table[option_idx].val;
55
56 switch (short_option)
57 {
58 case 'l':
59 if (language.SetLanguageFromCString (option_arg) == false)
60 {
61 error.SetErrorStringWithFormat("Invalid language option argument '%s'.\n", option_arg);
62 }
63 break;
64
65 case 'g':
66 debug = true;
67 break;
68
69 case 'f':
70 error = Args::StringToFormat(option_arg, format);
71 break;
72
73 default:
74 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
75 break;
76 }
77
78 return error;
79}
80
81void
82CommandObjectExpression::CommandOptions::ResetOptionValues ()
83{
84 Options::ResetOptionValues();
85 language.Clear();
86 debug = false;
87 format = eFormatDefault;
88 show_types = true;
89 show_summary = true;
90}
91
92const lldb::OptionDefinition*
93CommandObjectExpression::CommandOptions::GetDefinitions ()
94{
95 return g_option_table;
96}
97
98CommandObjectExpression::CommandObjectExpression () :
99 CommandObject (
100 "expression",
101 "Evaluate a C expression in the current program context, using variables currently in scope.",
102 "expression [<cmd-options>] <expr>"),
103 m_expr_line_count (0),
104 m_expr_lines ()
105{
106 SetHelpLong(
107"Examples: \n\
108\n\
109 expr my_struct->a = my_array[3] \n\
110 expr -f bin -- (index * 8) + 5 \n\
111 expr char c[] = \"foo\"; c[0]\n");
112}
113
114CommandObjectExpression::~CommandObjectExpression ()
115{
116}
117
118Options *
119CommandObjectExpression::GetOptions ()
120{
121 return &m_options;
122}
123
124
125bool
126CommandObjectExpression::Execute
127(
Greg Clayton63094e02010-06-23 01:19:29 +0000128 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000129 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000130 CommandReturnObject &result
131)
132{
133 return false;
134}
135
136
137size_t
138CommandObjectExpression::MultiLineExpressionCallback
139(
140 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000141 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000142 lldb::InputReaderAction notification,
143 const char *bytes,
144 size_t bytes_len
145)
146{
Chris Lattner24943d22010-06-08 16:52:24 +0000147 CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton;
148
149 switch (notification)
150 {
151 case eInputReaderActivate:
Greg Clayton63094e02010-06-23 01:19:29 +0000152 reader.GetDebugger().GetOutputStream().Printf("%s\n", "Enter expressions, then terminate with an empty line to evaluate:");
Chris Lattner24943d22010-06-08 16:52:24 +0000153 // Fall through
154 case eInputReaderReactivate:
155 //if (out_fh)
Greg Clayton63094e02010-06-23 01:19:29 +0000156 // reader.GetDebugger().GetOutputStream().Printf ("%3u: ", cmd_object_expr->m_expr_line_count);
Chris Lattner24943d22010-06-08 16:52:24 +0000157 break;
158
159 case eInputReaderDeactivate:
160 break;
161
162 case eInputReaderGotToken:
163 ++cmd_object_expr->m_expr_line_count;
164 if (bytes && bytes_len)
165 {
166 cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1);
167 }
168
169 if (bytes_len == 0)
Greg Clayton63094e02010-06-23 01:19:29 +0000170 reader.SetIsDone(true);
Chris Lattner24943d22010-06-08 16:52:24 +0000171 //else if (out_fh && !reader->IsDone())
172 // ::fprintf (out_fh, "%3u: ", cmd_object_expr->m_expr_line_count);
173 break;
174
175 case eInputReaderDone:
176 {
Chris Lattner24943d22010-06-08 16:52:24 +0000177 bool bare = false;
178 cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(),
179 bare,
Greg Clayton63094e02010-06-23 01:19:29 +0000180 reader.GetDebugger().GetOutputStream(),
181 reader.GetDebugger().GetErrorStream());
Chris Lattner24943d22010-06-08 16:52:24 +0000182 }
183 break;
184 }
185
186 return bytes_len;
187}
188
189bool
190CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream &output_stream, Stream &error_stream)
191{
192 bool success = false;
193 ConstString target_triple;
194 Target *target = m_exe_ctx.target;
195 if (target)
196 target->GetTargetTriple(target_triple);
197
198 if (!target_triple)
199 target_triple = Host::GetTargetTriple ();
200
201
202 if (target_triple)
203 {
204 const bool show_types = m_options.show_types;
205 const bool show_summary = m_options.show_summary;
206 const bool debug = m_options.debug;
207
208 ClangExpressionDeclMap expr_decl_map(&m_exe_ctx);
209 ClangExpression clang_expr(target_triple.AsCString(), &expr_decl_map);
210
211 unsigned num_errors = 0;
212
213 if (bare)
214 num_errors = clang_expr.ParseBareExpression (llvm::StringRef(expr), error_stream);
215 else
216 num_errors = clang_expr.ParseExpression (expr, error_stream);
217
218 if (num_errors == 0)
219 {
220 StreamString dwarf_opcodes;
221 dwarf_opcodes.SetByteOrder(eByteOrderHost);
222 dwarf_opcodes.GetFlags().Set(Stream::eBinary);
223 ClangExpressionVariableList expr_local_vars;
224 clang_expr.ConvertExpressionToDWARF (expr_local_vars, dwarf_opcodes);
225
226 success = true;
227
228 DataExtractor dwarf_opcodes_data(dwarf_opcodes.GetData(), dwarf_opcodes.GetSize(), eByteOrderHost, 8);
229 DWARFExpression expr(dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize(), NULL);
230 expr.SetExpressionLocalVariableList(&expr_local_vars);
231 if (debug)
232 {
233 output_stream << "Expression parsed ok, dwarf opcodes:";
234 output_stream.IndentMore();
235 expr.GetDescription(&output_stream, lldb::eDescriptionLevelVerbose);
236 output_stream.IndentLess();
237 output_stream.EOL();
238 }
239
240 clang::ASTContext *ast_context = clang_expr.GetASTContext();
241 Value expr_result;
242 Error expr_error;
243 bool expr_success = expr.Evaluate (&m_exe_ctx, ast_context, NULL, expr_result, &expr_error);
244 if (expr_success)
245 {
246 lldb::Format format = m_options.format;
247
248 // Resolve any values that are possible
249 expr_result.ResolveValue(&m_exe_ctx, ast_context);
250
251 if (expr_result.GetContextType() == Value::eContextTypeInvalid &&
252 expr_result.GetValueType() == Value::eValueTypeScalar &&
253 format == eFormatDefault)
254 {
255 // The expression result is just a scalar with no special formatting
256 expr_result.GetScalar().GetValue (&output_stream, show_types);
257 output_stream.EOL();
258 }
259 else
260 {
261 DataExtractor data;
262 expr_error = expr_result.GetValueAsData (&m_exe_ctx, ast_context, data, 0);
263 if (expr_error.Success())
264 {
265 if (format == eFormatDefault)
266 format = expr_result.GetValueDefaultFormat ();
267
268 void *clang_type = expr_result.GetValueOpaqueClangQualType();
269 if (clang_type)
270 {
271 if (show_types)
272 Type::DumpClangTypeName(&output_stream, clang_type);
273
274 Type::DumpValue (
275 &m_exe_ctx, // The execution context for memory and variable access
276 ast_context, // The ASTContext that the clang type belongs to
277 clang_type, // The opaque clang type we want to dump that value of
278 &output_stream, // Stream to dump to
279 format, // Format to use when dumping
280 data, // A buffer containing the bytes for the clang type
281 0, // Byte offset within "data" where value is
282 data.GetByteSize(), // Size in bytes of the value we are dumping
283 0, // Bitfield bit size
284 0, // Bitfield bit offset
285 show_types, // Show types?
286 show_summary, // Show summary?
287 debug, // Debug logging output?
288 UINT32_MAX); // Depth to dump in case this is an aggregate type
289 }
290 else
291 {
292 data.Dump(&output_stream, // Stream to dump to
293 0, // Byte offset within "data"
294 format, // Format to use when dumping
295 data.GetByteSize(), // Size in bytes of each item we are dumping
296 1, // Number of items to dump
297 UINT32_MAX, // Number of items per line
298 LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context
299 0, // Bitfield bit size
300 0); // Bitfield bit offset
301 }
302 output_stream.EOL();
303 }
304 else
305 {
306 error_stream.Printf ("error: %s\n", expr_error.AsCString());
307 success = false;
308 }
309 }
310 }
311 else
312 {
313 error_stream.Printf ("error: %s\n", expr_error.AsCString());
314 }
315 }
316 }
317 else
318 {
319 error_stream.PutCString ("error: invalid target triple\n");
320 }
321
322 return success;
323}
324
325bool
326CommandObjectExpression::ExecuteRawCommandString
327(
Greg Clayton63094e02010-06-23 01:19:29 +0000328 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000329 const char *command,
Chris Lattner24943d22010-06-08 16:52:24 +0000330 CommandReturnObject &result
331)
332{
333 ConstString target_triple;
Greg Clayton63094e02010-06-23 01:19:29 +0000334 Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000335 if (target)
336 target->GetTargetTriple(target_triple);
337
338 if (!target_triple)
339 target_triple = Host::GetTargetTriple ();
340
Greg Clayton63094e02010-06-23 01:19:29 +0000341 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000342
343 Stream &output_stream = result.GetOutputStream();
344
345 m_options.ResetOptionValues();
346
347 const char * expr = NULL;
348
349 if (command[0] == '\0')
350 {
351 m_expr_lines.clear();
352 m_expr_line_count = 0;
353
Greg Clayton63094e02010-06-23 01:19:29 +0000354 InputReaderSP reader_sp (new InputReader(interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000355 if (reader_sp)
356 {
357 Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback,
358 this, // baton
359 eInputReaderGranularityLine, // token size, to pass to callback function
Greg Clayton63094e02010-06-23 01:19:29 +0000360 NULL, // end token
Chris Lattner24943d22010-06-08 16:52:24 +0000361 NULL, // prompt
362 true)); // echo input
363 if (err.Success())
364 {
Greg Clayton63094e02010-06-23 01:19:29 +0000365 interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000366 result.SetStatus (eReturnStatusSuccessFinishNoResult);
367 }
368 else
369 {
370 result.AppendError (err.AsCString());
371 result.SetStatus (eReturnStatusFailed);
372 }
373 }
374 else
375 {
376 result.AppendError("out of memory");
377 result.SetStatus (eReturnStatusFailed);
378 }
379 return result.Succeeded();
380 }
381
382 if (command[0] == '-')
383 {
384 // We have some options and these options MUST end with --.
385 const char *end_options = NULL;
386 const char *s = command;
387 while (s && s[0])
388 {
389 end_options = ::strstr (s, "--");
390 if (end_options)
391 {
392 end_options += 2; // Get past the "--"
393 if (::isspace (end_options[0]))
394 {
395 expr = end_options;
396 while (::isspace (*expr))
397 ++expr;
398 break;
399 }
400 }
401 s = end_options;
402 }
403
404 if (end_options)
405 {
Greg Clayton63094e02010-06-23 01:19:29 +0000406 Args args (command, end_options - command);
407 if (!ParseOptions (interpreter, args, result))
Chris Lattner24943d22010-06-08 16:52:24 +0000408 return false;
409 }
410 }
411
412 const bool show_types = m_options.show_types;
413 const bool show_summary = m_options.show_summary;
414 const bool debug = m_options.debug;
415
416
417 if (expr == NULL)
418 expr = command;
419
420 if (target_triple)
421 {
422 ClangExpressionDeclMap expr_decl_map(&exe_ctx);
423
424 ClangExpression clang_expr(target_triple.AsCString(), &expr_decl_map);
425
426 unsigned num_errors = clang_expr.ParseExpression (expr, result.GetErrorStream());
427
428 if (num_errors == 0)
429 {
430 StreamString dwarf_opcodes;
431 dwarf_opcodes.SetByteOrder(eByteOrderHost);
432 dwarf_opcodes.GetFlags().Set(Stream::eBinary);
433 ClangExpressionVariableList expr_local_vars;
434 clang_expr.ConvertExpressionToDWARF (expr_local_vars, dwarf_opcodes);
435
436 result.SetStatus (eReturnStatusSuccessFinishResult);
437
438 DataExtractor dwarf_opcodes_data(dwarf_opcodes.GetData(), dwarf_opcodes.GetSize(), eByteOrderHost, 8);
439 DWARFExpression expr(dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize(), NULL);
440 expr.SetExpressionLocalVariableList(&expr_local_vars);
441 expr.SetExpressionDeclMap(&expr_decl_map);
442 if (debug)
443 {
444 output_stream << "Expression parsed ok, dwarf opcodes:";
445 output_stream.IndentMore();
446 expr.GetDescription(&output_stream, lldb::eDescriptionLevelVerbose);
447 output_stream.IndentLess();
448 output_stream.EOL();
449 }
450
451 clang::ASTContext *ast_context = clang_expr.GetASTContext();
452 Value expr_result;
453 Error expr_error;
454 bool expr_success = expr.Evaluate (&exe_ctx, ast_context, NULL, expr_result, &expr_error);
455 if (expr_success)
456 {
457 lldb::Format format = m_options.format;
458
459 // Resolve any values that are possible
460 expr_result.ResolveValue(&exe_ctx, ast_context);
461
462 if (expr_result.GetContextType() == Value::eContextTypeInvalid &&
463 expr_result.GetValueType() == Value::eValueTypeScalar &&
464 format == eFormatDefault)
465 {
466 // The expression result is just a scalar with no special formatting
467 expr_result.GetScalar().GetValue (&output_stream, show_types);
468 output_stream.EOL();
469 }
470 else
471 {
472 DataExtractor data;
473 expr_error = expr_result.GetValueAsData (&exe_ctx, ast_context, data, 0);
474 if (expr_error.Success())
475 {
476 if (format == eFormatDefault)
477 format = expr_result.GetValueDefaultFormat ();
478
479 void *clang_type = expr_result.GetValueOpaqueClangQualType();
480 if (clang_type)
481 {
482 if (show_types)
483 Type::DumpClangTypeName(&output_stream, clang_type);
484
485 Type::DumpValue (
486 &exe_ctx, // The execution context for memory and variable access
487 ast_context, // The ASTContext that the clang type belongs to
488 clang_type, // The opaque clang type we want to dump that value of
489 &output_stream, // Stream to dump to
490 format, // Format to use when dumping
491 data, // A buffer containing the bytes for the clang type
492 0, // Byte offset within "data" where value is
493 data.GetByteSize(), // Size in bytes of the value we are dumping
494 0, // Bitfield bit size
495 0, // Bitfield bit offset
496 show_types, // Show types?
497 show_summary, // Show summary?
498 debug, // Debug logging output?
499 UINT32_MAX); // Depth to dump in case this is an aggregate type
500 }
501 else
502 {
503 data.Dump(&output_stream, // Stream to dump to
504 0, // Byte offset within "data"
505 format, // Format to use when dumping
506 data.GetByteSize(), // Size in bytes of each item we are dumping
507 1, // Number of items to dump
508 UINT32_MAX, // Number of items per line
509 LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context
510 0, // Bitfield bit size
511 0); // Bitfield bit offset
512 }
513 output_stream.EOL();
514 }
515 else
516 {
517 result.AppendError(expr_error.AsCString());
518 result.SetStatus (eReturnStatusFailed);
519 }
520 }
521 }
522 else
523 {
524 result.AppendError (expr_error.AsCString());
525 result.SetStatus (eReturnStatusFailed);
526 }
527 }
528 else
529 {
530 result.SetStatus (eReturnStatusFailed);
531 }
532 }
533 else
534 {
535 result.AppendError ("invalid target triple");
536 result.SetStatus (eReturnStatusFailed);
537 }
538 return result.Succeeded();
539}
540
541lldb::OptionDefinition
542CommandObjectExpression::CommandOptions::g_option_table[] =
543{
Jim Ingham34e9a982010-06-15 18:47:14 +0000544{ LLDB_OPT_SET_1, true, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."},
545{ LLDB_OPT_SET_2, false, "format", 'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]", "Specify the format that the expression output should use."},
546{ LLDB_OPT_SET_3, false, "debug", 'g', no_argument, NULL, 0, NULL, "Enable verbose debug logging of the expression parsing and evaluation."},
Chris Lattner24943d22010-06-08 16:52:24 +0000547{ 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
548};
549