summaryrefslogtreecommitdiffstats
path: root/lldb/source/Commands/CommandObjectExpression.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-06-08 16:52:24 +0000
committerChris Lattner <sabre@nondot.org>2010-06-08 16:52:24 +0000
commit30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c (patch)
treef70013106f6a461a14abcd71c65f48a95a2979a6 /lldb/source/Commands/CommandObjectExpression.cpp
parent312c4c799da215b337f790fda330f70c4aa757cf (diff)
downloadbcm5719-llvm-30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c.tar.gz
bcm5719-llvm-30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c.zip
Initial checkin of lldb code from internal Apple repo.
llvm-svn: 105619
Diffstat (limited to 'lldb/source/Commands/CommandObjectExpression.cpp')
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp554
1 files changed, 554 insertions, 0 deletions
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
new file mode 100644
index 00000000000..9afc8c0a1a3
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -0,0 +1,554 @@
+//===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectExpression.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandObjectExpression::CommandOptions::CommandOptions () :
+ Options()
+{
+ // Keep only one place to reset the values to their defaults
+ ResetOptionValues();
+}
+
+
+CommandObjectExpression::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectExpression::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'l':
+ if (language.SetLanguageFromCString (option_arg) == false)
+ {
+ error.SetErrorStringWithFormat("Invalid language option argument '%s'.\n", option_arg);
+ }
+ break;
+
+ case 'g':
+ debug = true;
+ break;
+
+ case 'f':
+ error = Args::StringToFormat(option_arg, format);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectExpression::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+ language.Clear();
+ debug = false;
+ format = eFormatDefault;
+ show_types = true;
+ show_summary = true;
+}
+
+const lldb::OptionDefinition*
+CommandObjectExpression::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+CommandObjectExpression::CommandObjectExpression () :
+ CommandObject (
+ "expression",
+ "Evaluate a C expression in the current program context, using variables currently in scope.",
+ "expression [<cmd-options>] <expr>"),
+ m_expr_line_count (0),
+ m_expr_lines ()
+{
+ SetHelpLong(
+"Examples: \n\
+\n\
+ expr my_struct->a = my_array[3] \n\
+ expr -f bin -- (index * 8) + 5 \n\
+ expr char c[] = \"foo\"; c[0]\n");
+}
+
+CommandObjectExpression::~CommandObjectExpression ()
+{
+}
+
+Options *
+CommandObjectExpression::GetOptions ()
+{
+ return &m_options;
+}
+
+
+bool
+CommandObjectExpression::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ return false;
+}
+
+
+size_t
+CommandObjectExpression::MultiLineExpressionCallback
+(
+ void *baton,
+ InputReader *reader,
+ lldb::InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+ CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton;
+
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ if (out_fh)
+ ::fprintf (out_fh, "%s\n", "Enter expressions, then terminate with an empty line to evaluate:");
+ // Fall through
+ case eInputReaderReactivate:
+ //if (out_fh)
+ // ::fprintf (out_fh, "%3u: ", cmd_object_expr->m_expr_line_count);
+ break;
+
+ case eInputReaderDeactivate:
+ break;
+
+ case eInputReaderGotToken:
+ ++cmd_object_expr->m_expr_line_count;
+ if (bytes && bytes_len)
+ {
+ cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1);
+ }
+
+ if (bytes_len == 0)
+ reader->SetIsDone(true);
+ //else if (out_fh && !reader->IsDone())
+ // ::fprintf (out_fh, "%3u: ", cmd_object_expr->m_expr_line_count);
+ break;
+
+ case eInputReaderDone:
+ {
+ StreamFile out_stream(Debugger::GetSharedInstance().GetOutputFileHandle());
+ StreamFile err_stream(Debugger::GetSharedInstance().GetErrorFileHandle());
+ bool bare = false;
+ cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(),
+ bare,
+ out_stream,
+ err_stream);
+ }
+ break;
+ }
+
+ return bytes_len;
+}
+
+bool
+CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream &output_stream, Stream &error_stream)
+{
+ bool success = false;
+ ConstString target_triple;
+ Target *target = m_exe_ctx.target;
+ if (target)
+ target->GetTargetTriple(target_triple);
+
+ if (!target_triple)
+ target_triple = Host::GetTargetTriple ();
+
+
+ if (target_triple)
+ {
+ const bool show_types = m_options.show_types;
+ const bool show_summary = m_options.show_summary;
+ const bool debug = m_options.debug;
+
+ ClangExpressionDeclMap expr_decl_map(&m_exe_ctx);
+ ClangExpression clang_expr(target_triple.AsCString(), &expr_decl_map);
+
+ unsigned num_errors = 0;
+
+ if (bare)
+ num_errors = clang_expr.ParseBareExpression (llvm::StringRef(expr), error_stream);
+ else
+ num_errors = clang_expr.ParseExpression (expr, error_stream);
+
+ if (num_errors == 0)
+ {
+ StreamString dwarf_opcodes;
+ dwarf_opcodes.SetByteOrder(eByteOrderHost);
+ dwarf_opcodes.GetFlags().Set(Stream::eBinary);
+ ClangExpressionVariableList expr_local_vars;
+ clang_expr.ConvertExpressionToDWARF (expr_local_vars, dwarf_opcodes);
+
+ success = true;
+
+ DataExtractor dwarf_opcodes_data(dwarf_opcodes.GetData(), dwarf_opcodes.GetSize(), eByteOrderHost, 8);
+ DWARFExpression expr(dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize(), NULL);
+ expr.SetExpressionLocalVariableList(&expr_local_vars);
+ if (debug)
+ {
+ output_stream << "Expression parsed ok, dwarf opcodes:";
+ output_stream.IndentMore();
+ expr.GetDescription(&output_stream, lldb::eDescriptionLevelVerbose);
+ output_stream.IndentLess();
+ output_stream.EOL();
+ }
+
+ clang::ASTContext *ast_context = clang_expr.GetASTContext();
+ Value expr_result;
+ Error expr_error;
+ bool expr_success = expr.Evaluate (&m_exe_ctx, ast_context, NULL, expr_result, &expr_error);
+ if (expr_success)
+ {
+ lldb::Format format = m_options.format;
+
+ // Resolve any values that are possible
+ expr_result.ResolveValue(&m_exe_ctx, ast_context);
+
+ if (expr_result.GetContextType() == Value::eContextTypeInvalid &&
+ expr_result.GetValueType() == Value::eValueTypeScalar &&
+ format == eFormatDefault)
+ {
+ // The expression result is just a scalar with no special formatting
+ expr_result.GetScalar().GetValue (&output_stream, show_types);
+ output_stream.EOL();
+ }
+ else
+ {
+ DataExtractor data;
+ expr_error = expr_result.GetValueAsData (&m_exe_ctx, ast_context, data, 0);
+ if (expr_error.Success())
+ {
+ if (format == eFormatDefault)
+ format = expr_result.GetValueDefaultFormat ();
+
+ void *clang_type = expr_result.GetValueOpaqueClangQualType();
+ if (clang_type)
+ {
+ if (show_types)
+ Type::DumpClangTypeName(&output_stream, clang_type);
+
+ Type::DumpValue (
+ &m_exe_ctx, // The execution context for memory and variable access
+ ast_context, // The ASTContext that the clang type belongs to
+ clang_type, // The opaque clang type we want to dump that value of
+ &output_stream, // Stream to dump to
+ format, // Format to use when dumping
+ data, // A buffer containing the bytes for the clang type
+ 0, // Byte offset within "data" where value is
+ data.GetByteSize(), // Size in bytes of the value we are dumping
+ 0, // Bitfield bit size
+ 0, // Bitfield bit offset
+ show_types, // Show types?
+ show_summary, // Show summary?
+ debug, // Debug logging output?
+ UINT32_MAX); // Depth to dump in case this is an aggregate type
+ }
+ else
+ {
+ data.Dump(&output_stream, // Stream to dump to
+ 0, // Byte offset within "data"
+ format, // Format to use when dumping
+ data.GetByteSize(), // Size in bytes of each item we are dumping
+ 1, // Number of items to dump
+ UINT32_MAX, // Number of items per line
+ LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context
+ 0, // Bitfield bit size
+ 0); // Bitfield bit offset
+ }
+ output_stream.EOL();
+ }
+ else
+ {
+ error_stream.Printf ("error: %s\n", expr_error.AsCString());
+ success = false;
+ }
+ }
+ }
+ else
+ {
+ error_stream.Printf ("error: %s\n", expr_error.AsCString());
+ }
+ }
+ }
+ else
+ {
+ error_stream.PutCString ("error: invalid target triple\n");
+ }
+
+ return success;
+}
+
+bool
+CommandObjectExpression::ExecuteRawCommandString
+(
+ const char *command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ ConstString target_triple;
+ Target *target = context->GetTarget ();
+ if (target)
+ target->GetTargetTriple(target_triple);
+
+ if (!target_triple)
+ target_triple = Host::GetTargetTriple ();
+
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+
+ Stream &output_stream = result.GetOutputStream();
+
+ m_options.ResetOptionValues();
+
+ const char * expr = NULL;
+
+ if (command[0] == '\0')
+ {
+ m_expr_lines.clear();
+ m_expr_line_count = 0;
+
+ InputReaderSP reader_sp (new InputReader());
+ if (reader_sp)
+ {
+ Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback,
+ this, // baton
+ eInputReaderGranularityLine, // token size, to pass to callback function
+ NULL, // end token
+ NULL, // prompt
+ true)); // echo input
+ if (err.Success())
+ {
+ Debugger::GetSharedInstance().PushInputReader (reader_sp);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError (err.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError("out of memory");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+
+ if (command[0] == '-')
+ {
+ // We have some options and these options MUST end with --.
+ const char *end_options = NULL;
+ const char *s = command;
+ while (s && s[0])
+ {
+ end_options = ::strstr (s, "--");
+ if (end_options)
+ {
+ end_options += 2; // Get past the "--"
+ if (::isspace (end_options[0]))
+ {
+ expr = end_options;
+ while (::isspace (*expr))
+ ++expr;
+ break;
+ }
+ }
+ s = end_options;
+ }
+
+ if (end_options)
+ {
+ Args args(command, end_options - command);
+ if (!ParseOptions(args, interpreter, result))
+ return false;
+ }
+ }
+
+ const bool show_types = m_options.show_types;
+ const bool show_summary = m_options.show_summary;
+ const bool debug = m_options.debug;
+
+
+ if (expr == NULL)
+ expr = command;
+
+ if (target_triple)
+ {
+ ClangExpressionDeclMap expr_decl_map(&exe_ctx);
+
+ ClangExpression clang_expr(target_triple.AsCString(), &expr_decl_map);
+
+ unsigned num_errors = clang_expr.ParseExpression (expr, result.GetErrorStream());
+
+ if (num_errors == 0)
+ {
+ StreamString dwarf_opcodes;
+ dwarf_opcodes.SetByteOrder(eByteOrderHost);
+ dwarf_opcodes.GetFlags().Set(Stream::eBinary);
+ ClangExpressionVariableList expr_local_vars;
+ clang_expr.ConvertExpressionToDWARF (expr_local_vars, dwarf_opcodes);
+
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+
+ DataExtractor dwarf_opcodes_data(dwarf_opcodes.GetData(), dwarf_opcodes.GetSize(), eByteOrderHost, 8);
+ DWARFExpression expr(dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize(), NULL);
+ expr.SetExpressionLocalVariableList(&expr_local_vars);
+ expr.SetExpressionDeclMap(&expr_decl_map);
+ if (debug)
+ {
+ output_stream << "Expression parsed ok, dwarf opcodes:";
+ output_stream.IndentMore();
+ expr.GetDescription(&output_stream, lldb::eDescriptionLevelVerbose);
+ output_stream.IndentLess();
+ output_stream.EOL();
+ }
+
+ clang::ASTContext *ast_context = clang_expr.GetASTContext();
+ Value expr_result;
+ Error expr_error;
+ bool expr_success = expr.Evaluate (&exe_ctx, ast_context, NULL, expr_result, &expr_error);
+ if (expr_success)
+ {
+ lldb::Format format = m_options.format;
+
+ // Resolve any values that are possible
+ expr_result.ResolveValue(&exe_ctx, ast_context);
+
+ if (expr_result.GetContextType() == Value::eContextTypeInvalid &&
+ expr_result.GetValueType() == Value::eValueTypeScalar &&
+ format == eFormatDefault)
+ {
+ // The expression result is just a scalar with no special formatting
+ expr_result.GetScalar().GetValue (&output_stream, show_types);
+ output_stream.EOL();
+ }
+ else
+ {
+ DataExtractor data;
+ expr_error = expr_result.GetValueAsData (&exe_ctx, ast_context, data, 0);
+ if (expr_error.Success())
+ {
+ if (format == eFormatDefault)
+ format = expr_result.GetValueDefaultFormat ();
+
+ void *clang_type = expr_result.GetValueOpaqueClangQualType();
+ if (clang_type)
+ {
+ if (show_types)
+ Type::DumpClangTypeName(&output_stream, clang_type);
+
+ Type::DumpValue (
+ &exe_ctx, // The execution context for memory and variable access
+ ast_context, // The ASTContext that the clang type belongs to
+ clang_type, // The opaque clang type we want to dump that value of
+ &output_stream, // Stream to dump to
+ format, // Format to use when dumping
+ data, // A buffer containing the bytes for the clang type
+ 0, // Byte offset within "data" where value is
+ data.GetByteSize(), // Size in bytes of the value we are dumping
+ 0, // Bitfield bit size
+ 0, // Bitfield bit offset
+ show_types, // Show types?
+ show_summary, // Show summary?
+ debug, // Debug logging output?
+ UINT32_MAX); // Depth to dump in case this is an aggregate type
+ }
+ else
+ {
+ data.Dump(&output_stream, // Stream to dump to
+ 0, // Byte offset within "data"
+ format, // Format to use when dumping
+ data.GetByteSize(), // Size in bytes of each item we are dumping
+ 1, // Number of items to dump
+ UINT32_MAX, // Number of items per line
+ LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context
+ 0, // Bitfield bit size
+ 0); // Bitfield bit offset
+ }
+ output_stream.EOL();
+ }
+ else
+ {
+ result.AppendError(expr_error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ else
+ {
+ result.AppendError (expr_error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("invalid target triple");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+}
+
+lldb::OptionDefinition
+CommandObjectExpression::CommandOptions::g_option_table[] =
+{
+{ 0, true, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."},
+{ 0, 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."},
+{ 0, false, "debug", 'g', no_argument, NULL, 0, NULL, "Enable verbose debug logging of the expression parsing and evaluation."},
+{ 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
OpenPOWER on IntegriCloud