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,16 @@ 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); + llvm::Error error = t.CopyWatchpointsFrom( + static_cast(*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); 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/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(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/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/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")