1f3176f5fSMed Ismail Bennani""" 2f3176f5fSMed Ismail BennaniTest python scripted process in lldb 3f3176f5fSMed Ismail Bennani""" 4f3176f5fSMed Ismail Bennani 5976867b5SMed 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*c3ca2c6bSMed Ismail Bennani @skipUnlessDarwin 45caea440aSMed Ismail Bennani def test_invalid_scripted_register_context(self): 46caea440aSMed Ismail Bennani """Test that we can launch an lldb scripted process with an invalid 47caea440aSMed Ismail Bennani Scripted Thread, with invalid register context.""" 48caea440aSMed Ismail Bennani self.build() 49caea440aSMed Ismail Bennani target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 50caea440aSMed Ismail Bennani self.assertTrue(target, VALID_TARGET) 519c144b3bSMed Ismail Bennani log_file = self.getBuildArtifact('thread.log') 529c144b3bSMed Ismail Bennani self.runCmd("log enable lldb thread -f " + log_file) 539c144b3bSMed Ismail Bennani self.assertTrue(os.path.isfile(log_file)) 54caea440aSMed Ismail Bennani 55caea440aSMed Ismail Bennani os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 56caea440aSMed Ismail Bennani def cleanup(): 57caea440aSMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 58caea440aSMed Ismail Bennani self.addTearDownHook(cleanup) 59caea440aSMed Ismail Bennani 60caea440aSMed Ismail Bennani scripted_process_example_relpath = 'invalid_scripted_process.py' 61caea440aSMed Ismail Bennani self.runCmd("command script import " + os.path.join(self.getSourceDir(), 62caea440aSMed Ismail Bennani scripted_process_example_relpath)) 63caea440aSMed Ismail Bennani 64caea440aSMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 65caea440aSMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 66caea440aSMed Ismail Bennani launch_info.SetScriptedProcessClassName("invalid_scripted_process.InvalidScriptedProcess") 67caea440aSMed Ismail Bennani error = lldb.SBError() 689c144b3bSMed Ismail Bennani 69caea440aSMed Ismail Bennani process = target.Launch(launch_info, error) 70caea440aSMed Ismail Bennani 71caea440aSMed Ismail Bennani self.assertTrue(error.Success(), error.GetCString()) 72caea440aSMed Ismail Bennani self.assertTrue(process, PROCESS_IS_VALID) 73caea440aSMed Ismail Bennani self.assertEqual(process.GetProcessID(), 666) 74caea440aSMed Ismail Bennani self.assertEqual(process.GetNumThreads(), 0) 75caea440aSMed Ismail Bennani 769c144b3bSMed Ismail Bennani with open(log_file, 'r') as f: 779c144b3bSMed Ismail Bennani log = f.read() 789c144b3bSMed Ismail Bennani 799c144b3bSMed Ismail Bennani self.assertIn("Failed to get scripted thread registers data.", log) 80caea440aSMed Ismail Bennani 81*c3ca2c6bSMed Ismail Bennani @skipIf(archs=no_match(['x86_64', 'arm64', 'arm64e'])) 82a758c9f7SMed Ismail Bennani def test_scripted_process_and_scripted_thread(self): 83312b43daSMed Ismail Bennani """Test that we can launch an lldb scripted process using the SBAPI, 84a758c9f7SMed Ismail Bennani check its process ID, read string from memory, check scripted thread 85a758c9f7SMed Ismail Bennani id, name stop reason and register context. 86a758c9f7SMed Ismail Bennani """ 87312b43daSMed Ismail Bennani self.build() 88312b43daSMed Ismail Bennani target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 89312b43daSMed Ismail Bennani self.assertTrue(target, VALID_TARGET) 90312b43daSMed Ismail Bennani 91312b43daSMed Ismail Bennani os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 92419b4711SMed Ismail Bennani def cleanup(): 93419b4711SMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 94419b4711SMed Ismail Bennani self.addTearDownHook(cleanup) 95419b4711SMed Ismail Bennani 96419b4711SMed Ismail Bennani scripted_process_example_relpath = 'dummy_scripted_process.py' 97312b43daSMed Ismail Bennani self.runCmd("command script import " + os.path.join(self.getSourceDir(), 98a758c9f7SMed Ismail Bennani scripted_process_example_relpath)) 99312b43daSMed Ismail Bennani 100312b43daSMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 101312b43daSMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 102a758c9f7SMed Ismail Bennani launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess") 103312b43daSMed Ismail Bennani 104312b43daSMed Ismail Bennani error = lldb.SBError() 105312b43daSMed Ismail Bennani process = target.Launch(launch_info, error) 106312b43daSMed Ismail Bennani self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) 107312b43daSMed Ismail Bennani self.assertEqual(process.GetProcessID(), 42) 108312b43daSMed Ismail Bennani 10959d8dd79SMed Ismail Bennani self.assertEqual(process.GetNumThreads(), 1) 11059d8dd79SMed Ismail Bennani 11159d8dd79SMed Ismail Bennani thread = process.GetSelectedThread() 11259d8dd79SMed Ismail Bennani self.assertTrue(thread, "Invalid thread.") 11359d8dd79SMed Ismail Bennani self.assertEqual(thread.GetThreadID(), 0x19) 114a758c9f7SMed Ismail Bennani self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1") 11559d8dd79SMed Ismail Bennani self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) 11659d8dd79SMed Ismail Bennani 11759d8dd79SMed Ismail Bennani self.assertGreater(thread.GetNumFrames(), 0) 11859d8dd79SMed Ismail Bennani 11959d8dd79SMed Ismail Bennani frame = thread.GetFrameAtIndex(0) 120976867b5SMed Ismail Bennani GPRs = None 12159d8dd79SMed Ismail Bennani register_set = frame.registers # Returns an SBValueList. 12259d8dd79SMed Ismail Bennani for regs in register_set: 123976867b5SMed Ismail Bennani if 'general purpose' in regs.name.lower(): 124976867b5SMed Ismail Bennani GPRs = regs 12559d8dd79SMed Ismail Bennani break 12659d8dd79SMed Ismail Bennani 127976867b5SMed Ismail Bennani self.assertTrue(GPRs, "Invalid General Purpose Registers Set") 128*c3ca2c6bSMed Ismail Bennani self.assertGreater(GPRs.GetNumChildren(), 0) 129976867b5SMed Ismail Bennani for idx, reg in enumerate(GPRs, start=1): 130*c3ca2c6bSMed Ismail Bennani if idx > 21: 131*c3ca2c6bSMed Ismail Bennani break 13259d8dd79SMed Ismail Bennani self.assertEqual(idx, int(reg.value, 16)) 13359d8dd79SMed Ismail Bennani 134976867b5SMed Ismail Bennani def create_stack_skinny_corefile(self, file): 135976867b5SMed Ismail Bennani self.build() 136d3e0f7e1SMed Ismail Bennani target, process, thread, _ = lldbutil.run_to_source_breakpoint(self, "// break here", 137d3e0f7e1SMed Ismail Bennani lldb.SBFileSpec("main.cpp")) 138976867b5SMed Ismail Bennani self.assertTrue(process.IsValid(), "Process is invalid.") 139976867b5SMed Ismail Bennani # FIXME: Use SBAPI to save the process corefile. 140976867b5SMed Ismail Bennani self.runCmd("process save-core -s stack " + file) 141976867b5SMed Ismail Bennani self.assertTrue(os.path.exists(file), "No stack-only corefile found.") 142976867b5SMed Ismail Bennani self.assertTrue(self.dbg.DeleteTarget(target), "Couldn't delete target") 143976867b5SMed Ismail Bennani 144815c87fbSMed Ismail Bennani @skipUnlessDarwin 145419b4711SMed Ismail Bennani @skipIfOutOfTreeDebugserver 146a758c9f7SMed Ismail Bennani def test_launch_scripted_process_stack_frames(self): 147312b43daSMed Ismail Bennani """Test that we can launch an lldb scripted process from the command 148312b43daSMed Ismail Bennani line, check its process ID and read string from memory.""" 149312b43daSMed Ismail Bennani self.build() 150312b43daSMed Ismail Bennani target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 151312b43daSMed Ismail Bennani self.assertTrue(target, VALID_TARGET) 152312b43daSMed Ismail Bennani 153a758c9f7SMed Ismail Bennani for module in target.modules: 154a758c9f7SMed Ismail Bennani if 'a.out' in module.GetFileSpec().GetFilename(): 155a758c9f7SMed Ismail Bennani main_module = module 156976867b5SMed Ismail Bennani break 157a758c9f7SMed Ismail Bennani 158a758c9f7SMed Ismail Bennani self.assertTrue(main_module, "Invalid main module.") 159a758c9f7SMed Ismail Bennani error = target.SetModuleLoadAddress(main_module, 0) 160a758c9f7SMed Ismail Bennani self.assertTrue(error.Success(), "Reloading main module at offset 0 failed.") 161a758c9f7SMed Ismail Bennani 162976867b5SMed Ismail Bennani os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 163419b4711SMed Ismail Bennani def cleanup(): 164419b4711SMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 165419b4711SMed Ismail Bennani self.addTearDownHook(cleanup) 166419b4711SMed Ismail Bennani 167419b4711SMed Ismail Bennani scripted_process_example_relpath = 'stack_core_scripted_process.py' 168312b43daSMed Ismail Bennani self.runCmd("command script import " + os.path.join(self.getSourceDir(), 169976867b5SMed Ismail Bennani scripted_process_example_relpath)) 170312b43daSMed Ismail Bennani 171976867b5SMed Ismail Bennani corefile_process = None 172976867b5SMed Ismail Bennani with tempfile.NamedTemporaryFile() as file: 173976867b5SMed Ismail Bennani self.create_stack_skinny_corefile(file.name) 174976867b5SMed Ismail Bennani corefile_target = self.dbg.CreateTarget(None) 175976867b5SMed Ismail Bennani corefile_process = corefile_target.LoadCore(self.getBuildArtifact(file.name)) 176976867b5SMed Ismail Bennani self.assertTrue(corefile_process, PROCESS_IS_VALID) 177976867b5SMed Ismail Bennani 178976867b5SMed Ismail Bennani structured_data = lldb.SBStructuredData() 179976867b5SMed Ismail Bennani structured_data.SetFromJSON(json.dumps({ 180976867b5SMed Ismail Bennani "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget()) 181976867b5SMed Ismail Bennani })) 182976867b5SMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 183976867b5SMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 184976867b5SMed Ismail Bennani launch_info.SetScriptedProcessClassName("stack_core_scripted_process.StackCoreScriptedProcess") 185976867b5SMed Ismail Bennani launch_info.SetScriptedProcessDictionary(structured_data) 186976867b5SMed Ismail Bennani 187976867b5SMed Ismail Bennani error = lldb.SBError() 188976867b5SMed Ismail Bennani process = target.Launch(launch_info, error) 189976867b5SMed Ismail Bennani self.assertTrue(error.Success(), error.GetCString()) 190312b43daSMed Ismail Bennani self.assertTrue(process, PROCESS_IS_VALID) 191312b43daSMed Ismail Bennani self.assertEqual(process.GetProcessID(), 42) 192312b43daSMed Ismail Bennani 193d3e0f7e1SMed Ismail Bennani self.assertEqual(process.GetNumThreads(), 3) 194cfa55bfeSMed Ismail Bennani thread = process.GetThreadAtIndex(2) 195a758c9f7SMed Ismail Bennani self.assertTrue(thread, "Invalid thread.") 196cfa55bfeSMed Ismail Bennani self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-2") 197312b43daSMed Ismail Bennani 198cfa55bfeSMed Ismail Bennani self.assertEqual(thread.GetNumFrames(), 6) 199a758c9f7SMed Ismail Bennani frame = thread.GetSelectedFrame() 200a758c9f7SMed Ismail Bennani self.assertTrue(frame, "Invalid frame.") 201cfa55bfeSMed Ismail Bennani self.assertIn("bar", frame.GetFunctionName()) 202cfa55bfeSMed Ismail Bennani self.assertEqual(int(frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42) 203cfa55bfeSMed Ismail Bennani self.assertEqual(int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42) 204