1""" 2Test python scripted process in lldb 3""" 4 5import os, shutil 6 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11from lldbsuite.test import lldbtest 12 13import dummy_scripted_process 14 15class ScriptedProcesTestCase(TestBase): 16 17 NO_DEBUG_INFO_TESTCASE = True 18 19 @skipUnlessDarwin 20 def test_python_plugin_package(self): 21 """Test that the lldb python module has a `plugins.scripted_process` 22 package.""" 23 self.expect('script import lldb.plugins', 24 substrs=["ModuleNotFoundError"], matching=False) 25 26 self.expect('script dir(lldb.plugins)', 27 substrs=["scripted_process"]) 28 29 self.expect('script import lldb.plugins.scripted_process', 30 substrs=["ModuleNotFoundError"], matching=False) 31 32 self.expect('script dir(lldb.plugins.scripted_process)', 33 substrs=["ScriptedProcess"]) 34 35 self.expect('script from lldb.plugins.scripted_process import ScriptedProcess', 36 substrs=["ImportError"], matching=False) 37 38 self.expect('script dir(ScriptedProcess)', 39 substrs=["launch"]) 40 41 def move_blueprint_to_dsym(self, blueprint_name): 42 blueprint_origin_path = os.path.join(self.getSourceDir(), blueprint_name) 43 dsym_bundle = self.getBuildArtifact("a.out.dSYM") 44 blueprint_destination_path = os.path.join(dsym_bundle, "Contents", 45 "Resources", "Python") 46 if not os.path.exists(blueprint_destination_path): 47 os.mkdir(blueprint_destination_path) 48 49 blueprint_destination_path = os.path.join(blueprint_destination_path, "a_out.py") 50 shutil.copy(blueprint_origin_path, blueprint_destination_path) 51 52 @skipUnlessDarwin 53 def test_invalid_scripted_register_context(self): 54 """Test that we can launch an lldb scripted process with an invalid 55 Scripted Thread, with invalid register context.""" 56 self.build() 57 58 os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 59 def cleanup(): 60 del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 61 self.addTearDownHook(cleanup) 62 63 self.runCmd("settings set target.load-script-from-symbol-file true") 64 self.move_blueprint_to_dsym('invalid_scripted_process.py') 65 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 66 self.assertTrue(target, VALID_TARGET) 67 log_file = self.getBuildArtifact('thread.log') 68 self.runCmd("log enable lldb thread -f " + log_file) 69 self.assertTrue(os.path.isfile(log_file)) 70 71 launch_info = lldb.SBLaunchInfo(None) 72 launch_info.SetProcessPluginName("ScriptedProcess") 73 launch_info.SetScriptedProcessClassName("a_out.InvalidScriptedProcess") 74 error = lldb.SBError() 75 76 process = target.Launch(launch_info, error) 77 78 self.assertSuccess(error) 79 self.assertTrue(process, PROCESS_IS_VALID) 80 self.assertEqual(process.GetProcessID(), 666) 81 self.assertEqual(process.GetNumThreads(), 0) 82 83 addr = 0x500000000 84 buff = process.ReadMemory(addr, 4, error) 85 self.assertEqual(buff, None) 86 self.assertTrue(error.Fail()) 87 self.assertEqual(error.GetCString(), "This is an invalid scripted process!") 88 89 with open(log_file, 'r') as f: 90 log = f.read() 91 92 self.assertIn("Failed to get scripted thread registers data.", log) 93 94 @skipUnlessDarwin 95 def test_scripted_process_and_scripted_thread(self): 96 """Test that we can launch an lldb scripted process using the SBAPI, 97 check its process ID, read string from memory, check scripted thread 98 id, name stop reason and register context. 99 """ 100 self.build() 101 target_0 = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 102 self.assertTrue(target_0, VALID_TARGET) 103 104 os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 105 def cleanup(): 106 del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 107 self.addTearDownHook(cleanup) 108 109 scripted_process_example_relpath = 'dummy_scripted_process.py' 110 self.runCmd("command script import " + os.path.join(self.getSourceDir(), 111 scripted_process_example_relpath)) 112 113 launch_info = lldb.SBLaunchInfo(None) 114 launch_info.SetProcessPluginName("ScriptedProcess") 115 launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess") 116 117 error = lldb.SBError() 118 process_0 = target_0.Launch(launch_info, error) 119 self.assertTrue(process_0 and process_0.IsValid(), PROCESS_IS_VALID) 120 self.assertEqual(process_0.GetProcessID(), 42) 121 self.assertEqual(process_0.GetNumThreads(), 1) 122 123 py_impl = process_0.GetScriptedImplementation() 124 self.assertTrue(py_impl) 125 self.assertTrue(isinstance(py_impl, dummy_scripted_process.DummyScriptedProcess)) 126 self.assertFalse(hasattr(py_impl, 'my_super_secret_member')) 127 py_impl.my_super_secret_member = 42 128 self.assertTrue(hasattr(py_impl, 'my_super_secret_member')) 129 self.assertEqual(py_impl.my_super_secret_method(), 42) 130 131 # Try reading from target #0 process ... 132 addr = 0x500000000 133 message = "Hello, target 0" 134 buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error) 135 self.assertSuccess(error) 136 self.assertEqual(buff, message) 137 138 target_1 = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 139 self.assertTrue(target_1, VALID_TARGET) 140 error = lldb.SBError() 141 process_1 = target_1.Launch(launch_info, error) 142 self.assertTrue(process_1 and process_1.IsValid(), PROCESS_IS_VALID) 143 self.assertEqual(process_1.GetProcessID(), 42) 144 self.assertEqual(process_1.GetNumThreads(), 1) 145 146 # ... then try reading from target #1 process ... 147 addr = 0x500000000 148 message = "Hello, target 1" 149 buff = process_1.ReadCStringFromMemory(addr, len(message) + 1, error) 150 self.assertSuccess(error) 151 self.assertEqual(buff, message) 152 153 # ... now, reading again from target #0 process to make sure the call 154 # gets dispatched to the right target. 155 addr = 0x500000000 156 message = "Hello, target 0" 157 buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error) 158 self.assertSuccess(error) 159 self.assertEqual(buff, message) 160 161 thread = process_0.GetSelectedThread() 162 self.assertTrue(thread, "Invalid thread.") 163 self.assertEqual(thread.GetThreadID(), 0x19) 164 self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1") 165 self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal) 166 167 self.assertGreater(thread.GetNumFrames(), 0) 168 169 frame = thread.GetFrameAtIndex(0) 170 GPRs = None 171 register_set = frame.registers # Returns an SBValueList. 172 for regs in register_set: 173 if 'general purpose' in regs.name.lower(): 174 GPRs = regs 175 break 176 177 self.assertTrue(GPRs, "Invalid General Purpose Registers Set") 178 self.assertGreater(GPRs.GetNumChildren(), 0) 179 for idx, reg in enumerate(GPRs, start=1): 180 if idx > 21: 181 break 182 self.assertEqual(idx, int(reg.value, 16)) 183 184 self.assertTrue(frame.IsArtificial(), "Frame is not artificial") 185 pc = frame.GetPCAddress().GetLoadAddress(target_0) 186 self.assertEqual(pc, 0x0100001b00) 187