| """ | |
| Test process attach. | |
| """ | |
| import os | |
| import lldb | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test import lldbutil | |
| exe_name = "ProcessAttach" # Must match Makefile | |
| @requireNotWasm("attaching requires launching the inferior as a host process") | |
| class ProcessAttachTestCase(TestBase): | |
| SHARED_BUILD_TESTCASE = False | |
| NO_DEBUG_INFO_TESTCASE = True | |
| def setUp(self): | |
| # Call super's setUp(). | |
| TestBase.setUp(self) | |
| # Find the line number to break for main.c. | |
| self.line = line_number("main.cpp", "// Waiting to be attached...") | |
| @skipIfiOSSimulator | |
| def test_attach_to_process_by_id(self): | |
| """Test attach by process id""" | |
| self.build() | |
| exe = self.getBuildArtifact(exe_name) | |
| # Spawn a new process | |
| popen = self.spawnSubprocess(exe) | |
| self.runCmd("process attach -p " + str(popen.pid)) | |
| target = self.dbg.GetSelectedTarget() | |
| process = target.GetProcess() | |
| self.assertTrue(process, PROCESS_IS_VALID) | |
| @skipIfiOSSimulator | |
| def test_attach_to_process_by_id_autocontinue(self): | |
| """Test attach by process id""" | |
| self.build() | |
| exe = self.getBuildArtifact(exe_name) | |
| # Spawn a new process | |
| popen = self.spawnSubprocess(exe) | |
| # Don't wait for the continue to finish. | |
| self.setAsync(True) | |
| self.runCmd("process attach -c -p " + str(popen.pid)) | |
| target = self.dbg.GetSelectedTarget() | |
| # Start listening to process events. | |
| process = target.GetProcess() | |
| self.assertTrue(process, PROCESS_IS_VALID) | |
| broadcaster = process.GetBroadcaster() | |
| listener = self.dbg.GetListener() | |
| state = process.GetState() | |
| self.assertEqual( | |
| state, lldb.eStateStopped, "The attach stopped before continuing" | |
| ) | |
| # Listen for events until we see the process continue. | |
| event = lldb.SBEvent() | |
| got_running = False | |
| got_event = False | |
| timeout = 180 | |
| while listener.WaitForEventForBroadcaster(timeout, broadcaster, event): | |
| state = process.GetState() | |
| got_event = True | |
| if state == lldb.eStateRunning: | |
| got_running = True | |
| break | |
| self.assertTrue(got_event, "Didn't receive any events after attaching") | |
| self.assertTrue(got_running, "Process didn't auto-continue") | |
| def test_attach_to_process_from_different_dir_by_id(self): | |
| """Test attach by process id""" | |
| newdir = self.getBuildArtifact("newdir") | |
| os.makedirs(newdir, exist_ok=True) | |
| testdir = self.getBuildDir() | |
| exe = os.path.join(newdir, "proc_attach") | |
| self.buildProgram("main.cpp", exe) | |
| # Spawn a new process | |
| popen = self.spawnSubprocess(exe) | |
| os.chdir(newdir) | |
| sourcedir = self.getSourceDir() | |
| self.addTearDownHook(lambda: os.chdir(sourcedir)) | |
| self.runCmd("process attach -p " + str(popen.pid)) | |
| target = self.dbg.GetSelectedTarget() | |
| process = target.GetProcess() | |
| self.assertTrue(process, PROCESS_IS_VALID) | |
| def test_attach_to_process_by_name(self): | |
| """Test attach by process name""" | |
| self.build() | |
| exe = self.getBuildArtifact(exe_name) | |
| # Spawn a new process | |
| popen = self.spawnSubprocess(exe) | |
| self.runCmd("process attach -n " + exe_name) | |
| target = self.dbg.GetSelectedTarget() | |
| process = target.GetProcess() | |
| self.assertTrue(process, PROCESS_IS_VALID) | |
| @expectedFailureNetBSD | |
| def test_attach_to_process_by_id_correct_executable_offset(self): | |
| """ | |
| Test that after attaching to a process the executable offset | |
| is determined correctly on FreeBSD. This is a regression test | |
| for dyld plugin getting the correct executable path, | |
| and therefore being able to identify it in the module list. | |
| """ | |
| self.build() | |
| exe = self.getBuildArtifact(exe_name) | |
| # In order to reproduce, we must spawn using a relative path. | |
| os.chdir(self.getBuildDir()) | |
| sourcedir = self.getSourceDir() | |
| self.addTearDownHook(lambda: os.chdir(sourcedir)) | |
| popen = self.spawnSubprocess(os.path.join(os.curdir, os.path.basename(exe))) | |
| self.runCmd("process attach -p " + str(popen.pid)) | |
| # Make sure we did not attach too early. | |
| lldbutil.run_break_set_by_file_and_line( | |
| self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False | |
| ) | |
| self.runCmd("process continue") | |
| self.expect("v g_val", substrs=["12345"]) |