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