[Lldb-commits] [lldb] r161892 - in /lldb/trunk: include/lldb/Breakpoint/Watchpoint.h source/Breakpoint/Watchpoint.cpp source/Target/StopInfo.cpp test/functionalities/watchpoint/variable_out_of_scope/ test/functionalities/watchpoint/variable_out_of_scope/Makefile test/functionalities/watchpoint/variable_out_of_scope/TestWatchedVarHitWhenInScope.py test/functionalities/watchpoint/variable_out_of_scope/main.c

Johnny Chen johnny.chen at apple.com
Tue Aug 14 13:56:37 PDT 2012


Author: johnny
Date: Tue Aug 14 15:56:37 2012
New Revision: 161892

URL: http://llvm.org/viewvc/llvm-project?rev=161892&view=rev
Log:
When trying to take snapshots of a watched variable, if the frame is unable to evaluate the variable expression,
do not take the sanpshot and forget about the stop info.  It is possible that the variable expression has gone
out of scope, we'll revise the hit count due to the false alarms.

Added:
    lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/
    lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/Makefile
    lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/TestWatchedVarHitWhenInScope.py
    lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/main.c
Modified:
    lldb/trunk/include/lldb/Breakpoint/Watchpoint.h
    lldb/trunk/source/Breakpoint/Watchpoint.cpp
    lldb/trunk/source/Target/StopInfo.cpp

Modified: lldb/trunk/include/lldb/Breakpoint/Watchpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/Watchpoint.h?rev=161892&r1=161891&r2=161892&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/Watchpoint.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/Watchpoint.h Tue Aug 14 15:56:37 2012
@@ -36,6 +36,9 @@
 
     ~Watchpoint ();
 
+    void
+    IncrementFalseAlarmsAndReviseHitCount();
+
     bool
     IsEnabled () const;
 
@@ -162,7 +165,8 @@
                 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
                 m_watch_was_written:1; // Set to 1 when watchpoint is hit for a write access
-    uint32_t    m_ignore_count;        // Number of times to ignore this breakpoint
+    uint32_t    m_ignore_count;        // Number of times to ignore this watchpoint
+    uint32_t    m_false_alarms;        // Number of false alarms.
     std::string m_decl_str;            // Declaration information, if any.
     std::string m_watch_spec_str;      // Spec for the watchpoint.
     std::string m_snapshot_old_str;    // Old snapshot for the watchpoint value as by ValueObject::DumpValueObject().

Modified: lldb/trunk/source/Breakpoint/Watchpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/Watchpoint.cpp?rev=161892&r1=161891&r2=161892&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/Watchpoint.cpp (original)
+++ lldb/trunk/source/Breakpoint/Watchpoint.cpp Tue Aug 14 15:56:37 2012
@@ -34,6 +34,7 @@
     m_watch_was_read(0),
     m_watch_was_written(0),
     m_ignore_count(0),
+    m_false_alarms(0),
     m_decl_str(),
     m_watch_spec_str(),
     m_snapshot_old_str(),
@@ -183,6 +184,25 @@
     m_is_watch_variable = val;
 }
 
+void
+Watchpoint::IncrementFalseAlarmsAndReviseHitCount()
+{
+    ++m_false_alarms;
+    if (m_false_alarms)
+    {
+        if (m_hit_count >= m_false_alarms)
+        {
+            m_hit_count -= m_false_alarms;
+            m_false_alarms = 0;
+        }
+        else
+        {
+            m_false_alarms -= m_hit_count;
+            m_hit_count = 0;
+        }
+    }
+}
+
 // RETURNS - true if we should stop at this breakpoint, false if we
 // should continue.
 

Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=161892&r1=161891&r2=161892&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Tue Aug 14 15:56:37 2012
@@ -498,6 +498,7 @@
             StackFrame *frame = exe_ctx.GetFramePtr();
             if (frame)
             {
+                bool snapshot_taken = true;
                 if (!wp_sp->IsWatchVariable())
                 {
                     // We are not watching a variable, just read from the process memory for the watched location.
@@ -535,18 +536,29 @@
                         wp_sp->SetNewSnapshot(ss.GetString());
                     }
                     else
-                        wp_sp->SetNewSnapshot("snapshot attempt failed.");
+                    {
+                        // The variable expression has become out of scope?
+                        // Let us forget about this stop info.
+                        if (log)
+                            log->Printf("Snapshot attempt failed.  Variable expression has become out of scope?");
+                        snapshot_taken = false;
+                        m_should_stop = false;
+                        wp_sp->IncrementFalseAlarmsAndReviseHitCount();
+                    }
 
-                    if (log)
+                    if (log && snapshot_taken)
                         log->Printf("Watchpoint snapshot taken: '%s'\n", wp_sp->GetNewSnapshot().c_str());
                 }
 
                 // Now dump the snapshots we have taken.
-                Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
-                StreamSP output_sp = debugger.GetAsyncOutputStream ();
-                wp_sp->DumpSnapshots(output_sp.get());
-                output_sp->EOL();
-                output_sp->Flush();
+                if (snapshot_taken)
+                {
+                    Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
+                    StreamSP output_sp = debugger.GetAsyncOutputStream ();
+                    wp_sp->DumpSnapshots(output_sp.get());
+                    output_sp->EOL();
+                    output_sp->Flush();
+                }
             }
 
             if (m_should_stop && wp_sp->GetConditionText() != NULL)

Added: lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/Makefile?rev=161892&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/Makefile (added)
+++ lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/Makefile Tue Aug 14 15:56:37 2012
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/TestWatchedVarHitWhenInScope.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/TestWatchedVarHitWhenInScope.py?rev=161892&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/TestWatchedVarHitWhenInScope.py (added)
+++ lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/TestWatchedVarHitWhenInScope.py Tue Aug 14 15:56:37 2012
@@ -0,0 +1,88 @@
+"""
+Test that a variable watchpoint should only hit when in scope.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class WatchedVariableHitWhenInScopeTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "watchpoint", "variable_out_of_scope")
+
+    @dsym_test
+    def test_watched_var_should_only_hit_when_in_scope_with_dsym(self):
+        """Test that a variable watchpoint should only hit when in scope."""
+        self.buildDsym(dictionary=self.d)
+        self.setTearDownCleanup(dictionary=self.d)
+        self.watched_var()
+
+    @dwarf_test
+    def test_watched_var_should_only_hit_when_in_scope_with_dwarf(self):
+        """Test that a variable watchpoint should only hit when in scope."""
+        self.buildDwarf(dictionary=self.d)
+        self.setTearDownCleanup(dictionary=self.d)
+        self.watched_var()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Our simple source filename.
+        self.source = 'main.c'
+        self.exe_name = self.testMethodName
+        self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name}
+
+    def watched_var(self):
+        """Test a simple sequence of watchpoint creation and watchpoint hit."""
+        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 in main.
+        self.expect("breakpoint set -n main", BREAKPOINT_CREATED,
+            startstr = "Breakpoint created: 1: name = 'main'")
+
+        # 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 watchpoint for 'c.a'.
+        # There should be only one watchpoint hit (see main.c).
+        self.expect("watchpoint set variable c.a", WATCHPOINT_CREATED,
+            substrs = ['Watchpoint created', 'size = 4', 'type = w'])
+
+        # 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), but
+        # only once.  The stop reason of the thread should be watchpoint.
+        self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
+            substrs = ['stopped',
+                       'stop reason = watchpoint'])
+
+        self.runCmd("process continue")
+        # Don't expect the read of 'global' to trigger a stop exception.
+        # The process status should be 'exited'.
+        self.expect("process status",
+            substrs = ['exited'])
+
+        # Use the '-v' option to do verbose listing of the watchpoint.
+        # The hit count should now be 1.
+        self.expect("watchpoint list -v",
+            substrs = ['hit_count = 1'])
+
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/main.c?rev=161892&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/main.c (added)
+++ lldb/trunk/test/functionalities/watchpoint/variable_out_of_scope/main.c Tue Aug 14 15:56:37 2012
@@ -0,0 +1,15 @@
+typedef struct
+{
+    int a;
+    float b;
+} mystruct;
+
+int main()
+{
+    mystruct c;
+    
+    c.a = 5;
+    c.b = 3.6;
+    
+    return 0;
+}
\ No newline at end of file





More information about the lldb-commits mailing list