Author: Jim Ingham
Date: 2021-06-01T18:22:27-07:00
New Revision: 658f6ed1523b0e61ddee494ce1691f29a701c317

URL: 
https://github.com/llvm/llvm-project/commit/658f6ed1523b0e61ddee494ce1691f29a701c317
DIFF: 
https://github.com/llvm/llvm-project/commit/658f6ed1523b0e61ddee494ce1691f29a701c317.diff

LOG: Make ignore counts work as "after stop" modifiers so they play nicely with 
conditions

Previously ignore counts were checked when we stopped to do the sync callback 
in Breakpoint::ShouldStop. That meant we would do all the ignore count work 
even when
there is also a condition says the breakpoint should not stop.

That's wrong, lldb treats breakpoint hits that fail the thread or condition 
checks as "not having hit the breakpoint". So the ignore count check should 
happen after
the condition and thread checks in StopInfoBreakpoint::PerformAction.

The one side-effect of doing this is that if you have a breakpoint with a 
synchronous callback, it will run the synchronous callback before checking the 
ignore count.
That is probably a good thing, since this was already true of the condition and 
thread checks, so this removes an odd asymmetry. And breakpoints with sync 
callbacks
are all internal lldb breakpoints and there's not a really good reason why you 
would want one of these to use an ignore count (but not a condition or thread 
check...)

Differential Revision https://reviews.llvm.org/D103217

Added: 
    

Modified: 
    lldb/include/lldb/Breakpoint/Breakpoint.h
    lldb/include/lldb/Breakpoint/BreakpointLocation.h
    lldb/source/Breakpoint/Breakpoint.cpp
    lldb/source/Breakpoint/BreakpointLocation.cpp
    lldb/source/Target/StopInfo.cpp
    
lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py
    lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/main.c

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Breakpoint/Breakpoint.h 
b/lldb/include/lldb/Breakpoint/Breakpoint.h
index ddb70b719d6ed..37710bb33118f 100644
--- a/lldb/include/lldb/Breakpoint/Breakpoint.h
+++ b/lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -617,14 +617,6 @@ class Breakpoint : public 
std::enable_shared_from_this<Breakpoint>,
 
   void DecrementIgnoreCount();
 
-  // BreakpointLocation::IgnoreCountShouldStop &
-  // Breakpoint::IgnoreCountShouldStop can only be called once per stop, and
-  // BreakpointLocation::IgnoreCountShouldStop should be tested first, and if
-  // it returns false we should continue, otherwise we should test
-  // Breakpoint::IgnoreCountShouldStop.
-
-  bool IgnoreCountShouldStop();
-
 private:
   // To call from CopyFromBreakpoint.
   Breakpoint(Target &new_target, const Breakpoint &bp_to_copy_from);

diff  --git a/lldb/include/lldb/Breakpoint/BreakpointLocation.h 
b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
index a12696be91e38..ca1739161c0cc 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
@@ -297,6 +297,10 @@ class BreakpointLocation
 
   void DecrementIgnoreCount();
 
+  /// BreakpointLocation::IgnoreCountShouldStop  can only be called once
+  /// per stop.  This method checks first against the loc and then the owner.
+  /// It also takes care of decrementing the ignore counters.
+  /// If it returns false we should continue, otherwise stop.
   bool IgnoreCountShouldStop();
 
 private:

diff  --git a/lldb/source/Breakpoint/Breakpoint.cpp 
b/lldb/source/Breakpoint/Breakpoint.cpp
index a09efe79c4781..45e23f65aea62 100644
--- a/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -326,18 +326,6 @@ uint32_t Breakpoint::GetIgnoreCount() const {
   return m_options_up->GetIgnoreCount();
 }
 
-bool Breakpoint::IgnoreCountShouldStop() {
-  uint32_t ignore = GetIgnoreCount();
-  if (ignore != 0) {
-    // When we get here we know the location that caused the stop doesn't have
-    // an ignore count, since by contract we call it first...  So we don't have
-    // to find & decrement it, we only have to decrement our own ignore count.
-    DecrementIgnoreCount();
-    return false;
-  } else
-    return true;
-}
-
 uint32_t Breakpoint::GetHitCount() const { return m_hit_counter.GetValue(); }
 
 bool Breakpoint::IsOneShot() const { return m_options_up->IsOneShot(); }

diff  --git a/lldb/source/Breakpoint/BreakpointLocation.cpp 
b/lldb/source/Breakpoint/BreakpointLocation.cpp
index 617b89bf19643..acdffa12369cf 100644
--- a/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -357,15 +357,16 @@ void BreakpointLocation::DecrementIgnoreCount() {
 }
 
 bool BreakpointLocation::IgnoreCountShouldStop() {
-  if (m_options_up != nullptr) {
-    uint32_t loc_ignore = m_options_up->GetIgnoreCount();
-    if (loc_ignore != 0) {
-      m_owner.DecrementIgnoreCount();
-      DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
-                              // since it won't get a
-                              // chance to.
-      return false;
-    }
+  uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount();
+  uint32_t loc_ignore = 0;
+  if (m_options_up != nullptr)
+    loc_ignore = m_options_up->GetIgnoreCount();
+
+  if (loc_ignore != 0 || owner_ignore != 0) {
+    m_owner.DecrementIgnoreCount();
+    DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
+                            // since it won't get a chance to.
+    return false;
   }
   return true;
 }
@@ -400,12 +401,6 @@ bool 
BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
   if (!IsEnabled())
     return false;
 
-  if (!IgnoreCountShouldStop())
-    return false;
-
-  if (!m_owner.IgnoreCountShouldStop())
-    return false;
-
   // We only run synchronous callbacks in ShouldStop:
   context->is_synchronous = true;
   should_stop = InvokeCallback(context);

diff  --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index ae29b42e0e50c..466a0fa9cc727 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -483,6 +483,15 @@ class StopInfoBreakpoint : public StopInfo {
               }
             }
 
+            // We've done all the checks whose failure means "we consider lldb
+            // not to have hit the breakpoint".  Now we're going to check for
+            // conditions that might continue after hitting.  Start with the
+            // ignore count:
+            if (!bp_loc_sp->IgnoreCountShouldStop()) {
+              actually_said_continue = true;
+              continue;
+            }
+
             // 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

diff  --git 
a/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py
 
b/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py
index c54584abab687..ba5df2b7a18c3 100644
--- 
a/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py
+++ 
b/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py
@@ -27,10 +27,21 @@ def test_with_python_api(self):
         self.build()
         self.breakpoint_ignore_count_python()
 
+    @skipIfWindows # This test will hang on windows llvm.org/pr21753
+    def test_ignore_vrs_condition_bkpt(self):
+        self.build()
+        self.ignore_vrs_condition(False)
+        
+    @skipIfWindows # This test will hang on windows llvm.org/pr21753
+    def test_ignore_vrs_condition_loc(self):
+        self.build()
+        self.ignore_vrs_condition(True)
+        
     def setUp(self):
         # Call super's setUp().
         TestBase.setUp(self)
         # Find the line number to of function 'c'.
+        self.stop_in_main = "Stop here at start of main"
         self.line1 = line_number(
             'main.c', '// Find the line number of function "c" here.')
         self.line2 = line_number(
@@ -99,8 +110,9 @@ def breakpoint_ignore_count(self):
 
     def breakpoint_ignore_count_python(self):
         """Use Python APIs to set breakpoint ignore count."""
-        target = self.createTestTarget()
-
+        target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(self,
+                                                                          
self.stop_in_main,
+                                                                          
lldb.SBFileSpec("main.c"))
         # Now create a breakpoint on main.c by name 'c'.
         breakpoint = target.BreakpointCreateByName('c', 'a.out')
         self.assertTrue(breakpoint and
@@ -119,10 +131,8 @@ def breakpoint_ignore_count_python(self):
         self.assertEqual(location.GetIgnoreCount(), 2,
                         "SetIgnoreCount() works correctly")
 
-        # Now launch the process, and do not stop at entry point.
-        process = target.LaunchSimple(
-            None, None, self.get_process_working_directory())
-        self.assertTrue(process, PROCESS_IS_VALID)
+        # Now continue and hit our breakpoint on c:
+        process.Continue()
 
         # Frame#0 should be on main.c:37, frame#1 should be on main.c:25, and
         # frame#2 should be on main.c:48.
@@ -143,4 +153,31 @@ def breakpoint_ignore_count_python(self):
         # The hit count for the breakpoint should be 3.
         self.assertEqual(breakpoint.GetHitCount(), 3)
 
-        process.Continue()
+    def ignore_vrs_condition(self, use_location):
+        main_spec = lldb.SBFileSpec("main.c")
+        target, process, _ , _ = lldbutil.run_to_source_breakpoint(self,
+                                                                   
self.stop_in_main,
+                                                                   main_spec)
+        
+        # Now make a breakpoint on the loop, and set a condition and ignore 
count.
+        # Make sure that the condition fails don't count against the ignore 
count.
+        bkpt = target.BreakpointCreateBySourceRegex("Set a breakpoint here, 
with i", main_spec)
+        self.assertEqual(bkpt.GetNumLocations(), 1, "Wrong number of 
locations")
+
+        if use_location:
+            loc = bkpt.location[0]
+            self.assertTrue(loc.IsValid(), "Got a valid location")
+            loc.SetIgnoreCount(2)
+            loc.SetCondition("i >= 3")
+        else:
+            bkpt.SetIgnoreCount(2)
+            bkpt.SetCondition("i >= 3")
+
+        threads = lldbutil.continue_to_breakpoint(process, bkpt)
+        self.assertEqual(len(threads), 1, "Hit the breakpoint")
+        var = threads[0].frame[0].FindVariable("i")
+        self.assertTrue(var.IsValid(), "Didn't find the i variable")
+        val = var.GetValueAsUnsigned(10000)
+        self.assertNotEqual(val, 10000, "Got the fail value for i")
+        self.assertEqual(val, 5, "We didn't stop the right number of times")
+        self.assertEqual(bkpt.GetHitCount(), 3, "Hit count is not right")

diff  --git 
a/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/main.c 
b/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/main.c
index 3f80f22fb2bba..b39b8d0442e44 100644
--- a/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/main.c
+++ b/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/main.c
@@ -29,9 +29,15 @@ int c(int val)
     return val + 3; // Find the line number of function "c" here.
 }
 
+void spin_a_bit () {
+  for (unsigned int i = 0; i < 10; i++) {
+    printf("Set a breakpoint here, with i = %d.\n", i);
+  }
+}
+
 int main (int argc, char const *argv[])
 {
-    int A1 = a(1);  // a(1) -> b(1) -> c(1)
+    int A1 = a(1);  // a(1) -> b(1) -> c(1) // Stop here at start of main
     printf("a(1) returns %d\n", A1);
     
     int B2 = b(2);  // b(2) -> c(2) Find the call site of b(2).
@@ -42,5 +48,7 @@ int main (int argc, char const *argv[])
     
     int C1 = c(5); // Find the call site of c in main.
     printf ("c(5) returns %d\n", C1);
+
+    spin_a_bit();
     return 0;
 }


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to