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