xref: /llvm-project/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py (revision d327108d175fc5d1d4f5c018d129e337d162810c)
1"""
2Test python scripted process in lldb
3"""
4
5import os
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11from lldbsuite.test import lldbtest
12
13class ScriptedProcesTestCase(TestBase):
14
15    NO_DEBUG_INFO_TESTCASE = True
16
17    mydir = TestBase.compute_mydir(__file__)
18
19    def setUp(self):
20        TestBase.setUp(self)
21
22    def tearDown(self):
23        TestBase.tearDown(self)
24
25    def test_python_plugin_package(self):
26        """Test that the lldb python module has a `plugins.scripted_process`
27        package."""
28        self.expect('script import lldb.plugins',
29                    substrs=["ModuleNotFoundError"], matching=False)
30
31        self.expect('script dir(lldb.plugins)',
32                    substrs=["scripted_process"])
33
34        self.expect('script import lldb.plugins.scripted_process',
35                    substrs=["ModuleNotFoundError"], matching=False)
36
37        self.expect('script dir(lldb.plugins.scripted_process)',
38                    substrs=["ScriptedProcess"])
39
40        self.expect('script from lldb.plugins.scripted_process import ScriptedProcess',
41                    substrs=["ImportError"], matching=False)
42
43        self.expect('script dir(ScriptedProcess)',
44                    substrs=["launch"])
45
46    @skipUnlessDarwin
47    def test_invalid_scripted_register_context(self):
48        """Test that we can launch an lldb scripted process with an invalid
49        Scripted Thread, with invalid register context."""
50        self.build()
51        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
52        self.assertTrue(target, VALID_TARGET)
53        log_file = self.getBuildArtifact('thread.log')
54        self.runCmd("log enable lldb thread -f " + log_file)
55        self.assertTrue(os.path.isfile(log_file))
56
57        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
58        def cleanup():
59          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
60        self.addTearDownHook(cleanup)
61
62        scripted_process_example_relpath = 'invalid_scripted_process.py'
63        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
64                                                            scripted_process_example_relpath))
65
66        launch_info = lldb.SBLaunchInfo(None)
67        launch_info.SetProcessPluginName("ScriptedProcess")
68        launch_info.SetScriptedProcessClassName("invalid_scripted_process.InvalidScriptedProcess")
69        error = lldb.SBError()
70
71        process = target.Launch(launch_info, error)
72
73        self.assertTrue(error.Success(), error.GetCString())
74        self.assertTrue(process, PROCESS_IS_VALID)
75        self.assertEqual(process.GetProcessID(), 666)
76        self.assertEqual(process.GetNumThreads(), 0)
77
78        with open(log_file, 'r') as f:
79            log = f.read()
80
81        self.assertIn("Failed to get scripted thread registers data.", log)
82
83    @skipIf(archs=no_match(['x86_64', 'arm64', 'arm64e']))
84    def test_scripted_process_and_scripted_thread(self):
85        """Test that we can launch an lldb scripted process using the SBAPI,
86        check its process ID, read string from memory, check scripted thread
87        id, name stop reason and register context.
88        """
89        self.build()
90        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
91        self.assertTrue(target, VALID_TARGET)
92
93        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
94        def cleanup():
95          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
96        self.addTearDownHook(cleanup)
97
98        scripted_process_example_relpath = 'dummy_scripted_process.py'
99        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
100                                                            scripted_process_example_relpath))
101
102        launch_info = lldb.SBLaunchInfo(None)
103        launch_info.SetProcessPluginName("ScriptedProcess")
104        launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess")
105
106        error = lldb.SBError()
107        process = target.Launch(launch_info, error)
108        self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
109        self.assertEqual(process.GetProcessID(), 42)
110
111        self.assertEqual(process.GetNumThreads(), 1)
112
113        thread = process.GetSelectedThread()
114        self.assertTrue(thread, "Invalid thread.")
115        self.assertEqual(thread.GetThreadID(), 0x19)
116        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")
117        self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
118
119        self.assertGreater(thread.GetNumFrames(), 0)
120
121        frame = thread.GetFrameAtIndex(0)
122        GPRs = None
123        register_set = frame.registers # Returns an SBValueList.
124        for regs in register_set:
125            if 'general purpose' in regs.name.lower():
126                GPRs = regs
127                break
128
129        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")
130        self.assertGreater(GPRs.GetNumChildren(), 0)
131        for idx, reg in enumerate(GPRs, start=1):
132            if idx > 21:
133                break
134            self.assertEqual(idx, int(reg.value, 16))
135
136