xref: /llvm-project/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py (revision 4cc8f2a017c76af25234afc7c380550e9c93135c)
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 setUp(self):
18        TestBase.setUp(self)
19
20    def tearDown(self):
21        TestBase.tearDown(self)
22
23    def test_python_plugin_package(self):
24        """Test that the lldb python module has a `plugins.scripted_process`
25        package."""
26        self.expect('script import lldb.plugins',
27                    substrs=["ModuleNotFoundError"], matching=False)
28
29        self.expect('script dir(lldb.plugins)',
30                    substrs=["scripted_process"])
31
32        self.expect('script import lldb.plugins.scripted_process',
33                    substrs=["ModuleNotFoundError"], matching=False)
34
35        self.expect('script dir(lldb.plugins.scripted_process)',
36                    substrs=["ScriptedProcess"])
37
38        self.expect('script from lldb.plugins.scripted_process import ScriptedProcess',
39                    substrs=["ImportError"], matching=False)
40
41        self.expect('script dir(ScriptedProcess)',
42                    substrs=["launch"])
43
44    def move_blueprint_to_dsym(self, blueprint_name):
45        blueprint_origin_path = os.path.join(self.getSourceDir(), blueprint_name)
46        dsym_bundle = self.getBuildArtifact("a.out.dSYM")
47        blueprint_destination_path = os.path.join(dsym_bundle, "Contents",
48                                                  "Resources", "Python")
49        if not os.path.exists(blueprint_destination_path):
50            os.mkdir(blueprint_destination_path)
51
52        blueprint_destination_path = os.path.join(blueprint_destination_path, "a_out.py")
53        shutil.copy(blueprint_origin_path, blueprint_destination_path)
54
55    @skipUnlessDarwin
56    def test_invalid_scripted_register_context(self):
57        """Test that we can launch an lldb scripted process with an invalid
58        Scripted Thread, with invalid register context."""
59        self.build()
60
61        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
62        def cleanup():
63          del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
64        self.addTearDownHook(cleanup)
65
66        self.runCmd("settings set target.load-script-from-symbol-file true")
67        self.move_blueprint_to_dsym('invalid_scripted_process.py')
68        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
69        self.assertTrue(target, VALID_TARGET)
70        log_file = self.getBuildArtifact('thread.log')
71        self.runCmd("log enable lldb thread -f " + log_file)
72        self.assertTrue(os.path.isfile(log_file))
73
74        launch_info = lldb.SBLaunchInfo(None)
75        launch_info.SetProcessPluginName("ScriptedProcess")
76        launch_info.SetScriptedProcessClassName("a_out.InvalidScriptedProcess")
77        error = lldb.SBError()
78
79        process = target.Launch(launch_info, error)
80
81        self.assertSuccess(error)
82        self.assertTrue(process, PROCESS_IS_VALID)
83        self.assertEqual(process.GetProcessID(), 666)
84        self.assertEqual(process.GetNumThreads(), 0)
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
119        self.assertEqual(process.GetNumThreads(), 1)
120
121        thread = process.GetSelectedThread()
122        self.assertTrue(thread, "Invalid thread.")
123        self.assertEqual(thread.GetThreadID(), 0x19)
124        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")
125        self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
126
127        self.assertGreater(thread.GetNumFrames(), 0)
128
129        frame = thread.GetFrameAtIndex(0)
130        GPRs = None
131        register_set = frame.registers # Returns an SBValueList.
132        for regs in register_set:
133            if 'general purpose' in regs.name.lower():
134                GPRs = regs
135                break
136
137        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")
138        self.assertGreater(GPRs.GetNumChildren(), 0)
139        for idx, reg in enumerate(GPRs, start=1):
140            if idx > 21:
141                break
142            self.assertEqual(idx, int(reg.value, 16))
143
144        self.assertTrue(frame.IsArtificial(), "Frame is not artificial")
145        pc = frame.GetPCAddress().GetLoadAddress(target)
146        self.assertEqual(pc, 0x0100001b00)
147