diff --git a/lldb/packages/Python/lldbsuite/test/commands/watchpoints/hello_watchlocation/TestWatchLocation.py b/lldb/packages/Python/lldbsuite/test/commands/watchpoints/hello_watchlocation/TestWatchLocation.py --- a/lldb/packages/Python/lldbsuite/test/commands/watchpoints/hello_watchlocation/TestWatchLocation.py +++ b/lldb/packages/Python/lldbsuite/test/commands/watchpoints/hello_watchlocation/TestWatchLocation.py @@ -36,7 +36,6 @@ @expectedFailureAll(triple=re.compile('^mips')) # SystemZ and PowerPC also currently supports only one H/W watchpoint @expectedFailureAll(archs=['powerpc64le', 's390x']) - @expectedFailureNetBSD @skipIfDarwin def test_hello_watchlocation(self): """Test watching a location with '-s size' option.""" diff --git a/lldb/packages/Python/lldbsuite/test/commands/watchpoints/watchpoint_set_command/TestWatchLocationWithWatchSet.py b/lldb/packages/Python/lldbsuite/test/commands/watchpoints/watchpoint_set_command/TestWatchLocationWithWatchSet.py --- a/lldb/packages/Python/lldbsuite/test/commands/watchpoints/watchpoint_set_command/TestWatchLocationWithWatchSet.py +++ b/lldb/packages/Python/lldbsuite/test/commands/watchpoints/watchpoint_set_command/TestWatchLocationWithWatchSet.py @@ -34,7 +34,6 @@ 'aarch64', 'arm'], bugnumber="llvm.org/pr26031") - @expectedFailureNetBSD def test_watchlocation_using_watchpoint_set(self): """Test watching a location with 'watchpoint set expression -w write -s size' option.""" self.build() diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py @@ -15,7 +15,6 @@ @skipIfFreeBSD # timing out on buildbot # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD def test(self): """Test threads that trigger a breakpoint where one thread has a 1 second delay. """ self.build(dictionary=self.getBuildFlags()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py @@ -15,7 +15,6 @@ @skipIfFreeBSD # timing out on buildbot # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD def test(self): """ Test a thread that crashes while another thread hits a breakpoint.""" self.build(dictionary=self.getBuildFlags()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py @@ -15,7 +15,6 @@ @skipIfFreeBSD # timing out on buildbot # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD def test(self): """ Test a thread that crashes while another thread generates a signal.""" self.build(dictionary=self.getBuildFlags()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py @@ -15,7 +15,6 @@ @skipIfFreeBSD # timing out on buildbot # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD @add_test_categories(["watchpoint"]) def test(self): """ Test a thread that crashes while another thread hits a watchpoint.""" diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py @@ -15,7 +15,6 @@ @skipIfFreeBSD # timing out on buildbot # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD @add_test_categories(["watchpoint"]) def test(self): """ Test a thread that crashes while other threads generate a signal and hit a watchpoint and breakpoint. """ diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py @@ -15,7 +15,6 @@ @skipIfFreeBSD # timing out on buildbot # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD def test(self): """Test (1-second delay) signal and a breakpoint in multiple threads.""" self.build(dictionary=self.getBuildFlags()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py @@ -15,7 +15,6 @@ @skipIfFreeBSD # timing out on buildbot # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD def test(self): """ Test a thread with a delayed crash while other threads generate a signal and hit a breakpoint. """ self.build(dictionary=self.getBuildFlags()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py @@ -15,7 +15,6 @@ @skipIfFreeBSD # timing out on buildbot # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD @add_test_categories(["watchpoint"]) def test(self): """ Test a thread with a delayed crash while other threads hit a watchpoint and a breakpoint. """ diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py @@ -14,7 +14,6 @@ # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD @skipIfOutOfTreeDebugserver def test(self): """Test 100 breakpoints from 100 threads.""" diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py @@ -14,7 +14,6 @@ # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD @skipIfOutOfTreeDebugserver def test(self): """Test 100 threads that cause a segfault.""" diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py @@ -15,7 +15,6 @@ @skipIfFreeBSD # timing out on buildbot # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD def test(self): """Test signal and a breakpoint in multiple threads.""" self.build(dictionary=self.getBuildFlags()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py @@ -15,7 +15,6 @@ @skipIfFreeBSD # timing out on buildbot # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple='^mips') - @expectedFailureNetBSD def test(self): """Test two threads that trigger a breakpoint. """ self.build(dictionary=self.getBuildFlags()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py @@ -21,7 +21,6 @@ # Find the line number for our breakpoint. self.breakpoint = line_number('main.cpp', '// Set breakpoint here') - @expectedFailureNetBSD def test(self): """Test thread exit during breakpoint handling.""" self.build(dictionary=self.getBuildFlags()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py @@ -17,7 +17,6 @@ @skipIfFreeBSD # llvm.org/pr21411: test is hanging @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 - @expectedFailureNetBSD def test(self): """Test thread exit during step handling.""" self.build(dictionary=self.getBuildFlags()) @@ -28,7 +27,6 @@ @skipIfFreeBSD # llvm.org/pr21411: test is hanging @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 - @expectedFailureNetBSD def test_step_over(self): """Test thread exit during step-over handling.""" self.build(dictionary=self.getBuildFlags()) @@ -39,7 +37,6 @@ @skipIfFreeBSD # llvm.org/pr21411: test is hanging @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 - @expectedFailureNetBSD def test_step_in(self): """Test thread exit during step-in handling.""" self.build(dictionary=self.getBuildFlags()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py @@ -23,7 +23,6 @@ self.thread3_notify_all_line = line_number('main.cpp', '// Set thread3 break point on notify_all at this line.') self.thread3_before_lock_line = line_number('main.cpp', '// thread3-before-lock') - @expectedFailureNetBSD def test_number_of_threads(self): """Test number of threads.""" self.build() diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py @@ -25,7 +25,6 @@ self.break_4 = line_number('main.cpp', '// Set fourth breakpoint here') @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 - @expectedFailureNetBSD def test(self): """Test thread exit handling.""" self.build(dictionary=self.getBuildFlags()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py @@ -25,13 +25,11 @@ @add_test_categories(['pyapi']) @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], archs=['armv7', 'armv7k'], bugnumber='rdar://problem/34563920') # armv7 ios problem - breakpoint with tid qualifier isn't working - @expectedFailureNetBSD def test_thread_id(self): self.do_test(set_thread_id) @skipUnlessDarwin @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], archs=['armv7', 'armv7k'], bugnumber='rdar://problem/34563920') # armv7 ios problem - breakpoint with tid qualifier isn't working - @expectedFailureNetBSD def test_thread_name(self): self.do_test(set_thread_name) diff --git a/lldb/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py b/lldb/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py --- a/lldb/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py +++ b/lldb/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py @@ -91,7 +91,6 @@ self.assertTrue(yours[i] == mine[i], "ID of yours[{0}] and mine[{0}] matches".format(i)) - @expectedFailureNetBSD @add_test_categories(['pyapi']) def test_lldb_iter_frame(self): """Test iterator works correctly for SBProcess->SBThread->SBFrame.""" diff --git a/lldb/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py b/lldb/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py --- a/lldb/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py +++ b/lldb/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py @@ -27,7 +27,6 @@ self.violating_func = "do_bad_thing_with_location" @add_test_categories(['pyapi']) - @expectedFailureNetBSD def test_watch_address(self): """Exercise SBTarget.WatchAddress() API to set a watchpoint.""" self.build() diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_vContThreads.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_vContThreads.py new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_vContThreads.py @@ -0,0 +1,149 @@ +from __future__ import print_function + +import json +import re + +import gdbremote_testcase +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestGdbRemote_vContThreads(gdbremote_testcase.GdbRemoteTestCaseBase): + mydir = TestBase.compute_mydir(__file__) + + def start_threads(self, num): + procs = self.prep_debug_monitor_and_inferior( + inferior_args=['thread:new'] * num + ['@started']) + # start the process and wait for output + self.test_sequence.add_log_lines([ + "read packet: $c#63", + {"type": "output_match", "regex": self.maybe_strict_output_regex( + r"@started\r\n")}, + ], True) + # then interrupt it + self.add_interrupt_packets() + self.add_threadinfo_collection_packets() + + context = self.expect_gdbremote_sequence() + self.assertIsNotNone(context) + threads = self.parse_threadinfo_packets(context) + self.assertIsNotNone(threads) + self.assertEqual(len(threads), num + 1) + + self.reset_test_sequence() + return threads + + def signal_one_thread(self): + threads = self.start_threads(1) + # try sending a signal to one of the two threads + self.test_sequence.add_log_lines([ + "read packet: $vCont;C{0:x}:{1:x};c#00".format( + lldbutil.get_signal_number('SIGUSR1'), threads[0]), + {"direction": "send", "regex": r"^\$W00#b7$"}, + ], True) + + context = self.expect_gdbremote_sequence() + self.assertIsNotNone(context) + + @skipUnlessPlatform(["netbsd"]) + @debugserver_test + def test_signal_one_thread_debugserver(self): + self.init_debugserver_test() + self.build() + self.set_inferior_startup_launch() + self.signal_one_thread() + + @skipUnlessPlatform(["netbsd"]) + @llgs_test + def test_signal_one_thread_llgs(self): + self.init_llgs_test() + self.build() + self.set_inferior_startup_launch() + self.signal_one_thread() + + def signal_all_threads(self): + threads = self.start_threads(1) + # try sending a signal to two threads (= the process) + self.test_sequence.add_log_lines([ + "read packet: $vCont;C{0:x}:{1:x};C{0:x}:{2:x}#00".format( + lldbutil.get_signal_number('SIGUSR1'), + threads[0], threads[1]), + {"direction": "send", "regex": r"^\$W00#b7$"}, + ], True) + + context = self.expect_gdbremote_sequence() + self.assertIsNotNone(context) + + @skipUnlessPlatform(["netbsd"]) + @debugserver_test + def test_signal_all_threads_debugserver(self): + self.init_debugserver_test() + self.build() + self.set_inferior_startup_launch() + self.signal_all_threads() + + @skipUnlessPlatform(["netbsd"]) + @llgs_test + def test_signal_all_threads_llgs(self): + self.init_llgs_test() + self.build() + self.set_inferior_startup_launch() + self.signal_all_threads() + + def signal_two_of_three_threads(self): + threads = self.start_threads(2) + # try sending a signal to 2 out of 3 threads + self.test_sequence.add_log_lines([ + "read packet: $vCont;C{0:x}:{1:x};C{0:x}:{2:x};c#00".format( + lldbutil.get_signal_number('SIGUSR1'), + threads[1], threads[2]), + {"direction": "send", "regex": r"^\$E1e#db$"}, + ], True) + + context = self.expect_gdbremote_sequence() + self.assertIsNotNone(context) + + @skipUnlessPlatform(["netbsd"]) + @debugserver_test + def test_signal_two_of_three_threads_debugserver(self): + self.init_debugserver_test() + self.build() + self.set_inferior_startup_launch() + self.signal_two_of_three_threads() + + @skipUnlessPlatform(["netbsd"]) + @llgs_test + def test_signal_two_of_three_threads_llgs(self): + self.init_llgs_test() + self.build() + self.set_inferior_startup_launch() + self.signal_two_of_three_threads() + + def signal_two_signals(self): + threads = self.start_threads(1) + # try sending two different signals to two threads + self.test_sequence.add_log_lines([ + "read packet: $vCont;C{0:x}:{1:x};C{2:x}:{3:x}#00".format( + lldbutil.get_signal_number('SIGUSR1'), threads[0], + lldbutil.get_signal_number('SIGUSR2'), threads[1]), + {"direction": "send", "regex": r"^\$E1e#db$"}, + ], True) + + context = self.expect_gdbremote_sequence() + self.assertIsNotNone(context) + + @skipUnlessPlatform(["netbsd"]) + @debugserver_test + def test_signal_two_signals_debugserver(self): + self.init_debugserver_test() + self.build() + self.set_inferior_startup_launch() + self.signal_two_signals() + + @skipUnlessPlatform(["netbsd"]) + @llgs_test + def test_signal_two_signals_llgs(self): + self.init_llgs_test() + self.build() + self.set_inferior_startup_launch() + self.signal_two_signals() 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 @@ -100,6 +100,7 @@ bool HasThreadNoLock(lldb::tid_t thread_id); NativeThreadNetBSD &AddThread(lldb::tid_t thread_id); + void RemoveThread(lldb::tid_t thread_id); void MonitorCallback(lldb::pid_t pid, int signal); void MonitorExited(lldb::pid_t pid, WaitStatus status); 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 @@ -9,7 +9,6 @@ #include "NativeProcessNetBSD.h" - #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "lldb/Host/HostProcess.h" #include "lldb/Host/common/NativeRegisterContext.h" @@ -99,6 +98,17 @@ pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), 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(); if (status.Fail()) return status.ToError(); @@ -211,17 +221,32 @@ return; } + NativeThreadNetBSD* thread = nullptr; + if (info.psi_lwpid > 0) { + for (const auto &t : m_threads) { + if (t->GetID() == static_cast(info.psi_lwpid)) { + thread = static_cast(t.get()); + break; + } + static_cast(t.get())->SetStoppedWithNoReason(); + } + if (!thread) + LLDB_LOG(log, + "thread not found in m_threads, pid = {0}, LWP = {1}", pid, + info.psi_lwpid); + } + switch (info.psi_siginfo.si_code) { case TRAP_BRKPT: - for (const auto &thread : m_threads) { - static_cast(*thread).SetStoppedByBreakpoint(); - FixupBreakpointPCAsNeeded(static_cast(*thread)); + if (thread) { + thread->SetStoppedByBreakpoint(); + FixupBreakpointPCAsNeeded(*thread); } SetState(StateType::eStateStopped, true); break; case TRAP_TRACE: - for (const auto &thread : m_threads) - static_cast(*thread).SetStoppedByTrace(); + if (thread) + thread->SetStoppedByTrace(); SetState(StateType::eStateStopped, true); break; case TRAP_EXEC: { @@ -238,54 +263,54 @@ static_cast(*thread).SetStoppedByExec(); SetState(StateType::eStateStopped, true); } break; - case TRAP_DBREG: { - // Find the thread. - NativeThreadNetBSD* thread = nullptr; - for (const auto &t : m_threads) { - if (t->GetID() == info.psi_lwpid) { - thread = static_cast(t.get()); + case TRAP_LWP: { + ptrace_state_t pst; + Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst)); + if (error.Fail()) { + SetState(StateType::eStateInvalid); + return; + } + + switch (pst.pe_report_event) { + case PTRACE_LWP_CREATE: + LLDB_LOG(log, + "monitoring new thread, pid = {0}, LWP = {1}", pid, + pst.pe_lwp); + AddThread(pst.pe_lwp); + break; + case PTRACE_LWP_EXIT: + LLDB_LOG(log, + "removing exited thread, pid = {0}, LWP = {1}", pid, + pst.pe_lwp); + RemoveThread(pst.pe_lwp); break; - } } - if (!thread) { - LLDB_LOG(log, - "thread not found in m_threads, pid = {0}, LWP = {1}", - GetID(), info.psi_lwpid); - break; + + error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast(1), 0); + if (error.Fail()) { + SetState(StateType::eStateInvalid); + return; } + } break; + case TRAP_DBREG: { + if (!thread) + break; - // If a watchpoint was hit, report it uint32_t wp_index = LLDB_INVALID_INDEX32; Status error = thread->GetRegisterContext().GetWatchpointHitIndex( wp_index, (uintptr_t)info.psi_siginfo.si_addr); if (error.Fail()) LLDB_LOG(log, "received error while checking for watchpoint hits, pid = " - "{0}, LWP = {1}, error = {2}", - GetID(), info.psi_lwpid, error); + "{0}, LWP = {1}, error = {2}", pid, info.psi_lwpid, error); if (wp_index != LLDB_INVALID_INDEX32) { - for (const auto &thread : m_threads) - static_cast(*thread).SetStoppedByWatchpoint( - wp_index); + thread->SetStoppedByWatchpoint(wp_index); SetState(StateType::eStateStopped, true); break; } - // If a breakpoint was hit, report it - uint32_t bp_index = LLDB_INVALID_INDEX32; - error = thread->GetRegisterContext().GetHardwareBreakHitIndex( - bp_index, (uintptr_t)info.psi_siginfo.si_addr); - if (error.Fail()) - LLDB_LOG(log, - "received error while checking for hardware " - "breakpoint hits, pid = {0}, LWP = {1}, error = {2}", - GetID(), info.psi_lwpid, error); - if (bp_index != LLDB_INVALID_INDEX32) { - for (const auto &thread : m_threads) - static_cast(*thread).SetStoppedByBreakpoint(); - SetState(StateType::eStateStopped, true); - break; - } + thread->SetStoppedByTrace(); + SetState(StateType::eStateStopped, true); } break; } } @@ -295,9 +320,14 @@ const auto siginfo_err = PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); - for (const auto &thread : m_threads) { - static_cast(*thread).SetStoppedBySignal( - info.psi_siginfo.si_signo, &info.psi_siginfo); + for (const auto &abs_thread : m_threads) { + NativeThreadNetBSD &thread = static_cast(*abs_thread); + assert(info.psi_lwpid >= 0); + if (info.psi_lwpid == 0 || + static_cast(info.psi_lwpid) == thread.GetID()) + thread.SetStoppedBySignal(info.psi_siginfo.si_signo, &info.psi_siginfo); + else + thread.SetStoppedWithNoReason(); } SetState(StateType::eStateStopped, true); } @@ -325,59 +355,133 @@ return error; } +static llvm::Expected ComputeSignalInfo( + const std::vector> &threads, + const ResumeActionList &resume_actions) { + // We need to account for three possible scenarios: + // 1. no signal being sent. + // 2. a signal being sent to one thread. + // 3. a signal being sent to the whole process. + + // Count signaled threads. While at it, determine which signal is being sent + // and ensure there's only one. + size_t signaled_threads = 0; + int signal = LLDB_INVALID_SIGNAL_NUMBER; + lldb::tid_t signaled_lwp; + for (const auto &thread : threads) { + assert(thread && "thread list should not contain NULL threads"); + const ResumeAction *action = + resume_actions.GetActionForThread(thread->GetID(), true); + if (action) { + if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) { + signaled_threads++; + if (action->signal != signal) { + if (signal != LLDB_INVALID_SIGNAL_NUMBER) + return Status("NetBSD does not support passing multiple signals " + "simultaneously") + .ToError(); + signal = action->signal; + signaled_lwp = thread->GetID(); + } + } + } + } + + if (signaled_threads == 0) { + ptrace_siginfo_t siginfo; + siginfo.psi_siginfo.si_signo = LLDB_INVALID_SIGNAL_NUMBER; + return siginfo; + } + + if (signaled_threads > 1 && signaled_threads < threads.size()) + return Status("NetBSD does not support passing signal to 1GetID(), true); + Status ret; - if (action == nullptr) { - LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), - thread->GetID()); - return Status(); - } + Expected siginfo = + ComputeSignalInfo(m_threads, resume_actions); + if (!siginfo) + return Status(siginfo.takeError()); - Status error; - int signal = - action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0; - - switch (action->state) { - case eStateRunning: { - // Run the thread, possibly feeding it the signal. - error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1, - signal); - if (!error.Success()) - return error; - for (const auto &thread : m_threads) - static_cast(*thread).SetRunning(); - SetState(eStateRunning, true); - break; - } - case eStateStepping: - // Run the thread, possibly feeding it the signal. - error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1, - signal); - if (!error.Success()) - return error; - for (const auto &thread : m_threads) - static_cast(*thread).SetStepping(); - SetState(eStateStepping, true); - break; + for (const auto &abs_thread : m_threads) { + assert(abs_thread && "thread list should not contain NULL threads"); + NativeThreadNetBSD &thread = static_cast(*abs_thread); - case eStateSuspended: - case eStateStopped: - llvm_unreachable("Unexpected state"); + const ResumeAction *action = + resume_actions.GetActionForThread(thread.GetID(), true); + // we need to explicit issue suspend requests, so it is simpler to map it + // into proper action + ResumeAction suspend_action{thread.GetID(), eStateSuspended, + LLDB_INVALID_SIGNAL_NUMBER}; - default: - return Status("NativeProcessNetBSD::%s (): unexpected state %s specified " - "for pid %" PRIu64 ", tid %" PRIu64, - __FUNCTION__, StateAsCString(action->state), GetID(), - thread->GetID()); + if (action == nullptr) { + LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), + thread.GetID()); + action = &suspend_action; + } + + LLDB_LOG( + log, + "processing resume action state {0} signal {1} for pid {2} tid {3}", + action->state, action->signal, GetID(), thread.GetID()); + + switch (action->state) { + case eStateRunning: + ret = thread.Resume(); + break; + case eStateStepping: + ret = thread.SingleStep(); + break; + case eStateSuspended: + case eStateStopped: + if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) + return Status("Passing signal to suspended thread unsupported"); + + ret = thread.Suspend(); + break; + + default: + return Status("NativeProcessNetBSD::%s (): unexpected state %s specified " + "for pid %" PRIu64 ", tid %" PRIu64, + __FUNCTION__, StateAsCString(action->state), GetID(), + thread.GetID()); + } + + if (!ret.Success()) + return ret; } - return Status(); + int signal = 0; + if (siginfo->psi_siginfo.si_signo != LLDB_INVALID_SIGNAL_NUMBER) { + ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo.get(), + sizeof(*siginfo)); + if (!ret.Success()) + return ret; + signal = siginfo->psi_siginfo.si_signo; + } + + ret = PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast(1), + signal); + if (ret.Success()) + SetState(eStateRunning, true); + return ret; } Status NativeProcessNetBSD::Halt() { @@ -649,10 +753,10 @@ } NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); + assert(thread_id > 0); assert(!HasThreadNoLock(thread_id) && "attempted to add a thread by id that already exists"); @@ -664,6 +768,22 @@ return static_cast(*m_threads.back()); } +void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id); + + assert(thread_id > 0); + assert(HasThreadNoLock(thread_id) && + "attempted to remove a thread that does not exist"); + + for (auto it = m_threads.begin(); it != m_threads.end(); ++it) { + if ((*it)->GetID() == thread_id) { + m_threads.erase(it); + break; + } + } +} + Status NativeProcessNetBSD::Attach() { // Attach to the requested process. // An attach will cause the thread to stop with a SIGSTOP. 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 @@ -48,11 +48,16 @@ private: // Interface for friend classes + Status Resume(); + Status SingleStep(); + Status Suspend(); + void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr); void SetStoppedByBreakpoint(); void SetStoppedByTrace(); void SetStoppedByExec(); void SetStoppedByWatchpoint(uint32_t wp_index); + void SetStoppedWithNoReason(); void SetStopped(); void SetRunning(); void SetStepping(); 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 @@ -18,6 +18,11 @@ #include "lldb/Utility/State.h" #include "llvm/Support/Errno.h" +// clang-format off +#include +#include +// clang-format on + #include // clang-format off @@ -36,6 +41,38 @@ NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this) ), m_stop_description() {} +Status NativeThreadNetBSD::Resume() { + Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(), + nullptr, GetID()); + if (!ret.Success()) + return ret; + ret = NativeProcessNetBSD::PtraceWrapper(PT_CLEARSTEP, m_process.GetID(), + nullptr, GetID()); + if (ret.Success()) + SetRunning(); + return ret; +} + +Status NativeThreadNetBSD::SingleStep() { + Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(), + nullptr, GetID()); + if (!ret.Success()) + return ret; + ret = NativeProcessNetBSD::PtraceWrapper(PT_SETSTEP, m_process.GetID(), + nullptr, GetID()); + if (ret.Success()) + SetStepping(); + return ret; +} + +Status NativeThreadNetBSD::Suspend() { + Status ret = NativeProcessNetBSD::PtraceWrapper(PT_SUSPEND, m_process.GetID(), + nullptr, GetID()); + if (ret.Success()) + SetStopped(); + return ret; +} + void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo, const siginfo_t *info) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); @@ -95,6 +132,13 @@ m_stop_info.details.signal.signo = SIGTRAP; } +void NativeThreadNetBSD::SetStoppedWithNoReason() { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonNone; + m_stop_info.details.signal.signo = 0; +} + void NativeThreadNetBSD::SetStopped() { const StateType new_state = StateType::eStateStopped; m_state = new_state;