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 44caea440aSMed Ismail Bennani def test_invalid_scripted_register_context(self): 45caea440aSMed Ismail Bennani """Test that we can launch an lldb scripted process with an invalid 46caea440aSMed Ismail Bennani Scripted Thread, with invalid register context.""" 47caea440aSMed Ismail Bennani self.build() 48caea440aSMed Ismail Bennani target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 49caea440aSMed Ismail Bennani self.assertTrue(target, VALID_TARGET) 50*9c144b3bSMed Ismail Bennani log_file = self.getBuildArtifact('thread.log') 51*9c144b3bSMed Ismail Bennani self.runCmd("log enable lldb thread -f " + log_file) 52*9c144b3bSMed Ismail Bennani self.assertTrue(os.path.isfile(log_file)) 53caea440aSMed Ismail Bennani 54caea440aSMed Ismail Bennani os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 55caea440aSMed Ismail Bennani def cleanup(): 56caea440aSMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 57caea440aSMed Ismail Bennani self.addTearDownHook(cleanup) 58caea440aSMed Ismail Bennani 59caea440aSMed Ismail Bennani scripted_process_example_relpath = 'invalid_scripted_process.py' 60caea440aSMed Ismail Bennani self.runCmd("command script import " + os.path.join(self.getSourceDir(), 61caea440aSMed Ismail Bennani scripted_process_example_relpath)) 62caea440aSMed Ismail Bennani 63caea440aSMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 64caea440aSMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 65caea440aSMed Ismail Bennani launch_info.SetScriptedProcessClassName("invalid_scripted_process.InvalidScriptedProcess") 66caea440aSMed Ismail Bennani error = lldb.SBError() 67*9c144b3bSMed Ismail Bennani 68caea440aSMed Ismail Bennani process = target.Launch(launch_info, error) 69caea440aSMed Ismail Bennani 70caea440aSMed Ismail Bennani self.assertTrue(error.Success(), error.GetCString()) 71caea440aSMed Ismail Bennani self.assertTrue(process, PROCESS_IS_VALID) 72caea440aSMed Ismail Bennani self.assertEqual(process.GetProcessID(), 666) 73caea440aSMed Ismail Bennani self.assertEqual(process.GetNumThreads(), 0) 74caea440aSMed Ismail Bennani 75*9c144b3bSMed Ismail Bennani with open(log_file, 'r') as f: 76*9c144b3bSMed Ismail Bennani log = f.read() 77*9c144b3bSMed Ismail Bennani 78*9c144b3bSMed Ismail Bennani self.assertIn("Failed to get scripted thread registers data.", log) 79caea440aSMed Ismail Bennani 80976867b5SMed Ismail Bennani @skipIf(archs=no_match(['x86_64'])) 81a758c9f7SMed Ismail Bennani def test_scripted_process_and_scripted_thread(self): 82312b43daSMed Ismail Bennani """Test that we can launch an lldb scripted process using the SBAPI, 83a758c9f7SMed Ismail Bennani check its process ID, read string from memory, check scripted thread 84a758c9f7SMed Ismail Bennani id, name stop reason and register context. 85a758c9f7SMed Ismail Bennani """ 86312b43daSMed Ismail Bennani self.build() 87312b43daSMed Ismail Bennani target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 88312b43daSMed Ismail Bennani self.assertTrue(target, VALID_TARGET) 89312b43daSMed Ismail Bennani 90312b43daSMed Ismail Bennani os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 91419b4711SMed Ismail Bennani def cleanup(): 92419b4711SMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 93419b4711SMed Ismail Bennani self.addTearDownHook(cleanup) 94419b4711SMed Ismail Bennani 95419b4711SMed Ismail Bennani scripted_process_example_relpath = 'dummy_scripted_process.py' 96312b43daSMed Ismail Bennani self.runCmd("command script import " + os.path.join(self.getSourceDir(), 97a758c9f7SMed Ismail Bennani scripted_process_example_relpath)) 98312b43daSMed Ismail Bennani 99312b43daSMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 100312b43daSMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 101a758c9f7SMed Ismail Bennani launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess") 102312b43daSMed Ismail Bennani 103312b43daSMed Ismail Bennani error = lldb.SBError() 104312b43daSMed Ismail Bennani process = target.Launch(launch_info, error) 105312b43daSMed Ismail Bennani self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) 106312b43daSMed Ismail Bennani self.assertEqual(process.GetProcessID(), 42) 107312b43daSMed Ismail Bennani 10859d8dd79SMed Ismail Bennani self.assertEqual(process.GetNumThreads(), 1) 10959d8dd79SMed Ismail Bennani 11059d8dd79SMed Ismail Bennani thread = process.GetSelectedThread() 11159d8dd79SMed Ismail Bennani self.assertTrue(thread, "Invalid thread.") 11259d8dd79SMed Ismail Bennani self.assertEqual(thread.GetThreadID(), 0x19) 113a758c9f7SMed Ismail Bennani self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1") 11459d8dd79SMed Ismail Bennani self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) 11559d8dd79SMed Ismail Bennani 11659d8dd79SMed Ismail Bennani self.assertGreater(thread.GetNumFrames(), 0) 11759d8dd79SMed Ismail Bennani 11859d8dd79SMed Ismail Bennani frame = thread.GetFrameAtIndex(0) 119976867b5SMed Ismail Bennani GPRs = None 12059d8dd79SMed Ismail Bennani register_set = frame.registers # Returns an SBValueList. 12159d8dd79SMed Ismail Bennani for regs in register_set: 122976867b5SMed Ismail Bennani if 'general purpose' in regs.name.lower(): 123976867b5SMed Ismail Bennani GPRs = regs 12459d8dd79SMed Ismail Bennani break 12559d8dd79SMed Ismail Bennani 126976867b5SMed Ismail Bennani self.assertTrue(GPRs, "Invalid General Purpose Registers Set") 127976867b5SMed Ismail Bennani self.assertEqual(GPRs.GetNumChildren(), 21) 128976867b5SMed Ismail Bennani for idx, reg in enumerate(GPRs, start=1): 12959d8dd79SMed Ismail Bennani self.assertEqual(idx, int(reg.value, 16)) 13059d8dd79SMed Ismail Bennani 131976867b5SMed Ismail Bennani def create_stack_skinny_corefile(self, file): 132976867b5SMed Ismail Bennani self.build() 133976867b5SMed Ismail Bennani target, process, thread, _ = lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.c")) 134976867b5SMed Ismail Bennani self.assertTrue(process.IsValid(), "Process is invalid.") 135976867b5SMed Ismail Bennani # FIXME: Use SBAPI to save the process corefile. 136976867b5SMed Ismail Bennani self.runCmd("process save-core -s stack " + file) 137976867b5SMed Ismail Bennani self.assertTrue(os.path.exists(file), "No stack-only corefile found.") 138976867b5SMed Ismail Bennani self.assertTrue(self.dbg.DeleteTarget(target), "Couldn't delete target") 139976867b5SMed Ismail Bennani 140815c87fbSMed Ismail Bennani @skipUnlessDarwin 141419b4711SMed Ismail Bennani @skipIfOutOfTreeDebugserver 142fcd2d85cSJonas Devlieghere @skipIfAsan # rdar://85954489 143a758c9f7SMed Ismail Bennani def test_launch_scripted_process_stack_frames(self): 144312b43daSMed Ismail Bennani """Test that we can launch an lldb scripted process from the command 145312b43daSMed Ismail Bennani line, check its process ID and read string from memory.""" 146312b43daSMed Ismail Bennani self.build() 147312b43daSMed Ismail Bennani target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 148312b43daSMed Ismail Bennani self.assertTrue(target, VALID_TARGET) 149312b43daSMed Ismail Bennani 150a758c9f7SMed Ismail Bennani for module in target.modules: 151a758c9f7SMed Ismail Bennani if 'a.out' in module.GetFileSpec().GetFilename(): 152a758c9f7SMed Ismail Bennani main_module = module 153976867b5SMed Ismail Bennani break 154a758c9f7SMed Ismail Bennani 155a758c9f7SMed Ismail Bennani self.assertTrue(main_module, "Invalid main module.") 156a758c9f7SMed Ismail Bennani error = target.SetModuleLoadAddress(main_module, 0) 157a758c9f7SMed Ismail Bennani self.assertTrue(error.Success(), "Reloading main module at offset 0 failed.") 158a758c9f7SMed Ismail Bennani 159976867b5SMed Ismail Bennani os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 160419b4711SMed Ismail Bennani def cleanup(): 161419b4711SMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 162419b4711SMed Ismail Bennani self.addTearDownHook(cleanup) 163419b4711SMed Ismail Bennani 164419b4711SMed Ismail Bennani scripted_process_example_relpath = 'stack_core_scripted_process.py' 165312b43daSMed Ismail Bennani self.runCmd("command script import " + os.path.join(self.getSourceDir(), 166976867b5SMed Ismail Bennani scripted_process_example_relpath)) 167312b43daSMed Ismail Bennani 168976867b5SMed Ismail Bennani corefile_process = None 169976867b5SMed Ismail Bennani with tempfile.NamedTemporaryFile() as file: 170976867b5SMed Ismail Bennani self.create_stack_skinny_corefile(file.name) 171976867b5SMed Ismail Bennani corefile_target = self.dbg.CreateTarget(None) 172976867b5SMed Ismail Bennani corefile_process = corefile_target.LoadCore(self.getBuildArtifact(file.name)) 173976867b5SMed Ismail Bennani self.assertTrue(corefile_process, PROCESS_IS_VALID) 174976867b5SMed Ismail Bennani 175976867b5SMed Ismail Bennani structured_data = lldb.SBStructuredData() 176976867b5SMed Ismail Bennani structured_data.SetFromJSON(json.dumps({ 177976867b5SMed Ismail Bennani "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget()) 178976867b5SMed Ismail Bennani })) 179976867b5SMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 180976867b5SMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 181976867b5SMed Ismail Bennani launch_info.SetScriptedProcessClassName("stack_core_scripted_process.StackCoreScriptedProcess") 182976867b5SMed Ismail Bennani launch_info.SetScriptedProcessDictionary(structured_data) 183976867b5SMed Ismail Bennani 184976867b5SMed Ismail Bennani error = lldb.SBError() 185976867b5SMed Ismail Bennani process = target.Launch(launch_info, error) 186976867b5SMed Ismail Bennani self.assertTrue(error.Success(), error.GetCString()) 187312b43daSMed Ismail Bennani self.assertTrue(process, PROCESS_IS_VALID) 188312b43daSMed Ismail Bennani self.assertEqual(process.GetProcessID(), 42) 189312b43daSMed Ismail Bennani 190976867b5SMed Ismail Bennani self.assertEqual(process.GetNumThreads(), 1) 191a758c9f7SMed Ismail Bennani thread = process.GetSelectedThread() 192a758c9f7SMed Ismail Bennani self.assertTrue(thread, "Invalid thread.") 193976867b5SMed Ismail Bennani self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-1") 194312b43daSMed Ismail Bennani 195976867b5SMed Ismail Bennani self.assertEqual(thread.GetNumFrames(), 3) 196a758c9f7SMed Ismail Bennani frame = thread.GetSelectedFrame() 197a758c9f7SMed Ismail Bennani self.assertTrue(frame, "Invalid frame.") 198a758c9f7SMed Ismail Bennani self.assertEqual(frame.GetFunctionName(), "bar") 199a758c9f7SMed Ismail Bennani self.assertEqual(int(frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42) 200a758c9f7SMed Ismail Bennani self.assertEqual(int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42) 201