summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/API/LLDB.h1
-rw-r--r--lldb/include/lldb/API/SBBreakpoint.h10
-rw-r--r--lldb/include/lldb/API/SBBreakpointLocation.h1
-rw-r--r--lldb/include/lldb/API/SBBreakpointName.h115
-rw-r--r--lldb/include/lldb/API/SBDebugger.h2
-rw-r--r--lldb/include/lldb/API/SBDefines.h6
-rw-r--r--lldb/include/lldb/API/SBError.h1
-rw-r--r--lldb/include/lldb/API/SBStream.h1
-rw-r--r--lldb/include/lldb/API/SBStringList.h1
-rw-r--r--lldb/include/lldb/API/SBTarget.h5
-rw-r--r--lldb/include/lldb/API/SBThread.h1
-rw-r--r--lldb/include/lldb/Breakpoint/Breakpoint.h38
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointIDList.h4
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointList.h9
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointName.h213
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointOptions.h38
-rw-r--r--lldb/include/lldb/Target/Target.h39
-rw-r--r--lldb/include/lldb/lldb-forward.h2
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj26
-rw-r--r--lldb/lldb.xcodeproj/xcshareddata/xcschemes/LLDB.xcscheme2
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py2
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py2
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py247
-rw-r--r--lldb/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py11
-rw-r--r--lldb/packages/Python/lldbsuite/test/python_api/default-constructor/sb_breakpointname.py42
-rw-r--r--lldb/scripts/Python/python-extensions.swig15
-rw-r--r--lldb/scripts/Python/python-swigsafecast.swig7
-rw-r--r--lldb/scripts/interface/SBBreakpoint.i6
-rw-r--r--lldb/scripts/interface/SBBreakpointName.i108
-rw-r--r--lldb/scripts/interface/SBDebugger.i5
-rw-r--r--lldb/scripts/interface/SBTarget.i4
-rw-r--r--lldb/scripts/lldb.swig2
-rw-r--r--lldb/source/API/SBBreakpoint.cpp68
-rw-r--r--lldb/source/API/SBBreakpointName.cpp662
-rw-r--r--lldb/source/API/SBBreakpointOptionCommon.cpp84
-rw-r--r--lldb/source/API/SBBreakpointOptionCommon.h35
-rw-r--r--lldb/source/API/SBDebugger.cpp14
-rw-r--r--lldb/source/API/SBTarget.cpp33
-rw-r--r--lldb/source/Breakpoint/Breakpoint.cpp20
-rw-r--r--lldb/source/Breakpoint/BreakpointID.cpp11
-rw-r--r--lldb/source/Breakpoint/BreakpointIDList.cpp34
-rw-r--r--lldb/source/Breakpoint/BreakpointList.cpp33
-rw-r--r--lldb/source/Breakpoint/BreakpointName.cpp88
-rw-r--r--lldb/source/Breakpoint/BreakpointOptions.cpp91
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp1017
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.h19
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.cpp9
-rw-r--r--lldb/source/Interpreter/CommandObject.cpp3
-rw-r--r--lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp24
-rw-r--r--lldb/source/Target/Target.cpp140
50 files changed, 2744 insertions, 607 deletions
diff --git a/lldb/include/lldb/API/LLDB.h b/lldb/include/lldb/API/LLDB.h
index 3638c63a165..c51ced893d7 100644
--- a/lldb/include/lldb/API/LLDB.h
+++ b/lldb/include/lldb/API/LLDB.h
@@ -18,6 +18,7 @@
#include "lldb/API/SBAttachInfo.h"
#include "lldb/API/SBBlock.h"
#include "lldb/API/SBBreakpoint.h"
+#include "lldb/API/SBBreakpointName.h"
#include "lldb/API/SBBreakpointLocation.h"
#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBCommandInterpreter.h"
diff --git a/lldb/include/lldb/API/SBBreakpoint.h b/lldb/include/lldb/API/SBBreakpoint.h
index bdf2f650b52..216d675b9d2 100644
--- a/lldb/include/lldb/API/SBBreakpoint.h
+++ b/lldb/include/lldb/API/SBBreakpoint.h
@@ -18,9 +18,6 @@ namespace lldb {
class LLDB_API SBBreakpoint {
public:
- typedef bool (*BreakpointHitCallback)(void *baton, SBProcess &process,
- SBThread &thread,
- lldb::SBBreakpointLocation &location);
SBBreakpoint();
@@ -90,7 +87,7 @@ public:
const char *GetQueueName() const;
- void SetCallback(BreakpointHitCallback callback, void *baton);
+ void SetCallback(SBBreakpointHitCallback callback, void *baton);
void SetScriptCallbackFunction(const char *callback_function_name);
@@ -133,14 +130,11 @@ public:
private:
friend class SBBreakpointList;
friend class SBBreakpointLocation;
+ friend class SBBreakpointName;
friend class SBTarget;
SBBreakpoint(const lldb::BreakpointSP &bp_sp);
- static bool PrivateBreakpointHitCallback(
- void *baton, lldb_private::StoppointCallbackContext *context,
- lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
-
lldb::BreakpointSP GetSP() const;
lldb::BreakpointWP m_opaque_wp;
diff --git a/lldb/include/lldb/API/SBBreakpointLocation.h b/lldb/include/lldb/API/SBBreakpointLocation.h
index 5b942f362ea..4b34bcbf1f2 100644
--- a/lldb/include/lldb/API/SBBreakpointLocation.h
+++ b/lldb/include/lldb/API/SBBreakpointLocation.h
@@ -86,6 +86,7 @@ public:
private:
friend class SBBreakpoint;
+ friend class SBBreakpointCallbackBaton;
void SetLocation(const lldb::BreakpointLocationSP &break_loc_sp);
BreakpointLocationSP GetSP() const;
diff --git a/lldb/include/lldb/API/SBBreakpointName.h b/lldb/include/lldb/API/SBBreakpointName.h
new file mode 100644
index 00000000000..34d7db0d7da
--- /dev/null
+++ b/lldb/include/lldb/API/SBBreakpointName.h
@@ -0,0 +1,115 @@
+//===-- SBBreakpointName.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SBBreakpointName_h_
+#define LLDB_SBBreakpointName_h_
+
+#include "lldb/API/SBDefines.h"
+
+class SBBreakpointNameImpl;
+
+namespace lldb {
+
+class LLDB_API SBBreakpointName {
+public:
+// typedef bool (*BreakpointHitCallback)(void *baton, SBProcess &process,
+// SBThread &thread,
+// lldb::SBBreakpointLocation &location);
+
+ SBBreakpointName();
+
+ SBBreakpointName(SBTarget &target, const char *name);
+
+ SBBreakpointName(SBBreakpoint &bkpt, const char *name);
+
+ SBBreakpointName(const lldb::SBBreakpointName &rhs);
+
+ ~SBBreakpointName();
+
+ const lldb::SBBreakpointName &operator=(const lldb::SBBreakpointName &rhs);
+
+ // Tests to see if the opaque breakpoint object in this object matches the
+ // opaque breakpoint object in "rhs".
+ bool operator==(const lldb::SBBreakpointName &rhs);
+
+ bool operator!=(const lldb::SBBreakpointName &rhs);
+
+ bool IsValid() const;
+
+ const char *GetName() const;
+
+ void SetEnabled(bool enable);
+
+ bool IsEnabled();
+
+ void SetOneShot(bool one_shot);
+
+ bool IsOneShot() const;
+
+ void SetIgnoreCount(uint32_t count);
+
+ uint32_t GetIgnoreCount() const;
+
+ void SetCondition(const char *condition);
+
+ const char *GetCondition();
+
+ void SetAutoContinue(bool auto_continue);
+
+ bool GetAutoContinue();
+
+ void SetThreadID(lldb::tid_t sb_thread_id);
+
+ lldb::tid_t GetThreadID();
+
+ void SetThreadIndex(uint32_t index);
+
+ uint32_t GetThreadIndex() const;
+
+ void SetThreadName(const char *thread_name);
+
+ const char *GetThreadName() const;
+
+ void SetQueueName(const char *queue_name);
+
+ const char *GetQueueName() const;
+
+ void SetCallback(SBBreakpointHitCallback callback, void *baton);
+
+ void SetScriptCallbackFunction(const char *callback_function_name);
+
+ void SetCommandLineCommands(SBStringList &commands);
+
+ bool GetCommandLineCommands(SBStringList &commands);
+
+ SBError SetScriptCallbackBody(const char *script_body_text);
+
+ bool GetAllowList() const;
+ void SetAllowList(bool value);
+
+ bool GetAllowDelete();
+ void SetAllowDelete(bool value);
+
+ bool GetAllowDisable();
+ void SetAllowDisable(bool value);
+
+ bool GetDescription(lldb::SBStream &description);
+
+private:
+ friend class SBTarget;
+
+ lldb_private::BreakpointName *GetBreakpointName() const;
+ void UpdateName(lldb_private::BreakpointName &bp_name);
+
+ std::unique_ptr<SBBreakpointNameImpl> m_impl_up;
+};
+
+} // namespace lldb
+
+#endif // LLDB_SBBreakpointName_h_
diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h
index 28088b1b36b..8379a6911af 100644
--- a/lldb/include/lldb/API/SBDebugger.h
+++ b/lldb/include/lldb/API/SBDebugger.h
@@ -109,6 +109,8 @@ public:
const char *archname);
lldb::SBTarget CreateTarget(const char *filename);
+
+ lldb::SBTarget GetDummyTarget();
// Return true if target is deleted from the target list of the debugger.
bool DeleteTarget(lldb::SBTarget &target);
diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h
index 6c545ee2061..ec92c919673 100644
--- a/lldb/include/lldb/API/SBDefines.h
+++ b/lldb/include/lldb/API/SBDefines.h
@@ -32,6 +32,8 @@ class LLDB_API SBAddress;
class LLDB_API SBBlock;
class LLDB_API SBBreakpoint;
class LLDB_API SBBreakpointLocation;
+class LLDB_API SBBreakpointName;
+class LLDB_API SBBreakpointNameImpl;
class LLDB_API SBBroadcaster;
class LLDB_API SBCommand;
class LLDB_API SBCommandInterpreter;
@@ -99,6 +101,10 @@ class LLDB_API SBValueList;
class LLDB_API SBVariablesOptions;
class LLDB_API SBWatchpoint;
class LLDB_API SBUnixSignals;
+
+typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process,
+ SBThread &thread,
+ lldb::SBBreakpointLocation &location);
}
#endif // LLDB_SBDefines_h_
diff --git a/lldb/include/lldb/API/SBError.h b/lldb/include/lldb/API/SBError.h
index a099a9be271..a27d2d04269 100644
--- a/lldb/include/lldb/API/SBError.h
+++ b/lldb/include/lldb/API/SBError.h
@@ -67,6 +67,7 @@ protected:
friend class SBWatchpoint;
friend class SBBreakpoint;
friend class SBBreakpointLocation;
+ friend class SBBreakpointName;
lldb_private::Status *get();
diff --git a/lldb/include/lldb/API/SBStream.h b/lldb/include/lldb/API/SBStream.h
index 68fcae21c08..a75afc7ee37 100644
--- a/lldb/include/lldb/API/SBStream.h
+++ b/lldb/include/lldb/API/SBStream.h
@@ -53,6 +53,7 @@ protected:
friend class SBBlock;
friend class SBBreakpoint;
friend class SBBreakpointLocation;
+ friend class SBBreakpointName;
friend class SBCommandReturnObject;
friend class SBCompileUnit;
friend class SBData;
diff --git a/lldb/include/lldb/API/SBStringList.h b/lldb/include/lldb/API/SBStringList.h
index c50594db07f..943384e544c 100644
--- a/lldb/include/lldb/API/SBStringList.h
+++ b/lldb/include/lldb/API/SBStringList.h
@@ -45,6 +45,7 @@ protected:
friend class SBDebugger;
friend class SBBreakpoint;
friend class SBBreakpointLocation;
+ friend class SBBreakpointName;
SBStringList(const lldb_private::StringList *lldb_strings);
diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h
index 1ea96381884..4085a16b43f 100644
--- a/lldb/include/lldb/API/SBTarget.h
+++ b/lldb/include/lldb/API/SBTarget.h
@@ -716,6 +716,10 @@ public:
// Finds all breakpoints by name, returning the list in bkpt_list. Returns
// false if the name is not a valid breakpoint name, true otherwise.
bool FindBreakpointsByName(const char *name, SBBreakpointList &bkpt_list);
+
+ void GetBreakpointNames(SBStringList &names);
+
+ void DeleteBreakpointName(const char *name);
bool EnableAllBreakpoints();
@@ -810,6 +814,7 @@ protected:
friend class SBAddress;
friend class SBBlock;
friend class SBBreakpointList;
+ friend class SBBreakpointNameImpl;
friend class SBDebugger;
friend class SBExecutionContext;
friend class SBFunction;
diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h
index 502e5c973ef..7f1cf10cc45 100644
--- a/lldb/include/lldb/API/SBThread.h
+++ b/lldb/include/lldb/API/SBThread.h
@@ -196,6 +196,7 @@ public:
protected:
friend class SBBreakpoint;
friend class SBBreakpointLocation;
+ friend class SBBreakpointCallbackBaton;
friend class SBExecutionContext;
friend class SBFrame;
friend class SBProcess;
diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h
index 6deaeaad2b9..9a798090a59 100644
--- a/lldb/include/lldb/Breakpoint/Breakpoint.h
+++ b/lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -22,6 +22,7 @@
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/BreakpointLocationCollection.h"
#include "lldb/Breakpoint/BreakpointLocationList.h"
+#include "lldb/Breakpoint/BreakpointName.h"
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Breakpoint/Stoppoint.h"
#include "lldb/Core/Event.h"
@@ -603,6 +604,16 @@ public:
BreakpointOptions *GetOptions();
//------------------------------------------------------------------
+ /// Returns the BreakpointOptions structure set at the breakpoint level.
+ ///
+ /// Meant to be used by the BreakpointLocation class.
+ ///
+ /// @return
+ /// A pointer to this breakpoint's BreakpointOptions.
+ //------------------------------------------------------------------
+ const BreakpointOptions *GetOptions() const;
+
+ //------------------------------------------------------------------
/// Invoke the callback action when the breakpoint is hit.
///
/// Meant to be used by the BreakpointLocation class.
@@ -625,13 +636,16 @@ public:
lldb::SearchFilterSP GetSearchFilter() { return m_filter_sp; }
- bool AddName(llvm::StringRef new_name, Status &error);
+private: // The target needs to manage adding & removing names. It will do the
+ // checking for name validity as well.
+ bool AddName(llvm::StringRef new_name);
void RemoveName(const char *name_to_remove) {
if (name_to_remove)
m_name_list.erase(name_to_remove);
}
-
+
+public:
bool MatchesName(const char *name) {
return m_name_list.find(name) != m_name_list.end();
}
@@ -663,6 +677,25 @@ public:
bool EvaluatePrecondition(StoppointCallbackContext &context);
BreakpointPreconditionSP GetPrecondition() { return m_precondition_sp; }
+
+ // Produces the OR'ed values for all the names assigned to this breakpoint.
+ const BreakpointName::Permissions &GetPermissions() const {
+ return m_permissions;
+ }
+
+ BreakpointName::Permissions &GetPermissions() {
+ return m_permissions;
+ }
+
+ bool AllowList() const {
+ return GetPermissions().GetAllowList();
+ }
+ bool AllowDisable() const {
+ return GetPermissions().GetAllowDisable();
+ }
+ bool AllowDelete() const {
+ return GetPermissions().GetAllowDelete();
+ }
protected:
friend class Target;
@@ -762,6 +795,7 @@ private:
// hit. This is kept
// separately from the locations hit counts, since locations can go away when
// their backing library gets unloaded, and we would lose hit counts.
+ BreakpointName::Permissions m_permissions;
void SendBreakpointChangedEvent(lldb::BreakpointEventType eventKind);
diff --git a/lldb/include/lldb/Breakpoint/BreakpointIDList.h b/lldb/include/lldb/Breakpoint/BreakpointIDList.h
index 34cfbfe3268..5877b6c551a 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointIDList.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointIDList.h
@@ -18,7 +18,9 @@
// Other libraries and framework includes
// Project includes
+#include "lldb/lldb-enumerations.h"
#include "lldb/Breakpoint/BreakpointID.h"
+#include "lldb/Breakpoint/BreakpointName.h"
#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -64,6 +66,8 @@ public:
static void FindAndReplaceIDRanges(Args &old_args, Target *target,
bool allow_locations,
+ BreakpointName::Permissions
+ ::PermissionKinds purpose,
CommandReturnObject &result,
Args &new_args);
diff --git a/lldb/include/lldb/Breakpoint/BreakpointList.h b/lldb/include/lldb/Breakpoint/BreakpointList.h
index 2865288acc5..9f38f8aa120 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointList.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointList.h
@@ -154,12 +154,21 @@ public:
void SetEnabledAll(bool enabled);
+ void SetEnabledAllowed(bool enabled);
+
//------------------------------------------------------------------
/// Removes all the breakpoints from this list.
//------------------------------------------------------------------
void RemoveAll(bool notify);
//------------------------------------------------------------------
+ /// Removes all the breakpoints from this list - first checking the
+ /// ePermDelete on the breakpoints. This call should be used unless you
+ /// are shutting down and need to actually clear them all.
+ //------------------------------------------------------------------
+ void RemoveAllowed(bool notify);
+
+ //------------------------------------------------------------------
/// Tell all the breakpoints to update themselves due to a change in the
/// modules in \a module_list. \a added says whether the module was loaded
/// or unloaded.
diff --git a/lldb/include/lldb/Breakpoint/BreakpointName.h b/lldb/include/lldb/Breakpoint/BreakpointName.h
new file mode 100644
index 00000000000..1cfa141011a
--- /dev/null
+++ b/lldb/include/lldb/Breakpoint/BreakpointName.h
@@ -0,0 +1,213 @@
+//===-- BreakpointName.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Breakpoint_Name_h_
+#define liblldb_Breakpoint_Name_h_
+
+// C Includes
+// C++ Includes
+#include <memory>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointID.h"
+#include "lldb/Breakpoint/BreakpointLocationCollection.h"
+#include "lldb/Breakpoint/BreakpointLocationList.h"
+#include "lldb/Breakpoint/BreakpointOptions.h"
+#include "lldb/Breakpoint/Stoppoint.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Utility/Flags.h"
+#include "lldb/Utility/StringList.h"
+#include "lldb/Utility/StructuredData.h"
+
+namespace lldb_private {
+
+class BreakpointName {
+public:
+ class Permissions
+ {
+ public:
+
+ enum PermissionKinds { listPerm = 0, disablePerm = 1,
+ deletePerm = 2, allPerms = 3 };
+
+ Permissions(bool in_list, bool in_disable, bool in_delete)
+ {
+ m_permissions[listPerm] = in_list;
+ m_permissions[disablePerm] = in_disable;
+ m_permissions[deletePerm] = in_delete;
+ m_set_mask.Set(permissions_mask[allPerms]);
+ }
+
+ Permissions(const Permissions &rhs)
+ {
+ m_permissions[listPerm] = rhs.m_permissions[listPerm];
+ m_permissions[disablePerm] = rhs.m_permissions[disablePerm];
+ m_permissions[deletePerm] = rhs.m_permissions[deletePerm];
+ m_set_mask = rhs.m_set_mask;
+ }
+
+ Permissions()
+ {
+ m_permissions[listPerm] = true;
+ m_permissions[disablePerm] = true;
+ m_permissions[deletePerm] = true;
+ m_set_mask.Clear();
+ }
+
+ const Permissions &operator= (const Permissions &rhs)
+ {
+ if (this != &rhs) {
+ m_permissions[listPerm] = rhs.m_permissions[listPerm];
+ m_permissions[disablePerm] = rhs.m_permissions[disablePerm];
+ m_permissions[deletePerm] = rhs.m_permissions[deletePerm];
+ m_set_mask = rhs.m_set_mask;
+ }
+ return *this;
+ }
+
+ void Clear() {
+ *this = Permissions();
+ }
+
+ // Merge the permissions from incoming into this set of permissions.
+ // Only merge set permissions, and most restrictive permission wins.
+ void MergeInto(const Permissions &incoming)
+ {
+ MergePermission(incoming, listPerm);
+ MergePermission(incoming, disablePerm);
+ MergePermission(incoming, deletePerm);
+ }
+
+ bool GetAllowList() const { return GetPermission(listPerm); }
+ bool SetAllowList(bool value) { return SetPermission(listPerm, value); }
+
+ bool GetAllowDelete() const { return GetPermission(deletePerm); }
+ bool SetAllowDelete(bool value) { return SetPermission(deletePerm, value); }
+
+ bool GetAllowDisable() const { return GetPermission(disablePerm); }
+ bool SetAllowDisable(bool value) { return SetPermission(disablePerm,
+ value); }
+
+ bool GetPermission(enum PermissionKinds permission) const
+ {
+ return m_permissions[permission];
+ }
+
+ bool GetDescription(Stream *s, lldb::DescriptionLevel level);
+
+ bool IsSet(enum PermissionKinds permission) const
+ {
+ return m_set_mask.Test(permissions_mask[permission]);
+ }
+
+ bool AnySet() {
+ return m_set_mask.AnySet(permissions_mask[allPerms]);
+ }
+
+ private:
+ static const Flags::ValueType permissions_mask[allPerms + 1];
+
+ bool m_permissions[allPerms];
+ Flags m_set_mask;
+
+ bool SetPermission(enum PermissionKinds permission, bool value)
+ {
+ bool old_value = m_permissions[permission];
+ m_permissions[permission] = value;
+ m_set_mask.Set(permissions_mask[permission]);
+ return old_value;
+ }
+
+ // If either side disallows the permission, the resultant disallows it.
+ void MergePermission(const Permissions &incoming,
+ enum PermissionKinds permission)
+ {
+ if (incoming.IsSet(permission))
+ {
+ SetPermission(permission, !(m_permissions[permission] |
+ incoming.m_permissions[permission]));
+ }
+ }
+ };
+
+ BreakpointName(const ConstString &name, const char *help = nullptr) :
+ m_name(name), m_options(false)
+ {
+ SetHelp(help);
+ }
+
+ BreakpointName(const ConstString &name,
+ BreakpointOptions &options,
+ const Permissions &permissions = Permissions(),
+ const char *help = nullptr) :
+ m_name(name), m_options(options),
+ m_permissions(permissions) {
+ SetHelp(help);
+ };
+
+ BreakpointName(const BreakpointName &rhs) :
+ m_name(rhs.m_name), m_options(rhs.m_options),
+ m_permissions(rhs.m_permissions), m_help(rhs.m_help)
+ {}
+
+ BreakpointName(const ConstString &name, const Breakpoint &bkpt,
+ const char *help);
+
+ const ConstString &GetName() const { return m_name; }
+ BreakpointOptions &GetOptions() { return m_options; }
+ const BreakpointOptions &GetOptions() const { return m_options; }
+
+ void SetOptions(const BreakpointOptions &options) {
+ m_options = options;
+ }
+
+ Permissions &GetPermissions() { return m_permissions; }
+ const Permissions &GetPermissions() const { return m_permissions; }
+ void SetPermissions(const Permissions &permissions) {
+ m_permissions = permissions;
+ }
+
+ bool GetPermission(Permissions::PermissionKinds permission) const
+ {
+ return m_permissions.GetPermission(permission);
+ }
+
+ void SetHelp(const char *description)
+ {
+ if (description)
+ m_help.assign(description);
+ else
+ m_help.clear();
+ }
+
+ const char *GetHelp()
+ {
+ return m_help.c_str();
+ }
+
+ // Returns true if any options were set in the name
+ bool GetDescription(Stream *s, lldb::DescriptionLevel level);
+
+ void ConfigureBreakpoint(lldb::BreakpointSP bp_sp);
+
+private:
+ ConstString m_name;
+ BreakpointOptions m_options;
+ Permissions m_permissions;
+ std::string m_help;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Breakpoint_Name_h_
diff --git a/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
index b0276cb1568..0229d52df47 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointOptions.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
@@ -34,6 +34,8 @@ namespace lldb_private {
class BreakpointOptions {
friend class BreakpointLocation;
+friend class BreakpointName;
+friend class lldb_private::BreakpointOptionGroup;
friend class Breakpoint;
public:
@@ -44,7 +46,9 @@ public:
eIgnoreCount = 1 << 3,
eThreadSpec = 1 << 4,
eCondition = 1 << 5,
- eAutoContinue = 1 << 6
+ eAutoContinue = 1 << 6,
+ eAllOptions = (eCallback | eEnabled | eOneShot | eIgnoreCount | eThreadSpec
+ | eCondition | eAutoContinue)
};
struct CommandData {
CommandData()
@@ -98,6 +102,10 @@ public:
typedef std::shared_ptr<CommandBaton> CommandBatonSP;
//------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
/// This constructor allows you to specify all the breakpoint options
/// except the callback. That one is more complicated, and better
/// to do by hand.
@@ -116,6 +124,13 @@ public:
int32_t ignore = 0, bool one_shot = false,
bool auto_continue = false);
+ //------------------------------------------------------------------
+ /// Breakpoints make options with all flags set. Locations and Names make options
+ /// with no flags set.
+ //------------------------------------------------------------------
+ BreakpointOptions(bool all_flags_set);
+ BreakpointOptions(const BreakpointOptions &rhs);
+
virtual ~BreakpointOptions();
static std::unique_ptr<BreakpointOptions>
@@ -131,6 +146,11 @@ public:
// Operators
//------------------------------------------------------------------
const BreakpointOptions &operator=(const BreakpointOptions &rhs);
+
+ //------------------------------------------------------------------
+ /// Copy over only the options set in the incoming BreakpointOptions.
+ //------------------------------------------------------------------
+ void CopyOverSetOptions(const BreakpointOptions &rhs);
//------------------------------------------------------------------
// Callbacks
@@ -387,17 +407,13 @@ public:
//------------------------------------------------------------------
void SetCommandDataCallback(std::unique_ptr<CommandData> &cmd_data);
+ void Clear();
+
+ bool AnySet() const {
+ return m_set_flags.AnySet(eAllOptions);
+ }
+
protected:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- //------------------------------------------------------------------
- /// Breakpoints make options with all flags set. Locations make options
- /// with no flags set. Nobody else should make breakpoint options.
- //------------------------------------------------------------------
- BreakpointOptions(bool all_flags_set);
- BreakpointOptions(const BreakpointOptions &rhs);
-
//------------------------------------------------------------------
// Classes that inherit from BreakpointOptions can see and modify these
//------------------------------------------------------------------
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index ff945193990..44f0b5ae28f 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -21,6 +21,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointList.h"
+#include "lldb/Breakpoint/BreakpointName.h"
#include "lldb/Breakpoint/WatchpointList.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Broadcaster.h"
@@ -651,12 +652,45 @@ public:
}
WatchpointList &GetWatchpointList() { return m_watchpoint_list; }
-
+
+ // Manages breakpoint names:
+ void AddNameToBreakpoint(BreakpointID &id, const char *name, Status &error);
+
+ void AddNameToBreakpoint(lldb::BreakpointSP &bp_sp, const char *name,
+ Status &error);
+
+ void RemoveNameFromBreakpoint(lldb::BreakpointSP &bp_sp,
+ const ConstString &name);
+
+ BreakpointName *FindBreakpointName(const ConstString &name, bool can_create,
+ Status &error);
+
+ void DeleteBreakpointName(const ConstString &name);
+
+ void ConfigureBreakpointName(BreakpointName &bp_name,
+ const BreakpointOptions &options,
+ const BreakpointName::Permissions &permissions);
+ void ApplyNameToBreakpoints(BreakpointName &bp_name);
+
+
+ // This takes ownership of the name obj passed in.
+ void AddBreakpointName(BreakpointName *bp_name);
+
+ void GetBreakpointNames(std::vector<std::string> &names);
+
+ //This call removes ALL breakpoints regardless of permission.
void RemoveAllBreakpoints(bool internal_also = false);
+
+ // This removes all the breakpoints, but obeys the ePermDelete on them.
+ void RemoveAllowedBreakpoints();
void DisableAllBreakpoints(bool internal_also = false);
+
+ void DisableAllowedBreakpoints();
void EnableAllBreakpoints(bool internal_also = false);
+
+ void EnableAllowedBreakpoints();
bool DisableBreakpointByID(lldb::break_id_t break_id);
@@ -1218,6 +1252,9 @@ protected:
SectionLoadHistory m_section_load_history;
BreakpointList m_breakpoint_list;
BreakpointList m_internal_breakpoint_list;
+ using BreakpointNameList = std::map<ConstString, BreakpointName *>;
+ BreakpointNameList m_breakpoint_names;
+
lldb::BreakpointSP m_last_created_breakpoint;
WatchpointList m_watchpoint_list;
lldb::WatchpointSP m_last_created_watchpoint;
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 392dc641558..a324edf9da3 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -38,6 +38,8 @@ class BreakpointList;
class BreakpointLocation;
class BreakpointLocationCollection;
class BreakpointLocationList;
+class BreakpointName;
+class BreakpointOptionGroup;
class BreakpointOptions;
class BreakpointResolver;
class BreakpointSite;
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index 1bf87375b68..0559ab9672e 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -714,18 +714,23 @@
49E4F66B1C9CAD16008487EA /* DiagnosticManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49E4F6681C9CAD12008487EA /* DiagnosticManager.cpp */; };
49F811F31E931B2100F4E163 /* CPlusPlusNameParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49F811EF1E931B1500F4E163 /* CPlusPlusNameParser.cpp */; };
4C0083401B9F9BA900D5CF24 /* UtilityFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */; };
+ 4C05332B1F62121E00DED368 /* SBBreakpointOptionCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C0533291F6211FB00DED368 /* SBBreakpointOptionCommon.cpp */; };
4C2479BD1BA39295009C9A7B /* FunctionCaller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */; };
4C3ADCD61810D88B00357218 /* BreakpointResolverFileRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */; };
4C4EB7811E6A4DCC002035C0 /* DumpDataExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C4EB77F1E6A4DB8002035C0 /* DumpDataExtractor.cpp */; };
+ 4C54B27B1F61CE2800D469CA /* SBBreakpointName.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C54B2781F61CE1200D469CA /* SBBreakpointName.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4C54B27E1F61CE6300D469CA /* SBBreakpointName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C54B27C1F61CE5300D469CA /* SBBreakpointName.cpp */; };
4C562CC71CC07DF700C52EAC /* PDBASTParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C562CC21CC07DDD00C52EAC /* PDBASTParser.cpp */; };
4C56543119D1EFAA002E9C44 /* ThreadPlanPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */; };
4C56543519D2297A002E9C44 /* SBThreadPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C56543419D2297A002E9C44 /* SBThreadPlan.h */; settings = {ATTRIBUTES = (Public, ); }; };
4C56543719D22B32002E9C44 /* SBThreadPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */; };
4C7D48241F5099A1005314B4 /* SymbolFileDWARFDwp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D481C1F509963005314B4 /* SymbolFileDWARFDwp.cpp */; };
4C7D48251F5099B2005314B4 /* SymbolFileDWARFDwoDwp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D481F1F509964005314B4 /* SymbolFileDWARFDwoDwp.cpp */; };
+ 4C7D482C1F509CF5005314B4 /* BreakpointName.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7D482B1F509CF5005314B4 /* BreakpointName.h */; };
4C877B391F30EF990068FCFB /* SBProcessInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4987FB201F30EC9900E5C17D /* SBProcessInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
4C88BC2A1BA3722B00AA0964 /* Expression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C88BC291BA3722B00AA0964 /* Expression.cpp */; };
4C88BC2D1BA391B000AA0964 /* UserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C0083331B9A5DE200D5CF24 /* UserExpression.cpp */; };
+ 4CAA19E61F5A40040099E692 /* BreakpointName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D48281F509CCD005314B4 /* BreakpointName.cpp */; };
4CABA9E0134A8BCD00539BDD /* ValueObjectMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */; };
4CC7C6501D5298F30076FF94 /* OCamlLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7C64D1D5298E20076FF94 /* OCamlLanguage.cpp */; };
4CC7C6571D52997A0076FF94 /* OCamlASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7C6551D52996C0076FF94 /* OCamlASTContext.cpp */; };
@@ -1230,6 +1235,7 @@
files = (
9A20570F1F3B821A00F6C293 /* test-dwarf.cpp in CopyFiles */,
9A2057101F3B821A00F6C293 /* test-dwarf.exe in CopyFiles */,
+ 4C7D482C1F509CF5005314B4 /* BreakpointName.h in CopyFiles */,
AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
@@ -2523,6 +2529,8 @@
4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UtilityFunction.cpp; path = source/Expression/UtilityFunction.cpp; sourceTree = "<group>"; };
4C00986F11500B4300F316B0 /* UnixSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnixSignals.h; path = include/lldb/Target/UnixSignals.h; sourceTree = "<group>"; };
4C00987011500B4300F316B0 /* UnixSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnixSignals.cpp; path = source/Target/UnixSignals.cpp; sourceTree = "<group>"; };
+ 4C0533291F6211FB00DED368 /* SBBreakpointOptionCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBreakpointOptionCommon.cpp; path = source/API/SBBreakpointOptionCommon.cpp; sourceTree = "<group>"; };
+ 4C05332C1F63092A00DED368 /* SBBreakpointName.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBBreakpointName.i; sourceTree = "<group>"; };
4C08CDE711C81EF8001610A8 /* ThreadSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadSpec.cpp; path = source/Target/ThreadSpec.cpp; sourceTree = "<group>"; };
4C08CDEB11C81F1E001610A8 /* ThreadSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSpec.h; path = include/lldb/Target/ThreadSpec.h; sourceTree = "<group>"; };
4C09CB73116BD98B00C7A725 /* CommandCompletions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandCompletions.h; path = include/lldb/Interpreter/CommandCompletions.h; sourceTree = "<group>"; };
@@ -2539,6 +2547,9 @@
4C43DF8A11069C3200E55CBF /* ThreadPlanStepOverRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepOverRange.cpp; path = source/Target/ThreadPlanStepOverRange.cpp; sourceTree = "<group>"; };
4C4EB77F1E6A4DB8002035C0 /* DumpDataExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DumpDataExtractor.cpp; path = source/Core/DumpDataExtractor.cpp; sourceTree = "<group>"; };
4C4EB7821E6A4DE7002035C0 /* DumpDataExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DumpDataExtractor.h; path = include/lldb/Core/DumpDataExtractor.h; sourceTree = "<group>"; };
+ 4C54B2781F61CE1200D469CA /* SBBreakpointName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBBreakpointName.h; path = include/lldb/API/SBBreakpointName.h; sourceTree = "<group>"; };
+ 4C54B27C1F61CE5300D469CA /* SBBreakpointName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBreakpointName.cpp; path = source/API/SBBreakpointName.cpp; sourceTree = "<group>"; };
+ 4C54B2811F62081300D469CA /* SBBreakpointOptionCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBBreakpointOptionCommon.h; path = include/lldb/API/SBBreakpointOptionCommon.h; sourceTree = "<group>"; };
4C562CC21CC07DDD00C52EAC /* PDBASTParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PDBASTParser.cpp; path = PDB/PDBASTParser.cpp; sourceTree = "<group>"; };
4C562CC31CC07DDD00C52EAC /* PDBASTParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDBASTParser.h; path = PDB/PDBASTParser.h; sourceTree = "<group>"; };
4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanPython.cpp; path = source/Target/ThreadPlanPython.cpp; sourceTree = "<group>"; };
@@ -2555,6 +2566,8 @@
4C7D481D1F509964005314B4 /* SymbolFileDWARFDwoDwp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolFileDWARFDwoDwp.h; sourceTree = "<group>"; };
4C7D481E1F509964005314B4 /* SymbolFileDWARFDwp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolFileDWARFDwp.h; sourceTree = "<group>"; };
4C7D481F1F509964005314B4 /* SymbolFileDWARFDwoDwp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolFileDWARFDwoDwp.cpp; sourceTree = "<group>"; };
+ 4C7D48281F509CCD005314B4 /* BreakpointName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointName.cpp; path = source/Breakpoint/BreakpointName.cpp; sourceTree = "<group>"; };
+ 4C7D482B1F509CF5005314B4 /* BreakpointName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointName.h; path = include/lldb/Breakpoint/BreakpointName.h; sourceTree = "<group>"; };
4C88BC291BA3722B00AA0964 /* Expression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Expression.cpp; path = source/Expression/Expression.cpp; sourceTree = "<group>"; };
4C98D3DA118FB96F00E575D0 /* ClangFunctionCaller.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangFunctionCaller.cpp; path = ExpressionParser/Clang/ClangFunctionCaller.cpp; sourceTree = "<group>"; };
4C98D3DB118FB96F00E575D0 /* IRExecutionUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRExecutionUnit.cpp; path = source/Expression/IRExecutionUnit.cpp; sourceTree = "<group>"; };
@@ -2575,6 +2588,7 @@
4CB443BC1249920C00C13DC2 /* CPPLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CPPLanguageRuntime.cpp; path = source/Target/CPPLanguageRuntime.cpp; sourceTree = "<group>"; };
4CB443F212499B5000C13DC2 /* ObjCLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjCLanguageRuntime.cpp; path = source/Target/ObjCLanguageRuntime.cpp; sourceTree = "<group>"; };
4CB443F612499B6E00C13DC2 /* ObjCLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjCLanguageRuntime.h; path = include/lldb/Target/ObjCLanguageRuntime.h; sourceTree = "<group>"; };
+ 4CBFF0471F579A36004AFA92 /* Flags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Flags.h; path = include/lldb/Utility/Flags.h; sourceTree = "<group>"; };
4CC2A148128C73ED001531C4 /* ThreadPlanTracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanTracer.cpp; path = source/Target/ThreadPlanTracer.cpp; sourceTree = "<group>"; };
4CC2A14C128C7409001531C4 /* ThreadPlanTracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanTracer.h; path = include/lldb/Target/ThreadPlanTracer.h; sourceTree = "<group>"; };
4CC7C64C1D5298E20076FF94 /* OCamlLanguage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OCamlLanguage.h; path = Language/OCaml/OCamlLanguage.h; sourceTree = "<group>"; };
@@ -3939,6 +3953,7 @@
2611FEF0142D83060017FEA3 /* SBBlock.i */,
2611FEF1142D83060017FEA3 /* SBBreakpoint.i */,
2611FEF2142D83060017FEA3 /* SBBreakpointLocation.i */,
+ 4C05332C1F63092A00DED368 /* SBBreakpointName.i */,
2611FEF3142D83060017FEA3 /* SBBroadcaster.i */,
2611FEF4142D83060017FEA3 /* SBCommandInterpreter.i */,
2611FEF5142D83060017FEA3 /* SBCommandReturnObject.i */,
@@ -4032,6 +4047,10 @@
9AF16A9C11402D5B007A7B3F /* SBBreakpoint.cpp */,
9AF16CC611408686007A7B3F /* SBBreakpointLocation.h */,
9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */,
+ 4C54B2781F61CE1200D469CA /* SBBreakpointName.h */,
+ 4C54B27C1F61CE5300D469CA /* SBBreakpointName.cpp */,
+ 4C54B2811F62081300D469CA /* SBBreakpointOptionCommon.h */,
+ 4C0533291F6211FB00DED368 /* SBBreakpointOptionCommon.cpp */,
9A9830F31125FC5800A56CB0 /* SBBroadcaster.h */,
9A9830F21125FC5800A56CB0 /* SBBroadcaster.cpp */,
9A9830F71125FC5800A56CB0 /* SBCommandInterpreter.h */,
@@ -4353,6 +4372,7 @@
26BC7DD310F1B7D500F91463 /* Endian.h */,
AFC2DCE61E6E2ED000283714 /* FastDemangle.cpp */,
AFC2DCED1E6E2F9800283714 /* FastDemangle.h */,
+ 4CBFF0471F579A36004AFA92 /* Flags.h */,
AFC2DCF21E6E30CF00283714 /* History.cpp */,
AFC2DCF41E6E30D800283714 /* History.h */,
236124A61986B50E004EFC37 /* IOObject.h */,
@@ -5041,6 +5061,8 @@
26BC7E0F10F1B83100F91463 /* BreakpointLocationCollection.cpp */,
26BC7CF410F1B71400F91463 /* BreakpointLocationList.h */,
26BC7E1010F1B83100F91463 /* BreakpointLocationList.cpp */,
+ 4C7D48281F509CCD005314B4 /* BreakpointName.cpp */,
+ 4C7D482B1F509CF5005314B4 /* BreakpointName.h */,
26BC7CF510F1B71400F91463 /* BreakpointOptions.h */,
26BC7E1110F1B83100F91463 /* BreakpointOptions.cpp */,
26BC7CF610F1B71400F91463 /* BreakpointResolver.h */,
@@ -6662,6 +6684,7 @@
26C72C94124322890068DC16 /* SBStream.h in Headers */,
9A357671116E7B5200E8ED2F /* SBStringList.h in Headers */,
26DE205B11618FF600A093E2 /* SBSymbol.h in Headers */,
+ 4C54B27B1F61CE2800D469CA /* SBBreakpointName.h in Headers */,
262F12B71835469C00AEB384 /* SBPlatform.h in Headers */,
23DCBEA31D63E71F0084C36B /* SBStructuredData.h in Headers */,
26DE204111618AB900A093E2 /* SBSymbolContext.h in Headers */,
@@ -7266,6 +7289,7 @@
2668032C116005E2008E1FE4 /* SBFrame.cpp in Sources */,
2668032D116005E3008E1FE4 /* SBFileSpec.cpp in Sources */,
2668032E116005E5008E1FE4 /* SBEvent.cpp in Sources */,
+ 4C54B27E1F61CE6300D469CA /* SBBreakpointName.cpp in Sources */,
2668032F116005E6008E1FE4 /* SBError.cpp in Sources */,
23DCEA461D1C4D0F00A602B4 /* SBMemoryRegionInfo.cpp in Sources */,
26680330116005E7008E1FE4 /* SBDebugger.cpp in Sources */,
@@ -7289,6 +7313,7 @@
26DE20651161904E00A093E2 /* SBSymbol.cpp in Sources */,
9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */,
261744781168585B005ADD65 /* SBType.cpp in Sources */,
+ 4C05332B1F62121E00DED368 /* SBBreakpointOptionCommon.cpp in Sources */,
9A35758E116CFE0F00E8ED2F /* SBValueList.cpp in Sources */,
9A357673116E7B6400E8ED2F /* SBStringList.cpp in Sources */,
9A1E595C1EB2B141002206A5 /* SBTrace.cpp in Sources */,
@@ -7629,6 +7654,7 @@
947CF7771DC7B20D00EF980B /* ThreadMinidump.cpp in Sources */,
268900C913353E5F00698AC0 /* NameToDIE.cpp in Sources */,
268900CA13353E5F00698AC0 /* SymbolFileDWARF.cpp in Sources */,
+ 4CAA19E61F5A40040099E692 /* BreakpointName.cpp in Sources */,
268900CB13353E5F00698AC0 /* LogChannelDWARF.cpp in Sources */,
268900CC13353E5F00698AC0 /* SymbolFileDWARFDebugMap.cpp in Sources */,
268900CD13353E5F00698AC0 /* UniqueDWARFASTType.cpp in Sources */,
diff --git a/lldb/lldb.xcodeproj/xcshareddata/xcschemes/LLDB.xcscheme b/lldb/lldb.xcodeproj/xcshareddata/xcschemes/LLDB.xcscheme
index 881829e27fe..95f7ce4efd4 100644
--- a/lldb/lldb.xcodeproj/xcshareddata/xcschemes/LLDB.xcscheme
+++ b/lldb/lldb.xcodeproj/xcshareddata/xcschemes/LLDB.xcscheme
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -54,6 +55,7 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
displayScaleIsEnabled = "NO"
displayScale = "1.00"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py
index b1b37ae3817..9630e39e014 100644
--- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py
@@ -73,7 +73,7 @@ class BreakpointAutoContinue(TestBase):
self.assertEqual(bkpt.GetHitCount(), 2, "Should have run through the breakpoint twice")
def auto_continue_with_command(self):
- bpno = self.make_target_and_bkpt("-N BKPT -d 'break modify --auto-continue 0 BKPT'")
+ bpno = self.make_target_and_bkpt("-N BKPT -C 'break modify --auto-continue 0 BKPT'")
process = self.launch_it(lldb.eStateStopped)
state = process.GetState()
self.assertEqual(state, lldb.eStateStopped, "Process should be stopped")
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
index cb4aeadbf93..386eafbb0b6 100644
--- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
@@ -287,7 +287,7 @@ class BreakpointCommandTestCase(TestBase):
# Add a breakpoint.
lldbutil.run_break_set_by_file_and_line(
self, "main.c", self.line, num_expected_locations=1, loc_exact=True,
- extra_options='-d bt -d "thread list" -d continue')
+ extra_options='-C bt -C "thread list" -C continue')
bkpt = target.FindBreakpointByID(1)
self.assertTrue(bkpt.IsValid(), "Couldn't find breakpoint 1")
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py
index cc31ef80e8a..a758f76cc57 100644
--- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py
@@ -17,6 +17,7 @@ from lldbsuite.test import lldbutil
class BreakpointNames(TestBase):
mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
@add_test_categories(['pyapi'])
def test_setting_names(self):
@@ -37,6 +38,25 @@ class BreakpointNames(TestBase):
self.setup_target()
self.do_check_using_names()
+ def test_configuring_names(self):
+ """Use Python APIs to test that configuring options on breakpoint names works correctly."""
+ self.build()
+ self.make_a_dummy_name()
+ self.setup_target()
+ self.do_check_configuring_names()
+
+ def test_configuring_permissions_sb(self):
+ """Use Python APIs to test that configuring permissions on names works correctly."""
+ self.build()
+ self.setup_target()
+ self.do_check_configuring_permissions_sb()
+
+ def test_configuring_permissions_cli(self):
+ """Use Python APIs to test that configuring permissions on names works correctly."""
+ self.build()
+ self.setup_target()
+ self.do_check_configuring_permissions_cli()
+
def setup_target(self):
exe = os.path.join(os.getcwd(), "a.out")
@@ -45,10 +65,35 @@ class BreakpointNames(TestBase):
self.assertTrue(self.target, VALID_TARGET)
self.main_file_spec = lldb.SBFileSpec(os.path.join(os.getcwd(), "main.c"))
+ def check_name_in_target(self, bkpt_name):
+ name_list = lldb.SBStringList()
+ self.target.GetBreakpointNames(name_list)
+ found_it = False
+ for name in name_list:
+ if name == bkpt_name:
+ found_it = True
+ break
+ self.assertTrue(found_it, "Didn't find the name %s in the target's name list:"%(bkpt_name))
+
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
+ # These are the settings we're going to be putting into names & breakpoints:
+ self.bp_name_string = "ABreakpoint"
+ self.is_one_shot = True
+ self.ignore_count = 1000
+ self.condition = "1 == 2"
+ self.auto_continue = True
+ self.tid = 0xaaaa
+ self.tidx = 10
+ self.thread_name = "Fooey"
+ self.queue_name = "Blooey"
+ self.cmd_list = lldb.SBStringList()
+ self.cmd_list.AppendString("frame var")
+ self.cmd_list.AppendString("bt")
+
+
def do_check_names(self):
"""Use Python APIs to check that we can set & retrieve breakpoint names"""
bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
@@ -66,11 +111,15 @@ class BreakpointNames(TestBase):
matches = bkpt.MatchesName("NotABreakpoint")
self.assertTrue(not matches, "We matched a name we didn't set.")
+ # Make sure the name is also in the target:
+ self.check_name_in_target(bkpt_name)
+
# Add another name, make sure that works too:
bkpt.AddName(other_bkpt_name)
matches = bkpt.MatchesName(bkpt_name)
self.assertTrue(matches, "Adding a name means we didn't match the name we just set")
+ self.check_name_in_target(other_bkpt_name)
# Remove the name and make sure we no longer match it:
bkpt.RemoveName(bkpt_name)
@@ -89,26 +138,21 @@ class BreakpointNames(TestBase):
def do_check_illegal_names(self):
"""Use Python APIs to check that we reject illegal names."""
bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
- success = bkpt.AddName("-CantStartWithADash")
- self.assertTrue(not success,"We allowed a name starting with a dash.")
-
- success = bkpt.AddName("1CantStartWithANumber")
- self.assertTrue(not success, "We allowed a name starting with a number.")
-
- success = bkpt.AddName("^CantStartWithNonAlpha")
- self.assertTrue(not success, "We allowed a name starting with an ^.")
+ bad_names = ["-CantStartWithADash",
+ "1CantStartWithANumber",
+ "^CantStartWithNonAlpha",
+ "CantHave-ADash",
+ "Cant Have Spaces"]
+ for bad_name in bad_names:
+ success = bkpt.AddName(bad_name)
+ self.assertTrue(not success,"We allowed an illegal name: %s"%(bad_name))
+ bp_name = lldb.SBBreakpointName(self.target, bad_name)
+ self.assertFalse(bp_name.IsValid(), "We made a breakpoint name with an illegal name: %s"%(bad_name));
- success = bkpt.AddName("CantHave-ADash")
- self.assertTrue(not success, "We allowed a name with a dash in it.")
+ retval =lldb.SBCommandReturnObject()
+ self.dbg.GetCommandInterpreter().HandleCommand("break set -n whatever -N '%s'"%(bad_name), retval)
+ self.assertTrue(not retval.Succeeded(), "break set succeeded with: illegal name: %s"%(bad_name))
- success = bkpt.AddName("Cant Have Spaces")
- self.assertTrue(not success, "We allowed a name with spaces.")
-
- # Check from the command line as well:
- retval =lldb.SBCommandReturnObject()
- self.dbg.GetCommandInterpreter().HandleCommand("break set -n whatever -N has-dashes", retval)
- self.assertTrue(not retval.Succeeded(), "break set succeeded with: illegal name")
-
def do_check_using_names(self):
"""Use Python APIs to check names work in place of breakpoint ID's."""
@@ -133,9 +177,174 @@ class BreakpointNames(TestBase):
self.assertTrue(not bkpt.IsEnabled(), "We didn't disable the breakpoint.")
# Also make sure we don't apply commands to non-matching names:
- self.dbg.GetCommandInterpreter().HandleCommand("break modify --one-shot 1 %s"%(bkpt_name), retval)
+ self.dbg.GetCommandInterpreter().HandleCommand("break modify --one-shot 1 %s"%(other_bkpt_name), retval)
self.assertTrue(retval.Succeeded(), "break modify failed with: %s."%(retval.GetError()))
self.assertTrue(not bkpt.IsOneShot(), "We applied one-shot to the wrong breakpoint.")
+ def check_option_values(self, bp_object):
+ self.assertEqual(bp_object.IsOneShot(), self.is_one_shot, "IsOneShot")
+ self.assertEqual(bp_object.GetIgnoreCount(), self.ignore_count, "IgnoreCount")
+ self.assertEqual(bp_object.GetCondition(), self.condition, "Condition")
+ self.assertEqual(bp_object.GetAutoContinue(), self.auto_continue, "AutoContinue")
+ self.assertEqual(bp_object.GetThreadID(), self.tid, "Thread ID")
+ self.assertEqual(bp_object.GetThreadIndex(), self.tidx, "Thread Index")
+ self.assertEqual(bp_object.GetThreadName(), self.thread_name, "Thread Name")
+ self.assertEqual(bp_object.GetQueueName(), self.queue_name, "Queue Name")
+ set_cmds = lldb.SBStringList()
+ bp_object.GetCommandLineCommands(set_cmds)
+ self.assertEqual(set_cmds.GetSize(), self.cmd_list.GetSize(), "Size of command line commands")
+ for idx in range(0, set_cmds.GetSize()):
+ self.assertEqual(self.cmd_list.GetStringAtIndex(idx), set_cmds.GetStringAtIndex(idx), "Command %d"%(idx))
+
+ def make_a_dummy_name(self):
+ "This makes a breakpoint name in the dummy target to make sure it gets copied over"
+
+ dummy_target = self.dbg.GetDummyTarget()
+ self.assertTrue(dummy_target.IsValid(), "Dummy target was not valid.")
+
+ def cleanup ():
+ self.dbg.GetDummyTarget().DeleteBreakpointName(self.bp_name_string)
+
+ # Execute the cleanup function during test case tear down.
+ self.addTearDownHook(cleanup)
+
+ # Now find it in the dummy target, and make sure these settings took:
+ bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string)
+ # Make sure the name is right:
+ self.assertTrue (bp_name.GetName() == self.bp_name_string, "Wrong bp_name: %s"%(bp_name.GetName()))
+ bp_name.SetOneShot(self.is_one_shot)
+ bp_name.SetIgnoreCount(self.ignore_count)
+ bp_name.SetCondition(self.condition)
+ bp_name.SetAutoContinue(self.auto_continue)
+ bp_name.SetThreadID(self.tid)
+ bp_name.SetThreadIndex(self.tidx)
+ bp_name.SetThreadName(self.thread_name)
+ bp_name.SetQueueName(self.queue_name)
+ bp_name.SetCommandLineCommands(self.cmd_list)
+
+ # Now look it up again, and make sure it got set correctly.
+ bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string)
+ self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.")
+ self.check_option_values(bp_name)
+
+ def do_check_configuring_names(self):
+ """Use Python APIs to check that configuring breakpoint names works correctly."""
+ other_bp_name_string = "AnotherBreakpointName"
+ cl_bp_name_string = "CLBreakpointName"
+
+ # Now find the version copied in from the dummy target, and make sure these settings took:
+ bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)
+ self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.")
+ self.check_option_values(bp_name)
+
+ # Now add this name to a breakpoint, and make sure it gets configured properly
+ bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
+ success = bkpt.AddName(self.bp_name_string)
+ self.assertTrue(success, "Couldn't add this name to the breakpoint")
+ self.check_option_values(bkpt)
+
+ # Now make a name from this breakpoint, and make sure the new name is properly configured:
+ new_name = lldb.SBBreakpointName(bkpt, other_bp_name_string)
+ self.assertTrue(new_name.IsValid(), "Couldn't make a valid bp_name from a breakpoint.")
+ self.check_option_values(bkpt)
+
+ # Now change the name's option and make sure it gets propagated to
+ # the breakpoint:
+ new_auto_continue = not self.auto_continue
+ bp_name.SetAutoContinue(new_auto_continue)
+ self.assertEqual(bp_name.GetAutoContinue(), new_auto_continue, "Couldn't change auto-continue on the name")
+ self.assertEqual(bkpt.GetAutoContinue(), new_auto_continue, "Option didn't propagate to the breakpoint.")
+ # Now make this same breakpoint name - but from the command line
+ cmd_str = "breakpoint name configure %s -o %d -i %d -c '%s' -G %d -t %d -x %d -T '%s' -q '%s'"%(cl_bp_name_string,
+ self.is_one_shot,
+ self.ignore_count,
+ self.condition,
+ self.auto_continue,
+ self.tid,
+ self.tidx,
+ self.thread_name,
+ self.queue_name)
+ for cmd in self.cmd_list:
+ cmd_str += " -C '%s'"%(cmd)
+ result = lldb.SBCommandReturnObject()
+ self.dbg.GetCommandInterpreter().HandleCommand(cmd_str, result)
+ self.assertTrue(result.Succeeded())
+ # Now look up this name again and check its options:
+ cl_name = lldb.SBBreakpointName(self.target, cl_bp_name_string)
+ self.check_option_values(cl_name)
+
+ # We should have three names now, make sure the target can list them:
+ name_list = lldb.SBStringList()
+ self.target.GetBreakpointNames(name_list)
+ for name_string in [self.bp_name_string, other_bp_name_string, cl_bp_name_string]:
+ self.assertTrue(name_string in name_list, "Didn't find %s in names"%(name_string))
+
+ # Test that deleting the name we injected into the dummy target works (there's also a
+ # cleanup that will do this, but that won't test the result...
+ dummy_target = self.dbg.GetDummyTarget()
+ dummy_target.DeleteBreakpointName(self.bp_name_string)
+ name_list.Clear()
+ dummy_target.GetBreakpointNames(name_list)
+ self.assertTrue(self.bp_name_string not in name_list, "Didn't delete %s from the dummy target"%(self.bp_name_string))
+
+ def check_permission_results(self, bp_name):
+ self.assertEqual(bp_name.GetAllowDelete(), False, "Didn't set allow delete.")
+ protected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
+ protected_id = protected_bkpt.GetID()
+
+ unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
+ unprotected_id = unprotected_bkpt.GetID()
+
+ success = protected_bkpt.AddName(self.bp_name_string)
+ self.assertTrue(success, "Couldn't add this name to the breakpoint")
+
+ self.target.DisableAllBreakpoints()
+ self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled")
+ self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.")
+
+ # Try from the command line too:
+ unprotected_bkpt.SetEnabled(True)
+ result = lldb.SBCommandReturnObject()
+ self.dbg.GetCommandInterpreter().HandleCommand("break disable", result)
+ self.assertTrue(result.Succeeded())
+ self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled")
+ self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.")
+
+ self.target.DeleteAllBreakpoints()
+ bkpt = self.target.FindBreakpointByID(protected_id)
+ self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.")
+ bkpt = self.target.FindBreakpointByID(unprotected_id)
+ self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.")
+
+ # Remake the unprotected breakpoint and try again from the command line:
+ unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
+ unprotected_id = unprotected_bkpt.GetID()
+
+ self.dbg.GetCommandInterpreter().HandleCommand("break delete -f", result)
+ self.assertTrue(result.Succeeded())
+ bkpt = self.target.FindBreakpointByID(protected_id)
+ self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.")
+ bkpt = self.target.FindBreakpointByID(unprotected_id)
+ self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.")
+
+ def do_check_configuring_permissions_sb(self):
+ bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)
+
+ # Make a breakpoint name with delete disallowed:
+ bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)
+ self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name for valid name.")
+
+ bp_name.SetAllowDelete(False)
+ bp_name.SetAllowDisable(False)
+ bp_name.SetAllowList(False)
+ self.check_permission_results(bp_name)
+
+ def do_check_configuring_permissions_cli(self):
+ # Make the name with the right options using the command line:
+ self.runCmd("breakpoint name configure -L 0 -D 0 -A 0 %s"%(self.bp_name_string), check=True)
+ # Now look up the breakpoint we made, and check that it works.
+ bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)
+ self.assertTrue(bp_name.IsValid(), "Didn't make a breakpoint name we could find.")
+ self.check_permission_results(bp_name)
diff --git a/lldb/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py b/lldb/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py
index bea9f5962d6..5c0c7bbd766 100644
--- a/lldb/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py
+++ b/lldb/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py
@@ -73,6 +73,17 @@ class APIDefaultConstructorTestCase(TestBase):
@add_test_categories(['pyapi'])
@no_debug_info_test
+ def test_SBBreakpointName(self):
+ obj = lldb.SBBreakpointName()
+ if self.TraceOn():
+ print(obj)
+ self.assertFalse(obj)
+ # Do fuzz testing on the invalid obj, it should not crash lldb.
+ import sb_breakpointname
+ sb_breakpointname.fuzz_obj(obj)
+
+ @add_test_categories(['pyapi'])
+ @no_debug_info_test
def test_SBBroadcaster(self):
obj = lldb.SBBroadcaster()
if self.TraceOn():
diff --git a/lldb/packages/Python/lldbsuite/test/python_api/default-constructor/sb_breakpointname.py b/lldb/packages/Python/lldbsuite/test/python_api/default-constructor/sb_breakpointname.py
new file mode 100644
index 00000000000..56016c05c31
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/python_api/default-constructor/sb_breakpointname.py
@@ -0,0 +1,42 @@
+"""
+Fuzz tests an object after the default construction to make sure it does not crash lldb.
+"""
+
+import sys
+import lldb
+
+
+def fuzz_obj(obj):
+ obj.IsValid()
+ obj.GetName()
+ obj.SetEnabled(True)
+ obj.IsEnabled()
+ obj.SetOneShot(True)
+ obj.IsOneShot()
+ obj.SetIgnoreCount(1)
+ obj.GetIgnoreCount()
+ obj.SetCondition("1 == 2")
+ obj.GetCondition()
+ obj.SetAutoContinue(False)
+ obj.GetAutoContinue()
+ obj.SetThreadID(0x1234)
+ obj.GetThreadID()
+ obj.SetThreadIndex(10)
+ obj.GetThreadIndex()
+ obj.SetThreadName("AThread")
+ obj.GetThreadName()
+ obj.SetQueueName("AQueue")
+ obj.GetQueueName()
+ obj.SetScriptCallbackFunction("AFunction")
+ commands = lldb.SBStringList()
+ obj.SetCommandLineCommands(commands)
+ obj.GetCommandLineCommands(commands)
+ obj.SetScriptCallbackBody("Insert Python Code here")
+ obj.GetAllowList()
+ obj.SetAllowList(False)
+ obj.GetAllowDelete()
+ obj.SetAllowDelete(False)
+ obj.GetAllowDisable()
+ obj.SetAllowDisable(False)
+ stream = lldb.SBStream()
+ obj.GetDescription(stream)
diff --git a/lldb/scripts/Python/python-extensions.swig b/lldb/scripts/Python/python-extensions.swig
index 693b06b9aab..d79917b9215 100644
--- a/lldb/scripts/Python/python-extensions.swig
+++ b/lldb/scripts/Python/python-extensions.swig
@@ -71,6 +71,21 @@
}
}
+%extend lldb::SBBreakpointName {
+ PyObject *lldb::SBBreakpointName::__str__ (){
+ lldb::SBStream description;
+ $self->GetDescription (description);
+ const char *desc = description.GetData();
+ size_t desc_len = description.GetSize();
+ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
+ --desc_len;
+ if (desc_len > 0)
+ return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
+ else
+ return lldb_private::PythonString("").release();
+ }
+}
+
%extend lldb::SBBroadcaster {
%pythoncode %{
def __eq__(self, rhs):
diff --git a/lldb/scripts/Python/python-swigsafecast.swig b/lldb/scripts/Python/python-swigsafecast.swig
index ea3f21f859a..ffd7546323a 100644
--- a/lldb/scripts/Python/python-swigsafecast.swig
+++ b/lldb/scripts/Python/python-swigsafecast.swig
@@ -115,6 +115,13 @@ SBTypeToSWIGWrapper (lldb::SBBreakpointLocation* breakpoint_location_sb)
template <>
PyObject*
+SBTypeToSWIGWrapper (lldb::SBBreakpointName* breakpoint_name_sb)
+{
+ return SWIG_NewPointerObj((void *) breakpoint_name_sb, SWIGTYPE_p_lldb__SBBreakpointName, 0);
+}
+
+template <>
+PyObject*
SBTypeToSWIGWrapper (lldb::SBValue* value_sb)
{
return SWIG_NewPointerObj((void *) value_sb, SWIGTYPE_p_lldb__SBValue, 0);
diff --git a/lldb/scripts/interface/SBBreakpoint.i b/lldb/scripts/interface/SBBreakpoint.i
index 76ddd7259e9..525797ad91f 100644
--- a/lldb/scripts/interface/SBBreakpoint.i
+++ b/lldb/scripts/interface/SBBreakpoint.i
@@ -6,7 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
namespace lldb {
%feature("docstring",
@@ -81,11 +80,6 @@ class SBBreakpoint
{
public:
- typedef bool (*BreakpointHitCallback) (void *baton,
- SBProcess &process,
- SBThread &thread,
- lldb::SBBreakpointLocation &location);
-
SBBreakpoint ();
SBBreakpoint (const lldb::SBBreakpoint& rhs);
diff --git a/lldb/scripts/interface/SBBreakpointName.i b/lldb/scripts/interface/SBBreakpointName.i
new file mode 100644
index 00000000000..76f087cb314
--- /dev/null
+++ b/lldb/scripts/interface/SBBreakpointName.i
@@ -0,0 +1,108 @@
+//===-- SWIG interface for SBBreakpointName.h -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+namespace lldb {
+%feature("docstring",
+"Represents a breakpoint name registered in a given SBTarget.
+
+Breakpoint names provide a way to act on groups of breakpoints. When you add a
+name to a group of breakpoints, you can then use the name in all the command
+line lldb commands for that name. You can also configure the SBBreakpointName
+options and those options will be propagated to any SBBreakpoints currently
+using that name. Adding a name to a breakpoint will also apply any of the
+set options to that breakpoint.
+
+You can also set permissions on a breakpoint name to disable listing, deleting
+and disabling breakpoints. That will disallow the given operation for breakpoints
+except when the breakpoint is mentioned by ID. So for instance deleting all the
+breakpoints won't delete breakpoints so marked."
+) SBBreakpointName;
+class LLDB_API SBBreakpointName {
+public:
+ SBBreakpointName();
+
+ SBBreakpointName(SBTarget &target, const char *name);
+
+ SBBreakpointName(SBBreakpoint &bkpt, const char *name);
+
+ SBBreakpointName(const lldb::SBBreakpointName &rhs);
+
+ ~SBBreakpointName();
+
+ const lldb::SBBreakpointName &operator=(const lldb::SBBreakpointName &rhs);
+
+ // Tests to see if the opaque breakpoint object in this object matches the
+ // opaque breakpoint object in "rhs".
+ bool operator==(const lldb::SBBreakpointName &rhs);
+
+ bool operator!=(const lldb::SBBreakpointName &rhs);
+
+ bool IsValid() const;
+
+ const char *GetName() const;
+
+ void SetEnabled(bool enable);
+
+ bool IsEnabled();
+
+ void SetOneShot(bool one_shot);
+
+ bool IsOneShot() const;
+
+ void SetIgnoreCount(uint32_t count);
+
+ uint32_t GetIgnoreCount() const;
+
+ void SetCondition(const char *condition);
+
+ const char *GetCondition();
+
+ void SetAutoContinue(bool auto_continue);
+
+ bool GetAutoContinue();
+
+ void SetThreadID(lldb::tid_t sb_thread_id);
+
+ lldb::tid_t GetThreadID();
+
+ void SetThreadIndex(uint32_t index);
+
+ uint32_t GetThreadIndex() const;
+
+ void SetThreadName(const char *thread_name);
+
+ const char *GetThreadName() const;
+
+ void SetQueueName(const char *queue_name);
+
+ const char *GetQueueName() const;
+
+ void SetScriptCallbackFunction(const char *callback_function_name);
+
+ void SetCommandLineCommands(SBStringList &commands);
+
+ bool GetCommandLineCommands(SBStringList &commands);
+
+ SBError SetScriptCallbackBody(const char *script_body_text);
+
+ bool GetAllowList() const;
+ void SetAllowList(bool value);
+
+ bool GetAllowDelete();
+ void SetAllowDelete(bool value);
+
+ bool GetAllowDisable();
+ void SetAllowDisable(bool value);
+
+ bool GetDescription(lldb::SBStream &description);
+
+};
+
+} // namespace lldb
+
diff --git a/lldb/scripts/interface/SBDebugger.i b/lldb/scripts/interface/SBDebugger.i
index 07f049b82ba..9f746d36348 100644
--- a/lldb/scripts/interface/SBDebugger.i
+++ b/lldb/scripts/interface/SBDebugger.i
@@ -214,6 +214,11 @@ public:
CreateTarget (const char *filename);
%feature("docstring",
+ "The dummy target holds breakpoints and breakpoint names that will prime newly created targets."
+ ) GetDummyTarget;
+ lldb::SBTarget GetDummyTarget();
+
+ %feature("docstring",
"Return true if target is deleted from the target list of the debugger."
) DeleteTarget;
bool
diff --git a/lldb/scripts/interface/SBTarget.i b/lldb/scripts/interface/SBTarget.i
index c1d749c7ce7..bcec606005f 100644
--- a/lldb/scripts/interface/SBTarget.i
+++ b/lldb/scripts/interface/SBTarget.i
@@ -711,6 +711,10 @@ public:
bool FindBreakpointsByName(const char *name, SBBreakpointList &bkpt_list);
+ void DeleteBreakpointName(const char *name);
+
+ void GetBreakpointNames(SBStringList &names);
+
bool
EnableAllBreakpoints ();
diff --git a/lldb/scripts/lldb.swig b/lldb/scripts/lldb.swig
index 044cfc0b2cd..dc987040e76 100644
--- a/lldb/scripts/lldb.swig
+++ b/lldb/scripts/lldb.swig
@@ -82,6 +82,7 @@ import six
#include "lldb/API/SBBlock.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBBreakpointLocation.h"
+#include "lldb/API/SBBreakpointName.h"
#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandReturnObject.h"
@@ -168,6 +169,7 @@ import six
%include "./interface/SBBlock.i"
%include "./interface/SBBreakpoint.i"
%include "./interface/SBBreakpointLocation.i"
+%include "./interface/SBBreakpointName.i"
%include "./interface/SBBroadcaster.i"
%include "./interface/SBCommandInterpreter.i"
%include "./interface/SBCommandReturnObject.i"
diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp
index 9abdce0c928..6a0ff9536c2 100644
--- a/lldb/source/API/SBBreakpoint.cpp
+++ b/lldb/source/API/SBBreakpoint.cpp
@@ -37,6 +37,8 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"
+#include "SBBreakpointOptionCommon.h"
+
#include "lldb/lldb-enumerations.h"
#include "llvm/ADT/STLExtras.h"
@@ -44,21 +46,6 @@
using namespace lldb;
using namespace lldb_private;
-struct CallbackData {
- SBBreakpoint::BreakpointHitCallback callback;
- void *callback_baton;
-};
-
-class SBBreakpointCallbackBaton : public TypedBaton<CallbackData> {
-public:
- SBBreakpointCallbackBaton(SBBreakpoint::BreakpointHitCallback callback,
- void *baton)
- : TypedBaton(llvm::make_unique<CallbackData>()) {
- getItem()->callback = callback;
- getItem()->callback_baton = baton;
- }
-};
-
SBBreakpoint::SBBreakpoint() {}
SBBreakpoint::SBBreakpoint(const SBBreakpoint &rhs)
@@ -500,37 +487,9 @@ bool SBBreakpoint::GetDescription(SBStream &s, bool include_locations) {
return false;
}
-bool SBBreakpoint::PrivateBreakpointHitCallback(void *baton,
- StoppointCallbackContext *ctx,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id) {
- ExecutionContext exe_ctx(ctx->exe_ctx_ref);
- BreakpointSP bp_sp(
- exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id));
- if (baton && bp_sp) {
- CallbackData *data = (CallbackData *)baton;
- lldb_private::Breakpoint *bp = bp_sp.get();
- if (bp && data->callback) {
- Process *process = exe_ctx.GetProcessPtr();
- if (process) {
- SBProcess sb_process(process->shared_from_this());
- SBThread sb_thread;
- SBBreakpointLocation sb_location;
- assert(bp_sp);
- sb_location.SetLocation(bp_sp->FindLocationByID(break_loc_id));
- Thread *thread = exe_ctx.GetThreadPtr();
- if (thread)
- sb_thread.SetThread(thread->shared_from_this());
-
- return data->callback(data->callback_baton, sb_process, sb_thread,
- sb_location);
- }
- }
- }
- return true; // Return true if we should stop at this breakpoint
-}
-
-void SBBreakpoint::SetCallback(BreakpointHitCallback callback, void *baton) {
+void SBBreakpoint
+ ::SetCallback(SBBreakpointHitCallback callback,
+ void *baton) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
BreakpointSP bkpt_sp = GetSP();
LLDB_LOG(log, "breakpoint = {0}, callback = {1}, baton = {2}", bkpt_sp.get(),
@@ -540,7 +499,8 @@ void SBBreakpoint::SetCallback(BreakpointHitCallback callback, void *baton) {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton));
- bkpt_sp->SetCallback(SBBreakpoint::PrivateBreakpointHitCallback, baton_sp,
+ bkpt_sp->SetCallback(SBBreakpointCallbackBaton
+ ::PrivateBreakpointHitCallback, baton_sp,
false);
}
}
@@ -599,10 +559,17 @@ bool SBBreakpoint::AddName(const char *new_name) {
bkpt_sp->GetTarget().GetAPIMutex());
Status error; // Think I'm just going to swallow the error here, it's
// probably more annoying to have to provide it.
- return bkpt_sp->AddName(new_name, error);
+ bkpt_sp->GetTarget().AddNameToBreakpoint(bkpt_sp, new_name, error);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("Failed to add name: '%s' to breakpoint: %s",
+ new_name, error.AsCString());
+ return false;
+ }
}
- return false;
+ return true;
}
void SBBreakpoint::RemoveName(const char *name_to_remove) {
@@ -613,7 +580,8 @@ void SBBreakpoint::RemoveName(const char *name_to_remove) {
if (bkpt_sp) {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
- bkpt_sp->RemoveName(name_to_remove);
+ bkpt_sp->GetTarget().RemoveNameFromBreakpoint(bkpt_sp,
+ ConstString(name_to_remove));
}
}
diff --git a/lldb/source/API/SBBreakpointName.cpp b/lldb/source/API/SBBreakpointName.cpp
new file mode 100644
index 00000000000..b2ed5e71699
--- /dev/null
+++ b/lldb/source/API/SBBreakpointName.cpp
@@ -0,0 +1,662 @@
+//===-- SBBreakpointName.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/API/SBBreakpointName.h"
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/API/SBStringList.h"
+#include "lldb/API/SBTarget.h"
+
+#include "lldb/Breakpoint/BreakpointName.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadSpec.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Stream.h"
+
+#include "SBBreakpointOptionCommon.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace lldb
+{
+class SBBreakpointNameImpl {
+public:
+ SBBreakpointNameImpl(SBTarget &sb_target, const char *name)
+ {
+ if (!name || name[0] == '\0')
+ return;
+ m_name.assign(name);
+
+ if (!sb_target.IsValid())
+ return;
+
+ TargetSP target_sp = sb_target.GetSP();
+ if (!target_sp)
+ return;
+
+ m_target_wp = target_sp;
+ }
+
+ SBBreakpointNameImpl(TargetSP target_sp, const char *name)
+ {
+ if (!name || name[0] == '\0')
+ return;
+ m_name.assign(name);
+
+ if (!target_sp)
+ return;
+
+ m_target_wp = target_sp;
+ }
+
+ bool operator==(const SBBreakpointNameImpl &rhs) {
+ return m_name == rhs.m_name
+ && m_target_wp.lock() == rhs.m_target_wp.lock();
+ }
+
+ bool operator!=(const SBBreakpointNameImpl &rhs) {
+ return m_name != rhs.m_name
+ || m_target_wp.lock() != rhs.m_target_wp.lock();
+ }
+ // For now we take a simple approach and only keep the name, and relook
+ // up the location when we need it.
+
+ TargetSP GetTarget() {
+ return m_target_wp.lock();
+ }
+
+ const char *GetName() {
+ return m_name.c_str();
+ }
+
+ bool IsValid() {
+ return !m_name.empty() && m_target_wp.lock();
+ }
+
+ lldb_private::BreakpointName *GetBreakpointName()
+ {
+ if (!IsValid())
+ return nullptr;
+ TargetSP target_sp = GetTarget();
+ if (!target_sp)
+ return nullptr;
+ Status error;
+ return target_sp->FindBreakpointName(ConstString(m_name), true, error);
+ }
+
+ const lldb_private::BreakpointName *GetBreakpointName() const
+ {
+ return GetBreakpointName();
+ }
+
+private:
+ TargetWP m_target_wp;
+ std::string m_name;
+};
+} // namespace lldb
+
+SBBreakpointName::SBBreakpointName() {}
+
+SBBreakpointName::SBBreakpointName(SBTarget &sb_target, const char *name)
+{
+ m_impl_up.reset(new SBBreakpointNameImpl(sb_target, name));
+ // Call FindBreakpointName here to make sure the name is valid, reset if
+ // not:
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ m_impl_up.reset();
+}
+
+SBBreakpointName::SBBreakpointName(SBBreakpoint &sb_bkpt, const char *name)
+{
+ if (!sb_bkpt.IsValid()) {
+ m_impl_up.reset();
+ return;
+ }
+ BreakpointSP bkpt_sp = sb_bkpt.GetSP();
+ Target &target = bkpt_sp->GetTarget();
+
+ m_impl_up.reset(new SBBreakpointNameImpl(target.shared_from_this(), name));
+
+ // Call FindBreakpointName here to make sure the name is valid, reset if
+ // not:
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name) {
+ m_impl_up.reset();
+ return;
+ }
+
+ // Now copy over the breakpoint's options:
+ target.ConfigureBreakpointName(*bp_name, *bkpt_sp->GetOptions(),
+ BreakpointName::Permissions());
+}
+
+SBBreakpointName::SBBreakpointName(const SBBreakpointName &rhs)
+{
+ if (!rhs.m_impl_up)
+ return;
+ else
+ m_impl_up.reset(new SBBreakpointNameImpl(rhs.m_impl_up->GetTarget(),
+ rhs.m_impl_up->GetName()));
+}
+
+SBBreakpointName::~SBBreakpointName() = default;
+
+const SBBreakpointName &SBBreakpointName::operator=(const SBBreakpointName &rhs)
+{
+ if (!rhs.m_impl_up) {
+ m_impl_up.reset();
+ return *this;
+ }
+
+ m_impl_up.reset(new SBBreakpointNameImpl(rhs.m_impl_up->GetTarget(),
+ rhs.m_impl_up->GetName()));
+ return *this;
+}
+
+bool SBBreakpointName::operator==(const lldb::SBBreakpointName &rhs) {
+ return *m_impl_up.get() == *rhs.m_impl_up.get();
+}
+
+bool SBBreakpointName::operator!=(const lldb::SBBreakpointName &rhs) {
+ return *m_impl_up.get() != *rhs.m_impl_up.get();
+}
+
+bool SBBreakpointName::IsValid() const {
+ if (!m_impl_up)
+ return false;
+ return m_impl_up->IsValid();
+}
+
+const char *SBBreakpointName::GetName() const {
+ if (!m_impl_up)
+ return "<Invalid Breakpoint Name Object>";
+ return m_impl_up->GetName();
+}
+
+void SBBreakpointName::SetEnabled(bool enable) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+
+ LLDB_LOG(log, "Name: {0} enabled: {1}\n", bp_name->GetName(), enable);
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ bp_name->GetOptions().SetEnabled(enable);
+}
+
+void SBBreakpointName::UpdateName(BreakpointName &bp_name) {
+ if (!IsValid())
+ return;
+
+ TargetSP target_sp = m_impl_up->GetTarget();
+ if (!target_sp)
+ return;
+ target_sp->ApplyNameToBreakpoints(bp_name);
+
+}
+
+bool SBBreakpointName::IsEnabled() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return false;
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ return bp_name->GetOptions().IsEnabled();
+}
+
+void SBBreakpointName::SetOneShot(bool one_shot) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+
+ LLDB_LOG(log, "Name: {0} one_shot: {1}\n", bp_name->GetName(), one_shot);
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ bp_name->GetOptions().SetOneShot(one_shot);
+ UpdateName(*bp_name);
+}
+
+bool SBBreakpointName::IsOneShot() const {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ const BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return false;
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ return bp_name->GetOptions().IsOneShot();
+}
+
+void SBBreakpointName::SetIgnoreCount(uint32_t count) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+
+ LLDB_LOG(log, "Name: {0} one_shot: {1}\n", bp_name->GetName(), count);
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ bp_name->GetOptions().SetIgnoreCount(count);
+ UpdateName(*bp_name);
+}
+
+uint32_t SBBreakpointName::GetIgnoreCount() const {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return false;
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ return bp_name->GetOptions().GetIgnoreCount();
+}
+
+void SBBreakpointName::SetCondition(const char *condition) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+
+ LLDB_LOG(log, "Name: {0} one_shot: {1}\n", bp_name->GetName(),
+ condition ? condition : "<NULL>");
+
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ bp_name->GetOptions().SetCondition(condition);
+ UpdateName(*bp_name);
+}
+
+const char *SBBreakpointName::GetCondition() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return nullptr;
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ return bp_name->GetOptions().GetConditionText();
+}
+
+void SBBreakpointName::SetAutoContinue(bool auto_continue) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+
+ LLDB_LOG(log, "Name: {0} auto-continue: {1}\n", bp_name->GetName(), auto_continue);
+
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ bp_name->GetOptions().SetAutoContinue(auto_continue);
+ UpdateName(*bp_name);
+}
+
+bool SBBreakpointName::GetAutoContinue() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return nullptr;
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ return bp_name->GetOptions().IsAutoContinue();
+}
+
+void SBBreakpointName::SetThreadID(tid_t tid) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+
+ LLDB_LOG(log, "Name: {0} tid: {1:x}\n", bp_name->GetName(), tid);
+
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ bp_name->GetOptions().SetThreadID(tid);
+ UpdateName(*bp_name);
+}
+
+tid_t SBBreakpointName::GetThreadID() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return LLDB_INVALID_THREAD_ID;
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ return bp_name->GetOptions().GetThreadSpec()->GetTID();
+}
+
+void SBBreakpointName::SetThreadIndex(uint32_t index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+
+ LLDB_LOG(log, "Name: {0} thread index: {1}\n", bp_name->GetName(), index);
+
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ bp_name->GetOptions().GetThreadSpec()->SetIndex(index);
+ UpdateName(*bp_name);
+}
+
+uint32_t SBBreakpointName::GetThreadIndex() const {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return LLDB_INVALID_THREAD_ID;
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ return bp_name->GetOptions().GetThreadSpec()->GetIndex();
+}
+
+void SBBreakpointName::SetThreadName(const char *thread_name) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+
+ LLDB_LOG(log, "Name: {0} thread name: {1}\n", bp_name->GetName(), thread_name);
+
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ bp_name->GetOptions().GetThreadSpec()->SetName(thread_name);
+ UpdateName(*bp_name);
+}
+
+const char *SBBreakpointName::GetThreadName() const {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return nullptr;
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ return bp_name->GetOptions().GetThreadSpec()->GetName();
+}
+
+void SBBreakpointName::SetQueueName(const char *queue_name) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+
+ LLDB_LOG(log, "Name: {0} queue name: {1}\n", bp_name->GetName(), queue_name);
+
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ bp_name->GetOptions().GetThreadSpec()->SetQueueName(queue_name);
+ UpdateName(*bp_name);
+}
+
+const char *SBBreakpointName::GetQueueName() const {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return nullptr;
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ return bp_name->GetOptions().GetThreadSpec()->GetQueueName();
+}
+
+void SBBreakpointName::SetCommandLineCommands(SBStringList &commands) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+ if (commands.GetSize() == 0)
+ return;
+
+ LLDB_LOG(log, "Name: {0} commands\n", bp_name->GetName());
+
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+ std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up(
+ new BreakpointOptions::CommandData(*commands, eScriptLanguageNone));
+
+ bp_name->GetOptions().SetCommandDataCallback(cmd_data_up);
+ UpdateName(*bp_name);
+}
+
+bool SBBreakpointName::GetCommandLineCommands(SBStringList &commands) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return false;
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ StringList command_list;
+ bool has_commands =
+ bp_name->GetOptions().GetCommandLineCallbacks(command_list);
+ if (has_commands)
+ commands.AppendList(command_list);
+ return has_commands;
+}
+
+bool SBBreakpointName::GetDescription(SBStream &s) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ {
+ s.Printf("No value");
+ return false;
+ }
+
+ LLDB_LOG(log, "Name: {0}\n", bp_name->GetName());
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+ bp_name->GetDescription(s.get(), eDescriptionLevelFull);
+ return true;
+}
+
+void SBBreakpointName::SetCallback(SBBreakpointHitCallback callback,
+ void *baton) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+ LLDB_LOG(log, "callback = {1}, baton = {2}", callback, baton);
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton));
+ bp_name->GetOptions().SetCallback(SBBreakpointCallbackBaton
+ ::PrivateBreakpointHitCallback,
+ baton_sp,
+ false);
+ UpdateName(*bp_name);
+}
+
+void SBBreakpointName::SetScriptCallbackFunction(
+ const char *callback_function_name) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+
+ LLDB_LOG(log, "Name: {0} callback: {1}\n", bp_name->GetName(),
+ callback_function_name);
+
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ BreakpointOptions &bp_options = bp_name->GetOptions();
+ m_impl_up->GetTarget()
+ ->GetDebugger()
+ .GetCommandInterpreter()
+ .GetScriptInterpreter()
+ ->SetBreakpointCommandCallbackFunction(&bp_options,
+ callback_function_name);
+ UpdateName(*bp_name);
+}
+
+SBError SBBreakpointName::SetScriptCallbackBody(const char *callback_body_text)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+ SBError sb_error;
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return sb_error;
+
+ LLDB_LOG(log, "Name: {0} callback: {1}\n", bp_name->GetName(),
+ callback_body_text);
+
+ std::lock_guard<std::recursive_mutex> guard(
+ m_impl_up->GetTarget()->GetAPIMutex());
+
+ BreakpointOptions &bp_options = bp_name->GetOptions();
+ Status error =
+ m_impl_up->GetTarget()
+ ->GetDebugger()
+ .GetCommandInterpreter()
+ .GetScriptInterpreter()
+ ->SetBreakpointCommandCallback(&bp_options, callback_body_text);
+ sb_error.SetError(error);
+ if (!sb_error.Fail())
+ UpdateName(*bp_name);
+
+ return sb_error;
+}
+
+bool SBBreakpointName::GetAllowList() const
+{
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return false;
+ return bp_name->GetPermissions().GetAllowList();
+}
+
+void SBBreakpointName::SetAllowList(bool value)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+ if (log)
+ log->Printf("Setting allow list to %u for %s.", value,
+ bp_name->GetName().AsCString());
+ bp_name->GetPermissions().SetAllowList(value);
+}
+
+bool SBBreakpointName::GetAllowDelete()
+{
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return false;
+ return bp_name->GetPermissions().GetAllowDelete();
+}
+
+void SBBreakpointName::SetAllowDelete(bool value)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+ if (log)
+ log->Printf("Setting allow delete to %u for %s.", value,
+ bp_name->GetName().AsCString());
+ bp_name->GetPermissions().SetAllowDelete(value);
+}
+
+bool SBBreakpointName::GetAllowDisable()
+{
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return false;
+ return bp_name->GetPermissions().GetAllowDisable();
+}
+
+void SBBreakpointName::SetAllowDisable(bool value)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ BreakpointName *bp_name = GetBreakpointName();
+ if (!bp_name)
+ return;
+ if (log)
+ log->Printf("Setting allow disable to %u for %s.", value,
+ bp_name->GetName().AsCString());
+ bp_name->GetPermissions().SetAllowDisable(value);
+}
+
+lldb_private::BreakpointName *SBBreakpointName::GetBreakpointName() const
+{
+ if (!IsValid())
+ return nullptr;
+ return m_impl_up->GetBreakpointName();
+}
+
diff --git a/lldb/source/API/SBBreakpointOptionCommon.cpp b/lldb/source/API/SBBreakpointOptionCommon.cpp
new file mode 100644
index 00000000000..2a12491d6ec
--- /dev/null
+++ b/lldb/source/API/SBBreakpointOptionCommon.cpp
@@ -0,0 +1,84 @@
+//===-- SBBreakpointName.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/API/SBBreakpointName.h"
+#include "lldb/API/SBBreakpointLocation.h"
+#include "lldb/API/SBDebugger.h"
+#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/BreakpointName.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadSpec.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Stream.h"
+
+#include "lldb/lldb-enumerations.h"
+
+#include "SBBreakpointOptionCommon.h"
+
+#include "llvm/ADT/STLExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBBreakpointCallbackBaton::SBBreakpointCallbackBaton(SBBreakpointHitCallback
+ callback,
+ void *baton)
+ : TypedBaton(llvm::make_unique<CallbackData>()) {
+ getItem()->callback = callback;
+ getItem()->callback_baton = baton;
+ }
+
+ bool SBBreakpointCallbackBaton::PrivateBreakpointHitCallback(void *baton,
+ StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id)
+{
+ ExecutionContext exe_ctx(ctx->exe_ctx_ref);
+ BreakpointSP bp_sp(
+ exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id));
+ if (baton && bp_sp) {
+ CallbackData *data = (CallbackData *)baton;
+ lldb_private::Breakpoint *bp = bp_sp.get();
+ if (bp && data->callback) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process) {
+ SBProcess sb_process(process->shared_from_this());
+ SBThread sb_thread;
+ SBBreakpointLocation sb_location;
+ assert(bp_sp);
+ sb_location.SetLocation(bp_sp->FindLocationByID(break_loc_id));
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (thread)
+ sb_thread.SetThread(thread->shared_from_this());
+
+ return data->callback(data->callback_baton, sb_process, sb_thread,
+ sb_location);
+ }
+ }
+ }
+ return true; // Return true if we should stop at this breakpoint
+}
+
diff --git a/lldb/source/API/SBBreakpointOptionCommon.h b/lldb/source/API/SBBreakpointOptionCommon.h
new file mode 100644
index 00000000000..212fe398dd7
--- /dev/null
+++ b/lldb/source/API/SBBreakpointOptionCommon.h
@@ -0,0 +1,35 @@
+//===-- SBBreakpointOptionCommon.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SBBreakpointOptionCommons_h_
+#define LLDB_SBBreakpointOptionCommons_h_
+
+#include "lldb/API/SBDefines.h"
+#include "lldb/Utility/Baton.h"
+
+namespace lldb
+{
+struct CallbackData {
+ SBBreakpointHitCallback callback;
+ void *callback_baton;
+};
+
+class SBBreakpointCallbackBaton : public lldb_private::TypedBaton<CallbackData> {
+public:
+ SBBreakpointCallbackBaton(SBBreakpointHitCallback callback,
+ void *baton);
+
+ static bool PrivateBreakpointHitCallback(void *baton,
+ lldb_private::StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+};
+
+} // namespace lldb
+#endif // LLDB_SBBreakpointOptionCommons_h_
diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp
index cf6a27a049b..0185f1e9ec4 100644
--- a/lldb/source/API/SBDebugger.cpp
+++ b/lldb/source/API/SBDebugger.cpp
@@ -622,6 +622,20 @@ SBTarget SBDebugger::CreateTarget(const char *filename) {
return sb_target;
}
+SBTarget SBDebugger::GetDummyTarget() {
+ SBTarget sb_target;
+ if (m_opaque_sp) {
+ sb_target.SetSP(m_opaque_sp->GetDummyTarget()->shared_from_this());
+ }
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+ if (log)
+ log->Printf(
+ "SBDebugger(%p)::GetDummyTarget() => SBTarget(%p)",
+ static_cast<void *>(m_opaque_sp.get()),
+ static_cast<void *>(sb_target.GetSP().get()));
+ return sb_target;
+}
+
bool SBDebugger::DeleteTarget(lldb::SBTarget &target) {
bool result = false;
if (m_opaque_sp) {
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 417a15074c7..93869d71c62 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -1087,11 +1087,38 @@ bool SBTarget::FindBreakpointsByName(const char *name,
return true;
}
+void SBTarget::GetBreakpointNames(SBStringList &names)
+{
+ names.Clear();
+
+ TargetSP target_sp(GetSP());
+ if (target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
+
+ std::vector<std::string> name_vec;
+ target_sp->GetBreakpointNames(name_vec);
+ for (auto name : name_vec)
+ names.AppendString(name.c_str());
+ }
+}
+
+void SBTarget::DeleteBreakpointName(const char *name)
+{
+ TargetSP target_sp(GetSP());
+ if (target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
+
+ std::vector<std::string> name_vec;
+ target_sp->DeleteBreakpointName(ConstString(name));
+
+ }
+}
+
bool SBTarget::EnableAllBreakpoints() {
TargetSP target_sp(GetSP());
if (target_sp) {
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
- target_sp->EnableAllBreakpoints();
+ target_sp->EnableAllowedBreakpoints();
return true;
}
return false;
@@ -1101,7 +1128,7 @@ bool SBTarget::DisableAllBreakpoints() {
TargetSP target_sp(GetSP());
if (target_sp) {
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
- target_sp->DisableAllBreakpoints();
+ target_sp->DisableAllowedBreakpoints();
return true;
}
return false;
@@ -1111,7 +1138,7 @@ bool SBTarget::DeleteAllBreakpoints() {
TargetSP target_sp(GetSP());
if (target_sp) {
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
- target_sp->RemoveAllBreakpoints();
+ target_sp->RemoveAllowedBreakpoints();
return true;
}
return false;
diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp
index fd606aa83d6..3f6c63e1e5b 100644
--- a/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -210,7 +210,7 @@ lldb::BreakpointSP Breakpoint::CreateFromStructuredData(
llvm::StringRef name;
Status error;
success = names_array->GetItemAtIndexAsString(i, name);
- result_sp->AddName(name, error);
+ target.AddNameToBreakpoint(result_sp, name.str().c_str(), error);
}
}
@@ -455,6 +455,10 @@ bool Breakpoint::InvokeCallback(StoppointCallbackContext *context,
BreakpointOptions *Breakpoint::GetOptions() { return m_options_up.get(); }
+const BreakpointOptions *Breakpoint::GetOptions() const {
+ return m_options_up.get();
+}
+
void Breakpoint::ResolveBreakpoint() {
if (m_resolver_sp)
m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
@@ -841,18 +845,8 @@ size_t Breakpoint::GetNumResolvedLocations() const {
size_t Breakpoint::GetNumLocations() const { return m_locations.GetSize(); }
-bool Breakpoint::AddName(llvm::StringRef new_name, Status &error) {
- if (new_name.empty())
- return false;
- if (!BreakpointID::StringIsBreakpointName(new_name, error)) {
- error.SetErrorStringWithFormatv("input name \"{0}\" not a breakpoint name.",
- new_name);
- return false;
- }
- if (!error.Success())
- return false;
-
- m_name_list.insert(new_name);
+bool Breakpoint::AddName(llvm::StringRef new_name) {
+ m_name_list.insert(new_name.str().c_str());
return true;
}
diff --git a/lldb/source/Breakpoint/BreakpointID.cpp b/lldb/source/Breakpoint/BreakpointID.cpp
index 112f7c0b519..b8010654682 100644
--- a/lldb/source/Breakpoint/BreakpointID.cpp
+++ b/lldb/source/Breakpoint/BreakpointID.cpp
@@ -101,15 +101,24 @@ BreakpointID::ParseCanonicalReference(llvm::StringRef input) {
bool BreakpointID::StringIsBreakpointName(llvm::StringRef str, Status &error) {
error.Clear();
if (str.empty())
+ {
+ error.SetErrorStringWithFormat("Empty breakpoint names are not allowed");
return false;
+ }
// First character must be a letter or _
if (!isalpha(str[0]) && str[0] != '_')
+ {
+ error.SetErrorStringWithFormat("Breakpoint names must start with a "
+ "character or underscore: %s",
+ str.str().c_str());
return false;
+ }
// Cannot contain ., -, or space.
if (str.find_first_of(".- ") != llvm::StringRef::npos) {
- error.SetErrorStringWithFormat("invalid breakpoint name: \"%s\"",
+ error.SetErrorStringWithFormat("Breakpoint names cannot contain "
+ "'.' or '-': \"%s\"",
str.str().c_str());
return false;
}
diff --git a/lldb/source/Breakpoint/BreakpointIDList.cpp b/lldb/source/Breakpoint/BreakpointIDList.cpp
index 7b461147a4e..0a704fdc918 100644
--- a/lldb/source/Breakpoint/BreakpointIDList.cpp
+++ b/lldb/source/Breakpoint/BreakpointIDList.cpp
@@ -11,6 +11,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/lldb-enumerations.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -117,6 +118,8 @@ void BreakpointIDList::InsertStringArray(const char **string_array,
void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
bool allow_locations,
+ BreakpointName::Permissions
+ ::PermissionKinds purpose,
CommandReturnObject &result,
Args &new_args) {
llvm::StringRef range_from;
@@ -302,14 +305,29 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
}
// 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.GetString());
+ if (target && !names_found.empty()) {
+ Status error;
+ // Remove any names that aren't visible for this purpose:
+ auto iter = names_found.begin();
+ while (iter != names_found.end()) {
+ BreakpointName *bp_name = target->FindBreakpointName(ConstString(*iter),
+ true,
+ error);
+ if (bp_name && !bp_name->GetPermission(purpose))
+ iter = names_found.erase(iter);
+ else
+ iter++;
+ }
+
+ if (!names_found.empty()) {
+ 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.GetString());
+ }
}
}
}
diff --git a/lldb/source/Breakpoint/BreakpointList.cpp b/lldb/source/Breakpoint/BreakpointList.cpp
index 15bcb34a3d8..01ac59f0a90 100644
--- a/lldb/source/Breakpoint/BreakpointList.cpp
+++ b/lldb/source/Breakpoint/BreakpointList.cpp
@@ -71,6 +71,13 @@ void BreakpointList::SetEnabledAll(bool enabled) {
bp_sp->SetEnabled(enabled);
}
+void BreakpointList::SetEnabledAllowed(bool enabled) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ for (const auto &bp_sp : m_breakpoints)
+ if (bp_sp->AllowDisable())
+ bp_sp->SetEnabled(enabled);
+}
+
void BreakpointList::RemoveAll(bool notify) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
ClearAllBreakpointSites();
@@ -90,6 +97,32 @@ void BreakpointList::RemoveAll(bool notify) {
m_breakpoints.erase(m_breakpoints.begin(), m_breakpoints.end());
}
+void BreakpointList::RemoveAllowed(bool notify) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+
+ bp_collection::iterator pos, end = m_breakpoints.end();
+ if (notify) {
+ for (pos = m_breakpoints.begin(); pos != end; ++pos) {
+ if(!(*pos)->AllowDelete())
+ continue;
+ if ((*pos)->GetTarget().EventTypeHasListeners(
+ Target::eBroadcastBitBreakpointChanged)) {
+ (*pos)->GetTarget().BroadcastEvent(
+ Target::eBroadcastBitBreakpointChanged,
+ new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
+ *pos));
+ }
+ }
+ }
+ pos = m_breakpoints.begin();
+ while ( pos != end) {
+ if((*pos)->AllowDelete())
+ pos = m_breakpoints.erase(pos);
+ else
+ pos++;
+ }
+}
+
class BreakpointIDMatches {
public:
BreakpointIDMatches(break_id_t break_id) : m_break_id(break_id) {}
diff --git a/lldb/source/Breakpoint/BreakpointName.cpp b/lldb/source/Breakpoint/BreakpointName.cpp
new file mode 100644
index 00000000000..7b9a2acfbc4
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointName.cpp
@@ -0,0 +1,88 @@
+//===-- Breakpoint.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details->
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Casting.h"
+
+// Project includes
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointOptions.h"
+#include "lldb/Breakpoint/BreakpointLocationCollection.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const Flags::ValueType BreakpointName::Permissions::permissions_mask
+ [BreakpointName::Permissions::PermissionKinds::allPerms + 1] = {
+ (1u << 0),
+ (1u << 1),
+ (1u << 2),
+ (0x5u)
+};
+
+BreakpointName::BreakpointName(const ConstString &name, const Breakpoint &bkpt,
+ const char *help) :
+ m_name(name), m_options(bkpt.GetOptions())
+{
+ SetHelp(help);
+}
+
+bool BreakpointName::Permissions::GetDescription(Stream *s,
+ lldb::DescriptionLevel level) {
+ if (!AnySet())
+ return false;
+ s->IndentMore();
+ s->Indent();
+ if (IsSet(listPerm))
+ s->Printf("list: %s", GetAllowList() ? "allowed" : "disallowed");
+
+ if (IsSet(disablePerm))
+ s->Printf("disable: %s", GetAllowDisable() ? "allowed" : "disallowed");
+
+ if (IsSet(deletePerm))
+ s->Printf("delete: %s", GetAllowDelete() ? "allowed" : "disallowed");
+ s->IndentLess();
+ return true;
+}
+
+bool BreakpointName::GetDescription(Stream *s, lldb::DescriptionLevel level) {
+ bool printed_any = false;
+ if (GetOptions().AnySet())
+ {
+ s->PutCString("Options: \n");
+ s->IndentMore();
+ s->Indent();
+ GetOptions().GetDescription(s, level);
+ printed_any = true;
+ s->IndentLess();
+ }
+ if (GetPermissions().AnySet())
+ {
+ s->PutCString("Permissions: \n");
+ s->IndentMore();
+ s->Indent();
+ GetPermissions().GetDescription(s, level);
+ printed_any = true;
+ s->IndentLess();
+ }
+ return printed_any;
+}
+
+void BreakpointName::ConfigureBreakpoint(lldb::BreakpointSP bp_sp)
+{
+ bp_sp->GetOptions()->CopyOverSetOptions(GetOptions());
+ bp_sp->GetPermissions().MergeInto(GetPermissions());
+}
diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp
index 7159688102d..662b288794d 100644
--- a/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -132,7 +132,7 @@ BreakpointOptions::BreakpointOptions(bool all_flags_set)
m_baton_is_command_baton(false), m_callback_is_synchronous(false),
m_enabled(true), m_one_shot(false), m_ignore_count(0), m_thread_spec_ap(),
m_condition_text(), m_condition_text_hash(0), m_auto_continue(false),
- m_set_flags() {
+ m_set_flags(0) {
if (all_flags_set)
m_set_flags.Set(~((Flags::ValueType) 0));
}
@@ -142,11 +142,14 @@ BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
bool auto_continue)
: m_callback(nullptr), m_baton_is_command_baton(false),
m_callback_is_synchronous(false), m_enabled(enabled),
- m_one_shot(one_shot), m_ignore_count(ignore), m_condition_text(condition),
+ m_one_shot(one_shot), m_ignore_count(ignore),
m_condition_text_hash(0), m_auto_continue(auto_continue)
{
m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot
- | eCondition | eAutoContinue);
+ | eAutoContinue);
+ if (condition && *condition != '\0') {
+ SetCondition(condition);
+ }
}
//----------------------------------------------------------------------
@@ -187,6 +190,59 @@ operator=(const BreakpointOptions &rhs) {
return *this;
}
+void BreakpointOptions::CopyOverSetOptions(const BreakpointOptions &incoming)
+{
+ if (incoming.m_set_flags.Test(eEnabled))
+ {
+ m_enabled = incoming.m_enabled;
+ m_set_flags.Set(eEnabled);
+ }
+ if (incoming.m_set_flags.Test(eOneShot))
+ {
+ m_one_shot = incoming.m_one_shot;
+ m_set_flags.Set(eOneShot);
+ }
+ if (incoming.m_set_flags.Test(eCallback))
+ {
+ m_callback = incoming.m_callback;
+ m_callback_baton_sp = incoming.m_callback_baton_sp;
+ m_callback_is_synchronous = incoming.m_callback_is_synchronous;
+ m_baton_is_command_baton = incoming.m_baton_is_command_baton;
+ m_set_flags.Set(eCallback);
+ }
+ if (incoming.m_set_flags.Test(eIgnoreCount))
+ {
+ m_ignore_count = incoming.m_ignore_count;
+ m_set_flags.Set(eIgnoreCount);
+ }
+ if (incoming.m_set_flags.Test(eCondition))
+ {
+ // If we're copying over an empty condition, mark it as unset.
+ if (incoming.m_condition_text.empty()) {
+ m_condition_text.clear();
+ m_condition_text_hash = 0;
+ m_set_flags.Clear(eCondition);
+ } else {
+ m_condition_text = incoming.m_condition_text;
+ m_condition_text_hash = incoming.m_condition_text_hash;
+ m_set_flags.Set(eCondition);
+ }
+ }
+ if (incoming.m_set_flags.Test(eAutoContinue))
+ {
+ m_auto_continue = incoming.m_auto_continue;
+ m_set_flags.Set(eAutoContinue);
+ }
+ if (incoming.m_set_flags.Test(eThreadSpec) && incoming.m_thread_spec_ap)
+ {
+ if (!m_thread_spec_ap)
+ m_thread_spec_ap.reset(new ThreadSpec(*incoming.m_thread_spec_ap.get()));
+ else
+ *m_thread_spec_ap.get() = *incoming.m_thread_spec_ap.get();
+ m_set_flags.Set(eThreadSpec);
+ }
+}
+
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
@@ -327,23 +383,23 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
StructuredData::DictionarySP options_dict_sp(
new StructuredData::Dictionary());
- if (m_set_flags.Set(eEnabled))
+ if (m_set_flags.Test(eEnabled))
options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState),
m_enabled);
- if (m_set_flags.Set(eOneShot))
+ if (m_set_flags.Test(eOneShot))
options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
m_one_shot);
- if (m_set_flags.Set(eAutoContinue))
+ if (m_set_flags.Test(eAutoContinue))
options_dict_sp->AddBooleanItem(GetKey(OptionNames::AutoContinue),
m_auto_continue);
- if (m_set_flags.Set(eIgnoreCount))
+ if (m_set_flags.Test(eIgnoreCount))
options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
m_ignore_count);
- if (m_set_flags.Set(eCondition))
+ if (m_set_flags.Test(eCondition))
options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
m_condition_text);
- if (m_set_flags.Set(eCallback) && m_baton_is_command_baton) {
+ if (m_set_flags.Test(eCallback) && m_baton_is_command_baton) {
auto cmd_baton =
std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
StructuredData::ObjectSP commands_sp =
@@ -353,7 +409,7 @@ StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
BreakpointOptions::CommandData::GetSerializationKey(), commands_sp);
}
}
- if (m_set_flags.Set(eThreadSpec) && m_thread_spec_ap) {
+ if (m_set_flags.Test(eThreadSpec) && m_thread_spec_ap) {
StructuredData::ObjectSP thread_spec_sp =
m_thread_spec_ap->SerializeToStructuredData();
options_dict_sp->AddItem(ThreadSpec::GetSerializationKey(), thread_spec_sp);
@@ -618,3 +674,18 @@ bool BreakpointOptions::BreakpointOptionsCallbackFunction(
}
return ret_value;
}
+
+void BreakpointOptions::Clear()
+{
+ m_set_flags.Clear();
+ m_thread_spec_ap.release();
+ m_one_shot = false;
+ m_ignore_count = 0;
+ m_auto_continue = false;
+ m_callback = nullptr;
+ m_callback_baton_sp.reset();
+ m_baton_is_command_baton = false;
+ m_callback_is_synchronous = false;
+ m_enabled = false;
+ m_condition_text.clear();
+}
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index d53e681514d..f4276e4e979 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -45,6 +45,203 @@ static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
s->EOL();
}
+//-------------------------------------------------------------------------
+// Modifiable Breakpoint Options
+//-------------------------------------------------------------------------
+#pragma mark Modify::CommandOptions
+static OptionDefinition g_breakpoint_modify_options[] = {
+ // clang-format off
+ { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
+ { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
+ { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
+ { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
+ { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." },
+ { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." },
+ { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
+ { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
+ { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." },
+ { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." },
+ { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." },
+ // clang-format on
+};
+class lldb_private::BreakpointOptionGroup : public OptionGroup
+{
+public:
+ BreakpointOptionGroup() :
+ OptionGroup(),
+ m_bp_opts(false) {}
+
+ ~BreakpointOptionGroup() override = default;
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_breakpoint_modify_options);
+ }
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const int short_option = g_breakpoint_modify_options[option_idx].short_option;
+
+ switch (short_option) {
+ case 'c':
+ // Normally an empty breakpoint condition marks is as unset.
+ // But we need to say it was passed in.
+ m_bp_opts.SetCondition(option_arg.str().c_str());
+ m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
+ break;
+ case 'C':
+ m_commands.push_back(option_arg);
+ break;
+ case 'd':
+ m_bp_opts.SetEnabled(false);
+ break;
+ case 'e':
+ m_bp_opts.SetEnabled(true);
+ break;
+ case 'G': {
+ bool value, success;
+ value = Args::StringToBoolean(option_arg, false, &success);
+ if (success) {
+ m_bp_opts.SetAutoContinue(value);
+ } else
+ error.SetErrorStringWithFormat(
+ "invalid boolean value '%s' passed for -G option",
+ option_arg.str().c_str());
+ }
+ break;
+ case 'i':
+ {
+ uint32_t ignore_count;
+ if (option_arg.getAsInteger(0, ignore_count))
+ error.SetErrorStringWithFormat("invalid ignore count '%s'",
+ option_arg.str().c_str());
+ else
+ m_bp_opts.SetIgnoreCount(ignore_count);
+ }
+ break;
+ case 'o': {
+ bool value, success;
+ value = Args::StringToBoolean(option_arg, false, &success);
+ if (success) {
+ m_bp_opts.SetOneShot(value);
+ } else
+ error.SetErrorStringWithFormat(
+ "invalid boolean value '%s' passed for -o option",
+ option_arg.str().c_str());
+ } break;
+ case 't':
+ {
+ lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
+ if (option_arg[0] != '\0') {
+ if (option_arg.getAsInteger(0, thread_id))
+ error.SetErrorStringWithFormat("invalid thread id string '%s'",
+ option_arg.str().c_str());
+ }
+ m_bp_opts.SetThreadID(thread_id);
+ }
+ break;
+ case 'T':
+ m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
+ break;
+ case 'q':
+ m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
+ break;
+ case 'x':
+ {
+ uint32_t thread_index = UINT32_MAX;
+ if (option_arg[0] != '\n') {
+ if (option_arg.getAsInteger(0, thread_index))
+ error.SetErrorStringWithFormat("invalid thread index string '%s'",
+ option_arg.str().c_str());
+ }
+ m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_bp_opts.Clear();
+ m_commands.clear();
+ }
+
+ Status OptionParsingFinished(ExecutionContext *execution_context) override {
+ if (!m_commands.empty())
+ {
+ if (!m_commands.empty())
+ {
+ auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
+
+ for (std::string &str : m_commands)
+ cmd_data->user_source.AppendString(str);
+
+ cmd_data->stop_on_error = true;
+ m_bp_opts.SetCommandDataCallback(cmd_data);
+ }
+ }
+ return Status();
+ }
+
+ const BreakpointOptions &GetBreakpointOptions()
+ {
+ return m_bp_opts;
+ }
+
+ std::vector<std::string> m_commands;
+ BreakpointOptions m_bp_opts;
+
+};
+static OptionDefinition g_breakpoint_dummy_options[] = {
+ // clang-format off
+ { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, "
+ "which prime new targets." },
+ // clang-format on
+};
+
+class BreakpointDummyOptionGroup : public OptionGroup
+{
+public:
+ BreakpointDummyOptionGroup() :
+ OptionGroup() {}
+
+ ~BreakpointDummyOptionGroup() override = default;
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_breakpoint_dummy_options);
+ }
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const int short_option = g_breakpoint_modify_options[option_idx].short_option;
+
+ switch (short_option) {
+ case 'D':
+ m_use_dummy = true;
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_use_dummy = false;
+ }
+
+ bool m_use_dummy;
+
+};
+
// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
@@ -58,18 +255,7 @@ static OptionDefinition g_breakpoint_set_options[] = {
// clang-format off
{ LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option "
"multiple times to specify multiple shared libraries." },
- { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
- { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "The breakpoint is deleted the first time it causes a stop." },
- { LLDB_OPT_SET_ALL, false, "auto-continue", 'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
- { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
- { LLDB_OPT_SET_ALL, false, "command", 'd', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." },
- { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose indeX matches this argument." },
- { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
- { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this "
- "argument." },
{ LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
- { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by "
- "this argument." },
{ LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default "
"lldb only looks for files that are #included if they use the standard include "
"file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
@@ -127,8 +313,6 @@ static OptionDefinition g_breakpoint_set_options[] = {
"If not set the target.language setting is used." },
{ LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
{ LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. "
"At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
@@ -158,24 +342,30 @@ public:
interpreter, "breakpoint set",
"Sets a breakpoint or set of breakpoints in the executable.",
"breakpoint set <cmd-options>"),
- m_options() {}
+ m_bp_opts(), m_options() {
+ // We're picking up all the normal options, commands and disable.
+ m_all_options.Append(&m_bp_opts,
+ LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
+ LLDB_OPT_SET_ALL);
+ m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
+ m_all_options.Append(&m_options);
+ m_all_options.Finalize();
+ }
~CommandObjectBreakpointSet() override = default;
- Options *GetOptions() override { return &m_options; }
+ Options *GetOptions() override { return &m_all_options; }
- class CommandOptions : public Options {
+ class CommandOptions : public OptionGroup {
public:
CommandOptions()
- : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
+ : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
- m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
- m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(),
m_catch_bp(false), m_throw_bp(true), m_hardware(false),
m_exception_language(eLanguageTypeUnknown),
m_language(lldb::eLanguageTypeUnknown),
- m_skip_prologue(eLazyBoolCalculate), m_one_shot(false),
+ m_skip_prologue(eLazyBoolCalculate),
m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
~CommandOptions() override = default;
@@ -183,7 +373,7 @@ public:
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override {
Status error;
- const int short_option = m_getopt_table[option_idx].val;
+ const int short_option = g_breakpoint_set_options[option_idx].short_option;
switch (short_option) {
case 'a': {
@@ -206,18 +396,6 @@ public:
option_arg.str().c_str());
break;
- case 'c':
- m_condition.assign(option_arg);
- break;
-
- case 'd':
- m_commands.push_back(option_arg);
- break;
-
- case 'D':
- m_use_dummy = true;
- break;
-
case 'E': {
LanguageType language = Language::GetLanguageTypeFromString(option_arg);
@@ -262,15 +440,6 @@ public:
m_func_name_type_mask |= eFunctionNameTypeFull;
break;
- case 'G' : {
- bool success;
- m_auto_continue = Args::StringToBoolean(option_arg, true, &success);
- if (!success)
- error.SetErrorStringWithFormat(
- "Invalid boolean value for auto-continue option: '%s'",
- option_arg.str().c_str());
- } break;
-
case 'h': {
bool success;
m_catch_bp = Args::StringToBoolean(option_arg, true, &success);
@@ -284,12 +453,6 @@ public:
m_hardware = true;
break;
- case 'i':
- if (option_arg.getAsInteger(0, m_ignore_count))
- error.SetErrorStringWithFormat("invalid ignore count '%s'",
- option_arg.str().c_str());
- break;
-
case 'K': {
bool success;
bool value;
@@ -362,10 +525,6 @@ public:
m_offset_addr = tmp_offset_addr;
} break;
- case 'o':
- m_one_shot = true;
- break;
-
case 'O':
m_exception_extra_args.AppendArgument("-O");
m_exception_extra_args.AppendArgument(option_arg);
@@ -375,10 +534,6 @@ public:
m_source_text_regexp.assign(option_arg);
break;
- case 'q':
- m_queue_name.assign(option_arg);
- break;
-
case 'r':
m_func_regexp.assign(option_arg);
break;
@@ -392,16 +547,6 @@ public:
m_func_name_type_mask |= eFunctionNameTypeSelector;
break;
- case 't':
- if (option_arg.getAsInteger(0, m_thread_id))
- error.SetErrorStringWithFormat("invalid thread id string '%s'",
- option_arg.str().c_str());
- break;
-
- case 'T':
- m_thread_name.assign(option_arg);
- break;
-
case 'w': {
bool success;
m_throw_bp = Args::StringToBoolean(option_arg, true, &success);
@@ -411,12 +556,6 @@ public:
option_arg.str().c_str());
} break;
- case 'x':
- if (option_arg.getAsInteger(0, m_thread_index))
- error.SetErrorStringWithFormat("invalid thread index string '%s'",
- option_arg.str().c_str());
- break;
-
case 'X':
m_source_regex_func_names.insert(option_arg);
break;
@@ -431,7 +570,6 @@ public:
}
void OptionParsingStarting(ExecutionContext *execution_context) override {
- m_condition.clear();
m_filenames.Clear();
m_line_num = 0;
m_column = 0;
@@ -442,26 +580,17 @@ public:
m_modules.Clear();
m_load_addr = LLDB_INVALID_ADDRESS;
m_offset_addr = 0;
- m_ignore_count = 0;
- m_thread_id = LLDB_INVALID_THREAD_ID;
- m_thread_index = UINT32_MAX;
- m_thread_name.clear();
- m_queue_name.clear();
m_catch_bp = false;
m_throw_bp = true;
m_hardware = false;
m_exception_language = eLanguageTypeUnknown;
m_language = lldb::eLanguageTypeUnknown;
m_skip_prologue = eLazyBoolCalculate;
- m_one_shot = false;
- m_use_dummy = false;
m_breakpoint_names.clear();
m_all_files = false;
m_exception_extra_args.Clear();
m_move_to_nearest_code = eLazyBoolCalculate;
m_source_regex_func_names.clear();
- m_commands.clear();
- m_auto_continue = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -482,30 +611,21 @@ public:
FileSpecList m_modules;
lldb::addr_t m_load_addr;
lldb::addr_t m_offset_addr;
- uint32_t m_ignore_count;
- lldb::tid_t m_thread_id;
- uint32_t m_thread_index;
- std::string m_thread_name;
- std::string m_queue_name;
bool m_catch_bp;
bool m_throw_bp;
bool m_hardware; // Request to use hardware breakpoints
lldb::LanguageType m_exception_language;
lldb::LanguageType m_language;
LazyBool m_skip_prologue;
- bool m_one_shot;
- bool m_use_dummy;
bool m_all_files;
Args m_exception_extra_args;
LazyBool m_move_to_nearest_code;
std::unordered_set<std::string> m_source_regex_func_names;
- std::vector<std::string> m_commands;
- bool m_auto_continue;
};
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
- Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
+ Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
if (target == nullptr) {
result.AppendError("Invalid target. Must set target before setting "
@@ -540,7 +660,7 @@ protected:
else if (m_options.m_exception_language != eLanguageTypeUnknown)
break_type = eSetTypeException;
- Breakpoint *bp = nullptr;
+ BreakpointSP bp_sp = nullptr;
FileSpec module_spec;
const bool internal = false;
@@ -572,35 +692,32 @@ protected:
// Only check for inline functions if
LazyBool check_inlines = eLazyBoolCalculate;
- bp = target
- ->CreateBreakpoint(&(m_options.m_modules), file,
- m_options.m_line_num, m_options.m_offset_addr,
- check_inlines, m_options.m_skip_prologue,
- internal, m_options.m_hardware,
- m_options.m_move_to_nearest_code)
- .get();
+ bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
+ file,
+ m_options.m_line_num,
+ m_options.m_offset_addr,
+ check_inlines,
+ m_options.m_skip_prologue,
+ internal,
+ m_options.m_hardware,
+ m_options.m_move_to_nearest_code);
} break;
case eSetTypeAddress: // Breakpoint by address
{
// If a shared library has been specified, make an lldb_private::Address
- // with the library, and
- // use that. That way the address breakpoint will track the load location
- // of the library.
+ // with the library, and use that. That way the address breakpoint
+ // will track the load location of the library.
size_t num_modules_specified = m_options.m_modules.GetSize();
if (num_modules_specified == 1) {
const FileSpec *file_spec =
m_options.m_modules.GetFileSpecPointerAtIndex(0);
- bp = target
- ->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
- internal, file_spec,
- m_options.m_hardware)
- .get();
+ bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
+ internal, file_spec,
+ m_options.m_hardware);
} else if (num_modules_specified == 0) {
- bp = target
- ->CreateBreakpoint(m_options.m_load_addr, internal,
- m_options.m_hardware)
- .get();
+ bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
+ m_options.m_hardware);
} else {
result.AppendError("Only one shared library can be specified for "
"address breakpoints.");
@@ -616,13 +733,15 @@ protected:
if (name_type_mask == 0)
name_type_mask = eFunctionNameTypeAuto;
- bp = target
- ->CreateBreakpoint(
- &(m_options.m_modules), &(m_options.m_filenames),
- m_options.m_func_names, name_type_mask, m_options.m_language,
- m_options.m_offset_addr, m_options.m_skip_prologue, internal,
- m_options.m_hardware)
- .get();
+ bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
+ &(m_options.m_filenames),
+ m_options.m_func_names,
+ name_type_mask,
+ m_options.m_language,
+ m_options.m_offset_addr,
+ m_options.m_skip_prologue,
+ internal,
+ m_options.m_hardware);
} break;
case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
@@ -639,12 +758,13 @@ protected:
return false;
}
- bp = target
- ->CreateFuncRegexBreakpoint(
- &(m_options.m_modules), &(m_options.m_filenames), regexp,
- m_options.m_language, m_options.m_skip_prologue, internal,
- m_options.m_hardware)
- .get();
+ bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
+ &(m_options.m_filenames),
+ regexp,
+ m_options.m_language,
+ m_options.m_skip_prologue,
+ internal,
+ m_options.m_hardware);
}
break;
case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
@@ -673,26 +793,30 @@ protected:
result.SetStatus(eReturnStatusFailed);
return false;
}
- bp = target
- ->CreateSourceRegexBreakpoint(
- &(m_options.m_modules), &(m_options.m_filenames),
- m_options.m_source_regex_func_names, regexp, internal,
- m_options.m_hardware, m_options.m_move_to_nearest_code)
- .get();
+ bp_sp =
+ target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
+ &(m_options.m_filenames),
+ m_options
+ .m_source_regex_func_names,
+ regexp,
+ internal,
+ m_options.m_hardware,
+ m_options.m_move_to_nearest_code);
} break;
case eSetTypeException: {
Status precond_error;
- bp = target
- ->CreateExceptionBreakpoint(
- m_options.m_exception_language, m_options.m_catch_bp,
- m_options.m_throw_bp, internal,
- &m_options.m_exception_extra_args, &precond_error)
- .get();
+ bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
+ m_options.m_catch_bp,
+ m_options.m_throw_bp,
+ internal,
+ &m_options
+ .m_exception_extra_args,
+ &precond_error);
if (precond_error.Fail()) {
result.AppendErrorWithFormat(
"Error setting extra exception arguments: %s",
precond_error.AsCString());
- target->RemoveBreakpointByID(bp->GetID());
+ target->RemoveBreakpointByID(bp_sp->GetID());
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -702,76 +826,43 @@ protected:
}
// Now set the various options that were passed in:
- if (bp) {
- if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
- bp->SetThreadID(m_options.m_thread_id);
-
- if (m_options.m_thread_index != UINT32_MAX)
- bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
-
- if (!m_options.m_thread_name.empty())
- bp->GetOptions()->GetThreadSpec()->SetName(
- m_options.m_thread_name.c_str());
-
- if (!m_options.m_queue_name.empty())
- bp->GetOptions()->GetThreadSpec()->SetQueueName(
- m_options.m_queue_name.c_str());
-
- if (m_options.m_ignore_count != 0)
- bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
-
- if (!m_options.m_condition.empty())
- bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
+ if (bp_sp) {
+ bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
if (!m_options.m_breakpoint_names.empty()) {
Status name_error;
for (auto name : m_options.m_breakpoint_names) {
- bp->AddName(name.c_str(), name_error);
+ target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
if (name_error.Fail()) {
result.AppendErrorWithFormat("Invalid breakpoint name: %s",
name.c_str());
- target->RemoveBreakpointByID(bp->GetID());
+ target->RemoveBreakpointByID(bp_sp->GetID());
result.SetStatus(eReturnStatusFailed);
return false;
}
}
}
-
- bp->SetOneShot(m_options.m_one_shot);
- bp->SetAutoContinue(m_options.m_auto_continue);
-
- if (!m_options.m_commands.empty())
- {
- auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
-
- for (std::string &str : m_options.m_commands)
- cmd_data->user_source.AppendString(str);
-
- cmd_data->stop_on_error = true;
- bp->GetOptions()->SetCommandDataCallback(cmd_data);
- }
}
-
- if (bp) {
+
+ if (bp_sp) {
Stream &output_stream = result.GetOutputStream();
const bool show_locations = false;
- bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
+ bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
show_locations);
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) {
+ // set before the target is set, but we won't know how to actually set
+ // the breakpoint till we run.
+ if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
"actual locations.\n");
}
}
result.SetStatus(eReturnStatusSuccessFinishResult);
- } else if (!bp) {
+ } else if (!bp_sp) {
result.AppendError("Breakpoint creation failed: No breakpoint created.");
result.SetStatus(eReturnStatusFailed);
}
@@ -813,30 +904,15 @@ private:
return true;
}
+ BreakpointOptionGroup m_bp_opts;
+ BreakpointDummyOptionGroup m_dummy_options;
CommandOptions m_options;
+ OptionGroupOptions m_all_options;
};
//-------------------------------------------------------------------------
// CommandObjectBreakpointModify
//-------------------------------------------------------------------------
-
-#pragma mark Modify::CommandOptions
-static OptionDefinition g_breakpoint_modify_options[] = {
- // clang-format off
- { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
- { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
- { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
- { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
- { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." },
- { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." },
- { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
- { LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." },
- { LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." },
- { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
- { LLDB_OPT_SET_ALL, false, "auto-continue", 'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
- // clang-format on
-};
-
#pragma mark Modify
class CommandObjectBreakpointModify : public CommandObjectParsed {
@@ -857,163 +933,21 @@ public:
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments.push_back(arg);
+
+ m_options.Append(&m_bp_opts,
+ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
+ LLDB_OPT_SET_ALL);
+ m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
+ m_options.Finalize();
}
~CommandObjectBreakpointModify() override = default;
Options *GetOptions() override { return &m_options; }
- class CommandOptions : public Options {
- public:
- CommandOptions()
- : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
- m_thread_id_passed(false), m_thread_index(UINT32_MAX),
- m_thread_index_passed(false), m_thread_name(), m_queue_name(),
- m_condition(), m_one_shot(false), m_enable_passed(false),
- m_enable_value(false), m_name_passed(false), m_queue_passed(false),
- m_condition_passed(false), m_one_shot_passed(false),
- m_use_dummy(false) {}
-
- ~CommandOptions() override = default;
-
- Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) override {
- Status error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option) {
- case 'c':
- m_condition = option_arg;
- m_condition_passed = true;
- break;
- case 'd':
- 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;
- break;
- case 'G': {
- bool value, success;
- value = Args::StringToBoolean(option_arg, false, &success);
- if (success) {
- m_auto_continue_passed = true;
- m_auto_continue = value;
- } else
- error.SetErrorStringWithFormat(
- "invalid boolean value '%s' passed for -G option",
- option_arg.str().c_str());
- } break;
- case 'i':
- if (option_arg.getAsInteger(0, m_ignore_count))
- error.SetErrorStringWithFormat("invalid ignore count '%s'",
- option_arg.str().c_str());
- break;
- case 'o': {
- bool value, success;
- value = Args::StringToBoolean(option_arg, false, &success);
- if (success) {
- m_one_shot_passed = true;
- m_one_shot = value;
- } else
- error.SetErrorStringWithFormat(
- "invalid boolean value '%s' passed for -o option",
- option_arg.str().c_str());
- } break;
- case 't':
- if (option_arg[0] == '\0') {
- m_thread_id = LLDB_INVALID_THREAD_ID;
- m_thread_id_passed = true;
- } else {
- if (option_arg.getAsInteger(0, m_thread_id))
- error.SetErrorStringWithFormat("invalid thread id string '%s'",
- option_arg.str().c_str());
- else
- m_thread_id_passed = true;
- }
- break;
- case 'T':
- m_thread_name = option_arg;
- m_name_passed = true;
- break;
- case 'q':
- m_queue_name = option_arg;
- m_queue_passed = true;
- break;
- case 'x':
- if (option_arg[0] == '\n') {
- m_thread_index = UINT32_MAX;
- m_thread_index_passed = true;
- } else {
- if (option_arg.getAsInteger(0, m_thread_index))
- error.SetErrorStringWithFormat("invalid thread index string '%s'",
- option_arg.str().c_str());
- else
- m_thread_index_passed = true;
- }
- break;
- default:
- error.SetErrorStringWithFormat("unrecognized option '%c'",
- short_option);
- break;
- }
-
- return error;
- }
-
- void OptionParsingStarting(ExecutionContext *execution_context) override {
- m_ignore_count = 0;
- m_thread_id = LLDB_INVALID_THREAD_ID;
- m_thread_id_passed = false;
- m_thread_index = UINT32_MAX;
- m_thread_index_passed = false;
- m_thread_name.clear();
- m_queue_name.clear();
- m_condition.clear();
- m_one_shot = false;
- m_enable_passed = false;
- m_queue_passed = false;
- m_name_passed = false;
- m_condition_passed = false;
- m_one_shot_passed = false;
- m_use_dummy = false;
- m_auto_continue = false;
- m_auto_continue_passed = false;
- }
-
- llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
- return llvm::makeArrayRef(g_breakpoint_modify_options);
- }
-
- // Instance variables to hold the values for command options.
-
- uint32_t m_ignore_count;
- lldb::tid_t m_thread_id;
- bool m_thread_id_passed;
- uint32_t m_thread_index;
- bool m_thread_index_passed;
- std::string m_thread_name;
- std::string m_queue_name;
- std::string m_condition;
- bool m_one_shot;
- bool m_enable_passed;
- bool m_enable_value;
- bool m_name_passed;
- bool m_queue_passed;
- bool m_condition_passed;
- bool m_one_shot_passed;
- bool m_use_dummy;
- bool m_auto_continue;
- bool m_auto_continue_passed;
- };
-
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
- Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
+ Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
if (target == nullptr) {
result.AppendError("Invalid target. No existing target or breakpoints.");
result.SetStatus(eReturnStatusFailed);
@@ -1026,7 +960,8 @@ protected:
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::disablePerm);
if (result.Succeeded()) {
const size_t count = valid_bp_ids.GetSize();
@@ -1039,55 +974,12 @@ protected:
if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
BreakpointLocation *location =
bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
- if (location) {
- if (m_options.m_thread_id_passed)
- location->SetThreadID(m_options.m_thread_id);
-
- if (m_options.m_thread_index_passed)
- location->SetThreadIndex(m_options.m_thread_index);
-
- if (m_options.m_name_passed)
- location->SetThreadName(m_options.m_thread_name.c_str());
-
- if (m_options.m_queue_passed)
- location->SetQueueName(m_options.m_queue_name.c_str());
-
- if (m_options.m_ignore_count != 0)
- location->SetIgnoreCount(m_options.m_ignore_count);
-
- if (m_options.m_enable_passed)
- location->SetEnabled(m_options.m_enable_value);
-
- if (m_options.m_condition_passed)
- location->SetCondition(m_options.m_condition.c_str());
-
- if (m_options.m_auto_continue_passed)
- location->SetAutoContinue(m_options.m_auto_continue);
- }
+ if (location)
+ location->GetLocationOptions()
+ ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
} else {
- if (m_options.m_thread_id_passed)
- bp->SetThreadID(m_options.m_thread_id);
-
- if (m_options.m_thread_index_passed)
- bp->SetThreadIndex(m_options.m_thread_index);
-
- if (m_options.m_name_passed)
- bp->SetThreadName(m_options.m_thread_name.c_str());
-
- if (m_options.m_queue_passed)
- bp->SetQueueName(m_options.m_queue_name.c_str());
-
- if (m_options.m_ignore_count != 0)
- bp->SetIgnoreCount(m_options.m_ignore_count);
-
- if (m_options.m_enable_passed)
- bp->SetEnabled(m_options.m_enable_value);
-
- if (m_options.m_condition_passed)
- bp->SetCondition(m_options.m_condition.c_str());
-
- if (m_options.m_auto_continue_passed)
- bp->SetAutoContinue(m_options.m_auto_continue);
+ bp->GetOptions()
+ ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
}
}
}
@@ -1097,7 +989,9 @@ protected:
}
private:
- CommandOptions m_options;
+ BreakpointOptionGroup m_bp_opts;
+ BreakpointDummyOptionGroup m_dummy_opts;
+ OptionGroupOptions m_options;
};
//-------------------------------------------------------------------------
@@ -1146,7 +1040,7 @@ protected:
if (command.empty()) {
// No breakpoint selected; enable all currently set breakpoints.
- target->EnableAllBreakpoints();
+ target->EnableAllowedBreakpoints();
result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
" breakpoints)\n",
(uint64_t)num_breakpoints);
@@ -1155,7 +1049,8 @@ protected:
// Particular breakpoint selected; enable that breakpoint.
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::disablePerm);
if (result.Succeeded()) {
int enable_count = 0;
@@ -1259,7 +1154,7 @@ protected:
if (command.empty()) {
// No breakpoint selected; disable all currently set breakpoints.
- target->DisableAllBreakpoints();
+ target->DisableAllowedBreakpoints();
result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
" breakpoints)\n",
(uint64_t)num_breakpoints);
@@ -1269,7 +1164,8 @@ protected:
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::disablePerm);
if (result.Succeeded()) {
int disable_count = 0;
@@ -1436,14 +1332,17 @@ protected:
result.AppendMessage("Current breakpoints:");
for (size_t i = 0; i < num_breakpoints; ++i) {
Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
- AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level);
+ if (breakpoint->AllowList())
+ AddBreakpointDescription(&output_stream, breakpoint,
+ m_options.m_level);
}
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
// Particular breakpoints selected; show info about that breakpoint.
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::listPerm);
if (result.Succeeded()) {
for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
@@ -1731,7 +1630,7 @@ protected:
true)) {
result.AppendMessage("Operation cancelled...");
} else {
- target->RemoveAllBreakpoints();
+ target->RemoveAllowedBreakpoints();
result.AppendMessageWithFormat(
"All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
(uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
@@ -1741,7 +1640,8 @@ protected:
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::deletePerm);
if (result.Succeeded()) {
int delete_count = 0;
@@ -1789,7 +1689,7 @@ static OptionDefinition g_breakpoint_name_options[] = {
// clang-format off
{LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
{LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
- {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
+ {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
// clang-format on
};
class BreakpointNameOptionGroup : public OptionGroup {
@@ -1849,6 +1749,188 @@ public:
OptionValueBoolean m_use_dummy;
};
+static OptionDefinition g_breakpoint_access_options[] = {
+ // clang-format off
+ {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."},
+ {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."},
+ {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."},
+ // clang-format on
+};
+
+class BreakpointAccessOptionGroup : public OptionGroup
+{
+public:
+ BreakpointAccessOptionGroup() :
+ OptionGroup()
+ {}
+
+ ~BreakpointAccessOptionGroup() override = default;
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_breakpoint_access_options);
+ }
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const int short_option
+ = g_breakpoint_access_options[option_idx].short_option;
+
+ switch (short_option) {
+ case 'L': {
+ bool value, success;
+ value = Args::StringToBoolean(option_arg, false, &success);
+ if (success) {
+ m_permissions.SetAllowList(value);
+ } else
+ error.SetErrorStringWithFormat(
+ "invalid boolean value '%s' passed for -L option",
+ option_arg.str().c_str());
+ } break;
+ case 'A': {
+ bool value, success;
+ value = Args::StringToBoolean(option_arg, false, &success);
+ if (success) {
+ m_permissions.SetAllowDisable(value);
+ } else
+ error.SetErrorStringWithFormat(
+ "invalid boolean value '%s' passed for -L option",
+ option_arg.str().c_str());
+ } break;
+ case 'D': {
+ bool value, success;
+ value = Args::StringToBoolean(option_arg, false, &success);
+ if (success) {
+ m_permissions.SetAllowDelete(value);
+ } else
+ error.SetErrorStringWithFormat(
+ "invalid boolean value '%s' passed for -L option",
+ option_arg.str().c_str());
+ } break;
+
+ }
+
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ }
+
+ const BreakpointName::Permissions &GetPermissions() const
+ {
+ return m_permissions;
+ }
+ BreakpointName::Permissions m_permissions;
+};
+
+class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
+public:
+ CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "configure", "Configure the options for the breakpoint"
+ " name provided. "
+ "If you provide a breakpoint id, the options will be copied from "
+ "the breakpoint, otherwise only the options specified will be set "
+ "on the name.",
+ "breakpoint name configure <command-options> "
+ "<breakpoint-name-list>"),
+ m_bp_opts(), m_option_group() {
+ // Create the first variant for the first (and only) argument for this
+ // command.
+ CommandArgumentEntry arg1;
+ CommandArgumentData id_arg;
+ id_arg.arg_type = eArgTypeBreakpointName;
+ id_arg.arg_repetition = eArgRepeatOptional;
+ arg1.push_back(id_arg);
+ m_arguments.push_back(arg1);
+
+ m_option_group.Append(&m_bp_opts,
+ LLDB_OPT_SET_ALL,
+ LLDB_OPT_SET_1);
+ m_option_group.Append(&m_access_options,
+ LLDB_OPT_SET_ALL,
+ LLDB_OPT_SET_ALL);
+ m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2, LLDB_OPT_SET_2);
+ m_option_group.Finalize();
+ }
+
+ ~CommandObjectBreakpointNameConfigure() override = default;
+
+ Options *GetOptions() override { return &m_option_group; }
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ result.AppendError("No names provided.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Target *target =
+ GetSelectedOrDummyTarget(false);
+
+ if (target == nullptr) {
+ result.AppendError("Invalid target. No existing target or breakpoints.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ std::unique_lock<std::recursive_mutex> lock;
+ target->GetBreakpointList().GetListMutex(lock);
+
+ // Make a pass through first to see that all the names are legal.
+ for (auto &entry : command.entries()) {
+ Status error;
+ if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
+ {
+ result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
+ entry.c_str(), error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+ // Now configure them, we already pre-checked the names so we don't need
+ // to check the error:
+ BreakpointSP bp_sp;
+ if (m_bp_id.m_breakpoint.OptionWasSet())
+ {
+ lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
+ bp_sp = target->GetBreakpointByID(bp_id);
+ if (!bp_sp)
+ {
+ result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
+ bp_id);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ Status error;
+ for (auto &entry : command.entries()) {
+ ConstString name(entry.c_str());
+ BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
+ if (!bp_name)
+ continue;
+ if (bp_sp)
+ target->ConfigureBreakpointName(*bp_name,
+ *bp_sp->GetOptions(),
+ m_access_options.GetPermissions());
+ else
+ target->ConfigureBreakpointName(*bp_name,
+ m_bp_opts.GetBreakpointOptions(),
+ m_access_options.GetPermissions());
+ }
+ return true;
+ }
+
+private:
+ BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
+ BreakpointOptionGroup m_bp_opts;
+ BreakpointAccessOptionGroup m_access_options;
+ OptionGroupOptions m_option_group;
+};
+
class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
public:
CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
@@ -1904,7 +1986,8 @@ protected:
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::listPerm);
if (result.Succeeded()) {
if (valid_bp_ids.GetSize() == 0) {
@@ -1913,13 +1996,14 @@ protected:
return false;
}
size_t num_valid_ids = valid_bp_ids.GetSize();
+ const char *bp_name = m_name_options.m_name.GetCurrentValue();
+ Status error; // This error reports illegal names, but we've already
+ // checked that, so we don't need to check it again here.
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);
- Status 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);
+ target->AddNameToBreakpoint(bp_sp, bp_name, error);
}
}
@@ -1987,7 +2071,8 @@ protected:
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::deletePerm);
if (result.Succeeded()) {
if (valid_bp_ids.GetSize() == 0) {
@@ -1995,12 +2080,13 @@ protected:
result.SetStatus(eReturnStatusFailed);
return false;
}
+ ConstString bp_name(m_name_options.m_name.GetCurrentValue());
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());
+ target->RemoveNameFromBreakpoint(bp_sp, bp_name);
}
}
@@ -2016,11 +2102,12 @@ 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.",
+ "List either the names for a breakpoint or info "
+ "about a given name. With no arguments, lists all "
+ "names",
"breakpoint name list <command-options>"),
m_name_options(), m_option_group() {
- m_option_group.Append(&m_name_options);
+ m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
m_option_group.Finalize();
}
@@ -2038,42 +2125,57 @@ protected:
result.SetStatus(eReturnStatusFailed);
return false;
}
-
- if (m_name_options.m_name.OptionWasSet()) {
- const char *name = m_name_options.m_name.GetCurrentValue();
- std::unique_lock<std::recursive_mutex> lock;
- target->GetBreakpointList().GetListMutex(lock);
-
- BreakpointList &breakpoints = target->GetBreakpointList();
- for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
- if (bp_sp->MatchesName(name)) {
+
+
+ std::vector<std::string> name_list;
+ if (command.empty()) {
+ target->GetBreakpointNames(name_list);
+ } else {
+ for (const Args::ArgEntry &arg : command)
+ {
+ name_list.push_back(arg.c_str());
+ }
+ }
+
+ if (name_list.empty()) {
+ result.AppendMessage("No breakpoint names found.");
+ } else {
+ for (const std::string &name_str : name_list) {
+ const char *name = name_str.c_str();
+ // First print out the options for the name:
+ Status error;
+ BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
+ false,
+ error);
+ if (bp_name)
+ {
StreamString s;
- bp_sp->GetDescription(&s, eDescriptionLevelBrief);
- s.EOL();
- result.AppendMessage(s.GetString());
+ result.AppendMessageWithFormat("Name: %s\n", name);
+ if (bp_name->GetDescription(&s, eDescriptionLevelFull))
+ {
+ result.AppendMessage(s.GetString());
+ }
+
+ std::unique_lock<std::recursive_mutex> lock;
+ target->GetBreakpointList().GetListMutex(lock);
+
+ BreakpointList &breakpoints = target->GetBreakpointList();
+ bool any_set = false;
+ for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
+ if (bp_sp->MatchesName(name)) {
+ StreamString s;
+ any_set = true;
+ bp_sp->GetDescription(&s, eDescriptionLevelBrief);
+ s.EOL();
+ result.AppendMessage(s.GetString());
+ }
+ }
+ if (!any_set)
+ result.AppendMessage("No breakpoints using this name.");
+ } else {
+ result.AppendMessageWithFormat("Name: %s not found.\n", name);
}
}
-
- } 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;
}
@@ -2098,10 +2200,13 @@ public:
new CommandObjectBreakpointNameDelete(interpreter));
CommandObjectSP list_command_object(
new CommandObjectBreakpointNameList(interpreter));
+ CommandObjectSP configure_command_object(
+ new CommandObjectBreakpointNameConfigure(interpreter));
LoadSubCommand("add", add_command_object);
LoadSubCommand("delete", delete_command_object);
LoadSubCommand("list", list_command_object);
+ LoadSubCommand("configure", configure_command_object);
}
~CommandObjectBreakpointName() override = default;
@@ -2327,7 +2432,8 @@ protected:
BreakpointIDList valid_bp_ids;
if (!command.empty()) {
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::listPerm);
if (!result.Succeeded()) {
result.SetStatus(eReturnStatusFailed);
@@ -2412,7 +2518,10 @@ CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
bool allow_locations,
CommandReturnObject &result,
- BreakpointIDList *valid_ids) {
+ BreakpointIDList *valid_ids,
+ BreakpointName::Permissions
+ ::PermissionKinds
+ purpose) {
// args can be strings representing 1). integers (for breakpoint ids)
// 2). the full breakpoint & location
// canonical representation
@@ -2446,8 +2555,8 @@ void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
// all the breakpoint ids in the range, and shove all of those breakpoint id
// strings into TEMP_ARGS.
- BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
- result, temp_args);
+ BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
+ purpose, result, temp_args);
// NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
// BreakpointIDList:
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h
index 6e14b8f876a..5e1026a6b7e 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.h
+++ b/lldb/source/Commands/CommandObjectBreakpoint.h
@@ -18,11 +18,14 @@
// Other libraries and framework includes
// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Breakpoint/BreakpointName.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/STLUtils.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/Options.h"
+
namespace lldb_private {
//-------------------------------------------------------------------------
@@ -37,20 +40,26 @@ public:
static void VerifyBreakpointOrLocationIDs(Args &args, Target *target,
CommandReturnObject &result,
- BreakpointIDList *valid_ids) {
- VerifyIDs(args, target, true, result, valid_ids);
+ BreakpointIDList *valid_ids,
+ BreakpointName::Permissions
+ ::PermissionKinds purpose) {
+ VerifyIDs(args, target, true, result, valid_ids, purpose);
}
static void VerifyBreakpointIDs(Args &args, Target *target,
CommandReturnObject &result,
- BreakpointIDList *valid_ids) {
- VerifyIDs(args, target, false, result, valid_ids);
+ BreakpointIDList *valid_ids,
+ BreakpointName::Permissions::PermissionKinds
+ purpose) {
+ VerifyIDs(args, target, false, result, valid_ids, purpose);
}
private:
static void VerifyIDs(Args &args, Target *target, bool allow_locations,
CommandReturnObject &result,
- BreakpointIDList *valid_ids);
+ BreakpointIDList *valid_ids,
+ BreakpointName::Permissions::PermissionKinds
+ purpose);
};
} // namespace lldb_private
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
index ecb00f9a339..170cb851311 100644
--- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -390,7 +390,8 @@ protected:
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::listPerm);
m_bp_options_vec.clear();
@@ -571,7 +572,8 @@ protected:
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::listPerm);
if (result.Succeeded()) {
const size_t count = valid_bp_ids.GetSize();
@@ -662,7 +664,8 @@ protected:
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- command, target, result, &valid_bp_ids);
+ command, target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::listPerm);
if (result.Succeeded()) {
const size_t count = valid_bp_ids.GetSize();
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
index 96c245cb8bb..b1937d8b17b 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -1113,7 +1113,8 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = {
{ eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Watchpoint IDs are positive integers." },
{ eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { nullptr, false }, "For example, '1-3' or '1 to 3'." },
{ eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify the type for a watchpoint." },
- { eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." }
+ { eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." },
+ { eArgTypeCommand, "command", CommandCompletions::eNoCompletion, { nullptr, false }, "An LLDB Command line command." }
// clang-format on
};
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index 7e46afcccda..ad1083be028 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -3615,13 +3615,15 @@ RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name) {
}
BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
- BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(
+ Target &target = GetProcess()->GetTarget();
+ BreakpointSP bp = target.CreateBreakpoint(
m_filtersp, resolver_sp, false, false, false);
// Give RS breakpoints a specific name, so the user can manipulate them as a
// group.
Status err;
- if (!bp->AddName("RenderScriptKernel", err))
+ target.AddNameToBreakpoint(bp, "RenderScriptKernel", err);
+ if (err.Fail() && log)
if (log)
log->Printf("%s - error setting break name, '%s'.", __FUNCTION__,
err.AsCString());
@@ -3643,14 +3645,15 @@ RenderScriptRuntime::CreateReductionBreakpoint(const ConstString &name,
BreakpointResolverSP resolver_sp(new RSReduceBreakpointResolver(
nullptr, name, &m_rsmodules, kernel_types));
- BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(
+ Target &target = GetProcess()->GetTarget();
+ BreakpointSP bp = target.CreateBreakpoint(
m_filtersp, resolver_sp, false, false, false);
// Give RS breakpoints a specific name, so the user can manipulate them as a
// group.
Status err;
- if (!bp->AddName("RenderScriptReduction", err))
- if (log)
+ target.AddNameToBreakpoint(bp, "RenderScriptReduction", err);
+ if (err.Fail() && log)
log->Printf("%s - error setting break name, '%s'.", __FUNCTION__,
err.AsCString());
@@ -3885,15 +3888,16 @@ RenderScriptRuntime::CreateScriptGroupBreakpoint(const ConstString &name,
BreakpointResolverSP resolver_sp(new RSScriptGroupBreakpointResolver(
nullptr, name, m_scriptGroups, stop_on_all));
- BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(
+ Target &target = GetProcess()->GetTarget();
+ BreakpointSP bp = target.CreateBreakpoint(
m_filtersp, resolver_sp, false, false, false);
// Give RS breakpoints a specific name, so the user can manipulate them as a
// group.
Status err;
- if (!bp->AddName(name.AsCString(), err))
- if (log)
- log->Printf("%s - error setting break name, '%s'.", __FUNCTION__,
- err.AsCString());
+ target.AddNameToBreakpoint(bp, name.GetCString(), err);
+ if (err.Fail() && log)
+ log->Printf("%s - error setting break name, '%s'.", __FUNCTION__,
+ err.AsCString());
// ask the breakpoint to resolve itself
bp->ResolveBreakpoint();
return bp;
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index d97f651ca08..08546d57c2a 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -123,6 +123,13 @@ void Target::PrimeFromDummyTarget(Target *target) {
BreakpointSP new_bp(new Breakpoint(*this, *breakpoint_sp.get()));
AddBreakpoint(new_bp, false);
}
+
+ for (auto bp_name_entry : target->m_breakpoint_names)
+ {
+
+ BreakpointName *new_bp_name = new BreakpointName(*bp_name_entry.second);
+ AddBreakpointName(new_bp_name);
+ }
}
void Target::Dump(Stream *s, lldb::DescriptionLevel description_level) {
@@ -601,6 +608,112 @@ void Target::AddBreakpoint(lldb::BreakpointSP bp_sp, bool internal) {
}
}
+void Target::AddNameToBreakpoint(BreakpointID &id,
+ const char *name,
+ Status &error)
+ {
+ BreakpointSP bp_sp
+ = m_breakpoint_list.FindBreakpointByID(id.GetBreakpointID());
+ if (!bp_sp)
+ {
+ StreamString s;
+ id.GetDescription(&s, eDescriptionLevelBrief);
+ error.SetErrorStringWithFormat("Could not find breakpoint %s",
+ s.GetData());
+ return;
+ }
+ AddNameToBreakpoint(bp_sp, name, error);
+ }
+
+void Target::AddNameToBreakpoint(BreakpointSP &bp_sp,
+ const char *name,
+ Status &error)
+ {
+ if (!bp_sp)
+ return;
+
+ BreakpointName *bp_name = FindBreakpointName(ConstString(name), true, error);
+ if (!bp_name)
+ return;
+
+ bp_name->ConfigureBreakpoint(bp_sp);
+ bp_sp->AddName(name);
+ }
+
+void Target::AddBreakpointName(BreakpointName *bp_name) {
+ m_breakpoint_names.insert(std::make_pair(bp_name->GetName(), bp_name));
+}
+
+BreakpointName *Target::FindBreakpointName(const ConstString &name,
+ bool can_create,
+ Status &error)
+{
+ BreakpointID::StringIsBreakpointName(name.GetStringRef(), error);
+ if (!error.Success())
+ return nullptr;
+
+ BreakpointNameList::iterator iter = m_breakpoint_names.find(name);
+ if (iter == m_breakpoint_names.end()) {
+ if (!can_create)
+ {
+ error.SetErrorStringWithFormat("Breakpoint name \"%s\" doesn't exist and "
+ "can_create is false.", name.AsCString());
+ return nullptr;
+ }
+
+ iter = m_breakpoint_names.insert(std::make_pair(name,
+ new BreakpointName(name)))
+ .first;
+ }
+ return (iter->second);
+}
+
+void
+Target::DeleteBreakpointName(const ConstString &name)
+{
+ BreakpointNameList::iterator iter = m_breakpoint_names.find(name);
+
+ if (iter != m_breakpoint_names.end()) {
+ const char *name_cstr = name.AsCString();
+ m_breakpoint_names.erase(iter);
+ for (auto bp_sp : m_breakpoint_list.Breakpoints())
+ bp_sp->RemoveName(name_cstr);
+ }
+}
+
+void Target::RemoveNameFromBreakpoint(lldb::BreakpointSP &bp_sp,
+ const ConstString &name)
+{
+ bp_sp->RemoveName(name.AsCString());
+}
+
+void Target::ConfigureBreakpointName(BreakpointName &bp_name,
+ const BreakpointOptions &new_options,
+ const BreakpointName::Permissions &new_permissions)
+{
+ bp_name.GetOptions().CopyOverSetOptions(new_options);
+ bp_name.GetPermissions().MergeInto(new_permissions);
+ ApplyNameToBreakpoints(bp_name);
+}
+
+void Target::ApplyNameToBreakpoints(BreakpointName &bp_name) {
+ BreakpointList bkpts_with_name(false);
+ m_breakpoint_list.FindBreakpointsByName(bp_name.GetName().AsCString(),
+ bkpts_with_name);
+
+ for (auto bp_sp : bkpts_with_name.Breakpoints())
+ bp_name.ConfigureBreakpoint(bp_sp);
+}
+
+void Target::GetBreakpointNames(std::vector<std::string> &names)
+{
+ names.clear();
+ for (auto bp_name : m_breakpoint_names) {
+ names.push_back(bp_name.first.AsCString());
+ }
+ std::sort(names.begin(), names.end());
+}
+
bool Target::ProcessIsValid() {
return (m_process_sp && m_process_sp->IsAlive());
}
@@ -703,6 +816,17 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size,
return wp_sp;
}
+void Target::RemoveAllowedBreakpoints ()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf("Target::%s \n", __FUNCTION__);
+
+ m_breakpoint_list.RemoveAllowed(true);
+
+ m_last_created_breakpoint.reset();
+}
+
void Target::RemoveAllBreakpoints(bool internal_also) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
if (log)
@@ -727,6 +851,14 @@ void Target::DisableAllBreakpoints(bool internal_also) {
m_internal_breakpoint_list.SetEnabledAll(false);
}
+void Target::DisableAllowedBreakpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf("Target::%s", __FUNCTION__);
+
+ m_breakpoint_list.SetEnabledAllowed(false);
+}
+
void Target::EnableAllBreakpoints(bool internal_also) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
if (log)
@@ -738,6 +870,14 @@ void Target::EnableAllBreakpoints(bool internal_also) {
m_internal_breakpoint_list.SetEnabledAll(true);
}
+void Target::EnableAllowedBreakpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf("Target::%s", __FUNCTION__);
+
+ m_breakpoint_list.SetEnabledAllowed(true);
+}
+
bool Target::RemoveBreakpointByID(break_id_t break_id) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
if (log)
OpenPOWER on IntegriCloud