diff options
author | emaste <emaste@FreeBSD.org> | 2013-08-23 18:06:42 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2013-08-23 18:06:42 +0000 |
commit | 424d4dadd208e2a1e9a43c3d55f47f03ba0c4509 (patch) | |
tree | 05d762b98a499804ce690e6ce04033f1ddf4dee6 /contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp | |
parent | cde487f27a84e02a560384f75178fddca68740f6 (diff) | |
parent | dcd15f81789e389c1cb27d264fcdddfd0a6002bd (diff) | |
download | FreeBSD-src-424d4dadd208e2a1e9a43c3d55f47f03ba0c4509.zip FreeBSD-src-424d4dadd208e2a1e9a43c3d55f47f03ba0c4509.tar.gz |
Merge lldb r188801 to contrib/llvm/tools/lldb/
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp | 624 |
1 files changed, 624 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp new file mode 100644 index 0000000..aace3a6 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp @@ -0,0 +1,624 @@ +//===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-python.h" + +#include "CommandObjectFrame.h" + +// C Includes +// C++ Includes +#include <string> +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/Timer.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectVariable.h" +#include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/Host/Host.h" +#include "lldb/Interpreter/Args.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionGroupFormat.h" +#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" +#include "lldb/Interpreter/OptionGroupVariable.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +#pragma mark CommandObjectFrameInfo + +//------------------------------------------------------------------------- +// CommandObjectFrameInfo +//------------------------------------------------------------------------- + +class CommandObjectFrameInfo : public CommandObjectParsed +{ +public: + + CommandObjectFrameInfo (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "frame info", + "List information about the currently selected frame in the current thread.", + "frame info", + eFlagRequiresFrame | + eFlagTryTargetAPILock | + eFlagProcessMustBeLaunched | + eFlagProcessMustBePaused ) + { + } + + ~CommandObjectFrameInfo () + { + } + +protected: + bool + DoExecute (Args& command, CommandReturnObject &result) + { + m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat (&result.GetOutputStream()); + result.SetStatus (eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } +}; + +#pragma mark CommandObjectFrameSelect + +//------------------------------------------------------------------------- +// CommandObjectFrameSelect +//------------------------------------------------------------------------- + +class CommandObjectFrameSelect : public CommandObjectParsed +{ +public: + + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options(interpreter) + { + OptionParsingStarting (); + } + + virtual + ~CommandOptions () + { + } + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + Error error; + bool success = false; + const int short_option = m_getopt_table[option_idx].val; + switch (short_option) + { + case 'r': + relative_frame_offset = Args::StringToSInt32 (option_arg, INT32_MIN, 0, &success); + if (!success) + error.SetErrorStringWithFormat ("invalid frame offset argument '%s'", option_arg); + break; + + default: + error.SetErrorStringWithFormat ("invalid short option character '%c'", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting () + { + relative_frame_offset = INT32_MIN; + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + int32_t relative_frame_offset; + }; + + CommandObjectFrameSelect (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "frame select", + "Select a frame by index from within the current thread and make it the current frame.", + NULL, + eFlagRequiresThread | + eFlagTryTargetAPILock | + eFlagProcessMustBeLaunched | + eFlagProcessMustBePaused ), + m_options (interpreter) + { + CommandArgumentEntry arg; + CommandArgumentData index_arg; + + // Define the first (and only) variant of this arg. + index_arg.arg_type = eArgTypeFrameIndex; + index_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the argument entry. + arg.push_back (index_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg); + } + + ~CommandObjectFrameSelect () + { + } + + virtual + Options * + GetOptions () + { + return &m_options; + } + + +protected: + bool + DoExecute (Args& command, CommandReturnObject &result) + { + // No need to check "thread" for validity as eFlagRequiresThread ensures it is valid + Thread *thread = m_exe_ctx.GetThreadPtr(); + + uint32_t frame_idx = UINT32_MAX; + if (m_options.relative_frame_offset != INT32_MIN) + { + // The one and only argument is a signed relative frame index + frame_idx = thread->GetSelectedFrameIndex (); + if (frame_idx == UINT32_MAX) + frame_idx = 0; + + if (m_options.relative_frame_offset < 0) + { + if (frame_idx >= -m_options.relative_frame_offset) + frame_idx += m_options.relative_frame_offset; + else + { + if (frame_idx == 0) + { + //If you are already at the bottom of the stack, then just warn and don't reset the frame. + result.AppendError("Already at the bottom of the stack"); + result.SetStatus(eReturnStatusFailed); + return false; + } + else + frame_idx = 0; + } + } + else if (m_options.relative_frame_offset > 0) + { + // I don't want "up 20" where "20" takes you past the top of the stack to produce + // an error, but rather to just go to the top. So I have to count the stack here... + const uint32_t num_frames = thread->GetStackFrameCount(); + if (num_frames - frame_idx > m_options.relative_frame_offset) + frame_idx += m_options.relative_frame_offset; + else + { + if (frame_idx == num_frames - 1) + { + //If we are already at the top of the stack, just warn and don't reset the frame. + result.AppendError("Already at the top of the stack"); + result.SetStatus(eReturnStatusFailed); + return false; + } + else + frame_idx = num_frames - 1; + } + } + } + else + { + if (command.GetArgumentCount() == 1) + { + const char *frame_idx_cstr = command.GetArgumentAtIndex(0); + frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0); + } + else if (command.GetArgumentCount() == 0) + { + frame_idx = thread->GetSelectedFrameIndex (); + if (frame_idx == UINT32_MAX) + { + frame_idx = 0; + } + } + else + { + result.AppendError ("invalid arguments.\n"); + m_options.GenerateOptionUsage (result.GetErrorStream(), this); + } + } + + bool success = thread->SetSelectedFrameByIndexNoisily (frame_idx, result.GetOutputStream()); + if (success) + { + m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ()); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx); + result.SetStatus (eReturnStatusFailed); + } + + return result.Succeeded(); + } +protected: + + CommandOptions m_options; +}; + +OptionDefinition +CommandObjectFrameSelect::CommandOptions::g_option_table[] = +{ +{ LLDB_OPT_SET_1, false, "relative", 'r', required_argument, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."}, +{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } +}; + +#pragma mark CommandObjectFrameVariable +//---------------------------------------------------------------------- +// List images with associated information +//---------------------------------------------------------------------- +class CommandObjectFrameVariable : public CommandObjectParsed +{ +public: + + CommandObjectFrameVariable (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "frame variable", + "Show frame variables. All argument and local variables " + "that are in scope will be shown when no arguments are given. " + "If any arguments are specified, they can be names of " + "argument, local, file static and file global variables. " + "Children of aggregate variables can be specified such as " + "'var->child.x'.", + NULL, + eFlagRequiresFrame | + eFlagTryTargetAPILock | + eFlagProcessMustBeLaunched | + eFlagProcessMustBePaused | + eFlagRequiresProcess), + m_option_group (interpreter), + m_option_variable(true), // Include the frame specific options by passing "true" + m_option_format (eFormatDefault), + m_varobj_options() + { + CommandArgumentEntry arg; + CommandArgumentData var_name_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeVarName; + var_name_arg.arg_repetition = eArgRepeatStar; + + // There is only one variant this argument could be; put it into the argument entry. + arg.push_back (var_name_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg); + + m_option_group.Append (&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append (&m_option_format, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); + m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + virtual + ~CommandObjectFrameVariable () + { + } + + virtual + Options * + GetOptions () + { + return &m_option_group; + } + + + virtual int + HandleArgumentCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) + { + // Arguments are the standard source file completer. + std::string completion_str (input.GetArgumentAtIndex(cursor_index)); + completion_str.erase (cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, + CommandCompletions::eVariablePathCompletion, + completion_str.c_str(), + match_start_point, + max_return_elements, + NULL, + word_complete, + matches); + return matches.GetSize(); + } + +protected: + virtual bool + DoExecute (Args& command, CommandReturnObject &result) + { + // No need to check "frame" for validity as eFlagRequiresFrame ensures it is valid + StackFrame *frame = m_exe_ctx.GetFramePtr(); + + Stream &s = result.GetOutputStream(); + + bool get_file_globals = true; + + // Be careful about the stack frame, if any summary formatter runs code, it might clear the StackFrameList + // for the thread. So hold onto a shared pointer to the frame so it stays alive. + + VariableList *variable_list = frame->GetVariableList (get_file_globals); + + VariableSP var_sp; + ValueObjectSP valobj_sp; + + const char *name_cstr = NULL; + size_t idx; + + TypeSummaryImplSP summary_format_sp; + if (!m_option_variable.summary.IsCurrentValueEmpty()) + DataVisualization::NamedSummaryFormats::GetSummaryFormat(ConstString(m_option_variable.summary.GetCurrentValue()), summary_format_sp); + else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) + summary_format_sp.reset(new StringSummaryFormat(TypeSummaryImpl::Flags(),m_option_variable.summary_string.GetCurrentValue())); + + ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,eFormatDefault,summary_format_sp)); + + if (variable_list) + { + const Format format = m_option_format.GetFormat(); + options.SetFormat(format); + + if (command.GetArgumentCount() > 0) + { + VariableList regex_var_list; + + // If we have any args to the variable command, we will make + // variable objects from them... + for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx) + { + if (m_option_variable.use_regex) + { + const size_t regex_start_index = regex_var_list.GetSize(); + RegularExpression regex (name_cstr); + if (regex.Compile(name_cstr)) + { + size_t num_matches = 0; + const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, + regex_var_list, + num_matches); + if (num_new_regex_vars > 0) + { + for (size_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize(); + regex_idx < end_index; + ++regex_idx) + { + var_sp = regex_var_list.GetVariableAtIndex (regex_idx); + if (var_sp) + { + valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic); + if (valobj_sp) + { +// if (format != eFormatDefault) +// valobj_sp->SetFormat (format); + + if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) + { + bool show_fullpaths = false; + bool show_module = true; + if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) + s.PutCString (": "); + } + ValueObject::DumpValueObject (result.GetOutputStream(), + valobj_sp.get(), + options); + } + } + } + } + else if (num_matches == 0) + { + result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr); + } + } + else + { + char regex_error[1024]; + if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) + result.GetErrorStream().Printf ("error: %s\n", regex_error); + else + result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr); + } + } + else // No regex, either exact variable names or variable expressions. + { + Error error; + uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | + StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; + lldb::VariableSP var_sp; + valobj_sp = frame->GetValueForVariableExpressionPath (name_cstr, + m_varobj_options.use_dynamic, + expr_path_options, + var_sp, + error); + if (valobj_sp) + { +// if (format != eFormatDefault) +// valobj_sp->SetFormat (format); + if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration ().GetFile()) + { + var_sp->GetDeclaration ().DumpStopContext (&s, false); + s.PutCString (": "); + } + + options.SetFormat(format); + + Stream &output_stream = result.GetOutputStream(); + options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL); + ValueObject::DumpValueObject (output_stream, + valobj_sp.get(), + options); + } + else + { + const char *error_cstr = error.AsCString(NULL); + if (error_cstr) + result.GetErrorStream().Printf("error: %s\n", error_cstr); + else + result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", name_cstr); + } + } + } + } + else // No command arg specified. Use variable_list, instead. + { + const size_t num_variables = variable_list->GetSize(); + if (num_variables > 0) + { + for (size_t i=0; i<num_variables; i++) + { + var_sp = variable_list->GetVariableAtIndex(i); + bool dump_variable = true; + switch (var_sp->GetScope()) + { + case eValueTypeVariableGlobal: + dump_variable = m_option_variable.show_globals; + if (dump_variable && m_option_variable.show_scope) + s.PutCString("GLOBAL: "); + break; + + case eValueTypeVariableStatic: + dump_variable = m_option_variable.show_globals; + if (dump_variable && m_option_variable.show_scope) + s.PutCString("STATIC: "); + break; + + case eValueTypeVariableArgument: + dump_variable = m_option_variable.show_args; + if (dump_variable && m_option_variable.show_scope) + s.PutCString(" ARG: "); + break; + + case eValueTypeVariableLocal: + dump_variable = m_option_variable.show_locals; + if (dump_variable && m_option_variable.show_scope) + s.PutCString(" LOCAL: "); + break; + + default: + break; + } + + if (dump_variable) + { + // Use the variable object code to make sure we are + // using the same APIs as the the public API will be + // using... + valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, + m_varobj_options.use_dynamic); + if (valobj_sp) + { +// if (format != eFormatDefault) +// valobj_sp->SetFormat (format); + + // When dumping all variables, don't print any variables + // that are not in scope to avoid extra unneeded output + if (valobj_sp->IsInScope ()) + { + if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) + { + var_sp->GetDeclaration ().DumpStopContext (&s, false); + s.PutCString (": "); + } + + options.SetFormat(format); + options.SetRootValueObjectName(name_cstr); + ValueObject::DumpValueObject (result.GetOutputStream(), + valobj_sp.get(), + options); + } + } + } + } + } + } + result.SetStatus (eReturnStatusSuccessFinishResult); + } + + if (m_interpreter.TruncationWarningNecessary()) + { + result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), + m_cmd_name.c_str()); + m_interpreter.TruncationWarningGiven(); + } + + return result.Succeeded(); + } +protected: + + OptionGroupOptions m_option_group; + OptionGroupVariable m_option_variable; + OptionGroupFormat m_option_format; + OptionGroupValueObjectDisplay m_varobj_options; +}; + + +#pragma mark CommandObjectMultiwordFrame + +//------------------------------------------------------------------------- +// CommandObjectMultiwordFrame +//------------------------------------------------------------------------- + +CommandObjectMultiwordFrame::CommandObjectMultiwordFrame (CommandInterpreter &interpreter) : + CommandObjectMultiword (interpreter, + "frame", + "A set of commands for operating on the current thread's frames.", + "frame <subcommand> [<subcommand-options>]") +{ + LoadSubCommand ("info", CommandObjectSP (new CommandObjectFrameInfo (interpreter))); + LoadSubCommand ("select", CommandObjectSP (new CommandObjectFrameSelect (interpreter))); + LoadSubCommand ("variable", CommandObjectSP (new CommandObjectFrameVariable (interpreter))); +} + +CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame () +{ +} + |