[Lldb-commits] [lldb] r224392 - Add the ability to tag one or more breakpoints with a name. These

Jim Ingham jingham at apple.com
Tue Dec 16 15:40:15 PST 2014


Author: jingham
Date: Tue Dec 16 17:40:14 2014
New Revision: 224392

URL: http://llvm.org/viewvc/llvm-project?rev=224392&view=rev
Log:
Add the ability to tag one or more breakpoints with a name.  These
names can then be used in place of breakpoint id's or breakpoint id 
ranges in all the commands that operate on breakpoints.

<rdar://problem/10103959>

Modified:
    lldb/trunk/include/lldb/API/SBBreakpoint.h
    lldb/trunk/include/lldb/Breakpoint/Breakpoint.h
    lldb/trunk/include/lldb/Breakpoint/BreakpointID.h
    lldb/trunk/include/lldb/Breakpoint/BreakpointIDList.h
    lldb/trunk/include/lldb/lldb-enumerations.h
    lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
    lldb/trunk/scripts/Python/interface/SBBreakpoint.i
    lldb/trunk/source/API/SBBreakpoint.cpp
    lldb/trunk/source/Breakpoint/Breakpoint.cpp
    lldb/trunk/source/Breakpoint/BreakpointID.cpp
    lldb/trunk/source/Breakpoint/BreakpointIDList.cpp
    lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
    lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
    lldb/trunk/source/Commands/CommandObjectBreakpoint.h
    lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
    lldb/trunk/source/Interpreter/CommandObject.cpp

Modified: lldb/trunk/include/lldb/API/SBBreakpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBBreakpoint.h?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBBreakpoint.h (original)
+++ lldb/trunk/include/lldb/API/SBBreakpoint.h Tue Dec 16 17:40:14 2014
@@ -123,6 +123,18 @@ public:
     
     SBError
     SetScriptCallbackBody (const char *script_body_text);
+
+    bool
+    AddName (const char *new_name);
+
+    void
+    RemoveName (const char *name_to_remove);
+
+    bool
+    MatchesName (const char *name);
+
+    void
+    GetNames (SBStringList &names);
     
     size_t
     GetNumResolvedLocations() const;

Modified: lldb/trunk/include/lldb/Breakpoint/Breakpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/Breakpoint.h?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/Breakpoint.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/Breakpoint.h Tue Dec 16 17:40:14 2014
@@ -12,8 +12,11 @@
 
 // C Includes
 // C++ Includes
+#include <unordered_set>
+
 // Other libraries and framework includes
 // Project includes
+#include "lldb/Breakpoint/BreakpointID.h"
 #include "lldb/Breakpoint/BreakpointLocationList.h"
 #include "lldb/Breakpoint/BreakpointOptions.h"
 #include "lldb/Breakpoint/BreakpointLocationCollection.h"
@@ -636,6 +639,32 @@ public:
         return m_filter_sp;
     }
 
+    bool
+    AddName (const char *new_name, Error &error);
+
+    void
+    RemoveName (const char *name_to_remove)
+    {
+        if (name_to_remove)
+            m_name_list.erase(name_to_remove);
+    }
+
+    bool
+    MatchesName (const char *name)
+    {
+        return m_name_list.find(name) != m_name_list.end();
+    }
+
+    void
+    GetNames (std::vector<std::string> &names)
+    {
+        names.clear();
+        for (auto name : m_name_list)
+        {
+            names.push_back(name);
+        }
+    }
+
 protected:
     friend class Target;
     //------------------------------------------------------------------
@@ -697,6 +726,7 @@ private:
     bool m_being_created;
     bool m_hardware;                          // If this breakpoint is required to use a hardware breakpoint
     Target &m_target;                         // The target that holds this breakpoint.
+    std::unordered_set<std::string> m_name_list; // If not empty, this is the name of this breakpoint (many breakpoints can share the same name.)
     lldb::SearchFilterSP m_filter_sp;         // The filter that constrains the breakpoint's domain.
     lldb::BreakpointResolverSP m_resolver_sp; // The resolver that defines this breakpoint.
     BreakpointOptions m_options;              // Settable breakpoint options

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointID.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointID.h?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointID.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointID.h Tue Dec 16 17:40:14 2014
@@ -93,6 +93,21 @@ public:
 
 
     //------------------------------------------------------------------
+    /// Takes an input string and checks to see whether it is a breakpoint name.
+    /// If it is a mal-formed breakpoint name, error will be set to an appropriate
+    /// error string.
+    ///
+    /// @param[in] input
+    ///     A string containing JUST the breakpoint description.
+    /// @param[out] error
+    ///     If the name is a well-formed breakpoint name, set to success, otherwise set to an error.
+    /// @return
+    ///     \b true if the name is a breakpoint name (as opposed to an ID or range) false otherwise.
+    //------------------------------------------------------------------
+    static bool
+    StringIsBreakpointName (const char *name, Error &error);
+
+    //------------------------------------------------------------------
     /// Takes a breakpoint ID and the breakpoint location id and returns
     /// a string containing the canonical description for the breakpoint
     /// or breakpoint location.

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointIDList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointIDList.h?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointIDList.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointIDList.h Tue Dec 16 17:40:14 2014
@@ -68,7 +68,7 @@ public:
     StringContainsIDRangeExpression (const char *in_string, size_t *range_start_len, size_t *range_end_pos);
 
     static void
-    FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result, Args &new_args);
+    FindAndReplaceIDRanges (Args &old_args, Target *target, bool allow_locations, CommandReturnObject &result, Args &new_args);
 
 private:
     BreakpointIDArray m_breakpoint_ids;

Modified: lldb/trunk/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Tue Dec 16 17:40:14 2014
@@ -420,6 +420,7 @@ namespace lldb {
         eArgTypeBoolean,
         eArgTypeBreakpointID,
         eArgTypeBreakpointIDRange,
+        eArgTypeBreakpointName,
         eArgTypeByteSize,
         eArgTypeClassName,
         eArgTypeCommandName,

Modified: lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme (original)
+++ lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme Tue Dec 16 17:40:14 2014
@@ -84,14 +84,16 @@
    <LaunchAction
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      launchStyle = "1"
+      launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       customWorkingDirectory = "/Volumes/work/gclayton/Documents/devb/attach"
       buildConfiguration = "Debug"
       ignoresPersistentStateOnLaunch = "YES"
       debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
       allowLocationSimulation = "YES">
-      <BuildableProductRunnable>
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
          <BuildableReference
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "26F5C26910F3D9A4009D5894"
@@ -147,7 +149,8 @@
       buildConfiguration = "Release"
       ignoresPersistentStateOnLaunch = "YES"
       debugDocumentVersioning = "YES">
-      <BuildableProductRunnable>
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
          <BuildableReference
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "26F5C26910F3D9A4009D5894"

Modified: lldb/trunk/scripts/Python/interface/SBBreakpoint.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBBreakpoint.i?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBBreakpoint.i (original)
+++ lldb/trunk/scripts/Python/interface/SBBreakpoint.i Tue Dec 16 17:40:14 2014
@@ -200,6 +200,18 @@ public:
     SBError
     SetScriptCallbackBody (const char *script_body_text);
     
+    bool
+    AddName (const char *new_name);
+
+    void
+    RemoveName (const char *name_to_remove);
+
+    bool
+    MatchesName (const char *name);
+    
+    void
+    GetNames (SBStringList &names);
+    
     size_t
     GetNumResolvedLocations() const;
 

Modified: lldb/trunk/source/API/SBBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBBreakpoint.cpp?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/source/API/SBBreakpoint.cpp (original)
+++ lldb/trunk/source/API/SBBreakpoint.cpp Tue Dec 16 17:40:14 2014
@@ -13,6 +13,7 @@
 #include "lldb/API/SBEvent.h"
 #include "lldb/API/SBProcess.h"
 #include "lldb/API/SBStream.h"
+#include "lldb/API/SBStringList.h"
 #include "lldb/API/SBThread.h"
 
 #include "lldb/Breakpoint/Breakpoint.h"
@@ -653,6 +654,83 @@ SBBreakpoint::SetScriptCallbackBody (con
     return sb_error;
 }
 
+bool
+SBBreakpoint::AddName (const char *new_name)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+    if (log)
+        log->Printf ("SBBreakpoint(%p)::AddName (name=%s)",
+                     static_cast<void*>(m_opaque_sp.get()),
+                     new_name);
+
+    if (m_opaque_sp)
+    {
+        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
+        Error error;  // Think I'm just going to swallow the error here, it's probably more annoying to have to provide it.
+        return m_opaque_sp->AddName(new_name, error);
+    }
+
+    return false;
+}
+
+void
+SBBreakpoint::RemoveName (const char *name_to_remove)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+    if (log)
+        log->Printf ("SBBreakpoint(%p)::RemoveName (name=%s)",
+                     static_cast<void*>(m_opaque_sp.get()),
+                     name_to_remove);
+
+    if (m_opaque_sp)
+    {
+        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
+        m_opaque_sp->RemoveName(name_to_remove);
+    }
+}
+
+bool
+SBBreakpoint::MatchesName (const char *name)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+    if (log)
+        log->Printf ("SBBreakpoint(%p)::MatchesName (name=%s)",
+                     static_cast<void*>(m_opaque_sp.get()),
+                     name);
+
+    if (m_opaque_sp)
+    {
+        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
+        return m_opaque_sp->MatchesName(name);
+    }
+
+    return false;
+}
+
+void
+SBBreakpoint::GetNames (SBStringList &names)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+    if (log)
+        log->Printf ("SBBreakpoint(%p)::GetNames ()",
+                     static_cast<void*>(m_opaque_sp.get()));
+
+    if (m_opaque_sp)
+    {
+        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
+        std::vector<std::string> names_vec;
+        m_opaque_sp->GetNames(names_vec);
+        for (std::string name : names_vec)
+        {
+            names.AppendString (name.c_str());
+        }
+    }
+}
+
 lldb_private::Breakpoint *
 SBBreakpoint::operator->() const
 {

Modified: lldb/trunk/source/Breakpoint/Breakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/Breakpoint.cpp?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/Breakpoint.cpp (original)
+++ lldb/trunk/source/Breakpoint/Breakpoint.cpp Tue Dec 16 17:40:14 2014
@@ -71,7 +71,8 @@ Breakpoint::Breakpoint (Target &new_targ
     m_target(new_target),
     m_options (source_bp.m_options),
     m_locations(*this),
-    m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols)
+    m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols),
+    m_name_list (source_bp.m_name_list)
 {
     // Now go through and copy the filter & resolver:
     m_resolver_sp = source_bp.m_resolver_sp->CopyForBreakpoint(*this);
@@ -782,6 +783,23 @@ Breakpoint::GetNumLocations() const
     return m_locations.GetSize();
 }
 
+bool
+Breakpoint::AddName (const char *new_name, Error &error)
+{
+    if (!new_name)
+        return false;
+    if (!BreakpointID::StringIsBreakpointName(new_name, error))
+    {
+        error.SetErrorStringWithFormat("input name \"%s\" not a breakpoint name.", new_name);
+        return false;
+    }
+    if (!error.Success())
+        return false;
+
+    m_name_list.insert(new_name);
+    return true;
+}
+
 void
 Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations)
 {
@@ -832,6 +850,20 @@ Breakpoint::GetDescription (Stream *s, l
         
         if (level == lldb::eDescriptionLevelFull)
         {
+            if (!m_name_list.empty())
+            {
+                s->EOL();
+                s->Indent();
+                s->Printf ("Names:");
+                s->EOL();
+                s->IndentMore();
+                for (std::string name : m_name_list)
+                {
+                    s->Indent();
+                    s->Printf("%s\n", name.c_str());
+                }
+                s->IndentLess();
+            }
             s->IndentLess();
             s->EOL();
         }

Modified: lldb/trunk/source/Breakpoint/BreakpointID.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointID.cpp?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointID.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointID.cpp Tue Dec 16 17:40:14 2014
@@ -18,6 +18,7 @@
 #include "lldb/Breakpoint/BreakpointID.h"
 #include "lldb/Breakpoint/Breakpoint.h"
 #include "lldb/Core/Stream.h"
+#include "lldb/Core/Error.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -121,3 +122,19 @@ BreakpointID::ParseCanonicalReference (c
     return false;
 }
 
+bool
+BreakpointID::StringIsBreakpointName(const char *name, Error &error)
+{
+    error.Clear();
+
+    if (name && (name[0] >= 'A' && name[0] <= 'z'))
+    {
+        if (strcspn(name, ".- ") != strlen(name))
+        {
+            error.SetErrorStringWithFormat("invalid breakpoint name: \"%s\"", name);
+        }
+        return true;
+    }
+    else
+        return false;
+}

Modified: lldb/trunk/source/Breakpoint/BreakpointIDList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointIDList.cpp?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointIDList.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointIDList.cpp Tue Dec 16 17:40:14 2014
@@ -159,27 +159,52 @@ BreakpointIDList::InsertStringArray (con
 //  NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced by the members of the range.
 
 void
-BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result,
+BreakpointIDList::FindAndReplaceIDRanges (Args &old_args,
+                                          Target *target,
+                                          bool allow_locations,
+                                          CommandReturnObject &result,
                                           Args &new_args)
 {
     std::string range_start;
     const char *range_end;
     const char *current_arg;
     const size_t num_old_args = old_args.GetArgumentCount();
+    std::set<std::string> names_found;
 
     for (size_t i = 0; i < num_old_args; ++i)
     {
         bool is_range = false;
+
         current_arg = old_args.GetArgumentAtIndex (i);
+        if (!allow_locations && strchr(current_arg, '.') != nullptr)
+        {
+            result.AppendErrorWithFormat ("Breakpoint locations not allowed, saw location: %s.", current_arg);
+            new_args.Clear();
+            return;
+        }
 
         size_t range_start_len = 0;
         size_t range_end_pos = 0;
+        Error error;
+
         if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos))
         {
             is_range = true;
             range_start.assign (current_arg, range_start_len);
             range_end = current_arg + range_end_pos;
         }
+        else if (BreakpointID::StringIsBreakpointName(current_arg, error))
+        {
+            if (!error.Success())
+            {
+                new_args.Clear();
+                result.AppendError (error.AsCString());
+                result.SetStatus (eReturnStatusFailed);
+                return;
+            }
+            else
+                names_found.insert(current_arg);
+        }
         else if ((i + 2 < num_old_args)
                  && BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1))
                  && BreakpointID::IsValidIDExpression (current_arg)
@@ -342,6 +367,23 @@ BreakpointIDList::FindAndReplaceIDRanges
         }
     }
 
+    // Okay, now see if we found any names, and if we did, add them:
+    if (target && names_found.size())
+    {
+        for (BreakpointSP bkpt_sp : target->GetBreakpointList().Breakpoints())
+        {
+            for (std::string name : names_found)
+            {
+                if (bkpt_sp->MatchesName(name.c_str()))
+                {
+                    StreamString canonical_id_str;
+                    BreakpointID::GetCanonicalReference (&canonical_id_str, bkpt_sp->GetID(), LLDB_INVALID_BREAK_ID);
+                    new_args.AppendArgument (canonical_id_str.GetData());
+                }
+            }
+        }
+    }
+
     result.SetStatus (eReturnStatusSuccessFinishNoResult);
     return;
 }

Modified: lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointOptions.cpp?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointOptions.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointOptions.cpp Tue Dec 16 17:40:14 2014
@@ -237,8 +237,7 @@ BreakpointOptions::GetDescription (Strea
         
         if (m_thread_spec_ap.get())
             m_thread_spec_ap->GetDescription (s, level);
-        else if (level == eDescriptionLevelBrief)
-            s->PutCString ("thread spec: no ");
+
         if (level == lldb::eDescriptionLevelFull)
         {
             s->IndentLess();

Modified: lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp Tue Dec 16 17:40:14 2014
@@ -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"
@@ -240,6 +242,13 @@ public:
                     m_func_name_type_mask |= eFunctionNameTypeAuto;
                     break;
 
+                case 'N':
+                    if (BreakpointID::StringIsBreakpointName(option_arg, error))
+                        m_breakpoint_names.push_back (option_arg);
+                    else
+                        error.SetErrorStringWithFormat(error.AsCString());
+                    break;
+
                 case 'o':
                     m_one_shot = true;
                     break;
@@ -329,6 +338,7 @@ public:
             m_skip_prologue = eLazyBoolCalculate;
             m_one_shot = false;
             m_use_dummy = false;
+            m_breakpoint_names.clear();
         }
     
         const OptionDefinition*
@@ -348,6 +358,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;
@@ -558,6 +569,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);
         }
@@ -719,6 +737,9 @@ CommandObjectBreakpointSet::CommandOptio
     { 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 }
 };
 
@@ -954,7 +975,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())
         {
@@ -1106,7 +1127,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())
             {
@@ -1226,7 +1247,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())
             {
@@ -1419,7 +1440,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())
             {
@@ -1806,7 +1827,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())
             {
@@ -1861,6 +1882,401 @@ CommandObjectBreakpointDelete::CommandOp
 };
 
 //-------------------------------------------------------------------------
+// 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
 //-------------------------------------------------------------------------
 #pragma mark MultiwordBreakpoint
@@ -1879,6 +2295,7 @@ CommandObjectMultiwordBreakpoint::Comman
     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");
@@ -1888,6 +2305,7 @@ CommandObjectMultiwordBreakpoint::Comman
     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);
@@ -1897,6 +2315,7 @@ CommandObjectMultiwordBreakpoint::Comman
     LoadSubCommand ("set",        set_command_object);
     LoadSubCommand ("command",    command_command_object);
     LoadSubCommand ("modify",     modify_command_object);
+    LoadSubCommand ("name",       name_command_object);
 }
 
 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()
@@ -1904,13 +2323,17 @@ CommandObjectMultiwordBreakpoint::~Comma
 }
 
 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;
@@ -1934,7 +2357,7 @@ CommandObjectMultiwordBreakpoint::Verify
     // 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:
 

Modified: lldb/trunk/source/Commands/CommandObjectBreakpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpoint.h?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpoint.h (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpoint.h Tue Dec 16 17:40:14 2014
@@ -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

Modified: lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp Tue Dec 16 17:40:14 2014
@@ -467,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();
         
@@ -714,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())
         {
@@ -824,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())
         {

Modified: lldb/trunk/source/Interpreter/CommandObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=224392&r1=224391&r2=224392&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObject.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObject.cpp Tue Dec 16 17:40:14 2014
@@ -748,6 +748,22 @@ BreakpointIDRangeHelpTextCallback ()
 }
 
 static const char *
+BreakpointNameHelpTextCallback ()
+{
+    return "A name that can be added to a breakpoint when it is created, or later "
+    "on with the \"breakpoint name add\" command.  "
+    "Breakpoint names can be used to specify breakpoints in all the places breakpoint ID's "
+    "and breakpoint ID ranges can be used.  As such they provide a convenient way to group breakpoints, "
+    "and to operate on breakpoints you create without having to track the breakpoint number.  "
+    "Note, the attributes you set when using a breakpoint name in a breakpoint command don't "
+    "adhere to the name, but instead are set individually on all the breakpoints currently tagged with that name.  Future breakpoints "
+    "tagged with that name will not pick up the attributes previously given using that name.  "
+    "In order to distinguish breakpoint names from breakpoint ID's and ranges, "
+    "names must start with a letter from a-z or A-Z and cannot contain spaces, \".\" or \"-\".  "
+    "Also, breakpoint names can only be applied to breakpoints, not to breakpoint locations.";
+}
+
+static const char *
 GDBFormatHelpTextCallback ()
 {
     return "A GDB format consists of a repeat count, a format letter and a size letter. "
@@ -1112,6 +1128,7 @@ CommandObject::g_arguments_data[] =
     { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { nullptr, false }, "A Boolean value: 'true' or 'false'" },
     { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, nullptr },
     { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, nullptr },
+    { eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eNoCompletion, { BreakpointNameHelpTextCallback, false }, nullptr },
     { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { nullptr, false }, "Number of bytes to use." },
     { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { nullptr, false }, "Then name of a class from the debug information in the program." },
     { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." },





More information about the lldb-commits mailing list