diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp')
| -rw-r--r-- | contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp | 639 | 
1 files changed, 639 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 000000000000..9477b50a58df --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp @@ -0,0 +1,639 @@ +//===-- 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 "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/DataFormatters/ValueObjectPrinter.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/StringConvert.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/CompilerType.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.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", +                             eCommandRequiresFrame         | +                             eCommandTryTargetAPILock      | +                             eCommandProcessMustBeLaunched | +                             eCommandProcessMustBePaused   ) +    { +    } + +    ~CommandObjectFrameInfo () override +    { +    } + +protected: +    bool +    DoExecute (Args& command, CommandReturnObject &result) override +    { +        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 (); +        } + +        ~CommandOptions () override +        { +        } + +        Error +        SetOptionValue (uint32_t option_idx, const char *option_arg) override +        { +            Error error; +            bool success = false; +            const int short_option = m_getopt_table[option_idx].val; +            switch (short_option) +            { +            case 'r':    +                relative_frame_offset = StringConvert::ToSInt32 (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 () override +        { +            relative_frame_offset = INT32_MIN; +        } + +        const OptionDefinition* +        GetDefinitions () override +        { +            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, +                             eCommandRequiresThread        | +                             eCommandTryTargetAPILock      | +                             eCommandProcessMustBeLaunched | +                             eCommandProcessMustBePaused   ), +        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 () override +    { +    } + +    Options * +    GetOptions () override +    { +        return &m_options; +    } + + +protected: +    bool +    DoExecute (Args& command, CommandReturnObject &result) override +    { +        // No need to check "thread" for validity as eCommandRequiresThread 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 (static_cast<int32_t>(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 (static_cast<int32_t>(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); +                bool success = false; +                frame_idx = StringConvert::ToUInt32 (frame_idx_cstr, UINT32_MAX, 0, &success); +                if (!success) +                { +                    result.AppendErrorWithFormat ("invalid frame index argument '%s'", frame_idx_cstr); +                    result.SetStatus (eReturnStatusFailed); +                    return false; +                } +            } +            else if (command.GetArgumentCount() == 0) +            { +                frame_idx = thread->GetSelectedFrameIndex (); +                if (frame_idx == UINT32_MAX) +                { +                    frame_idx = 0; +                } +            } +            else +            { +                result.AppendErrorWithFormat ("too many arguments; expected frame-index, saw '%s'.\n", +                                              command.GetArgumentAtIndex(0)); +                m_options.GenerateOptionUsage (result.GetErrorStream(), this); +                return false; +            } +        } + +        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', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."}, +{ 0, false, NULL, 0, 0, NULL, 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, +                             eCommandRequiresFrame | +                             eCommandTryTargetAPILock | +                             eCommandProcessMustBeLaunched | +                             eCommandProcessMustBePaused | +                             eCommandRequiresProcess), +        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(); +    } + +    ~CommandObjectFrameVariable () override +    { +    } + +    Options * +    GetOptions () override +    { +        return &m_option_group; +    } +     +     +    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) override +    { +        // 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: +    bool +    DoExecute (Args& command, CommandReturnObject &result) override +    { +        // No need to check "frame" for validity as eCommandRequiresFrame 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())); +         +        DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,eFormatDefault,summary_format_sp)); +         +        const SymbolContext& sym_ctx = frame->GetSymbolContext(eSymbolContextFunction); +        if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction()) +            m_option_variable.show_globals = true; +         +        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 (": "); +                                            } +                                            valobj_sp->Dump(result.GetOutputStream(),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: unknown 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 | +                                                     StackFrame::eExpressionPathOptionsInspectAnonymousUnions; +                        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); +                            options.SetVariableFormatDisplayLanguage(valobj_sp->GetPreferredDisplayLanguage()); + +                            Stream &output_stream = result.GetOutputStream(); +                            options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL); +                            valobj_sp->Dump(output_stream,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; +                        std::string scope_string; +                        switch (var_sp->GetScope()) +                        { +                            case eValueTypeVariableGlobal: +                                dump_variable = m_option_variable.show_globals; +                                if (dump_variable && m_option_variable.show_scope) +                                    scope_string = "GLOBAL: "; +                                break; + +                            case eValueTypeVariableStatic: +                                dump_variable = m_option_variable.show_globals; +                                if (dump_variable && m_option_variable.show_scope) +                                    scope_string = "STATIC: "; +                                break; + +                            case eValueTypeVariableArgument: +                                dump_variable = m_option_variable.show_args; +                                if (dump_variable && m_option_variable.show_scope) +                                    scope_string = "   ARG: "; +                                break; + +                            case eValueTypeVariableLocal: +                                dump_variable = m_option_variable.show_locals; +                                if (dump_variable && m_option_variable.show_scope) +                                    scope_string = " LOCAL: "; +                                break; + +                            default: +                                break; +                        } + +                        if (dump_variable) +                        { +                            // Use the variable object code to make sure we are +                            // using the same APIs as 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 (false == valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() && +                                        true == valobj_sp->IsRuntimeSupportValue()) +                                        continue; +                                     +                                    if (!scope_string.empty()) +                                        s.PutCString(scope_string.c_str()); +                                     +                                    if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) +                                    { +                                        var_sp->GetDeclaration ().DumpStopContext (&s, false); +                                        s.PutCString (": "); +                                    } +                                     +                                    options.SetFormat(format); +                                    options.SetVariableFormatDisplayLanguage(valobj_sp->GetPreferredDisplayLanguage()); +                                    options.SetRootValueObjectName(name_cstr); +                                    valobj_sp->Dump(result.GetOutputStream(),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 () +{ +} + | 
