This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG9406d4313881: Make the stop-on-sharedlibrary-events setting 
work. (authored by jingham).

Changed prior to commit:
  https://reviews.llvm.org/D98914?vs=331744&id=331972#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D98914/new/

https://reviews.llvm.org/D98914

Files:
  lldb/source/Breakpoint/BreakpointOptions.cpp
  lldb/source/Target/StopInfo.cpp
  lldb/test/API/functionalities/stop-on-sharedlibrary-load/Makefile
  
lldb/test/API/functionalities/stop-on-sharedlibrary-load/TestStopOnSharedlibraryEvents.py
  lldb/test/API/functionalities/stop-on-sharedlibrary-load/a.cpp
  lldb/test/API/functionalities/stop-on-sharedlibrary-load/b.cpp
  lldb/test/API/functionalities/stop-on-sharedlibrary-load/main.cpp

Index: lldb/test/API/functionalities/stop-on-sharedlibrary-load/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/stop-on-sharedlibrary-load/main.cpp
@@ -0,0 +1,27 @@
+#include "dylib.h"
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(int argc, char const *argv[]) {
+  const char *a_name = "load_a";
+  void *a_dylib_handle = NULL;
+
+  a_dylib_handle = dylib_open(a_name); // Set a breakpoint here.
+  if (a_dylib_handle == NULL) { // Set another here - we should not hit this one
+    fprintf(stderr, "%s\n", dylib_last_error());
+    exit(1);
+  }
+
+  const char *b_name = "load_b";
+  void *b_dylib_handle = NULL;
+
+  b_dylib_handle = dylib_open(b_name);
+  if (b_dylib_handle == NULL) { // Set a third here - we should not hit this one
+    fprintf(stderr, "%s\n", dylib_last_error());
+    exit(1);
+  }
+
+  return 0;
+}
Index: lldb/test/API/functionalities/stop-on-sharedlibrary-load/b.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/stop-on-sharedlibrary-load/b.cpp
@@ -0,0 +1,6 @@
+extern int b_has_a_function();
+
+int
+b_has_a_function() {
+  return 100;
+}
Index: lldb/test/API/functionalities/stop-on-sharedlibrary-load/a.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/stop-on-sharedlibrary-load/a.cpp
@@ -0,0 +1,6 @@
+extern int a_has_a_function();
+
+int
+a_has_a_function() {
+  return 10;
+}
Index: lldb/test/API/functionalities/stop-on-sharedlibrary-load/TestStopOnSharedlibraryEvents.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/stop-on-sharedlibrary-load/TestStopOnSharedlibraryEvents.py
@@ -0,0 +1,96 @@
+""" Test that stop-on-sharedlibrary-events works and cooperates with breakpoints. """
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestStopOnSharedlibraryEvents(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @skipIfRemote
+    @skipIfWindows
+    @no_debug_info_test
+    def test_stopping_breakpoints(self):
+        self.do_test()
+
+    def test_auto_continue(self):
+        def auto_continue(bkpt):
+            bkpt.SetAutoContinue(True)
+        self.do_test(auto_continue)
+
+    def test_failing_condition(self):
+        def condition(bkpt):
+            bkpt.SetCondition("1 == 2")
+        self.do_test(condition)
+        
+    def test_continue_callback(self):
+        def bkpt_callback(bkpt):
+            bkpt.SetScriptCallbackBody("return False")
+        self.do_test(bkpt_callback)
+
+    def do_test(self, bkpt_modifier = None):
+        self.build()
+        main_spec = lldb.SBFileSpec("main.cpp")
+        # Launch and stop before the dlopen call.
+        target, process, _, _ = lldbutil.run_to_source_breakpoint(self,
+                                                                  "// Set a breakpoint here", main_spec)
+
+        # Now turn on shared library events, continue and make sure we stop for the event.
+        self.runCmd("settings set target.process.stop-on-sharedlibrary-events 1")
+        self.addTearDownHook(lambda: self.runCmd(
+            "settings set target.process.stop-on-sharedlibrary-events 0"))
+
+        # Since I don't know how to check that we are at the "right place" to stop for
+        # shared library events, make an breakpoint after the load is done and
+        # make sure we don't stop there:
+        backstop_bkpt_1 = target.BreakpointCreateBySourceRegex("Set another here - we should not hit this one", main_spec)
+        self.assertGreater(backstop_bkpt_1.GetNumLocations(), 0, "Set our second breakpoint")
+        
+        process.Continue() 
+        self.assertEqual(process.GetState(), lldb.eStateStopped, "We didn't stop for the load")
+        self.assertEqual(backstop_bkpt_1.GetHitCount(), 0, "Hit our backstop breakpoint")
+        
+        # We should be stopped after the library is loaded, check that:
+        found_it = False
+        for module in target.modules:
+            if module.file.basename.find("load_a") > -1:
+                found_it = True
+                break
+        self.assertTrue(found_it, "Found the loaded module.")
+
+        # Now capture the place where we stopped so we can set a breakpoint and make
+        # sure the breakpoint there works correctly:
+        load_address = process.GetSelectedThread().frames[0].addr
+        load_bkpt = target.BreakpointCreateBySBAddress(load_address)
+        self.assertGreater(load_bkpt.GetNumLocations(), 0, "Set the load breakpoint")
+
+        backstop_bkpt_1.SetEnabled(False)
+
+        backstop_bkpt_2 = target.BreakpointCreateBySourceRegex("Set a third here - we should not hit this one", main_spec)
+        self.assertGreater(backstop_bkpt_2.GetNumLocations(), 0, "Set our third breakpoint")
+            
+        if bkpt_modifier == None:
+            process.Continue() 
+            self.assertEqual(process.GetState(), lldb.eStateStopped, "We didn't stop for the load")
+            self.assertEqual(backstop_bkpt_2.GetHitCount(), 0, "Hit our backstop breakpoint")
+            
+            thread = process.GetSelectedThread()
+            self.assertEqual(thread.stop_reason, lldb.eStopReasonBreakpoint, "We attributed the stop to the breakpoint")
+            self.assertEqual(thread.GetStopReasonDataCount(), 2, "Only hit one breakpoint")
+            bkpt_no = thread.GetStopReasonDataAtIndex(0)
+            self.assertEqual(bkpt_no, load_bkpt.id, "We hit our breakpoint at the load address")
+        else:
+            bkpt_modifier(load_bkpt)
+            process.Continue()
+            self.assertEqual(process.GetState(), lldb.eStateStopped, "We didn't stop")
+            thread = process.GetSelectedThread()
+            self.assertEqual(thread.stop_reason, lldb.eStopReasonBreakpoint, "We didn't hit some breakpoint")
+            self.assertEqual(thread.GetStopReasonDataCount(), 2, "Only hit one breakpoint")
+            bkpt_no = thread.GetStopReasonDataAtIndex(0)
+            self.assertEqual(bkpt_no, backstop_bkpt_2.id, "We continued to the right breakpoint")
+
+        
+        
+        
+        
Index: lldb/test/API/functionalities/stop-on-sharedlibrary-load/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/stop-on-sharedlibrary-load/Makefile
@@ -0,0 +1,16 @@
+CXX_SOURCES := main.cpp
+USE_LIBDL := 1
+
+a.out: lib_a
+
+include Makefile.rules
+
+lib_a:
+	$(MAKE) -f $(MAKEFILE_RULES) \
+		DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=load_a
+
+lib_b:
+	$(MAKE) -f $(MAKEFILE_RULES) \
+		DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=load_b
+
+
Index: lldb/source/Target/StopInfo.cpp
===================================================================
--- lldb/source/Target/StopInfo.cpp
+++ lldb/source/Target/StopInfo.cpp
@@ -305,6 +305,20 @@
           // location said we should stop. But that's better than not running
           // all the callbacks.
 
+          // There's one other complication here.  We may have run an async
+          // breakpoint callback that said we should stop.  We only want to
+          // override that if another breakpoint action says we shouldn't 
+          // stop.  If nobody else has an opinion, then we should stop if the
+          // async callback says we should.  An example of this is the async
+          // shared library load notification breakpoint and the setting
+          // stop-on-sharedlibrary-events.
+          // We'll keep the async value in async_should_stop, and track whether
+          // anyone said we should NOT stop in actually_said_continue.
+          bool async_should_stop = false;
+          if (m_should_stop_is_valid)
+            async_should_stop = m_should_stop;
+          bool actually_said_continue = false;
+
           m_should_stop = false;
 
           // We don't select threads as we go through them testing breakpoint
@@ -422,9 +436,10 @@
 
             bool precondition_result =
                 bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context);
-            if (!precondition_result)
+            if (!precondition_result) {
+              actually_said_continue = true;
               continue;
-
+            }
             // Next run the condition for the breakpoint.  If that says we
             // should stop, then we'll run the callback for the breakpoint.  If
             // the callback says we shouldn't stop that will win.
@@ -462,6 +477,7 @@
                   // the condition fails. We've already bumped it by the time
                   // we get here, so undo the bump:
                   bp_loc_sp->UndoBumpHitCount();
+                  actually_said_continue = true;
                   continue;
                 }
               }
@@ -504,6 +520,9 @@
 
             if (callback_says_stop && auto_continue_says_stop)
               m_should_stop = true;
+            else
+              actually_said_continue = true;
+
                   
             // If we are going to stop for this breakpoint, then remove the
             // breakpoint.
@@ -517,9 +536,15 @@
             // here.
             if (HasTargetRunSinceMe()) {
               m_should_stop = false;
+              actually_said_continue = true;
               break;
             }
           }
+          // At this point if nobody actually told us to continue, we should
+          // give the async breakpoint callback a chance to weigh in:
+          if (!actually_said_continue && !m_should_stop) {
+            m_should_stop = async_should_stop;
+          }
         }
         // We've figured out what this stop wants to do, so mark it as valid so
         // we don't compute it again.
Index: lldb/source/Breakpoint/BreakpointOptions.cpp
===================================================================
--- lldb/source/Breakpoint/BreakpointOptions.cpp
+++ lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -453,9 +453,12 @@
                                           : nullptr,
                       context, break_id, break_loc_id);
     } else if (IsCallbackSynchronous()) {
-      // If a synchronous callback is called at async time, it should not say
-      // to stop.
-      return false;
+      // If a synchronous callback is called at async time, we will say we
+      // should stop, we're really expression no opinion about stopping, and
+      // the StopInfoBreakpoint::PerformAction will note whether an async
+      // callback had already made a claim to stop or not based on the incoming
+      // values of m_should_stop & m_should_stop_is_valid.
+      return true;
     }
   }
   return true;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to