1f3176f5fSMed Ismail Bennani"""
2f3176f5fSMed Ismail BennaniTest python scripted process in lldb
3f3176f5fSMed Ismail Bennani"""
4f3176f5fSMed Ismail Bennani
5*6aa48034SMed Ismail Bennaniimport os, shutil
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
15d327108dSMed Ismail Bennani    NO_DEBUG_INFO_TESTCASE = True
16d327108dSMed 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
46*6aa48034SMed Ismail Bennani    def move_blueprint_to_dsym(self, blueprint_name):
47*6aa48034SMed Ismail Bennani        blueprint_origin_path = os.path.join(self.getSourceDir(), blueprint_name)
48*6aa48034SMed Ismail Bennani        dsym_bundle = self.getBuildArtifact("a.out.dSYM")
49*6aa48034SMed Ismail Bennani        blueprint_destination_path = os.path.join(dsym_bundle, "Contents",
50*6aa48034SMed Ismail Bennani                                                  "Resources", "Python")
51*6aa48034SMed Ismail Bennani        if not os.path.exists(blueprint_destination_path):
52*6aa48034SMed Ismail Bennani            os.mkdir(blueprint_destination_path)
53*6aa48034SMed Ismail Bennani
54*6aa48034SMed Ismail Bennani        blueprint_destination_path = os.path.join(blueprint_destination_path, "a_out.py")
55*6aa48034SMed Ismail Bennani        shutil.copy(blueprint_origin_path, blueprint_destination_path)
56*6aa48034SMed Ismail Bennani
57c3ca2c6bSMed Ismail Bennani    @skipUnlessDarwin
58caea440aSMed Ismail Bennani    def test_invalid_scripted_register_context(self):
59caea440aSMed Ismail Bennani        """Test that we can launch an lldb scripted process with an invalid
60caea440aSMed Ismail Bennani        Scripted Thread, with invalid register context."""
61caea440aSMed Ismail Bennani        self.build()
62caea440aSMed Ismail Bennani
63caea440aSMed Ismail Bennani        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
64a6b56243SMed Ismail Bennani        def cleanup():
65a6b56243SMed Ismail Bennani          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
66a6b56243SMed Ismail Bennani        self.addTearDownHook(cleanup)
67a6b56243SMed Ismail Bennani
68*6aa48034SMed Ismail Bennani        self.runCmd("settings set target.load-script-from-symbol-file true")
69*6aa48034SMed Ismail Bennani        self.move_blueprint_to_dsym('invalid_scripted_process.py')
70*6aa48034SMed Ismail Bennani        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
71*6aa48034SMed Ismail Bennani        self.assertTrue(target, VALID_TARGET)
72*6aa48034SMed Ismail Bennani        log_file = self.getBuildArtifact('thread.log')
73*6aa48034SMed Ismail Bennani        self.runCmd("log enable lldb thread -f " + log_file)
74*6aa48034SMed Ismail Bennani        self.assertTrue(os.path.isfile(log_file))
75caea440aSMed Ismail Bennani
76caea440aSMed Ismail Bennani        launch_info = lldb.SBLaunchInfo(None)
77caea440aSMed Ismail Bennani        launch_info.SetProcessPluginName("ScriptedProcess")
78*6aa48034SMed Ismail Bennani        launch_info.SetScriptedProcessClassName("a_out.InvalidScriptedProcess")
79caea440aSMed Ismail Bennani        error = lldb.SBError()
809c144b3bSMed Ismail Bennani
81caea440aSMed Ismail Bennani        process = target.Launch(launch_info, error)
82caea440aSMed Ismail Bennani
83779bbbf2SDave Lee        self.assertSuccess(error)
84caea440aSMed Ismail Bennani        self.assertTrue(process, PROCESS_IS_VALID)
85caea440aSMed Ismail Bennani        self.assertEqual(process.GetProcessID(), 666)
86caea440aSMed Ismail Bennani        self.assertEqual(process.GetNumThreads(), 0)
87caea440aSMed Ismail Bennani
889c144b3bSMed Ismail Bennani        with open(log_file, 'r') as f:
899c144b3bSMed Ismail Bennani            log = f.read()
909c144b3bSMed Ismail Bennani
919c144b3bSMed Ismail Bennani        self.assertIn("Failed to get scripted thread registers data.", log)
92caea440aSMed Ismail Bennani
9386e6030eSMed Ismail Bennani    @skipUnlessDarwin
94a758c9f7SMed Ismail Bennani    def test_scripted_process_and_scripted_thread(self):
95312b43daSMed Ismail Bennani        """Test that we can launch an lldb scripted process using the SBAPI,
96a758c9f7SMed Ismail Bennani        check its process ID, read string from memory, check scripted thread
97a758c9f7SMed Ismail Bennani        id, name stop reason and register context.
98a758c9f7SMed Ismail Bennani        """
99312b43daSMed Ismail Bennani        self.build()
100312b43daSMed Ismail Bennani        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
101312b43daSMed Ismail Bennani        self.assertTrue(target, VALID_TARGET)
102312b43daSMed Ismail Bennani
103312b43daSMed Ismail Bennani        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
104a6b56243SMed Ismail Bennani        def cleanup():
105a6b56243SMed Ismail Bennani          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
106a6b56243SMed Ismail Bennani        self.addTearDownHook(cleanup)
107a6b56243SMed Ismail Bennani
108419b4711SMed Ismail Bennani        scripted_process_example_relpath = 'dummy_scripted_process.py'
109312b43daSMed Ismail Bennani        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
110a758c9f7SMed Ismail Bennani                                                            scripted_process_example_relpath))
111312b43daSMed Ismail Bennani
112312b43daSMed Ismail Bennani        launch_info = lldb.SBLaunchInfo(None)
113312b43daSMed Ismail Bennani        launch_info.SetProcessPluginName("ScriptedProcess")
114a758c9f7SMed Ismail Bennani        launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess")
115312b43daSMed Ismail Bennani
116312b43daSMed Ismail Bennani        error = lldb.SBError()
117312b43daSMed Ismail Bennani        process = target.Launch(launch_info, error)
118312b43daSMed Ismail Bennani        self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
119312b43daSMed Ismail Bennani        self.assertEqual(process.GetProcessID(), 42)
120312b43daSMed Ismail Bennani
12159d8dd79SMed Ismail Bennani        self.assertEqual(process.GetNumThreads(), 1)
12259d8dd79SMed Ismail Bennani
12359d8dd79SMed Ismail Bennani        thread = process.GetSelectedThread()
12459d8dd79SMed Ismail Bennani        self.assertTrue(thread, "Invalid thread.")
12559d8dd79SMed Ismail Bennani        self.assertEqual(thread.GetThreadID(), 0x19)
126a758c9f7SMed Ismail Bennani        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")
12759d8dd79SMed Ismail Bennani        self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
12859d8dd79SMed Ismail Bennani
12959d8dd79SMed Ismail Bennani        self.assertGreater(thread.GetNumFrames(), 0)
13059d8dd79SMed Ismail Bennani
13159d8dd79SMed Ismail Bennani        frame = thread.GetFrameAtIndex(0)
132976867b5SMed Ismail Bennani        GPRs = None
13359d8dd79SMed Ismail Bennani        register_set = frame.registers # Returns an SBValueList.
13459d8dd79SMed Ismail Bennani        for regs in register_set:
135976867b5SMed Ismail Bennani            if 'general purpose' in regs.name.lower():
136976867b5SMed Ismail Bennani                GPRs = regs
13759d8dd79SMed Ismail Bennani                break
13859d8dd79SMed Ismail Bennani
139976867b5SMed Ismail Bennani        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")
140c3ca2c6bSMed Ismail Bennani        self.assertGreater(GPRs.GetNumChildren(), 0)
141976867b5SMed Ismail Bennani        for idx, reg in enumerate(GPRs, start=1):
142c3ca2c6bSMed Ismail Bennani            if idx > 21:
143c3ca2c6bSMed Ismail Bennani                break
14459d8dd79SMed Ismail Bennani            self.assertEqual(idx, int(reg.value, 16))
14559d8dd79SMed Ismail Bennani
14670665844SMed Ismail Bennani        self.assertTrue(frame.IsArtificial(), "Frame is not artificial")
14770665844SMed Ismail Bennani        pc = frame.GetPCAddress().GetLoadAddress(target)
14870665844SMed Ismail Bennani        self.assertEqual(pc, 0x0100001b00)
149