[Lldb-commits] [lldb] r140811 - in /lldb/trunk: test/functionalities/watchpoint/multiple_threads/ tools/debugserver/source/ tools/debugserver/source/MacOSX/ tools/debugserver/source/MacOSX/i386/ tools/debugserver/source/MacOSX/x86_64/

Johnny Chen johnny.chen at apple.com
Thu Sep 29 14:48:53 PDT 2011


Author: johnny
Date: Thu Sep 29 16:48:52 2011
New Revision: 140811

URL: http://llvm.org/viewvc/llvm-project?rev=140811&view=rev
Log:
Modify the delegation chain from MachThreadList -> MachThread -> DNBArchProtocol so that when
the watchpoint state is changed, not only does the change propagate to all the thread instances,
it also updates a global debug state, if chosen by the DNBArchProtocol derivative.

Once implemented, the DNBArchProtocol derivative, also makes sure that when new thread comes along,
it tries to inherit from the global debug state, if it is valid.

Modify TestWatchpointMultipleThreads.py to test this functionality.

Modified:
    lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py
    lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp
    lldb/trunk/tools/debugserver/source/DNBArch.h
    lldb/trunk/tools/debugserver/source/MacOSX/MachThread.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/MachThread.h
    lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h
    lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h

Modified: lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py?rev=140811&r1=140810&r2=140811&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py (original)
+++ lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py Thu Sep 29 16:48:52 2011
@@ -30,7 +30,8 @@
         # Our simple source filename.
         self.source = 'main.cpp'
         # Find the line number to break inside main().
-        self.line = line_number(self.source, '// Set break point at this line.')
+        self.first_stop = line_number(self.source, '// Set break point at this line')
+        self.thread_function = line_number(self.source, '// Break here in order to allow the thread')
         # Build dictionary to have unique executable names for each test method.
         self.exe_name = self.testMethodName
         self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name}
@@ -41,9 +42,14 @@
         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,
+        self.expect("breakpoint set -l %d" % self.first_stop, BREAKPOINT_CREATED,
             startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" %
-                       (self.source, self.line))
+                       (self.source, self.first_stop))
+
+        # Set this breakpoint to allow newly created thread to inherit the global watchpoint state.
+        self.expect("breakpoint set -l %d" % self.thread_function, BREAKPOINT_CREATED,
+            startstr = "Breakpoint created: 2: file ='%s', line = %d, locations = 1" %
+                       (self.source, self.thread_function))
 
         # Run the program.
         self.runCmd("run", RUN_SUCCEEDED)
@@ -66,22 +72,28 @@
         self.expect("watchpoint list -v",
             substrs = ['hit_count = 0'])
 
-        self.runCmd("process continue")
-
-        # We should be stopped again due to the watchpoint (write type) in a
-        # different work thread.  And the stop reason of the thread should be
-        # watchpoint.
-        self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
-            substrs = ['stopped',
-                       'stop reason = watchpoint'])
+        breakpoint_stops = 0
+        while True:
+            self.runCmd("process continue")
+
+            self.runCmd("thread list")
+            if "stop reason = breakpoint" in self.res.GetOutput():
+                breakpoint_stops += 1
+                if breakpoint_stops > 3:
+                    self.fail("Do not expect to break more than 3 times")
+                continue
+            elif "stop reason = watchpoint" in self.res.GetOutput():
+                # Good, we verified that the watchpoint works!
+                self.runCmd("thread backtrace all")
+                break
+            else:
+                self.fail("The stop reason should be either break or watchpoint")
 
         # 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'])
 
-        self.runCmd("thread backtrace all")
-
 
 if __name__ == '__main__':
     import atexit

Modified: lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp?rev=140811&r1=140810&r2=140811&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp (original)
+++ lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp Thu Sep 29 16:48:52 2011
@@ -41,7 +41,8 @@
 void *
 thread_func (void *arg)
 {
-    uint32_t thread_index = *((uint32_t *)arg);
+    uint32_t thread_index = *((uint32_t *)arg); // Break here in order to allow the thread
+                                                // to inherit the global watchpoint state.
     printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index);
 
     uint32_t count = 0;
@@ -73,13 +74,13 @@
     uint32_t thread_index_2 = 2;
     uint32_t thread_index_3 = 3;
 
+    printf ("Before turning all three threads loose...\n"); // Set break point at this line,
+                                                            // in order to set our watchpoint.
     // Create 3 threads
     err = ::pthread_create (&g_thread_1, NULL, thread_func, &thread_index_1);
     err = ::pthread_create (&g_thread_2, NULL, thread_func, &thread_index_2);
     err = ::pthread_create (&g_thread_3, NULL, thread_func, &thread_index_3);
 
-    printf ("Before turning all three threads loose...\n"); // Set break point at this line.
-
     // Join all of our threads
     err = ::pthread_join (g_thread_1, &thread_result);
     err = ::pthread_join (g_thread_2, &thread_result);

Modified: lldb/trunk/tools/debugserver/source/DNBArch.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBArch.h?rev=140811&r1=140810&r2=140811&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBArch.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBArch.h Thu Sep 29 16:48:52 2011
@@ -77,6 +77,7 @@
     virtual uint32_t        NumSupportedHardwareWatchpoints() { return 0; }
     virtual uint32_t        EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size) { return INVALID_NUB_HW_INDEX; }
     virtual uint32_t        EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write) { return INVALID_NUB_HW_INDEX; }
+    virtual void            HardwareWatchpointStateChanged () { ; }
     virtual bool            DisableHardwareBreakpoint (uint32_t hw_index) { return false; }
     virtual bool            DisableHardwareWatchpoint (uint32_t hw_index) { return false; }
     virtual uint32_t        GetHardwareWatchpointHit() { return INVALID_NUB_HW_INDEX; }

Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachThread.cpp?rev=140811&r1=140810&r2=140811&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachThread.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachThread.cpp Thu Sep 29 16:48:52 2011
@@ -687,6 +687,13 @@
     return INVALID_NUB_HW_INDEX;
 }
 
+// Provide a chance to update the global view of the hardware watchpoint state.
+void
+MachThread::HardwareWatchpointStateChanged ()
+{
+    m_arch_ap->HardwareWatchpointStateChanged();
+}
+
 bool
 MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp)
 {

Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachThread.h?rev=140811&r1=140810&r2=140811&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachThread.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachThread.h Thu Sep 29 16:48:52 2011
@@ -31,6 +31,7 @@
 
 class DNBBreakpoint;
 class MachProcess;
+class MachThreadList;
 
 class MachThread
 {
@@ -131,6 +132,9 @@
     std::string                     m_dispatch_queue_name;
 #endif
 
+private:
+    friend class MachThreadList;
+    void HardwareWatchpointStateChanged(); // Provide a chance to update the global view of the hardware watchpoint state
 };
 
 typedef std::tr1::shared_ptr<MachThread> MachThreadSP;

Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp?rev=140811&r1=140810&r2=140811&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp Thu Sep 29 16:48:52 2011
@@ -480,6 +480,9 @@
             if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(wp)) == INVALID_NUB_HW_INDEX)
                 return INVALID_NUB_HW_INDEX;
         }
+        // Use an arbitrary thread to signal the completion of our transaction.
+        if (num_threads)
+            m_threads[0]->HardwareWatchpointStateChanged();
         return hw_index;
     }
     return INVALID_NUB_HW_INDEX;
@@ -497,6 +500,9 @@
             if (!m_threads[idx]->DisableHardwareWatchpoint(wp))
                 return false;
         }
+        // Use an arbitrary thread to signal the completion of our transaction.
+        if (num_threads)
+            m_threads[0]->HardwareWatchpointStateChanged();
         return true;
     }
     return false;

Modified: lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp?rev=140811&r1=140810&r2=140811&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp Thu Sep 29 16:48:52 2011
@@ -555,7 +555,7 @@
 
     // Reset the debug status register, if necessary, before we resume.
     kern_return_t kret = GetDBGState(false);
-    DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret);
+    DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret);
     if (kret != KERN_SUCCESS)
         return;
 
@@ -570,7 +570,7 @@
     {
         ClearWatchpointHits(debug_state);
         kret = SetDBGState();
-        DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret);
+        DNBLogThreadedIf(LOG_WATCHPOINTS,"DNBArchImplI386::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret);
     }
 }
 
@@ -894,6 +894,19 @@
     return false;
 }
 
+DNBArchImplI386::DBG DNBArchImplI386::Global_Debug_State = {0,0,0,0,0,0,0,0};
+bool DNBArchImplI386::Valid_Global_Debug_State = false;
+
+// Use this callback from MachThread, which in turn was called from MachThreadList, to update
+// the global view of the hardware watchpoint state, so that when new thread comes along, they
+// get to inherit the existing hardware watchpoint state.
+void
+DNBArchImplI386::HardwareWatchpointStateChanged ()
+{
+    Global_Debug_State = m_state.context.dbg;
+    Valid_Global_Debug_State = true;
+}
+
 // Iterate through the debug status register; return the index of the first hit.
 uint32_t
 DNBArchImplI386::GetHardwareWatchpointHit(nub_addr_t &addr)
@@ -1109,7 +1122,17 @@
 DNBArchProtocol *
 DNBArchImplI386::Create (MachThread *thread)
 {
-    return new DNBArchImplI386 (thread);
+    DNBArchImplI386 *obj = new DNBArchImplI386 (thread);
+
+    // When new thread comes along, it tries to inherit from the global debug state, if it is valid.
+    if (Valid_Global_Debug_State)
+    {
+        obj->m_state.context.dbg = Global_Debug_State;
+        kern_return_t kret = obj->SetDBGState();
+        DNBLogThreadedIf(LOG_WATCHPOINTS,
+                         "DNBArchImplX86_64::Create() Inherit and SetDBGState() => 0x%8.8x.", kret);
+    }
+    return obj;
 }
 
 const uint8_t * const

Modified: lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h?rev=140811&r1=140810&r2=140811&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h Thu Sep 29 16:48:52 2011
@@ -54,6 +54,7 @@
     virtual uint32_t        NumSupportedHardwareWatchpoints();
     virtual uint32_t        EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write);
     virtual bool            DisableHardwareWatchpoint (uint32_t hw_break_index);
+    virtual void            HardwareWatchpointStateChanged ();
     virtual uint32_t        GetHardwareWatchpointHit(nub_addr_t &addr);
 
 protected:
@@ -116,6 +117,10 @@
         DBG dbg;
     };
 
+    // See also HardwareWatchpointStateChanged() which updates this class-wide variable.
+    static DBG Global_Debug_State;
+    static bool Valid_Global_Debug_State;
+
     struct State
     {
         Context context;

Modified: lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp?rev=140811&r1=140810&r2=140811&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp Thu Sep 29 16:48:52 2011
@@ -821,6 +821,19 @@
     return false;
 }
 
+DNBArchImplX86_64::DBG DNBArchImplX86_64::Global_Debug_State = {0,0,0,0,0,0,0,0};
+bool DNBArchImplX86_64::Valid_Global_Debug_State = false;
+
+// Use this callback from MachThread, which in turn was called from MachThreadList, to update
+// the global view of the hardware watchpoint state, so that when new thread comes along, they
+// get to inherit the existing hardware watchpoint state.
+void
+DNBArchImplX86_64::HardwareWatchpointStateChanged ()
+{
+    Global_Debug_State = m_state.context.dbg;
+    Valid_Global_Debug_State = true;
+}
+
 // Iterate through the debug status register; return the index of the first hit.
 uint32_t
 DNBArchImplX86_64::GetHardwareWatchpointHit(nub_addr_t &addr)
@@ -1306,7 +1319,17 @@
 DNBArchProtocol *
 DNBArchImplX86_64::Create (MachThread *thread)
 {
-    return new DNBArchImplX86_64 (thread);
+    DNBArchImplX86_64 *obj = new DNBArchImplX86_64 (thread);
+
+    // When new thread comes along, it tries to inherit from the global debug state, if it is valid.
+    if (Valid_Global_Debug_State)
+    {
+        obj->m_state.context.dbg = Global_Debug_State;
+        kern_return_t kret = obj->SetDBGState();
+        DNBLogThreadedIf(LOG_WATCHPOINTS,
+                         "DNBArchImplX86_64::Create() Inherit and SetDBGState() => 0x%8.8x.", kret);
+    }
+    return obj;
 }
 
 const uint8_t * const

Modified: lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h?rev=140811&r1=140810&r2=140811&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h Thu Sep 29 16:48:52 2011
@@ -53,6 +53,7 @@
     virtual uint32_t        NumSupportedHardwareWatchpoints();
     virtual uint32_t        EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write);
     virtual bool            DisableHardwareWatchpoint (uint32_t hw_break_index);
+    virtual void            HardwareWatchpointStateChanged ();
     virtual uint32_t        GetHardwareWatchpointHit(nub_addr_t &addr);
 
 protected:
@@ -115,6 +116,10 @@
         DBG dbg;
     };
 
+    // See also HardwareWatchpointStateChanged() which updates this class-wide variable.
+    static DBG Global_Debug_State;
+    static bool Valid_Global_Debug_State;
+
     struct State
     {
         Context context;





More information about the lldb-commits mailing list