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 with open(log_file, 'r') as f: 81 log = f.read() 82 83 self.assertIn("Failed to get scripted thread registers data.", log) 84 85 @skipUnlessDarwin 86 def test_scripted_process_and_scripted_thread(self): 87 """Test that we can launch an lldb scripted process using the SBAPI, 88 check its process ID, read string from memory, check scripted thread 89 id, name stop reason and register context. 90 """ 91 self.build() 92 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 93 self.assertTrue(target, VALID_TARGET) 94 95 os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 96 def cleanup(): 97 del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 98 self.addTearDownHook(cleanup) 99 100 scripted_process_example_relpath = 'dummy_scripted_process.py' 101 self.runCmd("command script import " + os.path.join(self.getSourceDir(), 102 scripted_process_example_relpath)) 103 104 launch_info = lldb.SBLaunchInfo(None) 105 launch_info.SetProcessPluginName("ScriptedProcess") 106 launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess") 107 108 error = lldb.SBError() 109 process = target.Launch(launch_info, error) 110 self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) 111 self.assertEqual(process.GetProcessID(), 42) 112 113 self.assertEqual(process.GetNumThreads(), 1) 114 115 thread = process.GetSelectedThread() 116 self.assertTrue(thread, "Invalid thread.") 117 self.assertEqual(thread.GetThreadID(), 0x19) 118 self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1") 119 self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal) 120 121 self.assertGreater(thread.GetNumFrames(), 0) 122 123 frame = thread.GetFrameAtIndex(0) 124 GPRs = None 125 register_set = frame.registers # Returns an SBValueList. 126 for regs in register_set: 127 if 'general purpose' in regs.name.lower(): 128 GPRs = regs 129 break 130 131 self.assertTrue(GPRs, "Invalid General Purpose Registers Set") 132 self.assertGreater(GPRs.GetNumChildren(), 0) 133 for idx, reg in enumerate(GPRs, start=1): 134 if idx > 21: 135 break 136 self.assertEqual(idx, int(reg.value, 16)) 137 138 self.assertTrue(frame.IsArtificial(), "Frame is not artificial") 139 pc = frame.GetPCAddress().GetLoadAddress(target) 140 self.assertEqual(pc, 0x0100001b00) 141