xref: /llvm-project/lldb/test/API/commands/process/attach/TestProcessAttach.py (revision 096c530ab3ea5c96526451181117f30db17b4b1d)
1"""
2Test process attach.
3"""
4
5
6import os
7import lldb
8import shutil
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13exe_name = "ProcessAttach"  # Must match Makefile
14
15
16class ProcessAttachTestCase(TestBase):
17    NO_DEBUG_INFO_TESTCASE = True
18
19    def setUp(self):
20        # Call super's setUp().
21        TestBase.setUp(self)
22        # Find the line number to break for main.c.
23        self.line = line_number("main.cpp", "// Waiting to be attached...")
24
25    @skipIfiOSSimulator
26    def test_attach_to_process_by_id(self):
27        """Test attach by process id"""
28        self.build()
29        exe = self.getBuildArtifact(exe_name)
30
31        # Spawn a new process
32        popen = self.spawnSubprocess(exe)
33
34        self.runCmd("process attach -p " + str(popen.pid))
35
36        target = self.dbg.GetSelectedTarget()
37
38        process = target.GetProcess()
39        self.assertTrue(process, PROCESS_IS_VALID)
40
41    @skipIfiOSSimulator
42    def test_attach_to_process_by_id_autocontinue(self):
43        """Test attach by process id"""
44        self.build()
45        exe = self.getBuildArtifact(exe_name)
46
47        # Spawn a new process
48        popen = self.spawnSubprocess(exe)
49
50        self.runCmd("process attach -c -p " + str(popen.pid))
51
52        target = self.dbg.GetSelectedTarget()
53
54        process = target.GetProcess()
55        self.assertTrue(process, PROCESS_IS_VALID)
56        self.assertTrue(process.GetState(), lldb.eStateRunning)
57
58    @skipIfWindows  # This is flakey on Windows AND when it fails, it hangs: llvm.org/pr48806
59    def test_attach_to_process_from_different_dir_by_id(self):
60        """Test attach by process id"""
61        newdir = self.getBuildArtifact("newdir")
62        try:
63            os.mkdir(newdir)
64        except OSError as e:
65            if e.errno != os.errno.EEXIST:
66                raise
67        testdir = self.getBuildDir()
68        exe = os.path.join(newdir, "proc_attach")
69        self.buildProgram("main.cpp", exe)
70        self.addTearDownHook(lambda: shutil.rmtree(newdir))
71
72        # Spawn a new process
73        popen = self.spawnSubprocess(exe)
74
75        os.chdir(newdir)
76        sourcedir = self.getSourceDir()
77        self.addTearDownHook(lambda: os.chdir(sourcedir))
78        self.runCmd("process attach -p " + str(popen.pid))
79
80        target = self.dbg.GetSelectedTarget()
81
82        process = target.GetProcess()
83        self.assertTrue(process, PROCESS_IS_VALID)
84
85    def test_attach_to_process_by_name(self):
86        """Test attach by process name"""
87        self.build()
88        exe = self.getBuildArtifact(exe_name)
89
90        # Spawn a new process
91        popen = self.spawnSubprocess(exe)
92
93        self.runCmd("process attach -n " + exe_name)
94
95        target = self.dbg.GetSelectedTarget()
96
97        process = target.GetProcess()
98        self.assertTrue(process, PROCESS_IS_VALID)
99
100    @skipIfWindows  # This test is flaky on Windows
101    @expectedFailureNetBSD
102    def test_attach_to_process_by_id_correct_executable_offset(self):
103        """
104        Test that after attaching to a process the executable offset
105        is determined correctly on FreeBSD.  This is a regression test
106        for dyld plugin getting the correct executable path,
107        and therefore being able to identify it in the module list.
108        """
109
110        self.build()
111        exe = self.getBuildArtifact(exe_name)
112
113        # In order to reproduce, we must spawn using a relative path
114        popen = self.spawnSubprocess(os.path.relpath(exe))
115
116        self.runCmd("process attach -p " + str(popen.pid))
117
118        # Make sure we did not attach too early.
119        lldbutil.run_break_set_by_file_and_line(
120            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False
121        )
122        self.runCmd("process continue")
123        self.expect("v g_val", substrs=["12345"])
124
125    def tearDown(self):
126        # Destroy process before TestBase.tearDown()
127        self.dbg.GetSelectedTarget().GetProcess().Destroy()
128
129        # Call super's tearDown().
130        TestBase.tearDown(self)
131