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