[Lldb-commits] [lldb] r183139 - Fix setting of watchpoints on inferior thread creation for Linux.

Matt Kopec Matt.Kopec at intel.com
Mon Jun 3 10:40:20 PDT 2013


Author: mkopec
Date: Mon Jun  3 12:40:20 2013
New Revision: 183139

URL: http://llvm.org/viewvc/llvm-project?rev=183139&view=rev
Log:
Fix setting of watchpoints on inferior thread creation for Linux.

Modified:
    lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp
    lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h
    lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
    lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
    lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
    lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
    lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py

Modified: lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp?rev=183139&r1=183138&r2=183139&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp Mon Jun  3 12:40:20 2013
@@ -46,6 +46,20 @@ POSIXThread::POSIXThread(Process &proces
     Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
         log->Printf ("POSIXThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid);
+
+    // Set the current watchpoints for this thread.
+    Target &target = GetProcess()->GetTarget();
+    const WatchpointList &wp_list = target.GetWatchpointList();
+    size_t wp_size = wp_list.GetSize();
+
+    for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++)
+    {
+        lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
+        if (wp.get() && wp->IsEnabled())
+        {
+            assert(EnableHardwareWatchpoint(wp.get()));
+        }
+    }
 }
 
 POSIXThread::~POSIXThread()
@@ -272,27 +286,21 @@ POSIXThread::Notify(const ProcessMessage
 bool
 POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp)
 {
-    bool result = false;
+    bool wp_set = false;
     if (wp)
     {
         addr_t wp_addr = wp->GetLoadAddress();
         size_t wp_size = wp->GetByteSize();
         bool wp_read = wp->WatchpointRead();
         bool wp_write = wp->WatchpointWrite();
-        uint32_t wp_hw_index;
-        lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
-        if (reg_ctx_sp.get())
-        {
-            wp_hw_index = reg_ctx_sp->SetHardwareWatchpoint(wp_addr, wp_size,
-                                                            wp_read, wp_write);
-            if (wp_hw_index != LLDB_INVALID_INDEX32)
-            {
-                wp->SetHardwareIndex(wp_hw_index);
-                result = true;
-            }
-        }
+        uint32_t wp_hw_index = wp->GetHardwareIndex();
+        RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+        if (reg_ctx)
+            wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
+                                                             wp_read, wp_write,
+                                                             wp_hw_index);
     }
-    return result;
+    return wp_set;
 }
 
 bool
@@ -303,11 +311,7 @@ POSIXThread::DisableHardwareWatchpoint(W
     {
         lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
         if (reg_ctx_sp.get())
-        {
             result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
-            if (result == true)
-                wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
-        }
     }
     return result;
 }
@@ -321,6 +325,27 @@ POSIXThread::NumSupportedHardwareWatchpo
     return 0;
 }
 
+uint32_t
+POSIXThread::FindVacantWatchpointIndex()
+{
+    uint32_t hw_index = LLDB_INVALID_INDEX32;
+    uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
+    uint32_t wp_idx;
+    RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+    if (reg_ctx)
+    {
+        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+        {
+            if (reg_ctx->IsWatchpointVacant(wp_idx))
+            {
+                hw_index = wp_idx;
+                break;
+            }
+        }
+    }
+    return hw_index;
+}
+
 void
 POSIXThread::BreakNotify(const ProcessMessage &message)
 {

Modified: lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h?rev=183139&r1=183138&r2=183139&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h Mon Jun  3 12:40:20 2013
@@ -82,6 +82,8 @@ public:
 
     uint32_t NumSupportedHardwareWatchpoints();
 
+    uint32_t FindVacantWatchpointIndex();
+
 private:
     RegisterContextPOSIX *
     GetRegisterContextPOSIX ()

Modified: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp?rev=183139&r1=183138&r2=183139&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp Mon Jun  3 12:40:20 2013
@@ -654,31 +654,44 @@ ProcessPOSIX::EnableWatchpoint(Watchpoin
             return error;
         }
 
-        bool wp_enabled = true;
-        uint32_t thread_count = m_thread_list.GetSize(false);
-        for (uint32_t i = 0; i < thread_count; ++i)
-        {
-            POSIXThread *thread = static_cast<POSIXThread*>(
-                                  m_thread_list.GetThreadAtIndex(i, false).get());
-            if (thread)
-                wp_enabled &= thread->EnableHardwareWatchpoint(wp);
-            else
-            {
-                wp_enabled = false;
-                break;
-            }
-        }
-        if (wp_enabled)
+        // Try to find a vacant watchpoint slot in the inferiors' main thread
+        uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
+        POSIXThread *thread = static_cast<POSIXThread*>(
+                               m_thread_list.GetThreadAtIndex(0, false).get());
+
+        if (thread)
+            wp_hw_index = thread->FindVacantWatchpointIndex();
+
+        if (wp_hw_index == LLDB_INVALID_INDEX32)
         {
-            wp->SetEnabled(true, notify);
-            return error;
+            error.SetErrorString("Setting hardware watchpoint failed.");
         }
         else
         {
-            // Watchpoint enabling failed on at least one
-            // of the threads so roll back all of them
-            DisableWatchpoint(wp, false);
-            error.SetErrorString("Setting hardware watchpoint failed");
+            wp->SetHardwareIndex(wp_hw_index);
+            bool wp_enabled = true;
+            uint32_t thread_count = m_thread_list.GetSize(false);
+            for (uint32_t i = 0; i < thread_count; ++i)
+            {
+                thread = static_cast<POSIXThread*>(
+                         m_thread_list.GetThreadAtIndex(i, false).get());
+                if (thread)
+                    wp_enabled &= thread->EnableHardwareWatchpoint(wp);
+                else
+                    wp_enabled = false;
+            }
+            if (wp_enabled)
+            {
+                wp->SetEnabled(true, notify);
+                return error;
+            }
+            else
+            {
+                // Watchpoint enabling failed on at least one
+                // of the threads so roll back all of them
+                DisableWatchpoint(wp, false);
+                error.SetErrorString("Setting hardware watchpoint failed");
+            }
         }
     }
     else
@@ -724,6 +737,7 @@ ProcessPOSIX::DisableWatchpoint(Watchpoi
             }
             if (wp_disabled)
             {
+                wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
                 wp->SetEnabled(false, notify);
                 return error;
             }

Modified: lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h?rev=183139&r1=183138&r2=183139&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h Mon Jun  3 12:40:20 2013
@@ -25,7 +25,8 @@ class RegisterContextPOSIX
 public:
     RegisterContextPOSIX(lldb_private::Thread &thread,
                          uint32_t concrete_frame_idx)
-        : RegisterContext(thread, concrete_frame_idx) { }
+        : RegisterContext(thread, concrete_frame_idx)
+        { m_watchpoints_initialized = false; }
 
     /// Updates the register state of the associated thread after hitting a
     /// breakpoint (if that make sense for the architecture).  Default
@@ -52,7 +53,18 @@ public:
     // Returns the watchpoint address associated with a watchpoint hardware
     // index.
     virtual lldb::addr_t
-    GetWatchpointAddress (uint32_t hw_index) {return LLDB_INVALID_ADDRESS; }
+    GetWatchpointAddress (uint32_t hw_index) { return LLDB_INVALID_ADDRESS; }
+
+    virtual bool
+    IsWatchpointVacant (uint32_t hw_index) { return false; }
+
+    virtual bool
+    SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size,
+                                    bool read, bool write,
+                                    uint32_t hw_index) { return false; }
+
+protected:
+    bool m_watchpoints_initialized;
 };
 
 #endif // #ifndef liblldb_RegisterContextPOSIX_H_

Modified: lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp?rev=183139&r1=183138&r2=183139&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp Mon Jun  3 12:40:20 2013
@@ -1242,6 +1242,8 @@ RegisterContext_x86_64::IsWatchpointVaca
     bool is_vacant = false;
     RegisterValue value;
 
+    assert(hw_index < NumSupportedHardwareWatchpoints());
+
     if (ReadRegister(dr7, value))
     {
         uint64_t val = value.GetAsUInt64();
@@ -1282,23 +1284,47 @@ RegisterContext_x86_64::SetHardwareWatch
                                               bool read, bool write)
 {
     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+    uint32_t hw_index;
 
-    if (num_hw_watchpoints == 0)
-        return LLDB_INVALID_INDEX32;
+    for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+    {
+        if (IsWatchpointVacant(hw_index))
+            return SetHardwareWatchpointWithIndex(addr, size,
+                                                  read, write,
+                                                  hw_index);
+    }
+
+    return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContext_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
+                                                       bool read, bool write,
+                                                       uint32_t hw_index)
+{
+    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+
+    if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
+        return false;
 
     if (!(size == 1 || size == 2 || size == 4 || size == 8))
-        return LLDB_INVALID_INDEX32;
+        return false;
 
     if (read == false && write == false)
-        return LLDB_INVALID_INDEX32;
+        return false;
 
-    uint32_t hw_index = 0;
-    for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+    if (m_watchpoints_initialized == false)
     {
-        if (IsWatchpointVacant(hw_index))
-            break;
+        // Reset the debug status and debug control registers
+        RegisterValue zero_bits = RegisterValue(uint64_t(0));
+        if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits))
+            return false;
+        m_watchpoints_initialized = true;
     }
 
+    if (!IsWatchpointVacant(hw_index))
+        return false;
+
     // Set both dr7 (debug control register) and dri (debug address register).
 
     // dr7{7-0} encodes the local/gloabl enable bits:
@@ -1335,11 +1361,11 @@ RegisterContext_x86_64::SetHardwareWatch
 
             if (WriteRegister(dr0 + hw_index, RegisterValue(addr)) &&
                 WriteRegister(dr7, RegisterValue(new_dr7_bits)))
-                return hw_index;
+                return true;
         }
     }
 
-    return LLDB_INVALID_INDEX32;
+    return false;
 }
 
 bool

Modified: lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h?rev=183139&r1=183138&r2=183139&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h Mon Jun  3 12:40:20 2013
@@ -193,6 +193,10 @@ public:
     SetHardwareWatchpoint(lldb::addr_t, size_t size, bool read, bool write);
 
     bool
+    SetHardwareWatchpointWithIndex(lldb::addr_t, size_t size, bool read,
+                                   bool write, uint32_t hw_index);
+
+    bool
     ClearHardwareWatchpoint(uint32_t hw_index);
 
     bool

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=183139&r1=183138&r2=183139&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py (original)
+++ lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py Mon Jun  3 12:40:20 2013
@@ -21,7 +21,6 @@ class WatchpointForMultipleThreadsTestCa
         self.setTearDownCleanup(dictionary=self.d)
         self.hello_multiple_threads()
 
-    @skipIfLinux # llvm.org/pr14323 - skip due to incomplete multi-threaded debug support
     @dwarf_test
     def test_watchpoint_multiple_threads_with_dwarf(self):
         """Test that lldb watchpoint works for multiple threads."""
@@ -37,7 +36,6 @@ class WatchpointForMultipleThreadsTestCa
         self.setTearDownCleanup(dictionary=self.d)
         self.hello_multiple_threads_wp_set_and_then_delete()
 
-    @skipIfLinux # llvm.org/pr14323 - skip due to incomplete multi-threaded debug support
     @dwarf_test
     def test_watchpoint_multiple_threads_wp_set_and_then_delete_with_dwarf(self):
         """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires."""





More information about the lldb-commits mailing list