[Lldb-commits] [lldb] r309969 - Add an auto-continue flag to breakpoints & locations.

Jim Ingham via lldb-commits lldb-commits at lists.llvm.org
Thu Aug 3 11:13:24 PDT 2017


Author: jingham
Date: Thu Aug  3 11:13:24 2017
New Revision: 309969

URL: http://llvm.org/viewvc/llvm-project?rev=309969&view=rev
Log:
Add an auto-continue flag to breakpoints & locations.

You can get a breakpoint to auto-continue by adding "continue"
as a command, but that has the disadvantage that if you hit two
breakpoints simultaneously, the continue will force the process
to continue, and maybe even forstalling the commands on the other.
The auto-continue flag means the breakpoints can negotiate about
whether to stop.

Writing tests, I wanted to supply some commands when I made the
breakpoints, so I also added that ability.

Modified:
    lldb/trunk/include/lldb/API/SBBreakpoint.h
    lldb/trunk/include/lldb/API/SBBreakpointLocation.h
    lldb/trunk/include/lldb/Breakpoint/Breakpoint.h
    lldb/trunk/include/lldb/Breakpoint/BreakpointLocation.h
    lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h
    lldb/trunk/include/lldb/lldb-enumerations.h
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
    lldb/trunk/scripts/interface/SBBreakpoint.i
    lldb/trunk/scripts/interface/SBBreakpointLocation.i
    lldb/trunk/source/API/SBBreakpoint.cpp
    lldb/trunk/source/API/SBBreakpointLocation.cpp
    lldb/trunk/source/Breakpoint/Breakpoint.cpp
    lldb/trunk/source/Breakpoint/BreakpointLocation.cpp
    lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
    lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
    lldb/trunk/source/Target/StopInfo.cpp

Modified: lldb/trunk/include/lldb/API/SBBreakpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBBreakpoint.h?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBBreakpoint.h (original)
+++ lldb/trunk/include/lldb/API/SBBreakpoint.h Thu Aug  3 11:13:24 2017
@@ -70,6 +70,10 @@ public:
 
   const char *GetCondition();
 
+  void SetAutoContinue(bool auto_continue);
+
+  bool GetAutoContinue();
+
   void SetThreadID(lldb::tid_t sb_thread_id);
 
   lldb::tid_t GetThreadID();

Modified: lldb/trunk/include/lldb/API/SBBreakpointLocation.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBBreakpointLocation.h?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBBreakpointLocation.h (original)
+++ lldb/trunk/include/lldb/API/SBBreakpointLocation.h Thu Aug  3 11:13:24 2017
@@ -47,6 +47,10 @@ public:
   void SetCondition(const char *condition);
 
   const char *GetCondition();
+   
+  void SetAutoContinue(bool auto_continue);
+
+  bool GetAutoContinue();
 
   void SetScriptCallbackFunction(const char *callback_function_name);
 

Modified: lldb/trunk/include/lldb/Breakpoint/Breakpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/Breakpoint.h?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/Breakpoint.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/Breakpoint.h Thu Aug  3 11:13:24 2017
@@ -421,6 +421,18 @@ public:
   bool IsOneShot() const;
 
   //------------------------------------------------------------------
+  /// If \a auto_continue is \b true, breakpoint will auto-continue when on hit.
+  //------------------------------------------------------------------
+  void SetAutoContinue(bool auto_continue);
+
+  //------------------------------------------------------------------
+  /// Check the AutoContinue state.
+  /// @return
+  ///     \b true if the breakpoint is set to auto-continue, \b false otherwise.
+  //------------------------------------------------------------------
+  bool IsAutoContinue() const;
+
+  //------------------------------------------------------------------
   /// Set the valid thread to be checked when the breakpoint is hit.
   /// @param[in] thread_id
   ///    If this thread hits the breakpoint, we stop, otherwise not.

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointLocation.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointLocation.h?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointLocation.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointLocation.h Thu Aug  3 11:13:24 2017
@@ -107,6 +107,19 @@ public:
   bool IsEnabled() const;
 
   //------------------------------------------------------------------
+  /// If \a auto_continue is \b true, set the breakpoint to continue when hit.
+  //------------------------------------------------------------------
+  void SetAutoContinue(bool auto_continue);
+
+  //------------------------------------------------------------------
+  /// Check the AutoContinue state.
+  ///
+  /// @return
+  ///     \b true if the breakpoint is set to auto-continue, \b false if not.
+  //------------------------------------------------------------------
+  bool IsAutoContinue() const;
+
+  //------------------------------------------------------------------
   /// Return the current Ignore Count.
   ///
   /// @return

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h Thu Aug  3 11:13:24 2017
@@ -38,12 +38,13 @@ friend class Breakpoint;
 
 public:
   enum OptionKind {
-    eCallback =    1 << 0,
-    eEnabled  =    1 << 1,
-    eOneShot  =    1 << 2,
-    eIgnoreCount = 1 << 3,
-    eThreadSpec  = 1 << 4,
-    eCondition   = 1 << 5
+    eCallback     = 1 << 0,
+    eEnabled      = 1 << 1,
+    eOneShot      = 1 << 2,
+    eIgnoreCount  = 1 << 3,
+    eThreadSpec   = 1 << 4,
+    eCondition    = 1 << 5,
+    eAutoContinue = 1 << 6
   };
   struct CommandData {
     CommandData()
@@ -112,7 +113,8 @@ public:
   ///
   //------------------------------------------------------------------
   BreakpointOptions(const char *condition, bool enabled = true,
-                    int32_t ignore = 0, bool one_shot = false);
+                    int32_t ignore = 0, bool one_shot = false,
+                    bool auto_continue = false);
 
   virtual ~BreakpointOptions();
 
@@ -296,6 +298,21 @@ public:
   }
 
   //------------------------------------------------------------------
+  /// Check the auto-continue state.
+  /// @return
+  ///     \b true if the breakpoint is set to auto-continue, \b false otherwise.
+  //------------------------------------------------------------------
+  bool IsAutoContinue() const { return m_auto_continue; }
+
+  //------------------------------------------------------------------
+  /// Set the auto-continue state.
+  //------------------------------------------------------------------
+  void SetAutoContinue(bool auto_continue) { 
+    m_auto_continue = auto_continue;
+    m_set_flags.Set(eAutoContinue);
+  }
+
+  //------------------------------------------------------------------
   /// Check the One-shot state.
   /// @return
   ///     \b true if the breakpoint is one-shot, \b false otherwise.
@@ -394,6 +411,7 @@ protected:
     IgnoreCount,
     EnabledState,
     OneShotState,
+    AutoContinue,
     LastOptionName
   };
   static const char *g_option_names[(size_t)OptionNames::LastOptionName];
@@ -424,6 +442,7 @@ private:
   std::string m_condition_text; // The condition to test.
   size_t m_condition_text_hash; // Its hash, so that locations know when the
                                 // condition is updated.
+  bool m_auto_continue;         // If set, auto-continue from breakpoint.
   Flags m_set_flags;            // Which options are set at this level.  Drawn
                                 // from BreakpointOptions::SetOptionsFlags.
 };

Modified: lldb/trunk/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Thu Aug  3 11:13:24 2017
@@ -380,7 +380,8 @@ FLAGS_ENUM(BreakpointEventType){
     eBreakpointEventTypeCommandChanged = (1u << 8),
     eBreakpointEventTypeConditionChanged = (1u << 9),
     eBreakpointEventTypeIgnoreChanged = (1u << 10),
-    eBreakpointEventTypeThreadChanged = (1u << 11)};
+    eBreakpointEventTypeThreadChanged = (1u << 11),
+    eBreakpointEventTypeAutoContinueChanged = (1u << 12)};
 
 FLAGS_ENUM(WatchpointEventType){
     eWatchpointEventTypeInvalidType = (1u << 0),
@@ -566,6 +567,7 @@ enum CommandArgumentType {
   eArgTypeWatchpointIDRange,
   eArgTypeWatchType,
   eArgRawInput,
+  eArgTypeCommand,
   eArgTypeLastArg // Always keep this entry as the last entry in this
                   // enumeration!!
 };

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py Thu Aug  3 11:13:24 2017
@@ -24,12 +24,21 @@ class BreakpointCommandTestCase(TestBase
         cls.RemoveTempFile("output2.txt")
 
     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
-    def test(self):
+    def test_breakpoint_command_sequence(self):
         """Test a sequence of breakpoint command add, list, and delete."""
         self.build()
         self.breakpoint_command_sequence()
+
+    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
+    def test_script_parameters(self):
+        """Test a sequence of breakpoint command add, list, and delete."""
+        self.build()
         self.breakpoint_command_script_parameters()
 
+    def test_commands_on_creation(self):
+        self.build()
+        self.breakpoint_commands_on_creation()
+
     def setUp(self):
         # Call super's setUp().
         TestBase.setUp(self)
@@ -268,3 +277,23 @@ class BreakpointCommandTestCase(TestBase
 
         # Now remove 'output-2.txt'
         os.remove('output-2.txt')
+
+    def breakpoint_commands_on_creation(self):
+        """Test that setting breakpoint commands when creating the breakpoint works"""
+        exe = os.path.join(os.getcwd(), "a.out")
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target.IsValid(), "Created an invalid target.")
+
+        # 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')
+
+        bkpt = target.FindBreakpointByID(1)
+        self.assertTrue(bkpt.IsValid(), "Couldn't find breakpoint 1")
+        com_list = lldb.SBStringList()
+        bkpt.GetCommandLineCommands(com_list)
+        self.assertEqual(com_list.GetSize(), 3, "Got the wrong number of commands")
+        self.assertEqual(com_list.GetStringAtIndex(0), "bt", "First bt")
+        self.assertEqual(com_list.GetStringAtIndex(1), "thread list", "Next thread list")
+        self.assertEqual(com_list.GetStringAtIndex(2), "continue", "Last continue")

Modified: lldb/trunk/scripts/interface/SBBreakpoint.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBBreakpoint.i?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBBreakpoint.i (original)
+++ lldb/trunk/scripts/interface/SBBreakpoint.i Thu Aug  3 11:13:24 2017
@@ -153,6 +153,10 @@ public:
     const char *
     GetCondition ();
 
+    void SetAutoContinue(bool auto_continue);
+
+    bool GetAutoContinue();
+
     void
     SetThreadID (lldb::tid_t sb_thread_id);
 

Modified: lldb/trunk/scripts/interface/SBBreakpointLocation.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBBreakpointLocation.i?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBBreakpointLocation.i (original)
+++ lldb/trunk/scripts/interface/SBBreakpointLocation.i Thu Aug  3 11:13:24 2017
@@ -73,6 +73,10 @@ public:
     const char *
     GetCondition ();
 
+    bool GetAutoContinue();
+ 
+    void SetAutoContinue(bool auto_continue);
+
     %feature("docstring", "
     //------------------------------------------------------------------
     /// Set the callback to the given Python function name.

Modified: lldb/trunk/source/API/SBBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBBreakpoint.cpp?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/source/API/SBBreakpoint.cpp (original)
+++ lldb/trunk/source/API/SBBreakpoint.cpp Thu Aug  3 11:13:24 2017
@@ -264,6 +264,25 @@ const char *SBBreakpoint::GetCondition()
   return nullptr;
 }
 
+void SBBreakpoint::SetAutoContinue(bool auto_continue) {
+  BreakpointSP bkpt_sp = GetSP();
+  if (bkpt_sp) {
+    std::lock_guard<std::recursive_mutex> guard(
+        bkpt_sp->GetTarget().GetAPIMutex());
+    bkpt_sp->SetAutoContinue(auto_continue);
+  }
+}
+
+bool SBBreakpoint::GetAutoContinue() {
+  BreakpointSP bkpt_sp = GetSP();
+  if (bkpt_sp) {
+    std::lock_guard<std::recursive_mutex> guard(
+        bkpt_sp->GetTarget().GetAPIMutex());
+    return bkpt_sp->IsAutoContinue();
+  }
+  return nullptr;
+}
+
 uint32_t SBBreakpoint::GetHitCount() const {
   uint32_t count = 0;
   BreakpointSP bkpt_sp = GetSP();

Modified: lldb/trunk/source/API/SBBreakpointLocation.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBBreakpointLocation.cpp?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/source/API/SBBreakpointLocation.cpp (original)
+++ lldb/trunk/source/API/SBBreakpointLocation.cpp Thu Aug  3 11:13:24 2017
@@ -149,6 +149,25 @@ const char *SBBreakpointLocation::GetCon
   return NULL;
 }
 
+void SBBreakpointLocation::SetAutoContinue(bool auto_continue) {
+  BreakpointLocationSP loc_sp = GetSP();
+  if (loc_sp) {
+    std::lock_guard<std::recursive_mutex> guard(
+        loc_sp->GetTarget().GetAPIMutex());
+    loc_sp->SetAutoContinue(auto_continue);
+  }
+}
+
+bool SBBreakpointLocation::GetAutoContinue() {
+  BreakpointLocationSP loc_sp = GetSP();
+  if (loc_sp) {
+    std::lock_guard<std::recursive_mutex> guard(
+        loc_sp->GetTarget().GetAPIMutex());
+    return loc_sp->IsAutoContinue();
+  }
+  return NULL;
+}
+
 void SBBreakpointLocation::SetScriptCallbackFunction(
     const char *callback_function_name) {
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

Modified: lldb/trunk/source/Breakpoint/Breakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/Breakpoint.cpp?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/Breakpoint.cpp (original)
+++ lldb/trunk/source/Breakpoint/Breakpoint.cpp Thu Aug  3 11:13:24 2017
@@ -348,6 +348,14 @@ void Breakpoint::SetOneShot(bool one_sho
   m_options_up->SetOneShot(one_shot);
 }
 
+bool Breakpoint::IsAutoContinue() const { 
+  return m_options_up->IsAutoContinue();
+}
+
+void Breakpoint::SetAutoContinue(bool auto_continue) {
+  m_options_up->SetAutoContinue(auto_continue);
+}
+
 void Breakpoint::SetThreadID(lldb::tid_t thread_id) {
   if (m_options_up->GetThreadSpec()->GetTID() == thread_id)
     return;

Modified: lldb/trunk/source/Breakpoint/BreakpointLocation.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointLocation.cpp?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointLocation.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointLocation.cpp Thu Aug  3 11:13:24 2017
@@ -93,6 +93,19 @@ void BreakpointLocation::SetEnabled(bool
                                              : eBreakpointEventTypeDisabled);
 }
 
+bool BreakpointLocation::IsAutoContinue() const {
+  if (m_options_ap 
+      && m_options_ap->IsOptionSet(BreakpointOptions::eAutoContinue))
+    return m_options_ap->IsAutoContinue();
+  else
+    return m_owner.IsAutoContinue();
+}
+
+void BreakpointLocation::SetAutoContinue(bool auto_continue) {
+  GetLocationOptions()->SetAutoContinue(auto_continue);
+  SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
+}
+
 void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
   if (thread_id != LLDB_INVALID_THREAD_ID)
     GetLocationOptions()->SetThreadID(thread_id);

Modified: lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointOptions.cpp?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointOptions.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointOptions.cpp Thu Aug  3 11:13:24 2017
@@ -114,7 +114,8 @@ BreakpointOptions::CommandData::CreateFr
 
 const char *BreakpointOptions::g_option_names[(
     size_t)BreakpointOptions::OptionNames::LastOptionName]{
-    "ConditionText", "IgnoreCount", "EnabledState", "OneShotState"};
+    "ConditionText", "IgnoreCount", 
+    "EnabledState", "OneShotState", "AutoContinue"};
 
 bool BreakpointOptions::NullCallback(void *baton,
                                      StoppointCallbackContext *context,
@@ -130,20 +131,22 @@ BreakpointOptions::BreakpointOptions(boo
     : m_callback(BreakpointOptions::NullCallback), m_callback_baton_sp(),
       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_condition_text(), m_condition_text_hash(0), m_auto_continue(false),
       m_set_flags() {
         if (all_flags_set)
           m_set_flags.Set(~((Flags::ValueType) 0));
       }
 
 BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
-                                     int32_t ignore, bool one_shot)
+                                     int32_t ignore, bool one_shot, 
+                                     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_condition_text_hash(0)
+      m_condition_text_hash(0), m_auto_continue(auto_continue)
 {
-    m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot | eCondition);
+    m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot 
+                   | eCondition | eAutoContinue);
 }
 
 //----------------------------------------------------------------------
@@ -155,6 +158,7 @@ BreakpointOptions::BreakpointOptions(con
       m_callback_is_synchronous(rhs.m_callback_is_synchronous),
       m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot),
       m_ignore_count(rhs.m_ignore_count), m_thread_spec_ap(),
+      m_auto_continue(rhs.m_auto_continue),
       m_set_flags(rhs.m_set_flags) {
   if (rhs.m_thread_spec_ap.get() != nullptr)
     m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
@@ -178,6 +182,7 @@ operator=(const BreakpointOptions &rhs)
     m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
   m_condition_text = rhs.m_condition_text;
   m_condition_text_hash = rhs.m_condition_text_hash;
+  m_auto_continue = rhs.m_auto_continue;
   m_set_flags = rhs.m_set_flags;
   return *this;
 }
@@ -192,6 +197,7 @@ std::unique_ptr<BreakpointOptions> Break
     Status &error) {
   bool enabled = true;
   bool one_shot = false;
+  bool auto_continue = false;
   int32_t ignore_count = 0;
   llvm::StringRef condition_ref("");
   Flags set_options;
@@ -219,6 +225,17 @@ std::unique_ptr<BreakpointOptions> Break
       set_options.Set(eOneShot);
   }
   
+  key = GetKey(OptionNames::AutoContinue);
+  if (key) {
+    success = options_dict.GetValueForKeyAsBoolean(key, auto_continue);
+    if (!success) {
+      error.SetErrorStringWithFormat("%s key is not a boolean.",
+                                     GetKey(OptionNames::AutoContinue));
+      return nullptr;
+      }
+      set_options.Set(eAutoContinue);
+  }
+  
   key = GetKey(OptionNames::IgnoreCount);
   if (key) {
     success = options_dict.GetValueForKeyAsInteger(key, ignore_count);
@@ -257,7 +274,8 @@ std::unique_ptr<BreakpointOptions> Break
   }
 
   auto bp_options = llvm::make_unique<BreakpointOptions>(
-      condition_ref.str().c_str(), enabled, ignore_count, one_shot);
+      condition_ref.str().c_str(), enabled, 
+      ignore_count, one_shot, auto_continue);
   if (cmd_data_up.get()) {
     if (cmd_data_up->interpreter == eScriptLanguageNone)
       bp_options->SetCommandDataCallback(cmd_data_up);
@@ -315,6 +333,9 @@ StructuredData::ObjectSP BreakpointOptio
   if (m_set_flags.Set(eOneShot))
     options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
                                m_one_shot);
+  if (m_set_flags.Set(eAutoContinue))
+    options_dict_sp->AddBooleanItem(GetKey(OptionNames::AutoContinue),
+                               m_auto_continue);
   if (m_set_flags.Set(eIgnoreCount))
     options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
                                     m_ignore_count);
@@ -471,7 +492,7 @@ void BreakpointOptions::GetDescription(S
   // print
   // anything if there are:
 
-  if (m_ignore_count != 0 || !m_enabled || m_one_shot ||
+  if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue ||
       (GetThreadSpecNoCreate() != nullptr &&
        GetThreadSpecNoCreate()->HasSpecification())) {
     if (level == lldb::eDescriptionLevelVerbose) {
@@ -491,6 +512,9 @@ void BreakpointOptions::GetDescription(S
     if (m_one_shot)
       s->Printf("one-shot ");
 
+    if (m_auto_continue)
+      s->Printf("auto-continue ");
+
     if (m_thread_spec_ap.get())
       m_thread_spec_ap->GetDescription(s, level);
 

Modified: lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp Thu Aug  3 11:13:24 2017
@@ -60,7 +60,9 @@ static OptionDefinition g_breakpoint_set
   "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 "
@@ -208,6 +210,10 @@ public:
         m_condition.assign(option_arg);
         break;
 
+      case 'd':
+        m_commands.push_back(option_arg);
+        break;
+        
       case 'D':
         m_use_dummy = true;
         break;
@@ -255,6 +261,15 @@ public:
         m_func_names.push_back(option_arg);
         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;
@@ -445,6 +460,8 @@ public:
       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,6 +499,8 @@ public:
     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:
@@ -719,6 +738,18 @@ protected:
       }
 
       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) {
@@ -802,6 +833,7 @@ static OptionDefinition g_breakpoint_mod
   { 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
 };
 
@@ -865,6 +897,17 @@ public:
         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'",
@@ -938,6 +981,8 @@ public:
       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 {
@@ -962,6 +1007,8 @@ public:
     bool m_condition_passed;
     bool m_one_shot_passed;
     bool m_use_dummy;
+    bool m_auto_continue;
+    bool m_auto_continue_passed;
   };
 
 protected:
@@ -1013,6 +1060,9 @@ protected:
 
               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);
             }
           } else {
             if (m_options.m_thread_id_passed)
@@ -1035,6 +1085,9 @@ protected:
 
             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);
           }
         }
       }

Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=309969&r1=309968&r2=309969&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Thu Aug  3 11:13:24 2017
@@ -393,7 +393,10 @@ protected:
 
           for (size_t j = 0; j < num_owners; j++) {
             lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j);
-
+            StreamString loc_desc;
+            if (log) {
+              bp_loc_sp->GetDescription(&loc_desc, eDescriptionLevelBrief);
+            }
             // If another action disabled this breakpoint or its location, then
             // don't run the actions.
             if (!bp_loc_sp->IsEnabled() ||
@@ -405,16 +408,16 @@ protected:
             // this thread.  Skip the ones that aren't:
             if (!bp_loc_sp->ValidForThisThread(thread_sp.get())) {
               if (log) {
-                StreamString s;
-                bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief);
                 log->Printf("Breakpoint %s hit on thread 0x%llx but it was not "
                             "for this thread, continuing.",
-                            s.GetData(), static_cast<unsigned long long>(
+                            loc_desc.GetData(), static_cast<unsigned long long>(
                                              thread_sp->GetID()));
               }
               continue;
             }
 
+            internal_breakpoint = bp_loc_sp->GetBreakpoint().IsInternal();
+            
             // First run the precondition, but since the precondition is per
             // breakpoint, only run it once
             // per breakpoint.
@@ -458,11 +461,10 @@ protected:
                 error_sp->Flush();
               } else {
                 if (log) {
-                  StreamString s;
-                  bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief);
                   log->Printf("Condition evaluated for breakpoint %s on thread "
                               "0x%llx conditon_says_stop: %i.",
-                              s.GetData(), static_cast<unsigned long long>(
+                              loc_desc.GetData(), 
+                              static_cast<unsigned long long>(
                                                thread_sp->GetID()),
                               condition_says_stop);
                 }
@@ -477,7 +479,26 @@ protected:
               }
             }
 
-            bool callback_says_stop;
+            // Check the auto-continue bit on the location, do this before the
+            // callback since it may change this, but that would be for the
+            // NEXT hit.  Note, you might think you could check auto-continue
+            // before the condition, and not evaluate the condition if it says
+            // to continue.  But failing the condition means the breakpoint was
+            // effectively NOT HIT.  So these two states are different.
+            bool auto_continue_says_stop = true;
+            if (bp_loc_sp->IsAutoContinue())
+            {
+              if (log)
+                log->Printf("Continuing breakpoint %s as AutoContinue was set.",
+                            loc_desc.GetData());
+              // We want this stop reported, so you will know we auto-continued
+              // but only for external breakpoints:
+              if (!internal_breakpoint)
+                thread_sp->SetShouldReportStop(eVoteYes);
+              auto_continue_says_stop = false;
+            }
+
+            bool callback_says_stop = true;
 
             // FIXME: For now the callbacks have to run in async mode - the
             // first time we restart we need
@@ -493,11 +514,8 @@ protected:
 
             debugger.SetAsyncExecution(old_async);
 
-            if (callback_says_stop)
+            if (callback_says_stop && auto_continue_says_stop)
               m_should_stop = true;
-
-            if (m_should_stop && !bp_loc_sp->GetBreakpoint().IsInternal())
-              internal_breakpoint = false;
                   
             // If we are going to stop for this breakpoint, then remove the
             // breakpoint.
@@ -506,7 +524,6 @@ protected:
               thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID(
                   bp_loc_sp->GetBreakpoint().GetID());
             }
-
             // Also make sure that the callback hasn't continued the target.
             // If it did, when we'll set m_should_start to false and get out of
             // here.




More information about the lldb-commits mailing list