1""" 2Test python scripted process in lldb 3""" 4 5import os 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 NO_DEBUG_INFO_TESTCASE = True 16 17 mydir = TestBase.compute_mydir(__file__) 18 19 def setUp(self): 20 TestBase.setUp(self) 21 22 def tearDown(self): 23 TestBase.tearDown(self) 24 25 def test_python_plugin_package(self): 26 """Test that the lldb python module has a `plugins.scripted_process` 27 package.""" 28 self.expect('script import lldb.plugins', 29 substrs=["ModuleNotFoundError"], matching=False) 30 31 self.expect('script dir(lldb.plugins)', 32 substrs=["scripted_process"]) 33 34 self.expect('script import lldb.plugins.scripted_process', 35 substrs=["ModuleNotFoundError"], matching=False) 36 37 self.expect('script dir(lldb.plugins.scripted_process)', 38 substrs=["ScriptedProcess"]) 39 40 self.expect('script from lldb.plugins.scripted_process import ScriptedProcess', 41 substrs=["ImportError"], matching=False) 42 43 self.expect('script dir(ScriptedProcess)', 44 substrs=["launch"]) 45 46 @skipUnlessDarwin 47 def test_invalid_scripted_register_context(self): 48 """Test that we can launch an lldb scripted process with an invalid 49 Scripted Thread, with invalid register context.""" 50 self.build() 51 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 52 self.assertTrue(target, VALID_TARGET) 53 log_file = self.getBuildArtifact('thread.log') 54 self.runCmd("log enable lldb thread -f " + log_file) 55 self.assertTrue(os.path.isfile(log_file)) 56 57 os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 58 def cleanup(): 59 del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 60 self.addTearDownHook(cleanup) 61 62 scripted_process_example_relpath = 'invalid_scripted_process.py' 63 self.runCmd("command script import " + os.path.join(self.getSourceDir(), 64 scripted_process_example_relpath)) 65 66 launch_info = lldb.SBLaunchInfo(None) 67 launch_info.SetProcessPluginName("ScriptedProcess") 68 launch_info.SetScriptedProcessClassName("invalid_scripted_process.InvalidScriptedProcess") 69 error = lldb.SBError() 70 71 process = target.Launch(launch_info, error) 72 73 self.assertTrue(error.Success(), error.GetCString()) 74 self.assertTrue(process, PROCESS_IS_VALID) 75 self.assertEqual(process.GetProcessID(), 666) 76 self.assertEqual(process.GetNumThreads(), 0) 77 78 with open(log_file, 'r') as f: 79 log = f.read() 80 81 self.assertIn("Failed to get scripted thread registers data.", log) 82 83 @skipIf(archs=no_match(['x86_64', 'arm64', 'arm64e'])) 84 def test_scripted_process_and_scripted_thread(self): 85 """Test that we can launch an lldb scripted process using the SBAPI, 86 check its process ID, read string from memory, check scripted thread 87 id, name stop reason and register context. 88 """ 89 self.build() 90 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 91 self.assertTrue(target, VALID_TARGET) 92 93 os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 94 def cleanup(): 95 del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 96 self.addTearDownHook(cleanup) 97 98 scripted_process_example_relpath = 'dummy_scripted_process.py' 99 self.runCmd("command script import " + os.path.join(self.getSourceDir(), 100 scripted_process_example_relpath)) 101 102 launch_info = lldb.SBLaunchInfo(None) 103 launch_info.SetProcessPluginName("ScriptedProcess") 104 launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess") 105 106 error = lldb.SBError() 107 process = target.Launch(launch_info, error) 108 self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) 109 self.assertEqual(process.GetProcessID(), 42) 110 111 self.assertEqual(process.GetNumThreads(), 1) 112 113 thread = process.GetSelectedThread() 114 self.assertTrue(thread, "Invalid thread.") 115 self.assertEqual(thread.GetThreadID(), 0x19) 116 self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1") 117 self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) 118 119 self.assertGreater(thread.GetNumFrames(), 0) 120 121 frame = thread.GetFrameAtIndex(0) 122 GPRs = None 123 register_set = frame.registers # Returns an SBValueList. 124 for regs in register_set: 125 if 'general purpose' in regs.name.lower(): 126 GPRs = regs 127 break 128 129 self.assertTrue(GPRs, "Invalid General Purpose Registers Set") 130 self.assertGreater(GPRs.GetNumChildren(), 0) 131 for idx, reg in enumerate(GPRs, start=1): 132 if idx > 21: 133 break 134 self.assertEqual(idx, int(reg.value, 16)) 135 136