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 setUp(self): 18 TestBase.setUp(self) 19 20 def tearDown(self): 21 TestBase.tearDown(self) 22 23 def test_python_plugin_package(self): 24 """Test that the lldb python module has a `plugins.scripted_process` 25 package.""" 26 self.expect('script import lldb.plugins', 27 substrs=["ModuleNotFoundError"], matching=False) 28 29 self.expect('script dir(lldb.plugins)', 30 substrs=["scripted_process"]) 31 32 self.expect('script import lldb.plugins.scripted_process', 33 substrs=["ModuleNotFoundError"], matching=False) 34 35 self.expect('script dir(lldb.plugins.scripted_process)', 36 substrs=["ScriptedProcess"]) 37 38 self.expect('script from lldb.plugins.scripted_process import ScriptedProcess', 39 substrs=["ImportError"], matching=False) 40 41 self.expect('script dir(ScriptedProcess)', 42 substrs=["launch"]) 43 44 def move_blueprint_to_dsym(self, blueprint_name): 45 blueprint_origin_path = os.path.join(self.getSourceDir(), blueprint_name) 46 dsym_bundle = self.getBuildArtifact("a.out.dSYM") 47 blueprint_destination_path = os.path.join(dsym_bundle, "Contents", 48 "Resources", "Python") 49 if not os.path.exists(blueprint_destination_path): 50 os.mkdir(blueprint_destination_path) 51 52 blueprint_destination_path = os.path.join(blueprint_destination_path, "a_out.py") 53 shutil.copy(blueprint_origin_path, blueprint_destination_path) 54 55 @skipUnlessDarwin 56 def test_invalid_scripted_register_context(self): 57 """Test that we can launch an lldb scripted process with an invalid 58 Scripted Thread, with invalid register context.""" 59 self.build() 60 61 os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 62 def cleanup(): 63 del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 64 self.addTearDownHook(cleanup) 65 66 self.runCmd("settings set target.load-script-from-symbol-file true") 67 self.move_blueprint_to_dsym('invalid_scripted_process.py') 68 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 69 self.assertTrue(target, VALID_TARGET) 70 log_file = self.getBuildArtifact('thread.log') 71 self.runCmd("log enable lldb thread -f " + log_file) 72 self.assertTrue(os.path.isfile(log_file)) 73 74 launch_info = lldb.SBLaunchInfo(None) 75 launch_info.SetProcessPluginName("ScriptedProcess") 76 launch_info.SetScriptedProcessClassName("a_out.InvalidScriptedProcess") 77 error = lldb.SBError() 78 79 process = target.Launch(launch_info, error) 80 81 self.assertSuccess(error) 82 self.assertTrue(process, PROCESS_IS_VALID) 83 self.assertEqual(process.GetProcessID(), 666) 84 self.assertEqual(process.GetNumThreads(), 0) 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 119 self.assertEqual(process.GetNumThreads(), 1) 120 121 thread = process.GetSelectedThread() 122 self.assertTrue(thread, "Invalid thread.") 123 self.assertEqual(thread.GetThreadID(), 0x19) 124 self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1") 125 self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal) 126 127 self.assertGreater(thread.GetNumFrames(), 0) 128 129 frame = thread.GetFrameAtIndex(0) 130 GPRs = None 131 register_set = frame.registers # Returns an SBValueList. 132 for regs in register_set: 133 if 'general purpose' in regs.name.lower(): 134 GPRs = regs 135 break 136 137 self.assertTrue(GPRs, "Invalid General Purpose Registers Set") 138 self.assertGreater(GPRs.GetNumChildren(), 0) 139 for idx, reg in enumerate(GPRs, start=1): 140 if idx > 21: 141 break 142 self.assertEqual(idx, int(reg.value, 16)) 143 144 self.assertTrue(frame.IsArtificial(), "Frame is not artificial") 145 pc = frame.GetPCAddress().GetLoadAddress(target) 146 self.assertEqual(pc, 0x0100001b00) 147