[Lldb-commits] [lldb] r162483 - in /lldb/trunk: include/lldb/Breakpoint/Watchpoint.h source/Breakpoint/Watchpoint.cpp source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp source/Target/StopInfo.cpp test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py

Johnny Chen johnny.chen at apple.com
Thu Aug 23 15:28:27 PDT 2012


Author: johnny
Date: Thu Aug 23 17:28:26 2012
New Revision: 162483

URL: http://llvm.org/viewvc/llvm-project?rev=162483&view=rev
Log:
Cope with the case where the user-supplied callbacks want the watchpoint itself to be disabled!
Previously we put a WatchpointSentry object within StopInfo.cpp to disable-and-then-enable the watchpoint itself
while we are performing the actions associated with the triggered watchpoint, which can cause the user-initiated
watchpoint disabling action to be negated.

Add a test case to verify that a watchpoint can be disabled during the callbacks.

Modified:
    lldb/trunk/include/lldb/Breakpoint/Watchpoint.h
    lldb/trunk/source/Breakpoint/Watchpoint.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Target/StopInfo.cpp
    lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py

Modified: lldb/trunk/include/lldb/Breakpoint/Watchpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/Watchpoint.h?rev=162483&r1=162482&r2=162483&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/Watchpoint.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/Watchpoint.h Thu Aug 23 17:28:26 2012
@@ -156,6 +156,9 @@
     void
     TurnOffEphemeralMode();
 
+    bool
+    IsDisabledDuringEphemeralMode();
+
 private:
     friend class Target;
     friend class WatchpointList;
@@ -170,6 +173,10 @@
     bool        m_is_ephemeral;        // True if the watchpoint is in the ephemeral mode, meaning that it is
                                        // undergoing a pair of temporary disable/enable actions to avoid recursively
                                        // triggering further watchpoint events.
+    uint32_t    m_disabled_count;      // Keep track of the count that the watchpoint is disabled while in ephemeral mode.
+                                       // At the end of the ephemeral mode when the watchpoint is to be enabled agian,
+                                       // we check the count, if it is more than 1, it means the user-supplied actions
+                                       // actually want the watchpoint to be disabled!
     uint32_t    m_watch_read:1,        // 1 if we stop when the watched data is read from
                 m_watch_write:1,       // 1 if we stop when the watched data is written to
                 m_watch_was_read:1,    // Set to 1 when watchpoint is hit for a read access

Modified: lldb/trunk/source/Breakpoint/Watchpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/Watchpoint.cpp?rev=162483&r1=162482&r2=162483&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/Watchpoint.cpp (original)
+++ lldb/trunk/source/Breakpoint/Watchpoint.cpp Thu Aug 23 17:28:26 2012
@@ -30,6 +30,7 @@
     m_is_hardware(hardware),
     m_is_watch_variable(false),
     m_is_ephemeral(false),
+    m_disabled_count(0),
     m_watch_read(0),
     m_watch_write(0),
     m_watch_was_read(0),
@@ -322,6 +323,14 @@
 Watchpoint::TurnOffEphemeralMode()
 {
     m_is_ephemeral = false;
+    // Leaving ephemeral mode, reset the m_disabled_count!
+    m_disabled_count = 0;
+}
+
+bool
+Watchpoint::IsDisabledDuringEphemeralMode()
+{
+    return m_disabled_count > 1;
 }
 
 void
@@ -331,6 +340,9 @@
     {
         if (!m_is_ephemeral)
             SetHardwareIndex(LLDB_INVALID_INDEX32);
+        else
+            ++m_disabled_count;
+
         // Don't clear the snapshots for now.
         // Within StopInfo.cpp, we purposely do disable/enable watchpoint while performing watchpoint actions.
         //ClearSnapshots();

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=162483&r1=162482&r2=162483&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Thu Aug 23 17:28:26 2012
@@ -2281,6 +2281,10 @@
         {
             if (log)
                 log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %llu) addr = 0x%8.8llx -- SUCCESS (already disabled)", watchID, (uint64_t)addr);
+            // See also 'class WatchpointSentry' within StopInfo.cpp.
+            // This disabling attempt might come from the user-supplied actions, we'll route it in order for
+            // the watchpoint object to intelligently process this action.
+            wp->SetEnabled(false);
             return error;
         }
         

Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=162483&r1=162482&r2=162483&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Thu Aug 23 17:28:26 2012
@@ -463,7 +463,8 @@
         {
             if (process && watchpoint)
             {
-                process->EnableWatchpoint(watchpoint);
+                if (!watchpoint->IsDisabledDuringEphemeralMode())
+                    process->EnableWatchpoint(watchpoint);
                 watchpoint->TurnOffEphemeralMode();
             }
         }

Modified: lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py?rev=162483&r1=162482&r2=162483&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py (original)
+++ lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py Thu Aug 23 17:28:26 2012
@@ -39,6 +39,21 @@
         self.setTearDownCleanup(dictionary=self.d)
         self.watchpoint_command()
 
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @dsym_test
+    def test_watchpoint_command_can_disable_a_watchpoint_with_dsym(self):
+        """Test that 'watchpoint command' action can disable a watchpoint after it is triggered."""
+        self.buildDsym(dictionary=self.d)
+        self.setTearDownCleanup(dictionary=self.d)
+        self.watchpoint_command_can_disable_a_watchpoint()
+
+    @dwarf_test
+    def test_watchpoint_command_can_disable_a_watchpoint_with_dwarf(self):
+        """Test that 'watchpoint command' action can disable a watchpoint after it is triggered."""
+        self.buildDwarf(dictionary=self.d)
+        self.setTearDownCleanup(dictionary=self.d)
+        self.watchpoint_command_can_disable_a_watchpoint()
+
     def watchpoint_command(self):
         """Do 'watchpoint command add'."""
         exe = os.path.join(os.getcwd(), self.exe_name)
@@ -90,6 +105,59 @@
         self.expect("frame variable -g cookie",
             substrs = ['(int32_t)', 'cookie = 777'])
 
+    def watchpoint_command_can_disable_a_watchpoint(self):
+        """Test that 'watchpoint command' action can disable a watchpoint after it is triggered."""
+        exe = os.path.join(os.getcwd(), self.exe_name)
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
+        self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED,
+            startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" %
+                       (self.source, self.line))
+
+        # Run the program.
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # We should be stopped again due to the breakpoint.
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # Now let's set a write-type watchpoint for 'global'.
+        self.expect("watchpoint set variable -w write global", WATCHPOINT_CREATED,
+            substrs = ['Watchpoint created', 'size = 4', 'type = w',
+                       '%s:%d' % (self.source, self.decl)])
+
+        self.runCmd('watchpoint command add 1 -o "watchpoint disable 1"')
+
+        # List the watchpoint command we just added.
+        self.expect("watchpoint command list 1",
+            substrs = ['watchpoint disable 1'])
+
+        # Use the '-v' option to do verbose listing of the watchpoint.
+        # The hit count should be 0 initially.
+        self.expect("watchpoint list -v",
+            substrs = ['hit_count = 0'])
+
+        self.runCmd("process continue")
+
+        # We should be stopped again due to the watchpoint (write type).
+        # The stop reason of the thread should be watchpoint.
+        self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT,
+            substrs = ['stop reason = watchpoint'])
+
+        # Check that the watchpoint has been disabled.
+        self.expect("watchpoint list -v",
+            substrs = ['disabled'])
+
+        self.runCmd("process continue")
+
+        # There should be no more watchpoint hit and the process status should
+        # be 'exited'.
+        self.expect("process status",
+            substrs = ['exited'])
+
 
 if __name__ == '__main__':
     import atexit





More information about the lldb-commits mailing list