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