1f3176f5fSMed Ismail Bennani"""
2f3176f5fSMed Ismail BennaniTest python scripted process in lldb
3f3176f5fSMed Ismail Bennani"""
4f3176f5fSMed Ismail Bennani
5*976867b5SMed Ismail Bennaniimport os, json, tempfile
6f3176f5fSMed Ismail Bennani
7f3176f5fSMed Ismail Bennaniimport lldb
8f3176f5fSMed Ismail Bennanifrom lldbsuite.test.decorators import *
9f3176f5fSMed Ismail Bennanifrom lldbsuite.test.lldbtest import *
10f3176f5fSMed Ismail Bennanifrom lldbsuite.test import lldbutil
11f3176f5fSMed Ismail Bennanifrom lldbsuite.test import lldbtest
12f3176f5fSMed Ismail Bennani
13312b43daSMed Ismail Bennaniclass ScriptedProcesTestCase(TestBase):
14f3176f5fSMed Ismail Bennani
15f3176f5fSMed Ismail Bennani    mydir = TestBase.compute_mydir(__file__)
16f3176f5fSMed Ismail Bennani
17f3176f5fSMed Ismail Bennani    def setUp(self):
18f3176f5fSMed Ismail Bennani        TestBase.setUp(self)
19f3176f5fSMed Ismail Bennani
20f3176f5fSMed Ismail Bennani    def tearDown(self):
21f3176f5fSMed Ismail Bennani        TestBase.tearDown(self)
22f3176f5fSMed Ismail Bennani
23f3176f5fSMed Ismail Bennani    def test_python_plugin_package(self):
24f3176f5fSMed Ismail Bennani        """Test that the lldb python module has a `plugins.scripted_process`
25f3176f5fSMed Ismail Bennani        package."""
26f3176f5fSMed Ismail Bennani        self.expect('script import lldb.plugins',
27f3176f5fSMed Ismail Bennani                    substrs=["ModuleNotFoundError"], matching=False)
28f3176f5fSMed Ismail Bennani
29f3176f5fSMed Ismail Bennani        self.expect('script dir(lldb.plugins)',
30f3176f5fSMed Ismail Bennani                    substrs=["scripted_process"])
31f3176f5fSMed Ismail Bennani
32f3176f5fSMed Ismail Bennani        self.expect('script import lldb.plugins.scripted_process',
33f3176f5fSMed Ismail Bennani                    substrs=["ModuleNotFoundError"], matching=False)
34f3176f5fSMed Ismail Bennani
35f3176f5fSMed Ismail Bennani        self.expect('script dir(lldb.plugins.scripted_process)',
36f3176f5fSMed Ismail Bennani                    substrs=["ScriptedProcess"])
37f3176f5fSMed Ismail Bennani
38f3176f5fSMed Ismail Bennani        self.expect('script from lldb.plugins.scripted_process import ScriptedProcess',
39f3176f5fSMed Ismail Bennani                    substrs=["ImportError"], matching=False)
40f3176f5fSMed Ismail Bennani
41f3176f5fSMed Ismail Bennani        self.expect('script dir(ScriptedProcess)',
42f3176f5fSMed Ismail Bennani                    substrs=["launch"])
43f3176f5fSMed Ismail Bennani
44*976867b5SMed Ismail Bennani    @skipIf(archs=no_match(['x86_64']))
45a758c9f7SMed Ismail Bennani    def test_scripted_process_and_scripted_thread(self):
46312b43daSMed Ismail Bennani        """Test that we can launch an lldb scripted process using the SBAPI,
47a758c9f7SMed Ismail Bennani        check its process ID, read string from memory, check scripted thread
48a758c9f7SMed Ismail Bennani        id, name stop reason and register context.
49a758c9f7SMed Ismail Bennani        """
50312b43daSMed Ismail Bennani        self.build()
51312b43daSMed Ismail Bennani        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
52312b43daSMed Ismail Bennani        self.assertTrue(target, VALID_TARGET)
53312b43daSMed Ismail Bennani
54a758c9f7SMed Ismail Bennani        scripted_process_example_relpath = 'dummy_scripted_process.py'
55312b43daSMed Ismail Bennani        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
56312b43daSMed Ismail Bennani        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
57a758c9f7SMed Ismail Bennani                                                            scripted_process_example_relpath))
58312b43daSMed Ismail Bennani
59312b43daSMed Ismail Bennani        launch_info = lldb.SBLaunchInfo(None)
60312b43daSMed Ismail Bennani        launch_info.SetProcessPluginName("ScriptedProcess")
61a758c9f7SMed Ismail Bennani        launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess")
62312b43daSMed Ismail Bennani
63312b43daSMed Ismail Bennani        error = lldb.SBError()
64312b43daSMed Ismail Bennani        process = target.Launch(launch_info, error)
65312b43daSMed Ismail Bennani        self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
66312b43daSMed Ismail Bennani        self.assertEqual(process.GetProcessID(), 42)
67312b43daSMed Ismail Bennani
6859d8dd79SMed Ismail Bennani        self.assertEqual(process.GetNumThreads(), 1)
6959d8dd79SMed Ismail Bennani
7059d8dd79SMed Ismail Bennani        thread = process.GetSelectedThread()
7159d8dd79SMed Ismail Bennani        self.assertTrue(thread, "Invalid thread.")
7259d8dd79SMed Ismail Bennani        self.assertEqual(thread.GetThreadID(), 0x19)
73a758c9f7SMed Ismail Bennani        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")
7459d8dd79SMed Ismail Bennani        self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
7559d8dd79SMed Ismail Bennani
7659d8dd79SMed Ismail Bennani        self.assertGreater(thread.GetNumFrames(), 0)
7759d8dd79SMed Ismail Bennani
7859d8dd79SMed Ismail Bennani        frame = thread.GetFrameAtIndex(0)
79*976867b5SMed Ismail Bennani        GPRs = None
8059d8dd79SMed Ismail Bennani        register_set = frame.registers # Returns an SBValueList.
8159d8dd79SMed Ismail Bennani        for regs in register_set:
82*976867b5SMed Ismail Bennani            if 'general purpose' in regs.name.lower():
83*976867b5SMed Ismail Bennani                GPRs = regs
8459d8dd79SMed Ismail Bennani                break
8559d8dd79SMed Ismail Bennani
86*976867b5SMed Ismail Bennani        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")
87*976867b5SMed Ismail Bennani        self.assertEqual(GPRs.GetNumChildren(), 21)
88*976867b5SMed Ismail Bennani        for idx, reg in enumerate(GPRs, start=1):
8959d8dd79SMed Ismail Bennani            self.assertEqual(idx, int(reg.value, 16))
9059d8dd79SMed Ismail Bennani
91*976867b5SMed Ismail Bennani    def create_stack_skinny_corefile(self, file):
92*976867b5SMed Ismail Bennani        self.build()
93*976867b5SMed Ismail Bennani        target, process, thread, _ = lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.c"))
94*976867b5SMed Ismail Bennani        self.assertTrue(process.IsValid(), "Process is invalid.")
95*976867b5SMed Ismail Bennani        # FIXME: Use SBAPI to save the process corefile.
96*976867b5SMed Ismail Bennani        self.runCmd("process save-core -s stack  " + file)
97*976867b5SMed Ismail Bennani        self.assertTrue(os.path.exists(file), "No stack-only corefile found.")
98*976867b5SMed Ismail Bennani        self.assertTrue(self.dbg.DeleteTarget(target), "Couldn't delete target")
99*976867b5SMed Ismail Bennani
100815c87fbSMed Ismail Bennani    @skipUnlessDarwin
101*976867b5SMed Ismail Bennani    @skipIf(archs=no_match(['x86_64']))
102a758c9f7SMed Ismail Bennani    def test_launch_scripted_process_stack_frames(self):
103312b43daSMed Ismail Bennani        """Test that we can launch an lldb scripted process from the command
104312b43daSMed Ismail Bennani        line, check its process ID and read string from memory."""
105312b43daSMed Ismail Bennani        self.build()
106312b43daSMed Ismail Bennani        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
107312b43daSMed Ismail Bennani        self.assertTrue(target, VALID_TARGET)
108312b43daSMed Ismail Bennani
109a758c9f7SMed Ismail Bennani        for module in target.modules:
110a758c9f7SMed Ismail Bennani            if 'a.out' in module.GetFileSpec().GetFilename():
111a758c9f7SMed Ismail Bennani                main_module = module
112*976867b5SMed Ismail Bennani                break
113a758c9f7SMed Ismail Bennani
114a758c9f7SMed Ismail Bennani        self.assertTrue(main_module, "Invalid main module.")
115a758c9f7SMed Ismail Bennani        error = target.SetModuleLoadAddress(main_module, 0)
116a758c9f7SMed Ismail Bennani        self.assertTrue(error.Success(), "Reloading main module at offset 0 failed.")
117a758c9f7SMed Ismail Bennani
118*976867b5SMed Ismail Bennani        scripted_process_example_relpath = 'stack_core_scripted_process.py'
119*976867b5SMed Ismail Bennani        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
120312b43daSMed Ismail Bennani        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
121*976867b5SMed Ismail Bennani                                                            scripted_process_example_relpath))
122312b43daSMed Ismail Bennani
123*976867b5SMed Ismail Bennani        corefile_process = None
124*976867b5SMed Ismail Bennani        with tempfile.NamedTemporaryFile() as file:
125*976867b5SMed Ismail Bennani            self.create_stack_skinny_corefile(file.name)
126*976867b5SMed Ismail Bennani            corefile_target = self.dbg.CreateTarget(None)
127*976867b5SMed Ismail Bennani            corefile_process = corefile_target.LoadCore(self.getBuildArtifact(file.name))
128*976867b5SMed Ismail Bennani        self.assertTrue(corefile_process, PROCESS_IS_VALID)
129*976867b5SMed Ismail Bennani
130*976867b5SMed Ismail Bennani        structured_data = lldb.SBStructuredData()
131*976867b5SMed Ismail Bennani        structured_data.SetFromJSON(json.dumps({
132*976867b5SMed Ismail Bennani            "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget())
133*976867b5SMed Ismail Bennani        }))
134*976867b5SMed Ismail Bennani        launch_info = lldb.SBLaunchInfo(None)
135*976867b5SMed Ismail Bennani        launch_info.SetProcessPluginName("ScriptedProcess")
136*976867b5SMed Ismail Bennani        launch_info.SetScriptedProcessClassName("stack_core_scripted_process.StackCoreScriptedProcess")
137*976867b5SMed Ismail Bennani        launch_info.SetScriptedProcessDictionary(structured_data)
138*976867b5SMed Ismail Bennani
139*976867b5SMed Ismail Bennani        error = lldb.SBError()
140*976867b5SMed Ismail Bennani        process = target.Launch(launch_info, error)
141*976867b5SMed Ismail Bennani        self.assertTrue(error.Success(), error.GetCString())
142312b43daSMed Ismail Bennani        self.assertTrue(process, PROCESS_IS_VALID)
143312b43daSMed Ismail Bennani        self.assertEqual(process.GetProcessID(), 42)
144312b43daSMed Ismail Bennani
145*976867b5SMed Ismail Bennani        self.assertEqual(process.GetNumThreads(), 1)
146a758c9f7SMed Ismail Bennani        thread = process.GetSelectedThread()
147a758c9f7SMed Ismail Bennani        self.assertTrue(thread, "Invalid thread.")
148*976867b5SMed Ismail Bennani        self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-1")
149312b43daSMed Ismail Bennani
150*976867b5SMed Ismail Bennani        self.assertEqual(thread.GetNumFrames(), 3)
151a758c9f7SMed Ismail Bennani        frame = thread.GetSelectedFrame()
152a758c9f7SMed Ismail Bennani        self.assertTrue(frame, "Invalid frame.")
153a758c9f7SMed Ismail Bennani        self.assertEqual(frame.GetFunctionName(), "bar")
154a758c9f7SMed Ismail Bennani        self.assertEqual(int(frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42)
155a758c9f7SMed Ismail Bennani        self.assertEqual(int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42)
156