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    def setUp(self):
18f3176f5fSMed Ismail Bennani        TestBase.setUp(self)
19f3176f5fSMed Ismail Bennani
20f3176f5fSMed Ismail Bennani    def tearDown(self):
21f3176f5fSMed Ismail Bennani        TestBase.tearDown(self)
22f3176f5fSMed Ismail Bennani
23f3176f5fSMed Ismail Bennani    def test_python_plugin_package(self):
24f3176f5fSMed Ismail Bennani        """Test that the lldb python module has a `plugins.scripted_process`
25f3176f5fSMed Ismail Bennani        package."""
26f3176f5fSMed Ismail Bennani        self.expect('script import lldb.plugins',
27f3176f5fSMed Ismail Bennani                    substrs=["ModuleNotFoundError"], matching=False)
28f3176f5fSMed Ismail Bennani
29f3176f5fSMed Ismail Bennani        self.expect('script dir(lldb.plugins)',
30f3176f5fSMed Ismail Bennani                    substrs=["scripted_process"])
31f3176f5fSMed Ismail Bennani
32f3176f5fSMed Ismail Bennani        self.expect('script import lldb.plugins.scripted_process',
33f3176f5fSMed Ismail Bennani                    substrs=["ModuleNotFoundError"], matching=False)
34f3176f5fSMed Ismail Bennani
35f3176f5fSMed Ismail Bennani        self.expect('script dir(lldb.plugins.scripted_process)',
36f3176f5fSMed Ismail Bennani                    substrs=["ScriptedProcess"])
37f3176f5fSMed Ismail Bennani
38f3176f5fSMed Ismail Bennani        self.expect('script from lldb.plugins.scripted_process import ScriptedProcess',
39f3176f5fSMed Ismail Bennani                    substrs=["ImportError"], matching=False)
40f3176f5fSMed Ismail Bennani
41f3176f5fSMed Ismail Bennani        self.expect('script dir(ScriptedProcess)',
42f3176f5fSMed Ismail Bennani                    substrs=["launch"])
43f3176f5fSMed Ismail Bennani
44*6aa48034SMed Ismail Bennani    def move_blueprint_to_dsym(self, blueprint_name):
45*6aa48034SMed Ismail Bennani        blueprint_origin_path = os.path.join(self.getSourceDir(), blueprint_name)
46*6aa48034SMed Ismail Bennani        dsym_bundle = self.getBuildArtifact("a.out.dSYM")
47*6aa48034SMed Ismail Bennani        blueprint_destination_path = os.path.join(dsym_bundle, "Contents",
48*6aa48034SMed Ismail Bennani                                                  "Resources", "Python")
49*6aa48034SMed Ismail Bennani        if not os.path.exists(blueprint_destination_path):
50*6aa48034SMed Ismail Bennani            os.mkdir(blueprint_destination_path)
51*6aa48034SMed Ismail Bennani
52*6aa48034SMed Ismail Bennani        blueprint_destination_path = os.path.join(blueprint_destination_path, "a_out.py")
53*6aa48034SMed Ismail Bennani        shutil.copy(blueprint_origin_path, blueprint_destination_path)
54*6aa48034SMed Ismail Bennani
55c3ca2c6bSMed Ismail Bennani    @skipUnlessDarwin
56caea440aSMed Ismail Bennani    def test_invalid_scripted_register_context(self):
57caea440aSMed Ismail Bennani        """Test that we can launch an lldb scripted process with an invalid
58caea440aSMed Ismail Bennani        Scripted Thread, with invalid register context."""
59caea440aSMed Ismail Bennani        self.build()
60caea440aSMed Ismail Bennani
61caea440aSMed Ismail Bennani        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
62a6b56243SMed Ismail Bennani        def cleanup():
63a6b56243SMed Ismail Bennani          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
64a6b56243SMed Ismail Bennani        self.addTearDownHook(cleanup)
65a6b56243SMed Ismail Bennani
66*6aa48034SMed Ismail Bennani        self.runCmd("settings set target.load-script-from-symbol-file true")
67*6aa48034SMed Ismail Bennani        self.move_blueprint_to_dsym('invalid_scripted_process.py')
68*6aa48034SMed Ismail Bennani        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
69*6aa48034SMed Ismail Bennani        self.assertTrue(target, VALID_TARGET)
70*6aa48034SMed Ismail Bennani        log_file = self.getBuildArtifact('thread.log')
71*6aa48034SMed Ismail Bennani        self.runCmd("log enable lldb thread -f " + log_file)
72*6aa48034SMed Ismail Bennani        self.assertTrue(os.path.isfile(log_file))
73caea440aSMed Ismail Bennani
74caea440aSMed Ismail Bennani        launch_info = lldb.SBLaunchInfo(None)
75caea440aSMed Ismail Bennani        launch_info.SetProcessPluginName("ScriptedProcess")
76*6aa48034SMed Ismail Bennani        launch_info.SetScriptedProcessClassName("a_out.InvalidScriptedProcess")
77caea440aSMed Ismail Bennani        error = lldb.SBError()
789c144b3bSMed Ismail Bennani
79caea440aSMed Ismail Bennani        process = target.Launch(launch_info, error)
80caea440aSMed Ismail Bennani
81779bbbf2SDave Lee        self.assertSuccess(error)
82caea440aSMed Ismail Bennani        self.assertTrue(process, PROCESS_IS_VALID)
83caea440aSMed Ismail Bennani        self.assertEqual(process.GetProcessID(), 666)
84caea440aSMed Ismail Bennani        self.assertEqual(process.GetNumThreads(), 0)
85caea440aSMed Ismail Bennani
869c144b3bSMed Ismail Bennani        with open(log_file, 'r') as f:
879c144b3bSMed Ismail Bennani            log = f.read()
889c144b3bSMed Ismail Bennani
899c144b3bSMed Ismail Bennani        self.assertIn("Failed to get scripted thread registers data.", log)
90caea440aSMed Ismail Bennani
9186e6030eSMed Ismail Bennani    @skipUnlessDarwin
92a758c9f7SMed Ismail Bennani    def test_scripted_process_and_scripted_thread(self):
93312b43daSMed Ismail Bennani        """Test that we can launch an lldb scripted process using the SBAPI,
94a758c9f7SMed Ismail Bennani        check its process ID, read string from memory, check scripted thread
95a758c9f7SMed Ismail Bennani        id, name stop reason and register context.
96a758c9f7SMed Ismail Bennani        """
97312b43daSMed Ismail Bennani        self.build()
98312b43daSMed Ismail Bennani        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
99312b43daSMed Ismail Bennani        self.assertTrue(target, VALID_TARGET)
100312b43daSMed Ismail Bennani
101312b43daSMed Ismail Bennani        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
102a6b56243SMed Ismail Bennani        def cleanup():
103a6b56243SMed Ismail Bennani          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
104a6b56243SMed Ismail Bennani        self.addTearDownHook(cleanup)
105a6b56243SMed Ismail Bennani
106419b4711SMed Ismail Bennani        scripted_process_example_relpath = 'dummy_scripted_process.py'
107312b43daSMed Ismail Bennani        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
108a758c9f7SMed Ismail Bennani                                                            scripted_process_example_relpath))
109312b43daSMed Ismail Bennani
110312b43daSMed Ismail Bennani        launch_info = lldb.SBLaunchInfo(None)
111312b43daSMed Ismail Bennani        launch_info.SetProcessPluginName("ScriptedProcess")
112a758c9f7SMed Ismail Bennani        launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess")
113312b43daSMed Ismail Bennani
114312b43daSMed Ismail Bennani        error = lldb.SBError()
115312b43daSMed Ismail Bennani        process = target.Launch(launch_info, error)
116312b43daSMed Ismail Bennani        self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
117312b43daSMed Ismail Bennani        self.assertEqual(process.GetProcessID(), 42)
118312b43daSMed Ismail Bennani
11959d8dd79SMed Ismail Bennani        self.assertEqual(process.GetNumThreads(), 1)
12059d8dd79SMed Ismail Bennani
12159d8dd79SMed Ismail Bennani        thread = process.GetSelectedThread()
12259d8dd79SMed Ismail Bennani        self.assertTrue(thread, "Invalid thread.")
12359d8dd79SMed Ismail Bennani        self.assertEqual(thread.GetThreadID(), 0x19)
124a758c9f7SMed Ismail Bennani        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")
12559d8dd79SMed Ismail Bennani        self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
12659d8dd79SMed Ismail Bennani
12759d8dd79SMed Ismail Bennani        self.assertGreater(thread.GetNumFrames(), 0)
12859d8dd79SMed Ismail Bennani
12959d8dd79SMed Ismail Bennani        frame = thread.GetFrameAtIndex(0)
130976867b5SMed Ismail Bennani        GPRs = None
13159d8dd79SMed Ismail Bennani        register_set = frame.registers # Returns an SBValueList.
13259d8dd79SMed Ismail Bennani        for regs in register_set:
133976867b5SMed Ismail Bennani            if 'general purpose' in regs.name.lower():
134976867b5SMed Ismail Bennani                GPRs = regs
13559d8dd79SMed Ismail Bennani                break
13659d8dd79SMed Ismail Bennani
137976867b5SMed Ismail Bennani        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")
138c3ca2c6bSMed Ismail Bennani        self.assertGreater(GPRs.GetNumChildren(), 0)
139976867b5SMed Ismail Bennani        for idx, reg in enumerate(GPRs, start=1):
140c3ca2c6bSMed Ismail Bennani            if idx > 21:
141c3ca2c6bSMed Ismail Bennani                break
14259d8dd79SMed Ismail Bennani            self.assertEqual(idx, int(reg.value, 16))
14359d8dd79SMed Ismail Bennani
14470665844SMed Ismail Bennani        self.assertTrue(frame.IsArtificial(), "Frame is not artificial")
14570665844SMed Ismail Bennani        pc = frame.GetPCAddress().GetLoadAddress(target)
14670665844SMed Ismail Bennani        self.assertEqual(pc, 0x0100001b00)
147