1f3176f5fSMed Ismail Bennani"""
2f3176f5fSMed Ismail BennaniTest python scripted process in lldb
3f3176f5fSMed Ismail Bennani"""
4f3176f5fSMed Ismail Bennani
5*d327108dSMed Ismail Bennaniimport os
6f3176f5fSMed Ismail Bennani
7f3176f5fSMed Ismail Bennaniimport lldb
8f3176f5fSMed Ismail Bennanifrom lldbsuite.test.decorators import *
9f3176f5fSMed Ismail Bennanifrom lldbsuite.test.lldbtest import *
10f3176f5fSMed Ismail Bennanifrom lldbsuite.test import lldbutil
11f3176f5fSMed Ismail Bennanifrom lldbsuite.test import lldbtest
12f3176f5fSMed Ismail Bennani
13312b43daSMed Ismail Bennaniclass ScriptedProcesTestCase(TestBase):
14f3176f5fSMed Ismail Bennani
15*d327108dSMed Ismail Bennani    NO_DEBUG_INFO_TESTCASE = True
16*d327108dSMed Ismail Bennani
17f3176f5fSMed Ismail Bennani    mydir = TestBase.compute_mydir(__file__)
18f3176f5fSMed Ismail Bennani
19f3176f5fSMed Ismail Bennani    def setUp(self):
20f3176f5fSMed Ismail Bennani        TestBase.setUp(self)
21f3176f5fSMed Ismail Bennani
22f3176f5fSMed Ismail Bennani    def tearDown(self):
23f3176f5fSMed Ismail Bennani        TestBase.tearDown(self)
24f3176f5fSMed Ismail Bennani
25f3176f5fSMed Ismail Bennani    def test_python_plugin_package(self):
26f3176f5fSMed Ismail Bennani        """Test that the lldb python module has a `plugins.scripted_process`
27f3176f5fSMed Ismail Bennani        package."""
28f3176f5fSMed Ismail Bennani        self.expect('script import lldb.plugins',
29f3176f5fSMed Ismail Bennani                    substrs=["ModuleNotFoundError"], matching=False)
30f3176f5fSMed Ismail Bennani
31f3176f5fSMed Ismail Bennani        self.expect('script dir(lldb.plugins)',
32f3176f5fSMed Ismail Bennani                    substrs=["scripted_process"])
33f3176f5fSMed Ismail Bennani
34f3176f5fSMed Ismail Bennani        self.expect('script import lldb.plugins.scripted_process',
35f3176f5fSMed Ismail Bennani                    substrs=["ModuleNotFoundError"], matching=False)
36f3176f5fSMed Ismail Bennani
37f3176f5fSMed Ismail Bennani        self.expect('script dir(lldb.plugins.scripted_process)',
38f3176f5fSMed Ismail Bennani                    substrs=["ScriptedProcess"])
39f3176f5fSMed Ismail Bennani
40f3176f5fSMed Ismail Bennani        self.expect('script from lldb.plugins.scripted_process import ScriptedProcess',
41f3176f5fSMed Ismail Bennani                    substrs=["ImportError"], matching=False)
42f3176f5fSMed Ismail Bennani
43f3176f5fSMed Ismail Bennani        self.expect('script dir(ScriptedProcess)',
44f3176f5fSMed Ismail Bennani                    substrs=["launch"])
45f3176f5fSMed Ismail Bennani
46c3ca2c6bSMed Ismail Bennani    @skipUnlessDarwin
47caea440aSMed Ismail Bennani    def test_invalid_scripted_register_context(self):
48caea440aSMed Ismail Bennani        """Test that we can launch an lldb scripted process with an invalid
49caea440aSMed Ismail Bennani        Scripted Thread, with invalid register context."""
50caea440aSMed Ismail Bennani        self.build()
51caea440aSMed Ismail Bennani        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
52caea440aSMed Ismail Bennani        self.assertTrue(target, VALID_TARGET)
539c144b3bSMed Ismail Bennani        log_file = self.getBuildArtifact('thread.log')
549c144b3bSMed Ismail Bennani        self.runCmd("log enable lldb thread -f " + log_file)
559c144b3bSMed Ismail Bennani        self.assertTrue(os.path.isfile(log_file))
56caea440aSMed Ismail Bennani
57caea440aSMed Ismail Bennani        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
58a6b56243SMed Ismail Bennani        def cleanup():
59a6b56243SMed Ismail Bennani          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
60a6b56243SMed Ismail Bennani        self.addTearDownHook(cleanup)
61a6b56243SMed Ismail Bennani
62caea440aSMed Ismail Bennani        scripted_process_example_relpath = 'invalid_scripted_process.py'
63caea440aSMed Ismail Bennani        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
64caea440aSMed Ismail Bennani                                                            scripted_process_example_relpath))
65caea440aSMed Ismail Bennani
66caea440aSMed Ismail Bennani        launch_info = lldb.SBLaunchInfo(None)
67caea440aSMed Ismail Bennani        launch_info.SetProcessPluginName("ScriptedProcess")
68caea440aSMed Ismail Bennani        launch_info.SetScriptedProcessClassName("invalid_scripted_process.InvalidScriptedProcess")
69caea440aSMed Ismail Bennani        error = lldb.SBError()
709c144b3bSMed Ismail Bennani
71caea440aSMed Ismail Bennani        process = target.Launch(launch_info, error)
72caea440aSMed Ismail Bennani
73caea440aSMed Ismail Bennani        self.assertTrue(error.Success(), error.GetCString())
74caea440aSMed Ismail Bennani        self.assertTrue(process, PROCESS_IS_VALID)
75caea440aSMed Ismail Bennani        self.assertEqual(process.GetProcessID(), 666)
76caea440aSMed Ismail Bennani        self.assertEqual(process.GetNumThreads(), 0)
77caea440aSMed Ismail Bennani
789c144b3bSMed Ismail Bennani        with open(log_file, 'r') as f:
799c144b3bSMed Ismail Bennani            log = f.read()
809c144b3bSMed Ismail Bennani
819c144b3bSMed Ismail Bennani        self.assertIn("Failed to get scripted thread registers data.", log)
82caea440aSMed Ismail Bennani
83c3ca2c6bSMed Ismail Bennani    @skipIf(archs=no_match(['x86_64', 'arm64', 'arm64e']))
84a758c9f7SMed Ismail Bennani    def test_scripted_process_and_scripted_thread(self):
85312b43daSMed Ismail Bennani        """Test that we can launch an lldb scripted process using the SBAPI,
86a758c9f7SMed Ismail Bennani        check its process ID, read string from memory, check scripted thread
87a758c9f7SMed Ismail Bennani        id, name stop reason and register context.
88a758c9f7SMed Ismail Bennani        """
89312b43daSMed Ismail Bennani        self.build()
90312b43daSMed Ismail Bennani        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
91312b43daSMed Ismail Bennani        self.assertTrue(target, VALID_TARGET)
92312b43daSMed Ismail Bennani
93312b43daSMed Ismail Bennani        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
94a6b56243SMed Ismail Bennani        def cleanup():
95a6b56243SMed Ismail Bennani          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
96a6b56243SMed Ismail Bennani        self.addTearDownHook(cleanup)
97a6b56243SMed Ismail Bennani
98419b4711SMed Ismail Bennani        scripted_process_example_relpath = 'dummy_scripted_process.py'
99312b43daSMed Ismail Bennani        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
100a758c9f7SMed Ismail Bennani                                                            scripted_process_example_relpath))
101312b43daSMed Ismail Bennani
102312b43daSMed Ismail Bennani        launch_info = lldb.SBLaunchInfo(None)
103312b43daSMed Ismail Bennani        launch_info.SetProcessPluginName("ScriptedProcess")
104a758c9f7SMed Ismail Bennani        launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess")
105312b43daSMed Ismail Bennani
106312b43daSMed Ismail Bennani        error = lldb.SBError()
107312b43daSMed Ismail Bennani        process = target.Launch(launch_info, error)
108312b43daSMed Ismail Bennani        self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
109312b43daSMed Ismail Bennani        self.assertEqual(process.GetProcessID(), 42)
110312b43daSMed Ismail Bennani
11159d8dd79SMed Ismail Bennani        self.assertEqual(process.GetNumThreads(), 1)
11259d8dd79SMed Ismail Bennani
11359d8dd79SMed Ismail Bennani        thread = process.GetSelectedThread()
11459d8dd79SMed Ismail Bennani        self.assertTrue(thread, "Invalid thread.")
11559d8dd79SMed Ismail Bennani        self.assertEqual(thread.GetThreadID(), 0x19)
116a758c9f7SMed Ismail Bennani        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")
11759d8dd79SMed Ismail Bennani        self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
11859d8dd79SMed Ismail Bennani
11959d8dd79SMed Ismail Bennani        self.assertGreater(thread.GetNumFrames(), 0)
12059d8dd79SMed Ismail Bennani
12159d8dd79SMed Ismail Bennani        frame = thread.GetFrameAtIndex(0)
122976867b5SMed Ismail Bennani        GPRs = None
12359d8dd79SMed Ismail Bennani        register_set = frame.registers # Returns an SBValueList.
12459d8dd79SMed Ismail Bennani        for regs in register_set:
125976867b5SMed Ismail Bennani            if 'general purpose' in regs.name.lower():
126976867b5SMed Ismail Bennani                GPRs = regs
12759d8dd79SMed Ismail Bennani                break
12859d8dd79SMed Ismail Bennani
129976867b5SMed Ismail Bennani        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")
130c3ca2c6bSMed Ismail Bennani        self.assertGreater(GPRs.GetNumChildren(), 0)
131976867b5SMed Ismail Bennani        for idx, reg in enumerate(GPRs, start=1):
132c3ca2c6bSMed Ismail Bennani            if idx > 21:
133c3ca2c6bSMed Ismail Bennani                break
13459d8dd79SMed Ismail Bennani            self.assertEqual(idx, int(reg.value, 16))
13559d8dd79SMed Ismail Bennani
136