mgorny updated this revision to Diff 303957.
mgorny added a comment.
This revision is now accepted and ready to land.
Added a verbose comment why we're doing that.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D91032/new/
https://reviews.llvm.org/D91032
Files:
lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h
lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.cpp
lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.h
lldb/test/API/commands/watchpoints/multiple_threads/TestWatchpointMultipleThreads.py
Index: lldb/test/API/commands/watchpoints/multiple_threads/TestWatchpointMultipleThreads.py
===================================================================
--- lldb/test/API/commands/watchpoints/multiple_threads/TestWatchpointMultipleThreads.py
+++ lldb/test/API/commands/watchpoints/multiple_threads/TestWatchpointMultipleThreads.py
@@ -22,7 +22,6 @@
"""Test that we can hit a watchpoint we set before starting another thread"""
self.do_watchpoint_test("Before running the thread")
- @expectedFailureAll(oslist=["freebsd"])
def test_watchpoint_after_thread_launch(self):
"""Test that we can hit a watchpoint we set after launching another thread"""
self.do_watchpoint_test("After launching the thread")
Index: lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.h
===================================================================
--- lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.h
+++ lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.h
@@ -64,7 +64,7 @@
void SetRunning();
void SetStepping();
- Status CopyWatchpointsFrom(NativeThreadFreeBSD &source);
+ llvm::Error CopyWatchpointsFrom(NativeThreadFreeBSD &source);
// Member Variables
lldb::StateType m_state;
Index: lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.cpp
===================================================================
--- lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.cpp
+++ lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.cpp
@@ -273,3 +273,12 @@
return Status("Clearing hardware breakpoint failed.");
}
+
+llvm::Error NativeThreadFreeBSD::CopyWatchpointsFrom(NativeThreadFreeBSD &source) {
+ llvm::Error s = GetRegisterContext().CopyHardwareWatchpointsFrom(source.GetRegisterContext());
+ if (!s) {
+ m_watchpoint_index_map = source.m_watchpoint_index_map;
+ m_hw_break_index_map = source.m_hw_break_index_map;
+ }
+ return s;
+}
Index: lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
===================================================================
--- lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
+++ lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
@@ -50,6 +50,9 @@
Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+ llvm::Error
+ CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
private:
// Private member types.
enum { GPRegSet, FPRegSet, XSaveRegSet, DBRegSet };
Index: lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
===================================================================
--- lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
+++ lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
@@ -1169,4 +1169,19 @@
}
}
+llvm::Error NativeRegisterContextFreeBSD_x86_64::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextFreeBSD &source) {
+ auto &r_source = static_cast<NativeRegisterContextFreeBSD_x86_64&>(source);
+ Status res = r_source.ReadRegisterSet(DBRegSet);
+ if (!res.Fail()) {
+ // copy dbregs only if any watchpoints were set
+ if ((r_source.m_dbr.dr[7] & 0xFF) == 0)
+ return llvm::Error::success();
+
+ m_dbr = r_source.m_dbr;
+ res = WriteRegisterSet(DBRegSet);
+ }
+ return res.ToError();
+}
+
#endif // defined(__x86_64__)
Index: lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h
===================================================================
--- lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h
+++ lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h
@@ -29,6 +29,8 @@
static NativeRegisterContextFreeBSD *
CreateHostNativeRegisterContextFreeBSD(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
+ virtual llvm::Error
+ CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) = 0;
protected:
virtual NativeProcessFreeBSD &GetProcess();
Index: lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
===================================================================
--- lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
+++ lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
@@ -199,7 +199,26 @@
if (info.pl_flags & (PL_FLAG_BORN | PL_FLAG_EXITED)) {
if (info.pl_flags & PL_FLAG_BORN) {
LLDB_LOG(log, "monitoring new thread, tid = {0}", info.pl_lwpid);
- AddThread(info.pl_lwpid);
+ NativeThreadFreeBSD& t = AddThread(info.pl_lwpid);
+
+ // Technically, the FreeBSD kernel copies the debug registers to new
+ // threads. However, there is a non-negligible delay between acquiring
+ // the DR values and reporting the new thread during which the user may
+ // establish a new watchpoint. In order to ensure that watchpoints
+ // established during this period are propagated to new threads,
+ // explicitly copy the DR value at the time the new thread is reported.
+ //
+ // See also: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=250954
+
+ llvm::Error error = t.CopyWatchpointsFrom(
+ static_cast<NativeThreadFreeBSD &>(*GetCurrentThread()));
+ if (error) {
+ LLDB_LOG(log,
+ "failed to copy watchpoints to new thread {0}: {1}",
+ info.pl_lwpid, llvm::toString(std::move(error)));
+ SetState(StateType::eStateInvalid);
+ return;
+ }
} else /*if (info.pl_flags & PL_FLAG_EXITED)*/ {
LLDB_LOG(log, "thread exited, tid = {0}", info.pl_lwpid);
RemoveThread(info.pl_lwpid);
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits