[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