[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