diff options
| author | Ed Maste <emaste@FreeBSD.org> | 2015-02-06 21:38:51 +0000 | 
|---|---|---|
| committer | Ed Maste <emaste@FreeBSD.org> | 2015-02-06 21:38:51 +0000 | 
| commit | 205afe679855a4ce8149cdaa94d3f0868ce796dc (patch) | |
| tree | 09bc83f73246ee3c7a779605cd0122093d2a8a19 /source/Commands | |
| parent | 0cac4ca3916ac24ab6139d03cbfd18db9e715bfe (diff) | |
Notes
Diffstat (limited to 'source/Commands')
| -rw-r--r-- | source/Commands/CommandCompletions.cpp | 6 | ||||
| -rw-r--r-- | source/Commands/CommandObjectBreakpoint.cpp | 588 | ||||
| -rw-r--r-- | source/Commands/CommandObjectBreakpoint.h | 14 | ||||
| -rw-r--r-- | source/Commands/CommandObjectBreakpointCommand.cpp | 112 | ||||
| -rw-r--r-- | source/Commands/CommandObjectCommands.cpp | 238 | ||||
| -rw-r--r-- | source/Commands/CommandObjectExpression.cpp | 6 | ||||
| -rw-r--r-- | source/Commands/CommandObjectMemory.cpp | 113 | ||||
| -rw-r--r-- | source/Commands/CommandObjectPlatform.cpp | 5 | ||||
| -rw-r--r-- | source/Commands/CommandObjectProcess.cpp | 27 | ||||
| -rw-r--r-- | source/Commands/CommandObjectSource.cpp | 12 | ||||
| -rw-r--r-- | source/Commands/CommandObjectSyntax.cpp | 6 | ||||
| -rw-r--r-- | source/Commands/CommandObjectTarget.cpp | 120 | ||||
| -rw-r--r-- | source/Commands/CommandObjectThread.cpp | 666 | ||||
| -rw-r--r-- | source/Commands/CommandObjectType.cpp | 125 | ||||
| -rw-r--r-- | source/Commands/CommandObjectWatchpointCommand.cpp | 15 | 
15 files changed, 1618 insertions, 435 deletions
diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp index f0ad4a8967396..c65dd9d460f4a 100644 --- a/source/Commands/CommandCompletions.cpp +++ b/source/Commands/CommandCompletions.cpp @@ -112,7 +112,7 @@ CommandCompletions::SourceFiles      if (searcher == NULL)      {          lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); -        SearchFilter null_searcher (target_sp); +        SearchFilterForUnconstrainedSearches null_searcher (target_sp);          completer.DoCompletion (&null_searcher);      }      else @@ -375,7 +375,7 @@ CommandCompletions::Modules      if (searcher == NULL)      {          lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); -        SearchFilter null_searcher (target_sp); +        SearchFilterForUnconstrainedSearches null_searcher (target_sp);          completer.DoCompletion (&null_searcher);      }      else @@ -406,7 +406,7 @@ CommandCompletions::Symbols      if (searcher == NULL)      {          lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); -        SearchFilter null_searcher (target_sp); +        SearchFilterForUnconstrainedSearches null_searcher (target_sp);          completer.DoCompletion (&null_searcher);      }      else diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp index 13bf1278c78cd..3d4b3aff6fffd 100644 --- a/source/Commands/CommandObjectBreakpoint.cpp +++ b/source/Commands/CommandObjectBreakpoint.cpp @@ -20,6 +20,8 @@  #include "lldb/Breakpoint/BreakpointIDList.h"  #include "lldb/Breakpoint/BreakpointLocation.h"  #include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Interpreter/OptionValueUInt64.h"  #include "lldb/Core/RegularExpression.h"  #include "lldb/Core/StreamString.h"  #include "lldb/Interpreter/CommandInterpreter.h" @@ -145,6 +147,10 @@ public:                      m_condition.assign(option_arg);                      break; +                case 'D': +                    m_use_dummy = true; +                    break; +                  case 'E':                  {                      LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg); @@ -236,6 +242,11 @@ public:                      m_func_name_type_mask |= eFunctionNameTypeAuto;                      break; +                case 'N': +                    if (BreakpointID::StringIsBreakpointName(option_arg, error)) +                        m_breakpoint_names.push_back (option_arg); +                    break; +                  case 'o':                      m_one_shot = true;                      break; @@ -324,6 +335,8 @@ public:              m_language = eLanguageTypeUnknown;              m_skip_prologue = eLazyBoolCalculate;              m_one_shot = false; +            m_use_dummy = false; +            m_breakpoint_names.clear();          }          const OptionDefinition* @@ -343,6 +356,7 @@ public:          uint32_t m_line_num;          uint32_t m_column;          std::vector<std::string> m_func_names; +        std::vector<std::string> m_breakpoint_names;          uint32_t m_func_name_type_mask;          std::string m_func_regexp;          std::string m_source_text_regexp; @@ -359,16 +373,18 @@ public:          lldb::LanguageType m_language;          LazyBool m_skip_prologue;          bool m_one_shot; +        bool m_use_dummy;      };  protected:      virtual bool      DoExecute (Args& command, -             CommandReturnObject &result) +              CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); -        if (target == NULL) +        Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + +        if (target == nullptr)          {              result.AppendError ("Invalid target.  Must set target before setting breakpoints (see 'target create' command).");              result.SetStatus (eReturnStatusFailed); @@ -551,6 +567,13 @@ protected:              if (!m_options.m_condition.empty())                  bp->GetOptions()->SetCondition(m_options.m_condition.c_str()); + +            if (!m_options.m_breakpoint_names.empty()) +            { +                Error error;  // We don't need to check the error here, since the option parser checked it... +                for (auto name : m_options.m_breakpoint_names) +                    bp->AddName(name.c_str(), error); +            }              bp->SetOneShot (m_options.m_one_shot);          } @@ -560,10 +583,17 @@ protected:              Stream &output_stream = result.GetOutputStream();              const bool show_locations = false;              bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations); -            // Don't print out this warning for exception breakpoints.  They can get set before the target -            // is set, but we won't know how to actually set the breakpoint till we run. -            if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) -                output_stream.Printf ("WARNING:  Unable to resolve breakpoint to any actual locations.\n"); +            if (target == m_interpreter.GetDebugger().GetDummyTarget()) +                    output_stream.Printf ("Breakpoint set in dummy target, will get copied into future targets.\n"); +            else +            { +                // Don't print out this warning for exception breakpoints.  They can get set before the target +                // is set, but we won't know how to actually set the breakpoint till we run. +                if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) +                { +                    output_stream.Printf ("WARNING:  Unable to resolve breakpoint to any actual locations.\n"); +                } +            }              result.SetStatus (eReturnStatusSuccessFinishResult);          }          else if (!bp) @@ -709,6 +739,12 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =      { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,          "sKip the prologue if the breakpoint is at the beginning of a function.  If not set the target.skip-prologue setting is used." }, +    { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, +        "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + +    { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointName, +        "Adds this to the list of names for this breakopint."}, +      { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }  }; @@ -766,7 +802,8 @@ public:              m_name_passed (false),              m_queue_passed (false),              m_condition_passed (false), -            m_one_shot_passed (false) +            m_one_shot_passed (false), +            m_use_dummy (false)          {          } @@ -792,6 +829,9 @@ public:                      m_enable_passed = true;                      m_enable_value = false;                      break; +                case 'D': +                    m_use_dummy = true; +                    break;                  case 'e':                      m_enable_passed = true;                      m_enable_value = true; @@ -888,6 +928,7 @@ public:              m_name_passed = false;              m_condition_passed = false;              m_one_shot_passed = false; +            m_use_dummy = false;          }          const OptionDefinition* @@ -918,6 +959,7 @@ public:          bool m_queue_passed;          bool m_condition_passed;          bool m_one_shot_passed; +        bool m_use_dummy;      }; @@ -925,7 +967,7 @@ protected:      virtual bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);          if (target == NULL)          {              result.AppendError ("Invalid target.  No existing target or breakpoints."); @@ -938,7 +980,7 @@ protected:          BreakpointIDList valid_bp_ids; -        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); +        CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);          if (result.Succeeded())          { @@ -1024,6 +1066,8 @@ CommandObjectBreakpointModify::CommandOptions::g_option_table[] =  { LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},  { LLDB_OPT_SET_1,   false, "enable",       'e', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone, "Enable the breakpoint."},  { LLDB_OPT_SET_2,   false, "disable",      'd', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone, "Disable the breakpoint."}, +{ LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, +  { 0,                false, NULL,            0 , 0,                 NULL, NULL, 0, eArgTypeNone, NULL }  }; @@ -1055,7 +1099,7 @@ protected:      virtual bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget();          if (target == NULL)          {              result.AppendError ("Invalid target.  No existing target or breakpoints."); @@ -1088,7 +1132,7 @@ protected:          {              // Particular breakpoint selected; enable that breakpoint.              BreakpointIDList valid_bp_ids; -            CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); +            CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);              if (result.Succeeded())              { @@ -1175,7 +1219,7 @@ protected:      virtual bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget();          if (target == NULL)          {              result.AppendError ("Invalid target.  No existing target or breakpoints."); @@ -1208,7 +1252,7 @@ protected:              // Particular breakpoint selected; disable that breakpoint.              BreakpointIDList valid_bp_ids; -            CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); +            CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);              if (result.Succeeded())              { @@ -1293,7 +1337,8 @@ public:          CommandOptions (CommandInterpreter &interpreter) :              Options (interpreter), -            m_level (lldb::eDescriptionLevelBrief)  // Breakpoint List defaults to brief descriptions +            m_level (lldb::eDescriptionLevelBrief), +            m_use_dummy(false)          {          } @@ -1311,6 +1356,9 @@ public:                  case 'b':                      m_level = lldb::eDescriptionLevelBrief;                      break; +                case 'D': +                    m_use_dummy = true; +                    break;                  case 'f':                      m_level = lldb::eDescriptionLevelFull;                      break; @@ -1333,6 +1381,7 @@ public:          {              m_level = lldb::eDescriptionLevelFull;              m_internal = false; +            m_use_dummy = false;          }          const OptionDefinition * @@ -1350,13 +1399,15 @@ public:          lldb::DescriptionLevel m_level;          bool m_internal; +        bool m_use_dummy;      };  protected:      virtual bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); +          if (target == NULL)          {              result.AppendError ("Invalid target. No current target or breakpoints."); @@ -1394,7 +1445,7 @@ protected:          {              // Particular breakpoints selected; show info about that breakpoint.              BreakpointIDList valid_bp_ids; -            CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); +            CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);              if (result.Succeeded())              { @@ -1438,6 +1489,9 @@ CommandObjectBreakpointList::CommandOptions::g_option_table[] =      { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,          "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, +    { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, +        "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, +      { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }  }; @@ -1540,7 +1594,7 @@ protected:      virtual bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget();          if (target == NULL)          {              result.AppendError ("Invalid target. No existing target or breakpoints."); @@ -1656,7 +1710,8 @@ public:          CommandObjectParsed (interpreter,                               "breakpoint delete",                               "Delete the specified breakpoint(s).  If no breakpoints are specified, delete them all.", -                             NULL) +                             NULL), +        m_options (interpreter)      {          CommandArgumentEntry arg;          CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange); @@ -1667,11 +1722,78 @@ public:      virtual      ~CommandObjectBreakpointDelete () {} +    virtual Options * +    GetOptions () +    { +        return &m_options; +    } + +    class CommandOptions : public Options +    { +    public: + +        CommandOptions (CommandInterpreter &interpreter) : +            Options (interpreter), +            m_use_dummy (false), +            m_force (false) +        { +        } + +        virtual +        ~CommandOptions () {} + +        virtual Error +        SetOptionValue (uint32_t option_idx, const char *option_arg) +        { +            Error error; +            const int short_option = m_getopt_table[option_idx].val; + +            switch (short_option) +            { +                case 'f': +                    m_force = true; +                    break; + +                case 'D': +                    m_use_dummy = true; +                    break; + +                default: +                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); +                    break; +            } + +            return error; +        } + +        void +        OptionParsingStarting () +        { +            m_use_dummy = false; +            m_force = false; +        } + +        const OptionDefinition* +        GetDefinitions () +        { +            return g_option_table; +        } + +        // Options table: Required for subclasses of Options. + +        static OptionDefinition g_option_table[]; + +        // Instance variables to hold the values for command options. +        bool m_use_dummy; +        bool m_force; +    }; +  protected:      virtual bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); +          if (target == NULL)          {              result.AppendError ("Invalid target. No existing target or breakpoints."); @@ -1695,7 +1817,7 @@ protected:          if (command.GetArgumentCount() == 0)          { -            if (!m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true)) +            if (!m_options.m_force && !m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true))              {                  result.AppendMessage("Operation cancelled...");              } @@ -1710,7 +1832,7 @@ protected:          {              // Particular breakpoint selected; disable that breakpoint.              BreakpointIDList valid_bp_ids; -            CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); +            CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);              if (result.Succeeded())              { @@ -1748,7 +1870,416 @@ protected:          }          return result.Succeeded();      } +private: +    CommandOptions m_options; +}; + +OptionDefinition +CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = +{ +    { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, +        "Delete all breakpoints without querying for confirmation."}, + +    { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, +        "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + +    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +}; + +//------------------------------------------------------------------------- +// CommandObjectBreakpointName +//------------------------------------------------------------------------- + +static OptionDefinition +g_breakpoint_name_options[] = +{ +    { LLDB_OPT_SET_1,   false, "name", 'N', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, +    { LLDB_OPT_SET_2,   false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointID,   "Specify a breakpoint id to use."}, +    { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, +        "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},  }; +class BreakpointNameOptionGroup : public OptionGroup +{ +public: +    BreakpointNameOptionGroup() : +        OptionGroup(), +        m_breakpoint(LLDB_INVALID_BREAK_ID), +        m_use_dummy (false) +    { + +    } + +    virtual +    ~BreakpointNameOptionGroup () +    { +    } +     +    virtual uint32_t +    GetNumDefinitions () +    { +      return sizeof (g_breakpoint_name_options) / sizeof (OptionDefinition); +    } + +    virtual const OptionDefinition* +    GetDefinitions () +    { +        return g_breakpoint_name_options; +    } + +    virtual Error +    SetOptionValue (CommandInterpreter &interpreter, +                    uint32_t option_idx, +                    const char *option_value) +    { +        Error error; +        const int short_option = g_breakpoint_name_options[option_idx].short_option; +       +        switch (short_option) +        { +        case 'N': +            if (BreakpointID::StringIsBreakpointName(option_value, error) && error.Success()) +                m_name.SetValueFromCString(option_value); +            break; +           +        case 'B': +            if (m_breakpoint.SetValueFromCString(option_value).Fail()) +                error.SetErrorStringWithFormat ("unrecognized value \"%s\" for breakpoint", option_value); +            break; +        case 'D': +            if (m_use_dummy.SetValueFromCString(option_value).Fail()) +                error.SetErrorStringWithFormat ("unrecognized value \"%s\" for use-dummy", option_value); +            break; + +        default: +              error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); +              break; +        } +        return error; +    } + +    virtual void +    OptionParsingStarting (CommandInterpreter &interpreter) +    { +        m_name.Clear(); +        m_breakpoint.Clear(); +        m_use_dummy.Clear(); +        m_use_dummy.SetDefaultValue(false); +    } + +    OptionValueString m_name; +    OptionValueUInt64 m_breakpoint; +    OptionValueBoolean m_use_dummy; +}; + + +class CommandObjectBreakpointNameAdd : public CommandObjectParsed +{ +public: +    CommandObjectBreakpointNameAdd (CommandInterpreter &interpreter) : +        CommandObjectParsed (interpreter, +                             "add", +                             "Add a name to the breakpoints provided.", +                             "breakpoint name add <command-options> <breakpoint-id-list>"), +        m_name_options(), +        m_option_group(interpreter) +        { +            // Create the first variant for the first (and only) argument for this command. +            CommandArgumentEntry arg1; +            CommandArgumentData id_arg; +            id_arg.arg_type = eArgTypeBreakpointID; +            id_arg.arg_repetition = eArgRepeatOptional; +            arg1.push_back(id_arg); +            m_arguments.push_back (arg1); + +            m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); +            m_option_group.Finalize(); +        } + +    virtual +    ~CommandObjectBreakpointNameAdd () {} + +  Options * +  GetOptions () +  { +    return &m_option_group; +  } +   +protected: +    virtual bool +    DoExecute (Args& command, CommandReturnObject &result) +    { +        if (!m_name_options.m_name.OptionWasSet()) +        { +            result.SetError("No name option provided."); +            return false; +        } + +        Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); + +        if (target == NULL) +        { +            result.AppendError ("Invalid target. No existing target or breakpoints."); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } + +        Mutex::Locker locker; +        target->GetBreakpointList().GetListMutex(locker); +         +        const BreakpointList &breakpoints = target->GetBreakpointList(); + +        size_t num_breakpoints = breakpoints.GetSize(); +        if (num_breakpoints == 0) +        { +            result.SetError("No breakpoints, cannot add names."); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } + +        // Particular breakpoint selected; disable that breakpoint. +        BreakpointIDList valid_bp_ids; +        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + +        if (result.Succeeded()) +        { +            if (valid_bp_ids.GetSize() == 0) +            { +                result.SetError("No breakpoints specified, cannot add names."); +                result.SetStatus (eReturnStatusFailed); +                return false; +            } +            size_t num_valid_ids = valid_bp_ids.GetSize(); +            for (size_t index = 0; index < num_valid_ids; index++) +            { +                lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); +                BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); +                Error error;  // We don't need to check the error here, since the option parser checked it... +                bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error); +            } +        } + +        return true; +    } + +private: +    BreakpointNameOptionGroup m_name_options; +    OptionGroupOptions m_option_group; +}; + + + +class CommandObjectBreakpointNameDelete : public CommandObjectParsed +{ +public: +    CommandObjectBreakpointNameDelete (CommandInterpreter &interpreter) : +        CommandObjectParsed (interpreter, +                             "delete", +                             "Delete a name from the breakpoints provided.", +                             "breakpoint name delete <command-options> <breakpoint-id-list>"), +        m_name_options(), +        m_option_group(interpreter) +    { +        // Create the first variant for the first (and only) argument for this command. +        CommandArgumentEntry arg1; +        CommandArgumentData id_arg; +        id_arg.arg_type = eArgTypeBreakpointID; +        id_arg.arg_repetition = eArgRepeatOptional; +        arg1.push_back(id_arg); +        m_arguments.push_back (arg1); + +        m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); +        m_option_group.Finalize(); +    } + +    virtual +    ~CommandObjectBreakpointNameDelete () {} + +  Options * +  GetOptions () +  { +    return &m_option_group; +  } +   +protected: +    virtual bool +    DoExecute (Args& command, CommandReturnObject &result) +    { +        if (!m_name_options.m_name.OptionWasSet()) +        { +            result.SetError("No name option provided."); +            return false; +        } + +        Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); + +        if (target == NULL) +        { +            result.AppendError ("Invalid target. No existing target or breakpoints."); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } + +        Mutex::Locker locker; +        target->GetBreakpointList().GetListMutex(locker); +         +        const BreakpointList &breakpoints = target->GetBreakpointList(); + +        size_t num_breakpoints = breakpoints.GetSize(); +        if (num_breakpoints == 0) +        { +            result.SetError("No breakpoints, cannot delete names."); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } + +        // Particular breakpoint selected; disable that breakpoint. +        BreakpointIDList valid_bp_ids; +        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + +        if (result.Succeeded()) +        { +            if (valid_bp_ids.GetSize() == 0) +            { +                result.SetError("No breakpoints specified, cannot delete names."); +                result.SetStatus (eReturnStatusFailed); +                return false; +            } +            size_t num_valid_ids = valid_bp_ids.GetSize(); +            for (size_t index = 0; index < num_valid_ids; index++) +            { +                lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); +                BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); +                bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue()); +            } +        } + +        return true; +    } + +private: +    BreakpointNameOptionGroup m_name_options; +    OptionGroupOptions m_option_group; +}; + +class CommandObjectBreakpointNameList : public CommandObjectParsed +{ +public: +    CommandObjectBreakpointNameList (CommandInterpreter &interpreter) : +        CommandObjectParsed (interpreter, +                             "list", +                             "List either the names for a breakpoint or the breakpoints for a given name.", +                             "breakpoint name list <command-options>"), +        m_name_options(), +        m_option_group(interpreter) +    { +        m_option_group.Append (&m_name_options); +        m_option_group.Finalize(); +    } + +    virtual +    ~CommandObjectBreakpointNameList () {} + +  Options * +  GetOptions () +  { +    return &m_option_group; +  } +   +protected: +protected: +    virtual bool +    DoExecute (Args& command, CommandReturnObject &result) +    { +        Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); + +        if (target == NULL) +        { +            result.AppendError ("Invalid target. No existing target or breakpoints."); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } + +        if (m_name_options.m_name.OptionWasSet()) +        { +            const char *name = m_name_options.m_name.GetCurrentValue(); +            Mutex::Locker locker; +            target->GetBreakpointList().GetListMutex(locker); +             +            BreakpointList &breakpoints = target->GetBreakpointList(); +            for (BreakpointSP bp_sp : breakpoints.Breakpoints()) +            { +                if (bp_sp->MatchesName(name)) +                { +                    StreamString s; +                    bp_sp->GetDescription(&s, eDescriptionLevelBrief); +                    s.EOL(); +                    result.AppendMessage(s.GetData()); +                } +            } + +        } +        else if (m_name_options.m_breakpoint.OptionWasSet()) +        { +            BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(m_name_options.m_breakpoint.GetCurrentValue()); +            if (bp_sp) +            { +                std::vector<std::string> names; +                bp_sp->GetNames (names); +                result.AppendMessage ("Names:"); +                for (auto name : names) +                    result.AppendMessageWithFormat ("    %s\n", name.c_str()); +            } +            else +            { +                result.AppendErrorWithFormat ("Could not find breakpoint %" PRId64 ".\n", +                                           m_name_options.m_breakpoint.GetCurrentValue()); +                result.SetStatus (eReturnStatusFailed); +                return false; +            } +        } +        else +        { +            result.SetError ("Must specify -N or -B option to list."); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } +        return true; +    } + +private: +    BreakpointNameOptionGroup m_name_options; +    OptionGroupOptions m_option_group; +}; + +//------------------------------------------------------------------------- +// CommandObjectMultiwordBreakpoint +//------------------------------------------------------------------------- +class CommandObjectBreakpointName : public CommandObjectMultiword +{ +public: +    CommandObjectBreakpointName (CommandInterpreter &interpreter) : +        CommandObjectMultiword(interpreter, +                                "name", +                                "A set of commands to manage name tags for breakpoints", +                                "breakpoint name <command> [<command-options>]") +    { +        CommandObjectSP add_command_object (new CommandObjectBreakpointNameAdd (interpreter)); +        CommandObjectSP delete_command_object (new CommandObjectBreakpointNameDelete (interpreter)); +        CommandObjectSP list_command_object (new CommandObjectBreakpointNameList (interpreter)); + +        LoadSubCommand ("add", add_command_object); +        LoadSubCommand ("delete", delete_command_object); +        LoadSubCommand ("list", list_command_object); + +    } + +    virtual +    ~CommandObjectBreakpointName () +    { +    } + +}; +  //-------------------------------------------------------------------------  // CommandObjectMultiwordBreakpoint @@ -1769,6 +2300,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter      CommandObjectSP set_command_object (new CommandObjectBreakpointSet (interpreter));      CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter));      CommandObjectSP modify_command_object (new CommandObjectBreakpointModify(interpreter)); +    CommandObjectSP name_command_object (new CommandObjectBreakpointName(interpreter));      list_command_object->SetCommandName ("breakpoint list");      enable_command_object->SetCommandName("breakpoint enable"); @@ -1778,6 +2310,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter      set_command_object->SetCommandName("breakpoint set");      command_command_object->SetCommandName ("breakpoint command");      modify_command_object->SetCommandName ("breakpoint modify"); +    name_command_object->SetCommandName ("breakpoint name");      LoadSubCommand ("list",       list_command_object);      LoadSubCommand ("enable",     enable_command_object); @@ -1787,6 +2320,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter      LoadSubCommand ("set",        set_command_object);      LoadSubCommand ("command",    command_command_object);      LoadSubCommand ("modify",     modify_command_object); +    LoadSubCommand ("name",       name_command_object);  }  CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint () @@ -1794,13 +2328,17 @@ CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()  }  void -CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, -                                                         BreakpointIDList *valid_ids) +CommandObjectMultiwordBreakpoint::VerifyIDs (Args &args, +                                             Target *target, +                                             bool allow_locations, +                                             CommandReturnObject &result, +                                             BreakpointIDList *valid_ids)  {      // args can be strings representing 1). integers (for breakpoint ids)      //                                  2). the full breakpoint & location canonical representation      //                                  3). the word "to" or a hyphen, representing a range (in which case there      //                                      had *better* be an entry both before & after of one of the first two types. +    //                                  4). A breakpoint name      // If args is empty, we will use the last created breakpoint (if there is one.)      Args temp_args; @@ -1824,7 +2362,7 @@ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *targe      // the new TEMP_ARGS.  Do not copy breakpoint id range strings over; instead generate a list of strings for      // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS. -    BreakpointIDList::FindAndReplaceIDRanges (args, target, result, temp_args); +    BreakpointIDList::FindAndReplaceIDRanges (args, target, allow_locations, result, temp_args);      // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList: diff --git a/source/Commands/CommandObjectBreakpoint.h b/source/Commands/CommandObjectBreakpoint.h index 2d674b22d7046..3fdd2a5f56bed 100644 --- a/source/Commands/CommandObjectBreakpoint.h +++ b/source/Commands/CommandObjectBreakpoint.h @@ -38,8 +38,20 @@ public:      ~CommandObjectMultiwordBreakpoint ();      static void -    VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids); +    VerifyBreakpointOrLocationIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids) +    { +        VerifyIDs (args, target, true, result, valid_ids); +    } +    static void +    VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids) +    { +        VerifyIDs (args, target, false, result, valid_ids); +    } + +private: +    static void +    VerifyIDs (Args &args, Target *target, bool allow_locations, CommandReturnObject &result, BreakpointIDList *valid_ids);  };  } // namespace lldb_private diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp index fdb87d11900b7..8f8404b712a52 100644 --- a/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/source/Commands/CommandObjectBreakpointCommand.cpp @@ -307,17 +307,16 @@ one command per line.\n" );                  result.SetImmediateOutputStream (output_stream);                  result.SetImmediateErrorStream (error_stream); -                bool stop_on_continue = true; -                bool echo_commands    = false; -                bool print_results    = true; - -                debugger.GetCommandInterpreter().HandleCommands (commands,  +                CommandInterpreterRunOptions options; +                options.SetStopOnContinue(true); +                options.SetStopOnError (data->stop_on_error); +                options.SetEchoCommands (true); +                options.SetPrintResults (true); +                options.SetAddToHistory (false); + +                debugger.GetCommandInterpreter().HandleCommands (commands,                                                                   &exe_ctx, -                                                                 stop_on_continue,  -                                                                 data->stop_on_error,  -                                                                 echo_commands,  -                                                                 print_results, -                                                                 eLazyBoolNo, +                                                                 options,                                                                   result);                  result.GetImmediateOutputStream()->Flush();                  result.GetImmediateErrorStream()->Flush(); @@ -390,6 +389,10 @@ one command per line.\n" );                  }                  break; +            case 'D': +                m_use_dummy = true; +                break; +              default:                  break;              } @@ -406,6 +409,7 @@ one command per line.\n" );              m_stop_on_error = true;              m_one_liner.clear();              m_function_name.clear(); +            m_use_dummy = false;          }          const OptionDefinition* @@ -429,13 +433,14 @@ one command per line.\n" );          std::string m_one_liner;          bool m_stop_on_error;          std::string m_function_name; +        bool m_use_dummy;      };  protected:      virtual bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);          if (target == NULL)          { @@ -462,7 +467,7 @@ protected:          }          BreakpointIDList valid_bp_ids; -        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); +        CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);          m_bp_options_vec.clear(); @@ -581,6 +586,9 @@ CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =      { LLDB_OPT_SET_2,   false, "python-function",     'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,          "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."}, +    { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, +        "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, +      { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }  }; @@ -595,7 +603,8 @@ public:          CommandObjectParsed (interpreter,                                "delete",                               "Delete the set of commands from a breakpoint.", -                             NULL) +                             NULL), +        m_options (interpreter)      {          CommandArgumentEntry arg;          CommandArgumentData bp_id_arg; @@ -615,11 +624,70 @@ public:      virtual      ~CommandObjectBreakpointCommandDelete () {} +    virtual Options * +    GetOptions () +    { +        return &m_options; +    } + +    class CommandOptions : public Options +    { +    public: + +        CommandOptions (CommandInterpreter &interpreter) : +            Options (interpreter), +            m_use_dummy (false) +        { +        } + +        virtual +        ~CommandOptions () {} + +        virtual Error +        SetOptionValue (uint32_t option_idx, const char *option_arg) +        { +            Error error; +            const int short_option = m_getopt_table[option_idx].val; + +            switch (short_option) +            { +                case 'D': +                    m_use_dummy = true; +                    break; + +                default: +                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); +                    break; +            } + +            return error; +        } + +        void +        OptionParsingStarting () +        { +            m_use_dummy = false; +        } + +        const OptionDefinition* +        GetDefinitions () +        { +            return g_option_table; +        } + +        // Options table: Required for subclasses of Options. + +        static OptionDefinition g_option_table[]; + +        // Instance variables to hold the values for command options. +        bool m_use_dummy; +    }; +  protected:      virtual bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);          if (target == NULL)          { @@ -646,7 +714,7 @@ protected:          }          BreakpointIDList valid_bp_ids; -        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); +        CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);          if (result.Succeeded())          { @@ -680,8 +748,20 @@ protected:          }          return result.Succeeded();      } +private: +    CommandOptions m_options; +}; + +OptionDefinition +CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] = +{ +    { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, +        "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + +    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }  }; +  //-------------------------------------------------------------------------  // CommandObjectBreakpointCommandList  //------------------------------------------------------------------------- @@ -744,7 +824,7 @@ protected:          }          BreakpointIDList valid_bp_ids; -        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); +        CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);          if (result.Succeeded())          { diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp index 7d9bb7dad8fdd..f98eac055f242 100644 --- a/source/Commands/CommandObjectCommands.cpp +++ b/source/Commands/CommandObjectCommands.cpp @@ -366,7 +366,7 @@ protected:          // Instance variables to hold the values for command options.          OptionValueBoolean m_stop_on_error; -	    OptionValueBoolean m_silent_run; +        OptionValueBoolean m_silent_run;          OptionValueBoolean m_stop_on_continue;      }; @@ -387,14 +387,15 @@ protected:                  m_options.m_stop_on_continue.OptionWasSet())              {                  // Use user set settings -                LazyBool print_command = m_options.m_silent_run.GetCurrentValue() ? eLazyBoolNo : eLazyBoolYes; +                CommandInterpreterRunOptions options; +                options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue()); +                options.SetStopOnError (m_options.m_stop_on_error.GetCurrentValue()); +                options.SetEchoCommands (!m_options.m_silent_run.GetCurrentValue()); +                options.SetPrintResults (!m_options.m_silent_run.GetCurrentValue()); +                  m_interpreter.HandleCommandsFromFile (cmd_file,                                                        exe_ctx, -                                                      m_options.m_stop_on_continue.GetCurrentValue() ? eLazyBoolYes : eLazyBoolNo, // Stop on continue -                                                      m_options.m_stop_on_error.GetCurrentValue() ? eLazyBoolYes : eLazyBoolNo, // Stop on error -                                                      print_command,        // Echo command -                                                      print_command,        // Print command output -                                                      eLazyBoolCalculate,   // Add to history +                                                      options,                                                        result);              } @@ -402,13 +403,10 @@ protected:              {                  // No options were set, inherit any settings from nested "command source" commands,                  // or set to sane default settings... +                CommandInterpreterRunOptions options;                  m_interpreter.HandleCommandsFromFile (cmd_file,                                                        exe_ctx, -                                                      eLazyBoolCalculate, // Stop on continue -                                                      eLazyBoolCalculate, // Stop on error -                                                      eLazyBoolCalculate, // Echo command -                                                      eLazyBoolCalculate, // Print command output -                                                      eLazyBoolCalculate, // Add to history +                                                      options,                                                        result);              } @@ -830,8 +828,16 @@ protected:              {                  if (m_interpreter.CommandExists (command_name))                  { -                    result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", -                                                  command_name); +                    if (cmd_obj->IsRemovable()) +                    { +                        result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n", +                                                      command_name); +                    } +                    else +                    { +                        result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", +                                                      command_name); +                    }                      result.SetStatus (eReturnStatusFailed);                  }                  else @@ -868,6 +874,77 @@ protected:      }  }; +#pragma mark CommandObjectCommandsDelete +//------------------------------------------------------------------------- +// CommandObjectCommandsDelete +//------------------------------------------------------------------------- + +class CommandObjectCommandsDelete : public CommandObjectParsed +{ +public: +    CommandObjectCommandsDelete (CommandInterpreter &interpreter) : +    CommandObjectParsed (interpreter, +                         "command delete", +                         "Allow the user to delete user-defined regular expression, python or multi-word commands.", +                         NULL) +    { +        CommandArgumentEntry arg; +        CommandArgumentData alias_arg; + +        // Define the first (and only) variant of this arg. +        alias_arg.arg_type = eArgTypeCommandName; +        alias_arg.arg_repetition = eArgRepeatPlain; + +        // There is only one variant this argument could be; put it into the argument entry. +        arg.push_back (alias_arg); + +        // Push the data for the first argument into the m_arguments vector. +        m_arguments.push_back (arg); +    } + +    ~CommandObjectCommandsDelete() +    { +    } + +protected: +    bool +    DoExecute (Args& args, CommandReturnObject &result) +    { +        CommandObject::CommandMap::iterator pos; + +        if (args.GetArgumentCount() != 0) +        { +            const char *command_name = args.GetArgumentAtIndex(0); +            if (m_interpreter.CommandExists (command_name)) +            { +                if (m_interpreter.RemoveCommand (command_name)) +                { +                    result.SetStatus (eReturnStatusSuccessFinishNoResult); +                } +                else +                { +                    result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", +                                                  command_name); +                    result.SetStatus (eReturnStatusFailed); +                } +            } +            else +            { +                result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n", +                                              command_name); +                result.SetStatus (eReturnStatusFailed); +            } +        } +        else +        { +            result.AppendErrorWithFormat ("must call '%s' with one or more valid user defined regular expression, python or multi-word command names", GetCommandName ()); +            result.SetStatus (eReturnStatusFailed); +        } + +        return result.Succeeded(); +    } +}; +  //-------------------------------------------------------------------------  // CommandObjectCommandsAddRegex  //------------------------------------------------------------------------- @@ -875,7 +952,7 @@ protected:  class CommandObjectCommandsAddRegex :      public CommandObjectParsed, -    public IOHandlerDelegate +    public IOHandlerDelegateMultiline  {  public:      CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) : @@ -883,7 +960,7 @@ public:                         "command regex",                         "Allow the user to create a regular expression command.",                         "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), -        IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand), +        IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand),          m_options (interpreter)      {          SetHelpLong( @@ -920,8 +997,8 @@ public:  protected: -    virtual void -    IOHandlerActivated (IOHandler &io_handler) +    void +    IOHandlerActivated (IOHandler &io_handler) override      {          StreamFileSP output_sp(io_handler.GetOutputStreamFile());          if (output_sp) @@ -931,8 +1008,8 @@ protected:          }      } -    virtual void -    IOHandlerInputComplete (IOHandler &io_handler, std::string &data) +    void +    IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override      {          io_handler.SetIsDone(true);          if (m_regex_cmd_ap.get()) @@ -944,7 +1021,6 @@ protected:                  bool check_only = false;                  for (size_t i=0; i<num_lines; ++i)                  { -                    printf ("regex[%zu] = %s\n", i, lines[i].c_str());                      llvm::StringRef bytes_strref (lines[i]);                      Error error = AppendRegexSubstitution (bytes_strref, check_only);                      if (error.Fail()) @@ -964,54 +1040,9 @@ protected:              }          }      } -     -    virtual LineStatus -    IOHandlerLinesUpdated (IOHandler &io_handler, -                           StringList &lines, -                           uint32_t line_idx, -                           Error &error) -    { -        if (line_idx == UINT32_MAX) -        { -            // Return true to indicate we are done getting lines (this -            // is a "fake" line - the real terminating blank line was -            // removed during a previous call with the code below) -            error.Clear(); -            return LineStatus::Done; -        } -        else -        { -            const size_t num_lines = lines.GetSize(); -            if (line_idx + 1 == num_lines) -            { -                // The last line was edited, if this line is empty, then we are done -                // getting our multiple lines. -                if (lines[line_idx].empty()) -                { -                    // Remove the last empty line from "lines" so it doesn't appear -                    // in our final expression and return true to indicate we are done -                    // getting lines -                    lines.PopBack(); -                    return LineStatus::Done; -                } -            } -            // Check the current line to make sure it is formatted correctly -            bool check_only = true; -            llvm::StringRef regex_sed(lines[line_idx]); -            error = AppendRegexSubstitution (regex_sed, check_only); -            if (error.Fail()) -            { -                return LineStatus::Error; -            } -            else -            { -                return LineStatus::Success; -            } -        } -    }      bool -    DoExecute (Args& command, CommandReturnObject &result) +    DoExecute (Args& command, CommandReturnObject &result) override      {          const size_t argc = command.GetArgumentCount();          if (argc == 0) @@ -1027,16 +1058,22 @@ protected:                                                                   name,                                                                    m_options.GetHelp (),                                                                   m_options.GetSyntax (), -                                                                 10)); +                                                                 10, +                                                                 0, +                                                                 true));              if (argc == 1)              {                  Debugger &debugger = m_interpreter.GetDebugger(); +                bool color_prompt = debugger.GetUseColor();                  const bool multiple_lines = true; // Get multiple lines                  IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, +                                                                  IOHandler::Type::Other,                                                                    "lldb-regex", // Name of input reader for history -                                                                  "\033[K> ",   // Prompt and clear line +                                                                  "> ",         // Prompt +                                                                  NULL,         // Continuation prompt                                                                    multiple_lines, +                                                                  color_prompt,                                                                    0,            // Don't show line numbers                                                                    *this)); @@ -1110,21 +1147,25 @@ protected:          if (second_separator_char_pos == std::string::npos)          { -            error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",  +            error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'",                                             separator_char,                                              (int)(regex_sed.size() - first_separator_char_pos - 1), -                                           regex_sed.data() + (first_separator_char_pos + 1)); -            return error;             +                                           regex_sed.data() + (first_separator_char_pos + 1), +                                           (int)regex_sed.size(), +                                           regex_sed.data()); +            return error;          }          const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);          if (third_separator_char_pos == std::string::npos)          { -            error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",  +            error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'",                                             separator_char,                                              (int)(regex_sed.size() - second_separator_char_pos - 1), -                                           regex_sed.data() + (second_separator_char_pos + 1)); +                                           regex_sed.data() + (second_separator_char_pos + 1), +                                           (int)regex_sed.size(), +                                           regex_sed.data());              return error;                      } @@ -1262,8 +1303,8 @@ private:           std::string m_syntax;       }; -     virtual Options * -     GetOptions () +     Options * +     GetOptions () override       {           return &m_options;       } @@ -1292,15 +1333,24 @@ public:      CommandObjectPythonFunction (CommandInterpreter &interpreter,                                   std::string name,                                   std::string funct, +                                 std::string help,                                   ScriptedCommandSynchronicity synch) :          CommandObjectRaw (interpreter,                            name.c_str(), -                          (std::string("Run Python function ") + funct).c_str(), +                          NULL,                            NULL),          m_function_name(funct),          m_synchro(synch),          m_fetched_help_long(false)      { +        if (!help.empty()) +            SetHelp(help.c_str()); +        else +        { +            StreamString stream; +            stream.Printf("For more information run 'help %s'",name.c_str()); +            SetHelp(stream.GetData()); +        }      }      virtual @@ -1357,7 +1407,8 @@ protected:                                                           raw_command_line,                                                           m_synchro,                                                           result, -                                                         error) == false) +                                                         error, +                                                         m_exe_ctx) == false)          {              result.AppendError(error.AsCString());              result.SetStatus(eReturnStatusFailed); @@ -1617,7 +1668,12 @@ protected:              switch (short_option)              {                  case 'f': -                    m_funct_name = std::string(option_arg); +                    if (option_arg) +                        m_funct_name.assign(option_arg); +                    break; +                case 'h': +                    if (option_arg) +                        m_short_help.assign(option_arg);                      break;                  case 's':                      m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); @@ -1635,7 +1691,8 @@ protected:          void          OptionParsingStarting ()          { -            m_funct_name = ""; +            m_funct_name.clear(); +            m_short_help.clear();              m_synchronicity = eScriptedCommandSynchronicitySynchronous;          } @@ -1652,6 +1709,7 @@ protected:          // Instance variables to hold the values for command options.          std::string m_funct_name; +        std::string m_short_help;          ScriptedCommandSynchronicity m_synchronicity;      }; @@ -1695,6 +1753,7 @@ protected:                          CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter,                                                                                          m_cmd_name,                                                                                          funct_name_str.c_str(), +                                                                                        m_short_help,                                                                                          m_synchronicity));                          if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true)) @@ -1748,8 +1807,9 @@ protected:              return false;          } -        // Store the command name and synchronicity in case we get multi-line input +        // Store the options in case we get multi-line input          m_cmd_name = command.GetArgumentAtIndex(0); +        m_short_help.assign(m_options.m_short_help);          m_synchronicity = m_options.m_synchronicity;          if (m_options.m_funct_name.empty()) @@ -1764,6 +1824,7 @@ protected:              CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,                                                                      m_cmd_name,                                                                      m_options.m_funct_name, +                                                                    m_options.m_short_help,                                                                      m_synchronicity));              if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))              { @@ -1782,6 +1843,7 @@ protected:      CommandOptions m_options;      std::string m_cmd_name; +    std::string m_short_help;      ScriptedCommandSynchronicity m_synchronicity;  }; @@ -1797,6 +1859,7 @@ OptionDefinition  CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =  {      { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,        "Name of the Python function to bind to this command name."}, +    { LLDB_OPT_SET_1, false, "help"  , 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeHelpText, "The help text to display for this command."},      { LLDB_OPT_SET_1, false, "synchronicity", 's', OptionParser::eRequiredArgument, NULL, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity,        "Set the synchronicity of this command's executions with regard to LLDB event system."},      { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }  }; @@ -1949,11 +2012,11 @@ public:                              "A set of commands for managing or customizing script commands.",                              "command script <subcommand> [<subcommand-options>]")      { -        LoadSubCommand ("add",  CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter))); -        LoadSubCommand ("delete",   CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); -        LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter))); +        LoadSubCommand ("add",    CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter))); +        LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); +        LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));          LoadSubCommand ("list",   CommandObjectSP (new CommandObjectCommandsScriptList (interpreter))); -        LoadSubCommand ("import",   CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter))); +        LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));      }      ~CommandObjectMultiwordCommandsScript () @@ -1978,9 +2041,10 @@ CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpret      LoadSubCommand ("source",  CommandObjectSP (new CommandObjectCommandsSource (interpreter)));      LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));      LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter))); +    LoadSubCommand ("delete",  CommandObjectSP (new CommandObjectCommandsDelete (interpreter)));      LoadSubCommand ("regex",   CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter))); -    LoadSubCommand ("history",   CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); -    LoadSubCommand ("script",   CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter))); +    LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); +    LoadSubCommand ("script",  CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));  }  CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands () diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp index 079c62ddfdff9..b4c559c81cc5d 100644 --- a/source/Commands/CommandObjectExpression.cpp +++ b/source/Commands/CommandObjectExpression.cpp @@ -281,7 +281,7 @@ CommandObjectExpression::EvaluateExpression      Target *target = exe_ctx.GetTargetPtr();      if (!target) -        target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get(); +        target = GetDummyTarget();      if (target)      { @@ -425,11 +425,15 @@ CommandObjectExpression::GetMultilineExpression ()      m_expr_line_count = 0;      Debugger &debugger = GetCommandInterpreter().GetDebugger(); +    bool color_prompt = debugger.GetUseColor();      const bool multiple_lines = true; // Get multiple lines      IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, +                                                      IOHandler::Type::Expression,                                                        "lldb-expr",      // Name of input reader for history                                                        NULL,             // No prompt +                                                      NULL,             // Continuation prompt                                                        multiple_lines, +                                                      color_prompt,                                                        1,                // Show line numbers starting at 1                                                        *this)); diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp index bfbb296158a93..6c06ec8318308 100644 --- a/source/Commands/CommandObjectMemory.cpp +++ b/source/Commands/CommandObjectMemory.cpp @@ -33,8 +33,10 @@  #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"  #include "lldb/Interpreter/OptionValueString.h"  #include "lldb/Symbol/TypeList.h" +#include "lldb/Target/MemoryHistory.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/StackFrame.h" +#include "lldb/Target/Thread.h"  using namespace lldb;  using namespace lldb_private; @@ -612,7 +614,16 @@ protected:          }          size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); -        size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); + +        // TODO For non-8-bit byte addressable architectures this needs to be +        // revisited to fully support all lldb's range of formatting options. +        // Furthermore code memory reads (for those architectures) will not +        // be correctly formatted even w/o formatting options. +        size_t item_byte_size = +            target->GetArchitecture().GetDataByteSize() > 1 ? +            target->GetArchitecture().GetDataByteSize() : +            m_format_options.GetByteSizeValue().GetCurrentValue(); +          const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();          if (total_byte_size == 0) @@ -659,7 +670,7 @@ protected:              total_byte_size = end_addr - addr;              item_count = total_byte_size / item_byte_size;          } -         +          uint32_t max_unforced_size = target->GetMaximumMemReadSize();          if (total_byte_size > max_unforced_size && !m_memory_options.m_force) @@ -856,7 +867,8 @@ protected:          result.SetStatus(eReturnStatusSuccessFinishResult);          DataExtractor data (data_sp,                               target->GetArchitecture().GetByteOrder(),  -                            target->GetArchitecture().GetAddressByteSize()); +                            target->GetArchitecture().GetAddressByteSize(), +                            target->GetArchitecture().GetDataByteSize());          Format format = m_format_options.GetFormat();          if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) @@ -890,7 +902,7 @@ protected:                                           format,                                           item_byte_size,                                           item_count, -                                         num_per_line, +                                         num_per_line / target->GetArchitecture().GetDataByteSize(),                                           addr,                                           0,                                           0, @@ -1078,7 +1090,7 @@ protected:        lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);        if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())        { -          result.AppendError("invalid low address"); +          result.AppendError("invalid high address");            return false;        } @@ -1667,6 +1679,96 @@ protected:      OptionGroupWriteMemory m_memory_options;  }; +//---------------------------------------------------------------------- +// Get malloc/free history of a memory address. +//---------------------------------------------------------------------- +class CommandObjectMemoryHistory : public CommandObjectParsed +{ +public: +     +    CommandObjectMemoryHistory (CommandInterpreter &interpreter) : +    CommandObjectParsed (interpreter, +                         "memory history", +                         "Prints out the recorded stack traces for allocation/deallocation of a memory address.", +                         NULL, +                         eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched) +    { +        CommandArgumentEntry arg1; +        CommandArgumentData addr_arg; +         +        // Define the first (and only) variant of this arg. +        addr_arg.arg_type = eArgTypeAddress; +        addr_arg.arg_repetition = eArgRepeatPlain; +         +        // There is only one variant this argument could be; put it into the argument entry. +        arg1.push_back (addr_arg); +         +        // Push the data for the first argument into the m_arguments vector. +        m_arguments.push_back (arg1); +    } +     +    virtual +    ~CommandObjectMemoryHistory () +    { +    } +     +    virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) +    { +        return m_cmd_name.c_str(); +    } +     +protected: +    virtual bool +    DoExecute (Args& command, CommandReturnObject &result) +    { +        const size_t argc = command.GetArgumentCount(); +         +        if (argc == 0 || argc > 1) +        { +            result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str()); +            result.SetStatus(eReturnStatusFailed); +            return false; +        } +         +        Error error; +        lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, +                                                   command.GetArgumentAtIndex(0), +                                                   LLDB_INVALID_ADDRESS, +                                                   &error); +         +        if (addr == LLDB_INVALID_ADDRESS) +        { +            result.AppendError("invalid address expression"); +            result.AppendError(error.AsCString()); +            result.SetStatus(eReturnStatusFailed); +            return false; +        } +         +        Stream *output_stream = &result.GetOutputStream(); +         +        const ProcessSP &process_sp = m_exe_ctx.GetProcessSP(); +        const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp); +         +        if (! memory_history.get()) +        { +            result.AppendError("no available memory history provider"); +            result.SetStatus(eReturnStatusFailed); +            return false; +        } +         +        HistoryThreads thread_list = memory_history->GetHistoryThreads(addr); +         +        for (auto thread : thread_list) { +            thread->GetStatus(*output_stream, 0, UINT32_MAX, 0); +        } +         +        result.SetStatus(eReturnStatusSuccessFinishResult); +         +        return true; +    } +     +}; +  //-------------------------------------------------------------------------  // CommandObjectMemory @@ -1681,6 +1783,7 @@ CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :      LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));      LoadSubCommand ("read",  CommandObjectSP (new CommandObjectMemoryRead (interpreter)));      LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); +    LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));  }  CommandObjectMemory::~CommandObjectMemory () diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp index 9998dbdccdad0..d176d52cb4874 100644 --- a/source/Commands/CommandObjectPlatform.cpp +++ b/source/Commands/CommandObjectPlatform.cpp @@ -302,7 +302,7 @@ protected:          Stream &ostrm = result.GetOutputStream();          ostrm.Printf("Available platforms:\n"); -        PlatformSP host_platform_sp (Platform::GetDefaultPlatform()); +        PlatformSP host_platform_sp (Platform::GetHostPlatform());          ostrm.Printf ("%s: %s\n",                         host_platform_sp->GetPluginName().GetCString(),                        host_platform_sp->GetDescription()); @@ -1347,7 +1347,6 @@ protected:                  ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info,                                                                    debugger,                                                                   target, -                                                                 debugger.GetListener(),                                                                   error));                  if (process_sp && process_sp->IsAlive())                  { @@ -1933,7 +1932,7 @@ public:          {              Error err;              ProcessSP remote_process_sp = -            platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, m_interpreter.GetDebugger().GetListener(), err); +            platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, err);              if (err.Fail())              {                  result.AppendError(err.AsCString()); diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp index 6536c6ef16939..ec7b478fbecc4 100644 --- a/source/Commands/CommandObjectProcess.cpp +++ b/source/Commands/CommandObjectProcess.cpp @@ -258,8 +258,9 @@ protected:              // Save the arguments for subsequent runs in the current target.              target->SetRunArguments (launch_args);          } -         -        Error error = target->Launch(debugger.GetListener(), m_options.launch_info); + +        StreamString stream; +        Error error = target->Launch(m_options.launch_info, &stream);          if (error.Success())          { @@ -267,6 +268,9 @@ protected:              ProcessSP process_sp (target->GetProcessSP());              if (process_sp)              { +                const char *data = stream.GetData(); +                if (data && strlen(data) > 0) +                    result.AppendMessage(stream.GetData());                  result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), exe_module_sp->GetFileSpec().GetPath().c_str(), archname);                  result.SetStatus (eReturnStatusSuccessFinishResult);                  result.SetDidChangeProcessState (true); @@ -564,15 +568,18 @@ protected:                      if (error.Success())                      {                          result.SetStatus (eReturnStatusSuccessContinuingNoResult); -                        StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get()); +                        StreamString stream; +                        StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get(), &stream);                          process->RestoreProcessEvents();                          result.SetDidChangeProcessState (true); +                        if (stream.GetData()) +                            result.AppendMessage(stream.GetData()); +                          if (state == eStateStopped)                          { -                            result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));                              result.SetStatus (eReturnStatusSuccessFinishNoResult);                          }                          else @@ -791,7 +798,12 @@ protected:                  }              } -            Error error(process->Resume()); +            StreamString stream; +            Error error; +            if (synchronous_execution) +                error = process->ResumeSynchronous (&stream); +            else +                error = process->Resume ();              if (error.Success())              { @@ -803,10 +815,11 @@ protected:                  result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());                  if (synchronous_execution)                  { -                    state = process->WaitForProcessToStop (NULL); +                    // If any state changed events had anything to say, add that to the result +                    if (stream.GetData()) +                        result.AppendMessage(stream.GetData());                      result.SetDidChangeProcessState (true); -                    result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));                      result.SetStatus (eReturnStatusSuccessFinishNoResult);                  }                  else diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp index 6b1b6aacc8574..8fb03e69ac420 100644 --- a/source/Commands/CommandObjectSource.cpp +++ b/source/Commands/CommandObjectSource.cpp @@ -421,7 +421,7 @@ protected:              {                  const bool show_inlines = true;                  m_breakpoint_locations.Reset (start_file, 0, show_inlines); -                SearchFilter target_search_filter (m_exe_ctx.GetTargetSP()); +                SearchFilterForUnconstrainedSearches target_search_filter (m_exe_ctx.GetTargetSP());                  target_search_filter.Search (m_breakpoint_locations);              } @@ -682,19 +682,21 @@ protected:                          m_breakpoint_locations.Clear();                          const bool show_inlines = true;                          m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines); -                        SearchFilter target_search_filter (target->shared_from_this()); +                        SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this());                          target_search_filter.Search (m_breakpoint_locations);                      }                      bool show_fullpaths = true;                      bool show_module = true;                      bool show_inlined_frames = true; +                    const bool show_function_arguments = true;                      sc.DumpStopContext(&result.GetOutputStream(),                                         m_exe_ctx.GetBestExecutionContextScope(),                                         sc.line_entry.range.GetBaseAddress(),                                         show_fullpaths,                                         show_module, -                                       show_inlined_frames); +                                       show_inlined_frames, +                                       show_function_arguments);                      result.GetOutputStream().EOL();                      if (m_options.num_lines == 0) @@ -741,7 +743,7 @@ protected:                      {                          const bool show_inlines = true;                          m_breakpoint_locations.Reset (last_file_sp->GetFileSpec(), 0, show_inlines); -                        SearchFilter target_search_filter (target->shared_from_this()); +                        SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this());                          target_search_filter.Search (m_breakpoint_locations);                      }                  } @@ -844,7 +846,7 @@ protected:                      {                          const bool show_inlines = true;                          m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines); -                        SearchFilter target_search_filter (target->shared_from_this()); +                        SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this());                          target_search_filter.Search (m_breakpoint_locations);                      }                      else diff --git a/source/Commands/CommandObjectSyntax.cpp b/source/Commands/CommandObjectSyntax.cpp index d2021ea3eb193..5093c3b99339e 100644 --- a/source/Commands/CommandObjectSyntax.cpp +++ b/source/Commands/CommandObjectSyntax.cpp @@ -69,12 +69,18 @@ CommandObjectSyntax::DoExecute (Args& command, CommandReturnObject &result)          {              std::string sub_command = command.GetArgumentAtIndex (i);              if (!cmd_obj->IsMultiwordObject()) +            {                  all_okay = false; +                break; +            }              else              {                  cmd_obj = cmd_obj->GetSubcommandObject(sub_command.c_str());                  if (!cmd_obj) +                {                      all_okay = false; +                    break; +                }              }          } diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp index 024f7b5a04156..0d9ffda1e96b4 100644 --- a/source/Commands/CommandObjectTarget.cpp +++ b/source/Commands/CommandObjectTarget.cpp @@ -39,6 +39,7 @@  #include "lldb/Interpreter/OptionGroupPlatform.h"  #include "lldb/Interpreter/OptionGroupUInt64.h"  #include "lldb/Interpreter/OptionGroupUUID.h" +#include "lldb/Interpreter/OptionGroupString.h"  #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"  #include "lldb/Symbol/CompileUnit.h"  #include "lldb/Symbol/FuncUnwinders.h" @@ -2844,7 +2845,7 @@ public:                                                        "Set the load addresses for one or more sections in a target module.",                                                        "target modules load [--file <module> --uuid <uuid>] <sect-name> <address> [<sect-name> <address> ....]"),          m_option_group (interpreter), -        m_file_option (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeFilename, "Fullpath or basename for module to load."), +        m_file_option (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName, "Fullpath or basename for module to load.", ""),          m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset, "Set the load address for all sections to be the virtual address in the file plus the offset.", 0)      {          m_option_group.Append (&m_uuid_option_group, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); @@ -2884,7 +2885,26 @@ protected:              if (m_file_option.GetOptionValue().OptionWasSet())              {                  search_using_module_spec = true; -                module_spec.GetFileSpec() = m_file_option.GetOptionValue().GetCurrentValue(); +                const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue(); +                const bool use_global_module_list = true; +                ModuleList module_list; +                const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, use_global_module_list); +                if (num_matches == 1) +                { +                    module_spec.GetFileSpec() = module_list.GetModuleAtIndex(0)->GetFileSpec(); +                } +                else if (num_matches > 1 ) +                { +                    search_using_module_spec = false; +                    result.AppendErrorWithFormat ("more than 1 module matched by name '%s'\n", arg_cstr); +                    result.SetStatus (eReturnStatusFailed); +                } +                else +                { +                    search_using_module_spec = false; +                    result.AppendErrorWithFormat ("no object file for module '%s'\n", arg_cstr); +                    result.SetStatus (eReturnStatusFailed); +                }              }              if (m_uuid_option_group.GetOptionValue().OptionWasSet()) @@ -3070,7 +3090,7 @@ protected:      OptionGroupOptions m_option_group;      OptionGroupUUID m_uuid_option_group; -    OptionGroupFile m_file_option; +    OptionGroupString m_file_option;      OptionGroupUInt64 m_slide_option;  }; @@ -3724,45 +3744,85 @@ protected:              if (func_unwinders_sp.get() == NULL)                  continue; -            Address first_non_prologue_insn (func_unwinders_sp->GetFirstNonPrologueInsn(*target)); -            if (first_non_prologue_insn.IsValid()) -            { -                result.GetOutputStream().Printf("First non-prologue instruction is at address 0x%" PRIx64 " or offset %" PRId64 " into the function.\n", first_non_prologue_insn.GetLoadAddress(target), first_non_prologue_insn.GetLoadAddress(target) - start_addr); -                result.GetOutputStream().Printf ("\n"); -            } +            result.GetOutputStream().Printf("UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);              UnwindPlanSP non_callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread.get(), -1);              if (non_callsite_unwind_plan.get())              { -                result.GetOutputStream().Printf("Asynchronous (not restricted to call-sites) UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr); -                non_callsite_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); -                result.GetOutputStream().Printf ("\n"); +                result.GetOutputStream().Printf("Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n", non_callsite_unwind_plan->GetSourceName().AsCString());              } - -            UnwindPlanSP callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(-1); +            UnwindPlanSP callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(*target, -1);              if (callsite_unwind_plan.get())              { -                result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr); -                callsite_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); -                result.GetOutputStream().Printf ("\n"); +                result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan is '%s'\n", callsite_unwind_plan->GetSourceName().AsCString()); +            } +            UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*thread.get()); +            if (fast_unwind_plan.get()) +            { +                result.GetOutputStream().Printf("Fast UnwindPlan is '%s'\n", fast_unwind_plan->GetSourceName().AsCString());              } -            UnwindPlanSP arch_default_unwind_plan = func_unwinders_sp->GetUnwindPlanArchitectureDefault(*thread.get()); -            if (arch_default_unwind_plan.get()) +            result.GetOutputStream().Printf("\n"); + +            UnwindPlanSP assembly_sp = func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread.get(), 0); +            if (assembly_sp)              { -                result.GetOutputStream().Printf("Architecture default UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr); -                arch_default_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); -                result.GetOutputStream().Printf ("\n"); +                result.GetOutputStream().Printf("Assembly language inspection UnwindPlan:\n"); +                assembly_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); +                result.GetOutputStream().Printf("\n");              } +             -            UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*thread.get()); -            if (fast_unwind_plan.get()) +            UnwindPlanSP ehframe_sp = func_unwinders_sp->GetEHFrameUnwindPlan(*target, 0); +            if (ehframe_sp)              { -                result.GetOutputStream().Printf("Fast UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr); +                result.GetOutputStream().Printf("eh_frame UnwindPlan:\n"); +                ehframe_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); +                result.GetOutputStream().Printf("\n"); +            } + +            UnwindPlanSP ehframe_augmented_sp = func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread.get(), 0); +            if (ehframe_augmented_sp) +            { +                result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n"); +                ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); +                result.GetOutputStream().Printf("\n"); +            } + +            UnwindPlanSP compact_unwind_sp = func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0); +            if (compact_unwind_sp) +            { +                result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n"); +                compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); +                result.GetOutputStream().Printf("\n"); +            } + +            if (fast_unwind_plan) +            { +                result.GetOutputStream().Printf("Fast UnwindPlan:\n");                  fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); -                result.GetOutputStream().Printf ("\n"); +                result.GetOutputStream().Printf("\n");              } +            ABISP abi_sp = process->GetABI(); +            if (abi_sp) +            { +                UnwindPlan arch_default(lldb::eRegisterKindGeneric); +                if (abi_sp->CreateDefaultUnwindPlan (arch_default)) +                { +                    result.GetOutputStream().Printf("Arch default UnwindPlan:\n"); +                    arch_default.Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); +                    result.GetOutputStream().Printf("\n"); +                } + +                UnwindPlan arch_entry(lldb::eRegisterKindGeneric); +                if (abi_sp->CreateFunctionEntryUnwindPlan (arch_entry)) +                { +                    result.GetOutputStream().Printf("Arch default at entry point UnwindPlan:\n"); +                    arch_entry.Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); +                    result.GetOutputStream().Printf("\n"); +                } +            }              result.GetOutputStream().Printf ("\n");          } @@ -4999,7 +5059,7 @@ protected:      {          m_stop_hook_sp.reset(); -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget();          if (target)          {              Target::StopHookSP new_hook_sp = target->CreateStopHook(); @@ -5151,7 +5211,7 @@ protected:      bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget();          if (target)          {              // FIXME: see if we can use the breakpoint id style parser? @@ -5227,7 +5287,7 @@ protected:      bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget();          if (target)          {              // FIXME: see if we can use the breakpoint id style parser? @@ -5297,7 +5357,7 @@ protected:      bool      DoExecute (Args& command, CommandReturnObject &result)      { -        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); +        Target *target = GetSelectedOrDummyTarget();          if (!target)          {              result.AppendError ("invalid target\n"); diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index e7a8652ac898c..bace4e58b4ad6 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -46,7 +46,108 @@ using namespace lldb_private;  // CommandObjectThreadBacktrace  //------------------------------------------------------------------------- -class CommandObjectThreadBacktrace : public CommandObjectParsed +class CommandObjectIterateOverThreads : public CommandObjectParsed +{ +public: +    CommandObjectIterateOverThreads (CommandInterpreter &interpreter, +                         const char *name, +                         const char *help, +                         const char *syntax, +                         uint32_t flags) : +        CommandObjectParsed (interpreter, name, help, syntax, flags) +    { +    } + +    virtual ~CommandObjectIterateOverThreads() {} +    virtual bool +    DoExecute (Args& command, CommandReturnObject &result) +    {         +        result.SetStatus (m_success_return); + +        if (command.GetArgumentCount() == 0) +        { +            Thread *thread = m_exe_ctx.GetThreadPtr(); +            if (!HandleOneThread (*thread, result)) +                return false; +        } +        else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) +        { +            Process *process = m_exe_ctx.GetProcessPtr(); +            uint32_t idx = 0; +            for (ThreadSP thread_sp : process->Threads()) +            { +                if (idx != 0 && m_add_return) +                    result.AppendMessage(""); + +                if (!HandleOneThread(*(thread_sp.get()), result)) +                    return false; +                ++idx; +            } +        } +        else +        { +            const size_t num_args = command.GetArgumentCount(); +            Process *process = m_exe_ctx.GetProcessPtr(); +            Mutex::Locker locker (process->GetThreadList().GetMutex()); +            std::vector<ThreadSP> thread_sps; + +            for (size_t i = 0; i < num_args; i++) +            { +                bool success; +                 +                uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); +                if (!success) +                { +                    result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); +                    result.SetStatus (eReturnStatusFailed); +                    return false; +                } +                 +                thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx)); +                 +                if (!thread_sps[i]) +                { +                    result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); +                    result.SetStatus (eReturnStatusFailed); +                    return false; +                } +                 +            } +             +            for (uint32_t i = 0; i < num_args; i++) +            { +                if (!HandleOneThread (*(thread_sps[i].get()), result)) +                    return false; + +                if (i < num_args - 1 && m_add_return) +                    result.AppendMessage(""); +            } +        } +        return result.Succeeded(); +    } + +protected: + +    // Override this to do whatever you need to do for one thread. +    // +    // If you return false, the iteration will stop, otherwise it will proceed. +    // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration, +    // so you only need to set the return status in HandleOneThread if you want to indicate an error. +    // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.) + +    virtual bool +    HandleOneThread (Thread &thread, CommandReturnObject &result) = 0; + +    ReturnStatus m_success_return = eReturnStatusSuccessFinishResult; +    bool m_add_return = true; + +}; + +//------------------------------------------------------------------------- +// CommandObjectThreadBacktrace +//------------------------------------------------------------------------- + +class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads  {  public: @@ -134,7 +235,7 @@ public:      };      CommandObjectThreadBacktrace (CommandInterpreter &interpreter) : -        CommandObjectParsed (interpreter, +        CommandObjectIterateOverThreads (interpreter,                               "thread backtrace",                               "Show the stack for one or more threads.  If no threads are specified, show the currently selected thread.  Use the thread-index \"all\" to see all threads.",                               NULL, @@ -145,18 +246,6 @@ public:                               eFlagProcessMustBePaused   ),          m_options(interpreter)      { -        CommandArgumentEntry arg; -        CommandArgumentData thread_idx_arg; -         -        // Define the first (and only) variant of this arg. -        thread_idx_arg.arg_type = eArgTypeThreadIndex; -        thread_idx_arg.arg_repetition = eArgRepeatStar; -         -        // There is only one variant this argument could be; put it into the argument entry. -        arg.push_back (thread_idx_arg); -         -        // Push the data for the first argument into the m_arguments vector. -        m_arguments.push_back (arg);      }      ~CommandObjectThreadBacktrace() @@ -197,106 +286,28 @@ protected:      }      virtual bool -    DoExecute (Args& command, CommandReturnObject &result) -    {         -        result.SetStatus (eReturnStatusSuccessFinishResult); +    HandleOneThread (Thread &thread, CommandReturnObject &result) +    {          Stream &strm = result.GetOutputStream();          // Don't show source context when doing backtraces.          const uint32_t num_frames_with_source = 0; -        if (command.GetArgumentCount() == 0) -        { -            Thread *thread = m_exe_ctx.GetThreadPtr(); -            // Thread::GetStatus() returns the number of frames shown. -            if (thread->GetStatus (strm, + +        if (!thread.GetStatus (strm,                                     m_options.m_start,                                     m_options.m_count,                                     num_frames_with_source)) -            { -                result.SetStatus (eReturnStatusSuccessFinishResult); -                if (m_options.m_extended_backtrace) -                { -                    DoExtendedBacktrace (thread, result); -                } -            } -        } -        else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)          { -            Process *process = m_exe_ctx.GetProcessPtr(); -            uint32_t idx = 0; -            for (ThreadSP thread_sp : process->Threads()) -            { -                if (idx != 0) -                    result.AppendMessage(""); - -                if (!thread_sp->GetStatus (strm, -                                           m_options.m_start, -                                           m_options.m_count, -                                           num_frames_with_source)) -                { -                    result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", idx); -                    result.SetStatus (eReturnStatusFailed); -                    return false; -                } -                if (m_options.m_extended_backtrace) -                { -                    DoExtendedBacktrace (thread_sp.get(), result); -                } -                 -                ++idx; -            } +            result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID()); +            result.SetStatus (eReturnStatusFailed); +            return false;          } -        else +        if (m_options.m_extended_backtrace)          { -            const size_t num_args = command.GetArgumentCount(); -            Process *process = m_exe_ctx.GetProcessPtr(); -            Mutex::Locker locker (process->GetThreadList().GetMutex()); -            std::vector<ThreadSP> thread_sps; - -            for (size_t i = 0; i < num_args; i++) -            { -                bool success; -                 -                uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); -                if (!success) -                { -                    result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); -                    result.SetStatus (eReturnStatusFailed); -                    return false; -                } -                 -                thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx)); -                 -                if (!thread_sps[i]) -                { -                    result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); -                    result.SetStatus (eReturnStatusFailed); -                    return false; -                } -                 -            } -             -            for (uint32_t i = 0; i < num_args; i++) -            { -                if (!thread_sps[i]->GetStatus (strm, -                                               m_options.m_start, -                                               m_options.m_count, -                                               num_frames_with_source)) -                { -                    result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i)); -                    result.SetStatus (eReturnStatusFailed); -                    return false; -                } -                if (m_options.m_extended_backtrace) -                { -                    DoExtendedBacktrace (thread_sps[i].get(), result); -                } -                 -                if (i < num_args - 1) -                    result.AppendMessage(""); -            } +            DoExtendedBacktrace (&thread, result);          } -        return result.Succeeded(); + +        return true;      }      CommandOptions m_options; @@ -379,6 +390,12 @@ public:                      break;                  }                  break; +            case 'C': +                { +                    m_class_name.clear(); +                    m_class_name.assign(option_arg); +                } +                break;              case 'm':                  {                      OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;  @@ -416,6 +433,7 @@ public:              m_run_mode = eOnlyDuringStepping;              m_avoid_regexp.clear();              m_step_in_target.clear(); +            m_class_name.clear();              m_step_count = 1;          } @@ -435,7 +453,8 @@ public:          RunMode m_run_mode;          std::string m_avoid_regexp;          std::string m_step_in_target; -        int32_t m_step_count; +        std::string m_class_name; +        uint32_t m_step_count;      };      CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, @@ -520,6 +539,22 @@ protected:              }          } +        if (m_step_type == eStepTypeScripted) +        { +            if (m_options.m_class_name.empty()) +            { +                result.AppendErrorWithFormat ("empty class name for scripted step."); +                result.SetStatus(eReturnStatusFailed); +                return false; +            } +            else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str())) +            { +                result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str()); +                result.SetStatus(eReturnStatusFailed); +                return false; +            } +        } +          const bool abort_other_plans = false;          const lldb::RunMode stop_other_threads = m_options.m_run_mode; @@ -530,7 +565,7 @@ protected:              bool_stop_other_threads = false;          else if (m_options.m_run_mode == eOnlyDuringStepping)          { -            if (m_step_type == eStepTypeOut) +            if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted)                  bool_stop_other_threads = false;              else                  bool_stop_other_threads = true; @@ -599,6 +634,12 @@ protected:                                                            thread->GetSelectedFrameIndex(),                                                            m_options.m_step_out_avoid_no_debug);          } +        else if (m_step_type == eStepTypeScripted) +        { +            new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans, +                                                                  m_options.m_class_name.c_str(), +                                                                  bool_stop_other_threads); +        }          else          {              result.AppendError ("step type is not supported"); @@ -622,8 +663,15 @@ protected:                  }              } +              process->GetThreadList().SetSelectedThreadByID (thread->GetID()); -            process->Resume (); + +            StreamString stream; +            Error error; +            if (synchronous_execution) +                error = process->ResumeSynchronous (&stream); +            else +                error = process->Resume ();              // There is a race condition where this thread will return up the call stack to the main command handler              // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has @@ -632,17 +680,12 @@ protected:              if (synchronous_execution)              { -                StateType state = process->WaitForProcessToStop (NULL); -                 -                //EventSP event_sp; -                //StateType state = process->WaitForStateChangedEvents (NULL, event_sp); -                //while (! StateIsStoppedState (state)) -                //  { -                //    state = process->WaitForStateChangedEvents (NULL, event_sp); -                //  } +                // If any state changed events had anything to say, add that to the result +                if (stream.GetData()) +                    result.AppendMessage(stream.GetData()); +                  process->GetThreadList().SetSelectedThreadByID (thread->GetID());                  result.SetDidChangeProcessState (true); -                result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));                  result.SetStatus (eReturnStatusSuccessFinishNoResult);              }              else @@ -686,10 +729,11 @@ CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =  {  { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug",   'a', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeBoolean,     "A boolean value that sets whether stepping into functions will step over functions with no debug information."},  { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug",  'A', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeBoolean,     "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."}, -{ LLDB_OPT_SET_1, false, "count",           'c', OptionParser::eRequiredArgument, NULL, NULL,               1, eArgTypeCount,     "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."}, -{ LLDB_OPT_SET_1, false, "run-mode",        'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, -{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to not to stop at when stepping in."}, -{ LLDB_OPT_SET_1, false, "step-in-target",  't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."}, +{ LLDB_OPT_SET_1, false, "count",                     'c', OptionParser::eRequiredArgument, NULL, NULL,               1, eArgTypeCount,     "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."}, +{ LLDB_OPT_SET_1, false, "run-mode",                  'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, +{ LLDB_OPT_SET_1, false, "step-over-regexp",          'r', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to not to stop at when stepping in."}, +{ LLDB_OPT_SET_1, false, "step-in-target",            't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."}, +{ LLDB_OPT_SET_2, false, "python-class",              'C', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."},  { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }  }; @@ -860,17 +904,25 @@ public:                  }              } + +            StreamString stream; +            Error error; +            if (synchronous_execution) +                error = process->ResumeSynchronous (&stream); +            else +                error = process->Resume (); +              // We should not be holding the thread list lock when we do this. -            Error error (process->Resume());              if (error.Success())              {                  result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());                  if (synchronous_execution)                  { -                    state = process->WaitForProcessToStop (NULL); +                    // If any state changed events had anything to say, add that to the result +                    if (stream.GetData()) +                        result.AppendMessage(stream.GetData());                      result.SetDidChangeProcessState (true); -                    result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));                      result.SetStatus (eReturnStatusSuccessFinishNoResult);                  }                  else @@ -1191,17 +1243,27 @@ protected:              } + +              process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx); -            Error error (process->Resume ()); + +            StreamString stream; +            Error error; +            if (synchronous_execution) +                error = process->ResumeSynchronous (&stream); +            else +                error = process->Resume (); +              if (error.Success())              {                  result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());                  if (synchronous_execution)                  { -                    StateType state = process->WaitForProcessToStop (NULL); +                    // If any state changed events had anything to say, add that to the result +                    if (stream.GetData()) +                        result.AppendMessage(stream.GetData());                      result.SetDidChangeProcessState (true); -                    result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));                      result.SetStatus (eReturnStatusSuccessFinishNoResult);                  }                  else @@ -1358,32 +1420,22 @@ protected:  // CommandObjectThreadInfo  //------------------------------------------------------------------------- -class CommandObjectThreadInfo : public CommandObjectParsed +class CommandObjectThreadInfo : public CommandObjectIterateOverThreads  {  public:      CommandObjectThreadInfo (CommandInterpreter &interpreter) : -        CommandObjectParsed (interpreter,  -                             "thread info", -                             "Show an extended summary of information about thread(s) in a process.", -                             "thread info", -                             eFlagRequiresProcess       | -                             eFlagTryTargetAPILock      | -                             eFlagProcessMustBeLaunched | -                             eFlagProcessMustBePaused), +        CommandObjectIterateOverThreads (interpreter, +                                         "thread info", +                                         "Show an extended summary of information about thread(s) in a process.", +                                         "thread info", +                                         eFlagRequiresProcess       | +                                         eFlagTryTargetAPILock      | +                                         eFlagProcessMustBeLaunched | +                                         eFlagProcessMustBePaused),          m_options (interpreter)      { -        CommandArgumentEntry arg; -        CommandArgumentData thread_idx_arg; -         -        thread_idx_arg.arg_type = eArgTypeThreadIndex; -        thread_idx_arg.arg_repetition = eArgRepeatStar; -         -        // There is only one variant this argument could be; put it into the argument entry. -        arg.push_back (thread_idx_arg); -         -        // Push the data for the first argument into the m_arguments vector. -        m_arguments.push_back (arg); +        m_add_return = false;      }      class CommandOptions : public Options @@ -1399,7 +1451,8 @@ public:          void          OptionParsingStarting ()          { -            m_json = false; +            m_json_thread = false; +            m_json_stopinfo = false;          }          virtual @@ -1416,10 +1469,14 @@ public:              switch (short_option)              {                  case 'j': -                    m_json = true; +                    m_json_thread = true; +                    break; +                     +                case 's': +                    m_json_stopinfo = true;                      break; -                 default: +                default:                      return Error("invalid short option character '%c'", short_option);              } @@ -1432,7 +1489,8 @@ public:              return g_option_table;          } -        bool m_json; +        bool m_json_thread; +        bool m_json_stopinfo;          static OptionDefinition g_option_table[];      }; @@ -1451,81 +1509,16 @@ public:      }      virtual bool -    DoExecute (Args& command, CommandReturnObject &result) +    HandleOneThread (Thread &thread, CommandReturnObject &result)      { -        result.SetStatus (eReturnStatusSuccessFinishResult);          Stream &strm = result.GetOutputStream(); - -        if (command.GetArgumentCount() == 0) -        { -            Thread *thread = m_exe_ctx.GetThreadPtr(); -            if (thread->GetDescription (strm, eDescriptionLevelFull, m_options.m_json)) -            { -                result.SetStatus (eReturnStatusSuccessFinishResult); -            } -        } -        else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) -        { -            Process *process = m_exe_ctx.GetProcessPtr(); -            uint32_t idx = 0; -            for (ThreadSP thread_sp : process->Threads()) -            { -                if (idx != 0) -                    result.AppendMessage(""); -                if (!thread_sp->GetDescription (strm, eDescriptionLevelFull, m_options.m_json)) -                { -                    result.AppendErrorWithFormat ("error displaying info for thread: \"0x%4.4x\"\n", idx); -                    result.SetStatus (eReturnStatusFailed); -                    return false; -                } -                ++idx; -            } -        } -        else +        if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo))          { -            const size_t num_args = command.GetArgumentCount(); -            Process *process = m_exe_ctx.GetProcessPtr(); -            Mutex::Locker locker (process->GetThreadList().GetMutex()); -            std::vector<ThreadSP> thread_sps; - -            for (size_t i = 0; i < num_args; i++) -            { -                bool success; -                 -                uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); -                if (!success) -                { -                    result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); -                    result.SetStatus (eReturnStatusFailed); -                    return false; -                } -                 -                thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx)); -                 -                if (!thread_sps[i]) -                { -                    result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); -                    result.SetStatus (eReturnStatusFailed); -                    return false; -                } -                 -            } -             -            for (uint32_t i = 0; i < num_args; i++) -            { -                if (!thread_sps[i]->GetDescription (strm, eDescriptionLevelFull, m_options.m_json)) -                { -                    result.AppendErrorWithFormat ("error displaying info for thread: \"%s\"\n", command.GetArgumentAtIndex(i)); -                    result.SetStatus (eReturnStatusFailed); -                    return false; -                } -                 -                if (i < num_args - 1) -                    result.AppendMessage(""); -            } - +            result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID()); +            result.SetStatus (eReturnStatusFailed); +            return false;          } -        return result.Succeeded(); +        return true;      }      CommandOptions m_options; @@ -1536,6 +1529,7 @@ OptionDefinition  CommandObjectThreadInfo::CommandOptions::g_option_table[] =  {      { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."}, +    { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."},      { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }  }; @@ -1958,6 +1952,228 @@ CommandObjectThreadJump::CommandOptions::g_option_table[] =  };  //------------------------------------------------------------------------- +// Next are the subcommands of CommandObjectMultiwordThreadPlan +//------------------------------------------------------------------------- + + +//------------------------------------------------------------------------- +// CommandObjectThreadPlanList +//------------------------------------------------------------------------- +class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads +{ +public: + +    class CommandOptions : public Options +    { +    public: + +        CommandOptions (CommandInterpreter &interpreter) : +            Options(interpreter) +        { +            // Keep default values of all options in one place: OptionParsingStarting () +            OptionParsingStarting (); +        } + +        virtual +        ~CommandOptions () +        { +        } + +        virtual Error +        SetOptionValue (uint32_t option_idx, const char *option_arg) +        { +            Error error; +            const int short_option = m_getopt_table[option_idx].val; + +            switch (short_option) +            { +                case 'i': +                { +                    m_internal = true; +                } +                break; +                case 'v': +                { +                    m_verbose = true; +                } +                break; +                default: +                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); +                    break; + +            } +            return error; +        } + +        void +        OptionParsingStarting () +        { +            m_verbose = false; +            m_internal = false; +        } + +        const OptionDefinition* +        GetDefinitions () +        { +            return g_option_table; +        } + +        // Options table: Required for subclasses of Options. + +        static OptionDefinition g_option_table[]; + +        // Instance variables to hold the values for command options. +        bool m_verbose; +        bool m_internal; +    }; + +    CommandObjectThreadPlanList (CommandInterpreter &interpreter) : +        CommandObjectIterateOverThreads (interpreter, +                                         "thread plan list", +                                         "Show thread plans for one or more threads.  If no threads are specified, show the " +                                         "currently selected thread.  Use the thread-index \"all\" to see all threads.", +                                         NULL, +                                         eFlagRequiresProcess       | +                                         eFlagRequiresThread        | +                                         eFlagTryTargetAPILock      | +                                         eFlagProcessMustBeLaunched | +                                         eFlagProcessMustBePaused   ), +        m_options(interpreter) +    { +    } + +    ~CommandObjectThreadPlanList () +    { +    } + +    virtual Options * +    GetOptions () +    { +        return &m_options; +    } + +protected: +    virtual bool +    HandleOneThread (Thread &thread, CommandReturnObject &result) +    { +        Stream &strm = result.GetOutputStream(); +        DescriptionLevel desc_level = eDescriptionLevelFull; +        if (m_options.m_verbose) +            desc_level = eDescriptionLevelVerbose; + +        thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true); +        return true; +    } +    CommandOptions m_options; +}; + +OptionDefinition +CommandObjectThreadPlanList::CommandOptions::g_option_table[] = +{ +{ LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"}, +{ LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"}, +{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +}; + +class CommandObjectThreadPlanDiscard : public CommandObjectParsed +{ +public: +    CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) : +        CommandObjectParsed (interpreter, +                             "thread plan discard", +                             "Discards thread plans up to and including the plan passed as the command argument." +                             "Only user visible plans can be discarded, use the index from \"thread plan list\"" +                             " without the \"-i\" argument.", +                             NULL, +                             eFlagRequiresProcess       | +                             eFlagRequiresThread        | +                             eFlagTryTargetAPILock      | +                             eFlagProcessMustBeLaunched | +                             eFlagProcessMustBePaused   ) +    { +        CommandArgumentEntry arg; +        CommandArgumentData plan_index_arg; + +        // Define the first (and only) variant of this arg. +        plan_index_arg.arg_type = eArgTypeUnsignedInteger; +        plan_index_arg.arg_repetition = eArgRepeatPlain; + +        // There is only one variant this argument could be; put it into the argument entry. +        arg.push_back (plan_index_arg); + +        // Push the data for the first argument into the m_arguments vector. +        m_arguments.push_back (arg); +    } + +    virtual ~CommandObjectThreadPlanDiscard () {} + +    bool +    DoExecute (Args& args, CommandReturnObject &result) +    { +        Thread *thread = m_exe_ctx.GetThreadPtr(); +        if (args.GetArgumentCount() != 1) +        { +            result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.", +                                         args.GetArgumentCount()); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } + +        bool success; +        uint32_t thread_plan_idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); +        if (!success) +        { +            result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.", +                                         args.GetArgumentAtIndex(0)); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } + +        if (thread_plan_idx == 0) +        { +            result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan."); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } + +        if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) +        { +            result.SetStatus(eReturnStatusSuccessFinishNoResult); +            return true; +        } +        else +        { +            result.AppendErrorWithFormat("Could not find User thread plan with index %s.", +                                         args.GetArgumentAtIndex(0)); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } +    } +}; + +//------------------------------------------------------------------------- +// CommandObjectMultiwordThreadPlan +//------------------------------------------------------------------------- + +class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword +{ +public: +    CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) : +        CommandObjectMultiword (interpreter, +                                "plan", +                                "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.", +                                "thread plan <subcommand> [<subcommand objects]") +    { +        LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter))); +        LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter))); +    } + +    virtual ~CommandObjectMultiwordThreadPlan () {} + + +}; + +//-------------------------------------------------------------------------  // CommandObjectMultiwordThread  //------------------------------------------------------------------------- @@ -2014,6 +2230,16 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &                                                      NULL,                                                      eStepTypeTraceOver,                                                      eStepScopeInstruction))); + +    LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( +                                                    interpreter, +                                                    "thread step-scripted", +                                                    "Step as instructed by the script class passed in the -C option.", +                                                    NULL, +                                                    eStepTypeScripted, +                                                    eStepScopeSource))); + +    LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter)));  }  CommandObjectMultiwordThread::~CommandObjectMultiwordThread () diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp index 640fd6dd3fa42..3a4c60c00f8b0 100644 --- a/source/Commands/CommandObjectType.cpp +++ b/source/Commands/CommandObjectType.cpp @@ -16,6 +16,7 @@  #include <ctype.h>  // C++ Includes +#include <functional>  #include "llvm/ADT/StringRef.h" @@ -31,6 +32,11 @@  #include "lldb/Interpreter/CommandReturnObject.h"  #include "lldb/Interpreter/Options.h"  #include "lldb/Interpreter/OptionGroupFormat.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadList.h"  using namespace lldb;  using namespace lldb_private; @@ -2465,22 +2471,7 @@ protected:          if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)          { -            // we want to make sure to enable "system" last and "default" first -            DataVisualization::Categories::Enable(ConstString("default"), TypeCategoryMap::First); -            uint32_t num_categories = DataVisualization::Categories::GetCount(); -            for (uint32_t i = 0; i < num_categories; i++) -            { -                lldb::TypeCategoryImplSP category_sp = DataVisualization::Categories::GetCategoryAtIndex(i); -                if (category_sp) -                { -                    if ( ::strcmp(category_sp->GetName(), "system") == 0 || -                         ::strcmp(category_sp->GetName(), "default") == 0 ) -                        continue; -                    else -                        DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default); -                } -            } -            DataVisualization::Categories::Enable(ConstString("system"), TypeCategoryMap::Last); +            DataVisualization::Categories::EnableStar();          }          else          { @@ -2630,14 +2621,7 @@ protected:          if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)          { -            uint32_t num_categories = DataVisualization::Categories::GetCount(); -            for (uint32_t i = 0; i < num_categories; i++) -            { -                lldb::TypeCategoryImplSP category_sp = DataVisualization::Categories::GetCategoryAtIndex(i); -                // no need to check if the category is enabled - disabling a disabled category has no effect -                if (category_sp) -                    DataVisualization::Categories::Disable(category_sp); -            } +            DataVisualization::Categories::DisableStar();          }          else          { @@ -4253,6 +4237,84 @@ CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =      { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }  }; +template <typename FormatterType> +class CommandObjectFormatterInfo : public CommandObjectRaw +{ +public: +    typedef std::function<typename FormatterType::SharedPointer(ValueObject&)> DiscoveryFunction; +    CommandObjectFormatterInfo (CommandInterpreter &interpreter, +                                const char* formatter_name, +                                DiscoveryFunction discovery_func) : +    CommandObjectRaw(interpreter, +                     nullptr, +                     nullptr, +                     nullptr, +                     eFlagRequiresFrame), +    m_formatter_name(formatter_name ? formatter_name : ""), +    m_discovery_function(discovery_func) +    { +        StreamString name; +        name.Printf("type %s info", formatter_name); +        SetCommandName(name.GetData()); +        StreamString help; +        help.Printf("This command evaluates the provided expression and shows which %s is applied to the resulting value (if any).", formatter_name); +        SetHelp(help.GetData()); +        StreamString syntax; +        syntax.Printf("type %s info <expr>", formatter_name); +        SetSyntax(syntax.GetData()); +    } +     +    virtual +    ~CommandObjectFormatterInfo () +    { +    } +     +protected: +    virtual bool +    DoExecute (const char *command, CommandReturnObject &result) +    { +        auto target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); +        auto frame_sp = target_sp->GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame(); +        ValueObjectSP result_valobj_sp; +        EvaluateExpressionOptions options; +        lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(command, frame_sp.get(), result_valobj_sp, options); +        if (expr_result == eExpressionCompleted && result_valobj_sp) +        { +            result_valobj_sp = result_valobj_sp->GetQualifiedRepresentationIfAvailable(target_sp->GetPreferDynamicValue(), target_sp->GetEnableSyntheticValue()); +            typename FormatterType::SharedPointer formatter_sp = m_discovery_function(*result_valobj_sp); +            if (formatter_sp) +            { +                std::string description(formatter_sp->GetDescription()); +                result.AppendMessageWithFormat("%s applied to (%s) %s is: %s\n", +                                               m_formatter_name.c_str(), +                                               result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), +                                               command, +                                               description.c_str()); +                result.SetStatus(lldb::eReturnStatusSuccessFinishResult); +            } +            else +            { +                result.AppendMessageWithFormat("no %s applies to (%s) %s\n", +                                               m_formatter_name.c_str(), +                                               result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), +                                               command); +                result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); +            } +            return true; +        } +        else +        { +            result.AppendError("failed to evaluate expression"); +            result.SetStatus(lldb::eReturnStatusFailed); +            return false; +        } +    } + +private: +    std::string m_formatter_name; +    DiscoveryFunction m_discovery_function; +}; +  class CommandObjectTypeFormat : public CommandObjectMultiword  {  public: @@ -4266,6 +4328,11 @@ public:          LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectTypeFormatClear (interpreter)));          LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter)));          LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); +        LoadSubCommand ("info",   CommandObjectSP (new CommandObjectFormatterInfo<TypeFormatImpl>(interpreter, +                                                                                                  "format", +                                                                                                  [](ValueObject& valobj) -> TypeFormatImpl::SharedPointer { +                                                                                                      return valobj.GetValueFormat(); +                                                                                                  })));      } @@ -4289,6 +4356,11 @@ public:          LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSynthClear (interpreter)));          LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter)));          LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSynthList (interpreter))); +        LoadSubCommand ("info",          CommandObjectSP (new CommandObjectFormatterInfo<SyntheticChildren>(interpreter, +                                                                                                            "synthetic", +                                                                                                            [](ValueObject& valobj) -> SyntheticChildren::SharedPointer { +                                                                                                                return valobj.GetSyntheticChildren(); +                                                                                                            })));      } @@ -4354,6 +4426,11 @@ public:          LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));          LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));          LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); +        LoadSubCommand ("info",          CommandObjectSP (new CommandObjectFormatterInfo<TypeSummaryImpl>(interpreter, +                                                                                                          "summary", +                                                                                                            [](ValueObject& valobj) -> TypeSummaryImpl::SharedPointer { +                                                                                                                return valobj.GetSummaryFormat(); +                                                                                                            })));      } diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp index f46db7a6a82bb..275ee925adcc3 100644 --- a/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/source/Commands/CommandObjectWatchpointCommand.cpp @@ -279,17 +279,16 @@ but do NOT enter more than one command per line. \n" );                  result.SetImmediateOutputStream (output_stream);                  result.SetImmediateErrorStream (error_stream); -                bool stop_on_continue = true; -                bool echo_commands    = false; -                bool print_results    = true; +                CommandInterpreterRunOptions options; +                options.SetStopOnContinue (true); +                options.SetStopOnError (data->stop_on_error); +                options.SetEchoCommands (false); +                options.SetPrintResults (true); +                options.SetAddToHistory (false);                  debugger.GetCommandInterpreter().HandleCommands (commands,                                                                    &exe_ctx, -                                                                 stop_on_continue,  -                                                                 data->stop_on_error,  -                                                                 echo_commands,  -                                                                 print_results, -                                                                 eLazyBoolNo, +                                                                 options,                                                                   result);                  result.GetImmediateOutputStream()->Flush();                  result.GetImmediateErrorStream()->Flush();  | 
