xref: /llvm-project/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py (revision 976867b513abbf72e505506686219efaa7f3520f)
1"""
2Test python scripted process in lldb
3"""
4
5import os, json, tempfile
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    mydir = TestBase.compute_mydir(__file__)
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    @skipIf(archs=no_match(['x86_64']))
45    def test_scripted_process_and_scripted_thread(self):
46        """Test that we can launch an lldb scripted process using the SBAPI,
47        check its process ID, read string from memory, check scripted thread
48        id, name stop reason and register context.
49        """
50        self.build()
51        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
52        self.assertTrue(target, VALID_TARGET)
53
54        scripted_process_example_relpath = 'dummy_scripted_process.py'
55        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
56        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
57                                                            scripted_process_example_relpath))
58
59        launch_info = lldb.SBLaunchInfo(None)
60        launch_info.SetProcessPluginName("ScriptedProcess")
61        launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess")
62
63        error = lldb.SBError()
64        process = target.Launch(launch_info, error)
65        self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
66        self.assertEqual(process.GetProcessID(), 42)
67
68        self.assertEqual(process.GetNumThreads(), 1)
69
70        thread = process.GetSelectedThread()
71        self.assertTrue(thread, "Invalid thread.")
72        self.assertEqual(thread.GetThreadID(), 0x19)
73        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")
74        self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
75
76        self.assertGreater(thread.GetNumFrames(), 0)
77
78        frame = thread.GetFrameAtIndex(0)
79        GPRs = None
80        register_set = frame.registers # Returns an SBValueList.
81        for regs in register_set:
82            if 'general purpose' in regs.name.lower():
83                GPRs = regs
84                break
85
86        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")
87        self.assertEqual(GPRs.GetNumChildren(), 21)
88        for idx, reg in enumerate(GPRs, start=1):
89            self.assertEqual(idx, int(reg.value, 16))
90
91    def create_stack_skinny_corefile(self, file):
92        self.build()
93        target, process, thread, _ = lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.c"))
94        self.assertTrue(process.IsValid(), "Process is invalid.")
95        # FIXME: Use SBAPI to save the process corefile.
96        self.runCmd("process save-core -s stack  " + file)
97        self.assertTrue(os.path.exists(file), "No stack-only corefile found.")
98        self.assertTrue(self.dbg.DeleteTarget(target), "Couldn't delete target")
99
100    @skipUnlessDarwin
101    @skipIf(archs=no_match(['x86_64']))
102    def test_launch_scripted_process_stack_frames(self):
103        """Test that we can launch an lldb scripted process from the command
104        line, check its process ID and read string from memory."""
105        self.build()
106        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
107        self.assertTrue(target, VALID_TARGET)
108
109        for module in target.modules:
110            if 'a.out' in module.GetFileSpec().GetFilename():
111                main_module = module
112                break
113
114        self.assertTrue(main_module, "Invalid main module.")
115        error = target.SetModuleLoadAddress(main_module, 0)
116        self.assertTrue(error.Success(), "Reloading main module at offset 0 failed.")
117
118        scripted_process_example_relpath = 'stack_core_scripted_process.py'
119        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
120        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
121                                                            scripted_process_example_relpath))
122
123        corefile_process = None
124        with tempfile.NamedTemporaryFile() as file:
125            self.create_stack_skinny_corefile(file.name)
126            corefile_target = self.dbg.CreateTarget(None)
127            corefile_process = corefile_target.LoadCore(self.getBuildArtifact(file.name))
128        self.assertTrue(corefile_process, PROCESS_IS_VALID)
129
130        structured_data = lldb.SBStructuredData()
131        structured_data.SetFromJSON(json.dumps({
132            "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget())
133        }))
134        launch_info = lldb.SBLaunchInfo(None)
135        launch_info.SetProcessPluginName("ScriptedProcess")
136        launch_info.SetScriptedProcessClassName("stack_core_scripted_process.StackCoreScriptedProcess")
137        launch_info.SetScriptedProcessDictionary(structured_data)
138
139        error = lldb.SBError()
140        process = target.Launch(launch_info, error)
141        self.assertTrue(error.Success(), error.GetCString())
142        self.assertTrue(process, PROCESS_IS_VALID)
143        self.assertEqual(process.GetProcessID(), 42)
144
145        self.assertEqual(process.GetNumThreads(), 1)
146        thread = process.GetSelectedThread()
147        self.assertTrue(thread, "Invalid thread.")
148        self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-1")
149
150        self.assertEqual(thread.GetNumFrames(), 3)
151        frame = thread.GetSelectedFrame()
152        self.assertTrue(frame, "Invalid frame.")
153        self.assertEqual(frame.GetFunctionName(), "bar")
154        self.assertEqual(int(frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42)
155        self.assertEqual(int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42)
156