diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h --- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -107,6 +107,7 @@ void SigchldHandler(); Status Attach(); + Status SetupTrace(); Status ReinitializeThreads(); }; diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp --- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -98,18 +98,7 @@ pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate, Info.GetArchitecture(), mainloop)); - // Enable event reporting - ptrace_event_t events; - status = PtraceWrapper(PT_GET_EVENT_MASK, pid, &events, sizeof(events)); - if (status.Fail()) - return status.ToError(); - // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN? - events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT; - status = PtraceWrapper(PT_SET_EVENT_MASK, pid, &events, sizeof(events)); - if (status.Fail()) - return status.ToError(); - - status = process_up->ReinitializeThreads(); + status = process_up->SetupTrace(); if (status.Fail()) return status.ToError(); @@ -218,10 +207,14 @@ // Get details on the signal raised. if (siginfo_err.Fail()) { + LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err); return; } + LLDB_LOG(log, "got SIGTRAP, pid = {0}, lwpid = {1}, si_code = {2}", pid, + info.psi_lwpid, info.psi_siginfo.si_code); NativeThreadNetBSD* thread = nullptr; + if (info.psi_lwpid > 0) { for (const auto &t : m_threads) { if (t->GetID() == static_cast(info.psi_lwpid)) { @@ -243,12 +236,12 @@ FixupBreakpointPCAsNeeded(*thread); } SetState(StateType::eStateStopped, true); - break; + return; case TRAP_TRACE: if (thread) thread->SetStoppedByTrace(); SetState(StateType::eStateStopped, true); - break; + return; case TRAP_EXEC: { Status error = ReinitializeThreads(); if (error.Fail()) { @@ -262,7 +255,8 @@ for (const auto &thread : m_threads) static_cast(*thread).SetStoppedByExec(); SetState(StateType::eStateStopped, true); - } break; + return; + } case TRAP_LWP: { ptrace_state_t pst; Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst)); @@ -296,11 +290,10 @@ } error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast(1), 0); - if (error.Fail()) { + if (error.Fail()) SetState(StateType::eStateInvalid); - return; - } - } break; + return; + } case TRAP_DBREG: { if (!thread) break; @@ -318,19 +311,31 @@ thread->SetStoppedByWatchpoint(wp_index); regctx.ClearWatchpointHit(wp_index); SetState(StateType::eStateStopped, true); - break; + return; } thread->SetStoppedByTrace(); SetState(StateType::eStateStopped, true); - } break; + return; } + } + + // Either user-generated SIGTRAP or an unknown event that would + // otherwise leave the debugger hanging. + LLDB_LOG(log, "unknown SIGTRAP, passing to generic handler"); + MonitorSignal(pid, SIGTRAP); } void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); ptrace_siginfo_t info; + const auto siginfo_err = PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); + if (siginfo_err.Fail()) { + LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err); + return; + } for (const auto &abs_thread : m_threads) { NativeThreadNetBSD &thread = static_cast(*abs_thread); @@ -801,8 +806,9 @@ m_pid, nullptr, WALLSIG)) < 0) return Status(errno, eErrorTypePOSIX); - /* Initialize threads */ - status = ReinitializeThreads(); + // Initialize threads and tracing status + // NB: this needs to be called before we set thread state + status = SetupTrace(); if (status.Fail()) return status; @@ -810,7 +816,8 @@ static_cast(*thread).SetStoppedBySignal(SIGSTOP); // Let our process instance know the thread has stopped. - SetState(StateType::eStateStopped); + SetCurrentThreadID(m_threads.front()->GetID()); + SetState(StateType::eStateStopped, false); return Status(); } @@ -855,7 +862,8 @@ io.piod_len = size; do { - io.piod_addr = const_cast(static_cast(src + bytes_written)); + io.piod_addr = + const_cast(static_cast(src + bytes_written)); io.piod_offs = (void *)(addr + bytes_written); Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io); @@ -900,6 +908,21 @@ return std::move(buf); } +Status NativeProcessNetBSD::SetupTrace() { + // Enable event reporting + ptrace_event_t events; + Status status = PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events)); + if (status.Fail()) + return status; + // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN? + events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT; + status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events)); + if (status.Fail()) + return status; + + return ReinitializeThreads(); +} + Status NativeProcessNetBSD::ReinitializeThreads() { // Clear old threads m_threads.clear(); diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h --- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h +++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h @@ -29,7 +29,7 @@ static NativeRegisterContextNetBSD * CreateHostNativeRegisterContextNetBSD(const ArchSpec &target_arch, NativeThreadProtocol &native_thread); - virtual Status + virtual llvm::Error CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) = 0; protected: diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h --- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h +++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -48,7 +48,7 @@ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - Status + llvm::Error CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) override; private: diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp --- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -1087,19 +1087,19 @@ } } -Status NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom( +llvm::Error NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom( NativeRegisterContextNetBSD &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 res; + return llvm::Error::success(); m_dbr = r_source.m_dbr; res = WriteRegisterSet(DBRegSet); } - return res; + return res.ToError(); } #endif // defined(__x86_64__) diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h --- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h +++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h @@ -64,7 +64,7 @@ void SetRunning(); void SetStepping(); - Status CopyWatchpointsFrom(NativeThreadNetBSD& source); + llvm::Error CopyWatchpointsFrom(NativeThreadNetBSD& source); // Member Variables lldb::StateType m_state; diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp --- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp @@ -116,8 +116,6 @@ } void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) { - SetStopped(); - lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); std::ostringstream ostr; @@ -126,8 +124,8 @@ ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index); + SetStopped(); m_stop_description = ostr.str(); - m_stop_info.reason = StopReason::eStopReasonWatchpoint; m_stop_info.details.signal.signo = SIGTRAP; } @@ -204,7 +202,6 @@ bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info, std::string &description) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - description.clear(); switch (m_state) { @@ -239,14 +236,14 @@ Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) { + assert(m_state == eStateStopped); if (!hardware) return Status("not implemented"); - if (m_state == eStateLaunching) - return Status(); Status error = RemoveWatchpoint(addr); if (error.Fail()) return error; - uint32_t wp_index = GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags); + uint32_t wp_index = + GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags); if (wp_index == LLDB_INVALID_INDEX32) return Status("Setting hardware watchpoint failed."); m_watchpoint_index_map.insert({addr, wp_index}); @@ -266,9 +263,7 @@ Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) { - if (m_state == eStateLaunching) - return Status(); - + assert(m_state == eStateStopped); Status error = RemoveHardwareBreakpoint(addr); if (error.Fail()) return error; @@ -296,10 +291,11 @@ return Status("Clearing hardware breakpoint failed."); } -Status NativeThreadNetBSD::CopyWatchpointsFrom(NativeThreadNetBSD &source) { - Status s = GetRegisterContext().CopyHardwareWatchpointsFrom( +llvm::Error +NativeThreadNetBSD::CopyWatchpointsFrom(NativeThreadNetBSD &source) { + llvm::Error s = GetRegisterContext().CopyHardwareWatchpointsFrom( source.GetRegisterContext()); - if (!s.Fail()) { + if (!s) { m_watchpoint_index_map = source.m_watchpoint_index_map; m_hw_break_index_map = source.m_hw_break_index_map; } diff --git a/lldb/test/API/commands/process/attach/TestProcessAttach.py b/lldb/test/API/commands/process/attach/TestProcessAttach.py --- a/lldb/test/API/commands/process/attach/TestProcessAttach.py +++ b/lldb/test/API/commands/process/attach/TestProcessAttach.py @@ -21,7 +21,6 @@ NO_DEBUG_INFO_TESTCASE = True @skipIfiOSSimulator - @expectedFailureNetBSD def test_attach_to_process_by_id(self): """Test attach by process id""" self.build() @@ -37,7 +36,6 @@ process = target.GetProcess() self.assertTrue(process, PROCESS_IS_VALID) - @expectedFailureNetBSD @skipIfReproducer # FIXME: Unexpected packet during (active) replay def test_attach_to_process_from_different_dir_by_id(self): """Test attach by process id""" @@ -64,7 +62,6 @@ process = target.GetProcess() self.assertTrue(process, PROCESS_IS_VALID) - @expectedFailureNetBSD def test_attach_to_process_by_name(self): """Test attach by process name""" self.build() diff --git a/lldb/test/API/commands/register/register/register_command/TestRegisters.py b/lldb/test/API/commands/register/register/register_command/TestRegisters.py --- a/lldb/test/API/commands/register/register/register_command/TestRegisters.py +++ b/lldb/test/API/commands/register/register/register_command/TestRegisters.py @@ -70,7 +70,6 @@ @skipIf(archs=no_match(['amd64', 'i386', 'x86_64'])) @skipIfOutOfTreeDebugserver @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37995") - @expectedFailureNetBSD def test_fp_special_purpose_register_read(self): """Test commands that read fpu special purpose registers.""" self.build() @@ -116,7 +115,6 @@ @skipIfiOSSimulator @skipIf(archs=no_match(['amd64', 'x86_64'])) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37683") - @expectedFailureNetBSD def test_convenience_registers_with_process_attach(self): """Test convenience registers after a 'process attach'.""" self.build() @@ -125,7 +123,6 @@ @skipIfiOSSimulator @skipIf(archs=no_match(['amd64', 'x86_64'])) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37683") - @expectedFailureNetBSD def test_convenience_registers_16bit_with_process_attach(self): """Test convenience registers after a 'process attach'.""" self.build() diff --git a/lldb/test/API/functionalities/deleted-executable/TestDeletedExecutable.py b/lldb/test/API/functionalities/deleted-executable/TestDeletedExecutable.py --- a/lldb/test/API/functionalities/deleted-executable/TestDeletedExecutable.py +++ b/lldb/test/API/functionalities/deleted-executable/TestDeletedExecutable.py @@ -16,7 +16,7 @@ NO_DEBUG_INFO_TESTCASE = True @skipIfWindows # cannot delete a running executable - @expectedFailureAll(oslist=["freebsd", "linux", "netbsd"], + @expectedFailureAll(oslist=["freebsd", "linux"], triple=no_match('aarch64-.*-android')) # determining the architecture of the process fails @skipIfReproducer # File synchronization is not supported during replay. diff --git a/lldb/test/API/functionalities/thread/num_threads/TestNumThreads.py b/lldb/test/API/functionalities/thread/num_threads/TestNumThreads.py --- a/lldb/test/API/functionalities/thread/num_threads/TestNumThreads.py +++ b/lldb/test/API/functionalities/thread/num_threads/TestNumThreads.py @@ -62,7 +62,6 @@ @skipIfDarwin # rdar://33462362 @skipIfWindows # This is flakey on Windows: llvm.org/pr37658, llvm.org/pr38373 - @expectedFailureNetBSD def test_unique_stacks(self): """Test backtrace unique with multiple threads executing the same stack.""" self.build() diff --git a/lldb/test/API/python_api/hello_world/TestHelloWorld.py b/lldb/test/API/python_api/hello_world/TestHelloWorld.py --- a/lldb/test/API/python_api/hello_world/TestHelloWorld.py +++ b/lldb/test/API/python_api/hello_world/TestHelloWorld.py @@ -74,7 +74,6 @@ @add_test_categories(['pyapi']) @skipIfiOSSimulator - @expectedFailureNetBSD @skipIfReproducer # File synchronization is not supported during replay. def test_with_attach_to_process_with_id_api(self): """Create target, spawn a process, and attach to it with process id.""" @@ -108,7 +107,6 @@ @add_test_categories(['pyapi']) @skipIfiOSSimulator @skipIfAsan # FIXME: Hangs indefinitely. - @expectedFailureNetBSD @skipIfReproducer # FIXME: Unexpected packet during (active) replay def test_with_attach_to_process_with_name_api(self): """Create target, spawn a process, and attach to it with process name.""" diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteAttach.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteAttach.py --- a/lldb/test/API/tools/lldb-server/TestGdbRemoteAttach.py +++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteAttach.py @@ -58,7 +58,6 @@ self.set_inferior_startup_attach_manually() self.attach_with_vAttach() - @expectedFailureNetBSD @llgs_test def test_attach_with_vAttach_llgs(self): self.init_llgs_test() diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteKill.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteKill.py --- a/lldb/test/API/tools/lldb-server/TestGdbRemoteKill.py +++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteKill.py @@ -51,7 +51,6 @@ self.set_inferior_startup_attach() self.attach_commandline_kill_after_initial_stop() - @expectedFailureNetBSD @llgs_test def test_attach_commandline_kill_after_initial_stop_llgs(self): self.init_llgs_test() diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteProcessInfo.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteProcessInfo.py --- a/lldb/test/API/tools/lldb-server/TestGdbRemoteProcessInfo.py +++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteProcessInfo.py @@ -74,7 +74,6 @@ self.set_inferior_startup_attach() self.attach_commandline_qProcessInfo_reports_correct_pid() - @expectedFailureNetBSD @llgs_test def test_attach_commandline_qProcessInfo_reports_correct_pid_llgs(self): self.init_llgs_test() diff --git a/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py b/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py --- a/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py +++ b/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py @@ -227,7 +227,6 @@ self.set_inferior_startup_attach() self.attach_commandline_continue_app_exits() - @expectedFailureNetBSD @llgs_test def test_attach_commandline_continue_app_exits_llgs(self): self.init_llgs_test() @@ -480,7 +479,6 @@ self.qThreadInfo_contains_thread() @expectedFailureAll(oslist=["windows"]) # expect one more thread stopped - @expectedFailureNetBSD @llgs_test def test_qThreadInfo_contains_thread_attach_llgs(self): self.init_llgs_test() @@ -540,7 +538,6 @@ self.qThreadInfo_matches_qC() @expectedFailureAll(oslist=["windows"]) # expect one more thread stopped - @expectedFailureNetBSD @llgs_test def test_qThreadInfo_matches_qC_attach_llgs(self): self.init_llgs_test() @@ -688,7 +685,6 @@ self.Hg_switches_to_3_threads() @expectedFailureAll(oslist=["windows"]) # expecting one more thread - @expectedFailureNetBSD @llgs_test def test_Hg_switches_to_3_threads_attach_llgs(self): self.init_llgs_test()