xref: /llvm-project/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py (revision 6aa48034f9e6eeca731bac0c33688a3396531a3c)
1"""
2Test python scripted process in lldb
3"""
4
5import os, shutil
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    def move_blueprint_to_dsym(self, blueprint_name):
47        blueprint_origin_path = os.path.join(self.getSourceDir(), blueprint_name)
48        dsym_bundle = self.getBuildArtifact("a.out.dSYM")
49        blueprint_destination_path = os.path.join(dsym_bundle, "Contents",
50                                                  "Resources", "Python")
51        if not os.path.exists(blueprint_destination_path):
52            os.mkdir(blueprint_destination_path)
53
54        blueprint_destination_path = os.path.join(blueprint_destination_path, "a_out.py")
55        shutil.copy(blueprint_origin_path, blueprint_destination_path)
56
57    @skipUnlessDarwin
58    def test_invalid_scripted_register_context(self):
59        """Test that we can launch an lldb scripted process with an invalid
60        Scripted Thread, with invalid register context."""
61        self.build()
62
63        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
64        def cleanup():
65          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
66        self.addTearDownHook(cleanup)
67
68        self.runCmd("settings set target.load-script-from-symbol-file true")
69        self.move_blueprint_to_dsym('invalid_scripted_process.py')
70        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
71        self.assertTrue(target, VALID_TARGET)
72        log_file = self.getBuildArtifact('thread.log')
73        self.runCmd("log enable lldb thread -f " + log_file)
74        self.assertTrue(os.path.isfile(log_file))
75
76        launch_info = lldb.SBLaunchInfo(None)
77        launch_info.SetProcessPluginName("ScriptedProcess")
78        launch_info.SetScriptedProcessClassName("a_out.InvalidScriptedProcess")
79        error = lldb.SBError()
80
81        process = target.Launch(launch_info, error)
82
83        self.assertSuccess(error)
84        self.assertTrue(process, PROCESS_IS_VALID)
85        self.assertEqual(process.GetProcessID(), 666)
86        self.assertEqual(process.GetNumThreads(), 0)
87
88        with open(log_file, 'r') as f:
89            log = f.read()
90
91        self.assertIn("Failed to get scripted thread registers data.", log)
92
93    @skipUnlessDarwin
94    def test_scripted_process_and_scripted_thread(self):
95        """Test that we can launch an lldb scripted process using the SBAPI,
96        check its process ID, read string from memory, check scripted thread
97        id, name stop reason and register context.
98        """
99        self.build()
100        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
101        self.assertTrue(target, VALID_TARGET)
102
103        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
104        def cleanup():
105          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
106        self.addTearDownHook(cleanup)
107
108        scripted_process_example_relpath = 'dummy_scripted_process.py'
109        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
110                                                            scripted_process_example_relpath))
111
112        launch_info = lldb.SBLaunchInfo(None)
113        launch_info.SetProcessPluginName("ScriptedProcess")
114        launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess")
115
116        error = lldb.SBError()
117        process = target.Launch(launch_info, error)
118        self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
119        self.assertEqual(process.GetProcessID(), 42)
120
121        self.assertEqual(process.GetNumThreads(), 1)
122
123        thread = process.GetSelectedThread()
124        self.assertTrue(thread, "Invalid thread.")
125        self.assertEqual(thread.GetThreadID(), 0x19)
126        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")
127        self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
128
129        self.assertGreater(thread.GetNumFrames(), 0)
130
131        frame = thread.GetFrameAtIndex(0)
132        GPRs = None
133        register_set = frame.registers # Returns an SBValueList.
134        for regs in register_set:
135            if 'general purpose' in regs.name.lower():
136                GPRs = regs
137                break
138
139        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")
140        self.assertGreater(GPRs.GetNumChildren(), 0)
141        for idx, reg in enumerate(GPRs, start=1):
142            if idx > 21:
143                break
144            self.assertEqual(idx, int(reg.value, 16))
145
146        self.assertTrue(frame.IsArtificial(), "Frame is not artificial")
147        pc = frame.GetPCAddress().GetLoadAddress(target)
148        self.assertEqual(pc, 0x0100001b00)
149