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