1f3176f5fSMed Ismail Bennani""" 2f3176f5fSMed Ismail BennaniTest python scripted process in lldb 3f3176f5fSMed Ismail Bennani""" 4f3176f5fSMed Ismail Bennani 56aa48034SMed Ismail Bennaniimport os, shutil 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 13c1928033SMed Ismail Bennaniimport dummy_scripted_process 14c1928033SMed Ismail Bennani 15f3176f5fSMed Ismail Bennani 162238dcc3SJonas Devlieghereclass ScriptedProcesTestCase(TestBase): 17d327108dSMed Ismail Bennani NO_DEBUG_INFO_TESTCASE = True 18d327108dSMed Ismail Bennani 19d69e5dfaSMed Ismail Bennani @skipUnlessDarwin 20f3176f5fSMed Ismail Bennani def test_python_plugin_package(self): 21f3176f5fSMed Ismail Bennani """Test that the lldb python module has a `plugins.scripted_process` 22f3176f5fSMed Ismail Bennani package.""" 232238dcc3SJonas Devlieghere self.expect( 242238dcc3SJonas Devlieghere "script import lldb.plugins", 252238dcc3SJonas Devlieghere substrs=["ModuleNotFoundError"], 262238dcc3SJonas Devlieghere matching=False, 272238dcc3SJonas Devlieghere ) 28f3176f5fSMed Ismail Bennani 292238dcc3SJonas Devlieghere self.expect("script dir(lldb.plugins)", substrs=["scripted_process"]) 30f3176f5fSMed Ismail Bennani 312238dcc3SJonas Devlieghere self.expect( 322238dcc3SJonas Devlieghere "script import lldb.plugins.scripted_process", 332238dcc3SJonas Devlieghere substrs=["ModuleNotFoundError"], 342238dcc3SJonas Devlieghere matching=False, 352238dcc3SJonas Devlieghere ) 36f3176f5fSMed Ismail Bennani 372238dcc3SJonas Devlieghere self.expect( 382238dcc3SJonas Devlieghere "script dir(lldb.plugins.scripted_process)", substrs=["ScriptedProcess"] 392238dcc3SJonas Devlieghere ) 40f3176f5fSMed Ismail Bennani 412238dcc3SJonas Devlieghere self.expect( 422238dcc3SJonas Devlieghere "script from lldb.plugins.scripted_process import ScriptedProcess", 432238dcc3SJonas Devlieghere substrs=["ImportError"], 442238dcc3SJonas Devlieghere matching=False, 452238dcc3SJonas Devlieghere ) 46f3176f5fSMed Ismail Bennani 472238dcc3SJonas Devlieghere self.expect("script dir(ScriptedProcess)", substrs=["launch"]) 48f3176f5fSMed Ismail Bennani 496aa48034SMed Ismail Bennani def move_blueprint_to_dsym(self, blueprint_name): 506aa48034SMed Ismail Bennani blueprint_origin_path = os.path.join(self.getSourceDir(), blueprint_name) 516aa48034SMed Ismail Bennani dsym_bundle = self.getBuildArtifact("a.out.dSYM") 522238dcc3SJonas Devlieghere blueprint_destination_path = os.path.join( 532238dcc3SJonas Devlieghere dsym_bundle, "Contents", "Resources", "Python" 542238dcc3SJonas Devlieghere ) 556aa48034SMed Ismail Bennani if not os.path.exists(blueprint_destination_path): 566aa48034SMed Ismail Bennani os.mkdir(blueprint_destination_path) 576aa48034SMed Ismail Bennani 582238dcc3SJonas Devlieghere blueprint_destination_path = os.path.join( 592238dcc3SJonas Devlieghere blueprint_destination_path, "a_out.py" 602238dcc3SJonas Devlieghere ) 616aa48034SMed Ismail Bennani shutil.copy(blueprint_origin_path, blueprint_destination_path) 626aa48034SMed Ismail Bennani 63ea828534SDavid Spickett # No dylib on Windows. 64ea828534SDavid Spickett @skipIfWindows 650a211446SMed Ismail Bennani def test_missing_methods_scripted_register_context(self): 660a211446SMed Ismail Bennani """Test that we only instanciate scripted processes if they implement 670a211446SMed Ismail Bennani all the required abstract methods.""" 680a211446SMed Ismail Bennani self.build() 690a211446SMed Ismail Bennani 700a211446SMed Ismail Bennani os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1" 710a211446SMed Ismail Bennani 720a211446SMed Ismail Bennani def cleanup(): 730a211446SMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 740a211446SMed Ismail Bennani 750a211446SMed Ismail Bennani self.addTearDownHook(cleanup) 760a211446SMed Ismail Bennani 770a211446SMed Ismail Bennani target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 780a211446SMed Ismail Bennani self.assertTrue(target, VALID_TARGET) 790a211446SMed Ismail Bennani log_file = self.getBuildArtifact("script.log") 800a211446SMed Ismail Bennani self.runCmd("log enable lldb script -f " + log_file) 810a211446SMed Ismail Bennani self.assertTrue(os.path.isfile(log_file)) 820a211446SMed Ismail Bennani script_path = os.path.join( 830a211446SMed Ismail Bennani self.getSourceDir(), "missing_methods_scripted_process.py" 840a211446SMed Ismail Bennani ) 850a211446SMed Ismail Bennani self.runCmd("command script import " + script_path) 860a211446SMed Ismail Bennani 870a211446SMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 880a211446SMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 890a211446SMed Ismail Bennani launch_info.SetScriptedProcessClassName( 900a211446SMed Ismail Bennani "missing_methods_scripted_process.MissingMethodsScriptedProcess" 910a211446SMed Ismail Bennani ) 920a211446SMed Ismail Bennani error = lldb.SBError() 930a211446SMed Ismail Bennani 940a211446SMed Ismail Bennani process = target.Launch(launch_info, error) 950a211446SMed Ismail Bennani 960a211446SMed Ismail Bennani self.assertFailure(error) 970a211446SMed Ismail Bennani 980a211446SMed Ismail Bennani with open(log_file, "r") as f: 990a211446SMed Ismail Bennani log = f.read() 1000a211446SMed Ismail Bennani 1010a211446SMed Ismail Bennani self.assertIn( 1020a211446SMed Ismail Bennani "Abstract method MissingMethodsScriptedProcess.read_memory_at_address not implemented", 1030a211446SMed Ismail Bennani log, 1040a211446SMed Ismail Bennani ) 1050a211446SMed Ismail Bennani self.assertIn( 1060a211446SMed Ismail Bennani "Abstract method MissingMethodsScriptedProcess.is_alive not implemented", 1070a211446SMed Ismail Bennani log, 1080a211446SMed Ismail Bennani ) 1090a211446SMed Ismail Bennani self.assertIn( 1100a211446SMed Ismail Bennani "Abstract method MissingMethodsScriptedProcess.get_scripted_thread_plugin not implemented", 1110a211446SMed Ismail Bennani log, 1120a211446SMed Ismail Bennani ) 1130a211446SMed Ismail Bennani 114c3ca2c6bSMed Ismail Bennani @skipUnlessDarwin 115caea440aSMed Ismail Bennani def test_invalid_scripted_register_context(self): 116caea440aSMed Ismail Bennani """Test that we can launch an lldb scripted process with an invalid 117caea440aSMed Ismail Bennani Scripted Thread, with invalid register context.""" 118caea440aSMed Ismail Bennani self.build() 119caea440aSMed Ismail Bennani 1202238dcc3SJonas Devlieghere os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1" 1212238dcc3SJonas Devlieghere 122a6b56243SMed Ismail Bennani def cleanup(): 123a6b56243SMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 1242238dcc3SJonas Devlieghere 125a6b56243SMed Ismail Bennani self.addTearDownHook(cleanup) 126a6b56243SMed Ismail Bennani 1276aa48034SMed Ismail Bennani self.runCmd("settings set target.load-script-from-symbol-file true") 1282238dcc3SJonas Devlieghere self.move_blueprint_to_dsym("invalid_scripted_process.py") 1296aa48034SMed Ismail Bennani target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 1306aa48034SMed Ismail Bennani self.assertTrue(target, VALID_TARGET) 1312238dcc3SJonas Devlieghere log_file = self.getBuildArtifact("thread.log") 1326aa48034SMed Ismail Bennani self.runCmd("log enable lldb thread -f " + log_file) 1336aa48034SMed Ismail Bennani self.assertTrue(os.path.isfile(log_file)) 134caea440aSMed Ismail Bennani 135caea440aSMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 136caea440aSMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 1376aa48034SMed Ismail Bennani launch_info.SetScriptedProcessClassName("a_out.InvalidScriptedProcess") 138caea440aSMed Ismail Bennani error = lldb.SBError() 1399c144b3bSMed Ismail Bennani 140caea440aSMed Ismail Bennani process = target.Launch(launch_info, error) 141caea440aSMed Ismail Bennani 142779bbbf2SDave Lee self.assertSuccess(error) 143caea440aSMed Ismail Bennani self.assertTrue(process, PROCESS_IS_VALID) 144caea440aSMed Ismail Bennani self.assertEqual(process.GetProcessID(), 666) 145caea440aSMed Ismail Bennani self.assertEqual(process.GetNumThreads(), 0) 146caea440aSMed Ismail Bennani 147ebdbc26aSMed Ismail Bennani impl = process.GetScriptedImplementation() 148ebdbc26aSMed Ismail Bennani self.assertTrue(impl) 149ebdbc26aSMed Ismail Bennani impl = process.GetScriptedImplementation() 150ebdbc26aSMed Ismail Bennani self.assertTrue(impl) 151ebdbc26aSMed Ismail Bennani impl = process.GetScriptedImplementation() 152ebdbc26aSMed Ismail Bennani self.assertTrue(impl) 153ebdbc26aSMed Ismail Bennani impl = process.GetScriptedImplementation() 154ebdbc26aSMed Ismail Bennani self.assertTrue(impl) 155ebdbc26aSMed Ismail Bennani 1567e01924eSMed Ismail Bennani addr = 0x500000000 1577e01924eSMed Ismail Bennani buff = process.ReadMemory(addr, 4, error) 1587e01924eSMed Ismail Bennani self.assertEqual(buff, None) 1597e01924eSMed Ismail Bennani self.assertTrue(error.Fail()) 1607e01924eSMed Ismail Bennani self.assertEqual(error.GetCString(), "This is an invalid scripted process!") 1617e01924eSMed Ismail Bennani 1622238dcc3SJonas Devlieghere with open(log_file, "r") as f: 1639c144b3bSMed Ismail Bennani log = f.read() 1649c144b3bSMed Ismail Bennani 1659c144b3bSMed Ismail Bennani self.assertIn("Failed to get scripted thread registers data.", log) 166caea440aSMed Ismail Bennani 16786e6030eSMed Ismail Bennani @skipUnlessDarwin 168a758c9f7SMed Ismail Bennani def test_scripted_process_and_scripted_thread(self): 169312b43daSMed Ismail Bennani """Test that we can launch an lldb scripted process using the SBAPI, 170a758c9f7SMed Ismail Bennani check its process ID, read string from memory, check scripted thread 171a758c9f7SMed Ismail Bennani id, name stop reason and register context. 172a758c9f7SMed Ismail Bennani """ 173312b43daSMed Ismail Bennani self.build() 174a3d4f739SMed Ismail Bennani target_0 = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 175a3d4f739SMed Ismail Bennani self.assertTrue(target_0, VALID_TARGET) 176312b43daSMed Ismail Bennani 1772238dcc3SJonas Devlieghere os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1" 1782238dcc3SJonas Devlieghere 179a6b56243SMed Ismail Bennani def cleanup(): 180a6b56243SMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 1812238dcc3SJonas Devlieghere 182a6b56243SMed Ismail Bennani self.addTearDownHook(cleanup) 183a6b56243SMed Ismail Bennani 1842238dcc3SJonas Devlieghere scripted_process_example_relpath = "dummy_scripted_process.py" 1852238dcc3SJonas Devlieghere self.runCmd( 1862238dcc3SJonas Devlieghere "command script import " 1872238dcc3SJonas Devlieghere + os.path.join(self.getSourceDir(), scripted_process_example_relpath) 1882238dcc3SJonas Devlieghere ) 189312b43daSMed Ismail Bennani 190*b3a835e1SMed Ismail Bennani self.runCmd( 191*b3a835e1SMed Ismail Bennani "target stop-hook add -k first -v 1 -k second -v 2 -P dummy_scripted_process.DummyStopHook" 192*b3a835e1SMed Ismail Bennani ) 193*b3a835e1SMed Ismail Bennani 194312b43daSMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 195312b43daSMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 1962238dcc3SJonas Devlieghere launch_info.SetScriptedProcessClassName( 1972238dcc3SJonas Devlieghere "dummy_scripted_process.DummyScriptedProcess" 1982238dcc3SJonas Devlieghere ) 199312b43daSMed Ismail Bennani 200312b43daSMed Ismail Bennani error = lldb.SBError() 201a3d4f739SMed Ismail Bennani process_0 = target_0.Launch(launch_info, error) 202a3d4f739SMed Ismail Bennani self.assertTrue(process_0 and process_0.IsValid(), PROCESS_IS_VALID) 203a3d4f739SMed Ismail Bennani self.assertEqual(process_0.GetProcessID(), 42) 204a3d4f739SMed Ismail Bennani self.assertEqual(process_0.GetNumThreads(), 1) 20559d8dd79SMed Ismail Bennani 206a3d4f739SMed Ismail Bennani py_impl = process_0.GetScriptedImplementation() 207c1928033SMed Ismail Bennani self.assertTrue(py_impl) 2089c246882SJordan Rupprecht self.assertIsInstance(py_impl, dummy_scripted_process.DummyScriptedProcess) 2092238dcc3SJonas Devlieghere self.assertFalse(hasattr(py_impl, "my_super_secret_member")) 210c1928033SMed Ismail Bennani py_impl.my_super_secret_member = 42 2112238dcc3SJonas Devlieghere self.assertTrue(hasattr(py_impl, "my_super_secret_member")) 212c1928033SMed Ismail Bennani self.assertEqual(py_impl.my_super_secret_method(), 42) 213c1928033SMed Ismail Bennani 214*b3a835e1SMed Ismail Bennani self.assertTrue(hasattr(py_impl, "handled_stop")) 215*b3a835e1SMed Ismail Bennani self.assertTrue(py_impl.handled_stop) 216*b3a835e1SMed Ismail Bennani 217a3d4f739SMed Ismail Bennani # Try reading from target #0 process ... 2187e01924eSMed Ismail Bennani addr = 0x500000000 219a3d4f739SMed Ismail Bennani message = "Hello, target 0" 220a3d4f739SMed Ismail Bennani buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error) 2217e01924eSMed Ismail Bennani self.assertSuccess(error) 2227e01924eSMed Ismail Bennani self.assertEqual(buff, message) 2237e01924eSMed Ismail Bennani 224a3d4f739SMed Ismail Bennani target_1 = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 225a3d4f739SMed Ismail Bennani self.assertTrue(target_1, VALID_TARGET) 226b9d4c94aSMed Ismail Bennani 227b9d4c94aSMed Ismail Bennani # We still need to specify a PID when attaching even for scripted processes 228b9d4c94aSMed Ismail Bennani attach_info = lldb.SBAttachInfo(42) 229b9d4c94aSMed Ismail Bennani attach_info.SetProcessPluginName("ScriptedProcess") 2302238dcc3SJonas Devlieghere attach_info.SetScriptedProcessClassName( 2312238dcc3SJonas Devlieghere "dummy_scripted_process.DummyScriptedProcess" 2322238dcc3SJonas Devlieghere ) 233b9d4c94aSMed Ismail Bennani 234a3d4f739SMed Ismail Bennani error = lldb.SBError() 235b9d4c94aSMed Ismail Bennani process_1 = target_1.Attach(attach_info, error) 236a3d4f739SMed Ismail Bennani self.assertTrue(process_1 and process_1.IsValid(), PROCESS_IS_VALID) 237a3d4f739SMed Ismail Bennani self.assertEqual(process_1.GetProcessID(), 42) 238a3d4f739SMed Ismail Bennani self.assertEqual(process_1.GetNumThreads(), 1) 239a3d4f739SMed Ismail Bennani 240a3d4f739SMed Ismail Bennani # ... then try reading from target #1 process ... 241a3d4f739SMed Ismail Bennani message = "Hello, target 1" 242a3d4f739SMed Ismail Bennani buff = process_1.ReadCStringFromMemory(addr, len(message) + 1, error) 243a3d4f739SMed Ismail Bennani self.assertSuccess(error) 244a3d4f739SMed Ismail Bennani self.assertEqual(buff, message) 245a3d4f739SMed Ismail Bennani 246a3d4f739SMed Ismail Bennani # ... now, reading again from target #0 process to make sure the call 247a3d4f739SMed Ismail Bennani # gets dispatched to the right target. 248a3d4f739SMed Ismail Bennani message = "Hello, target 0" 249a3d4f739SMed Ismail Bennani buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error) 250a3d4f739SMed Ismail Bennani self.assertSuccess(error) 251a3d4f739SMed Ismail Bennani self.assertEqual(buff, message) 252a3d4f739SMed Ismail Bennani 253f190ec68SMed Ismail Bennani # Let's write some memory. 254f190ec68SMed Ismail Bennani message = "Hello, world!" 255f190ec68SMed Ismail Bennani bytes_written = process_0.WriteMemoryAsCString(addr, message, error) 256f190ec68SMed Ismail Bennani self.assertSuccess(error) 257f190ec68SMed Ismail Bennani self.assertEqual(bytes_written, len(message) + 1) 258f190ec68SMed Ismail Bennani 259f190ec68SMed Ismail Bennani # ... and check if that memory was saved properly. 260f190ec68SMed Ismail Bennani buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error) 261f190ec68SMed Ismail Bennani self.assertSuccess(error) 262f190ec68SMed Ismail Bennani self.assertEqual(buff, message) 263f190ec68SMed Ismail Bennani 264a3d4f739SMed Ismail Bennani thread = process_0.GetSelectedThread() 26559d8dd79SMed Ismail Bennani self.assertTrue(thread, "Invalid thread.") 26659d8dd79SMed Ismail Bennani self.assertEqual(thread.GetThreadID(), 0x19) 267a758c9f7SMed Ismail Bennani self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1") 2688f407b8eSMed Ismail Bennani self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonTrace) 26959d8dd79SMed Ismail Bennani 27059d8dd79SMed Ismail Bennani self.assertGreater(thread.GetNumFrames(), 0) 27159d8dd79SMed Ismail Bennani 27259d8dd79SMed Ismail Bennani frame = thread.GetFrameAtIndex(0) 273976867b5SMed Ismail Bennani GPRs = None 27459d8dd79SMed Ismail Bennani register_set = frame.registers # Returns an SBValueList. 27559d8dd79SMed Ismail Bennani for regs in register_set: 2762238dcc3SJonas Devlieghere if "general purpose" in regs.name.lower(): 277976867b5SMed Ismail Bennani GPRs = regs 27859d8dd79SMed Ismail Bennani break 27959d8dd79SMed Ismail Bennani 280976867b5SMed Ismail Bennani self.assertTrue(GPRs, "Invalid General Purpose Registers Set") 281c3ca2c6bSMed Ismail Bennani self.assertGreater(GPRs.GetNumChildren(), 0) 282976867b5SMed Ismail Bennani for idx, reg in enumerate(GPRs, start=1): 283c3ca2c6bSMed Ismail Bennani if idx > 21: 284c3ca2c6bSMed Ismail Bennani break 28559d8dd79SMed Ismail Bennani self.assertEqual(idx, int(reg.value, 16)) 28659d8dd79SMed Ismail Bennani 28770665844SMed Ismail Bennani self.assertTrue(frame.IsArtificial(), "Frame is not artificial") 288a3d4f739SMed Ismail Bennani pc = frame.GetPCAddress().GetLoadAddress(target_0) 2892238dcc3SJonas Devlieghere self.assertEqual(pc, 0x0100001B00) 290