1""" 2Test python scripted process in lldb 3""" 4 5import os, json, tempfile 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 mydir = TestBase.compute_mydir(__file__) 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 @skipIf(archs=no_match(['x86_64'])) 45 def test_scripted_process_and_scripted_thread(self): 46 """Test that we can launch an lldb scripted process using the SBAPI, 47 check its process ID, read string from memory, check scripted thread 48 id, name stop reason and register context. 49 """ 50 self.build() 51 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 52 self.assertTrue(target, VALID_TARGET) 53 54 os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 55 def cleanup(): 56 del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 57 self.addTearDownHook(cleanup) 58 59 scripted_process_example_relpath = 'dummy_scripted_process.py' 60 self.runCmd("command script import " + os.path.join(self.getSourceDir(), 61 scripted_process_example_relpath)) 62 63 launch_info = lldb.SBLaunchInfo(None) 64 launch_info.SetProcessPluginName("ScriptedProcess") 65 launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess") 66 67 error = lldb.SBError() 68 process = target.Launch(launch_info, error) 69 self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) 70 self.assertEqual(process.GetProcessID(), 42) 71 72 self.assertEqual(process.GetNumThreads(), 1) 73 74 thread = process.GetSelectedThread() 75 self.assertTrue(thread, "Invalid thread.") 76 self.assertEqual(thread.GetThreadID(), 0x19) 77 self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1") 78 self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) 79 80 self.assertGreater(thread.GetNumFrames(), 0) 81 82 frame = thread.GetFrameAtIndex(0) 83 GPRs = None 84 register_set = frame.registers # Returns an SBValueList. 85 for regs in register_set: 86 if 'general purpose' in regs.name.lower(): 87 GPRs = regs 88 break 89 90 self.assertTrue(GPRs, "Invalid General Purpose Registers Set") 91 self.assertEqual(GPRs.GetNumChildren(), 21) 92 for idx, reg in enumerate(GPRs, start=1): 93 self.assertEqual(idx, int(reg.value, 16)) 94 95 def create_stack_skinny_corefile(self, file): 96 self.build() 97 target, process, thread, _ = lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.c")) 98 self.assertTrue(process.IsValid(), "Process is invalid.") 99 # FIXME: Use SBAPI to save the process corefile. 100 self.runCmd("process save-core -s stack " + file) 101 self.assertTrue(os.path.exists(file), "No stack-only corefile found.") 102 self.assertTrue(self.dbg.DeleteTarget(target), "Couldn't delete target") 103 104 @skipUnlessDarwin 105 @skipIfOutOfTreeDebugserver 106 @skipIf(archs=no_match(['x86_64'])) 107 @skipIfAsan # rdar://85954489 108 def test_launch_scripted_process_stack_frames(self): 109 """Test that we can launch an lldb scripted process from the command 110 line, check its process ID and read string from memory.""" 111 self.build() 112 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 113 self.assertTrue(target, VALID_TARGET) 114 115 for module in target.modules: 116 if 'a.out' in module.GetFileSpec().GetFilename(): 117 main_module = module 118 break 119 120 self.assertTrue(main_module, "Invalid main module.") 121 error = target.SetModuleLoadAddress(main_module, 0) 122 self.assertTrue(error.Success(), "Reloading main module at offset 0 failed.") 123 124 os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 125 def cleanup(): 126 del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 127 self.addTearDownHook(cleanup) 128 129 scripted_process_example_relpath = 'stack_core_scripted_process.py' 130 self.runCmd("command script import " + os.path.join(self.getSourceDir(), 131 scripted_process_example_relpath)) 132 133 corefile_process = None 134 with tempfile.NamedTemporaryFile() as file: 135 self.create_stack_skinny_corefile(file.name) 136 corefile_target = self.dbg.CreateTarget(None) 137 corefile_process = corefile_target.LoadCore(self.getBuildArtifact(file.name)) 138 self.assertTrue(corefile_process, PROCESS_IS_VALID) 139 140 structured_data = lldb.SBStructuredData() 141 structured_data.SetFromJSON(json.dumps({ 142 "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget()) 143 })) 144 launch_info = lldb.SBLaunchInfo(None) 145 launch_info.SetProcessPluginName("ScriptedProcess") 146 launch_info.SetScriptedProcessClassName("stack_core_scripted_process.StackCoreScriptedProcess") 147 launch_info.SetScriptedProcessDictionary(structured_data) 148 149 error = lldb.SBError() 150 process = target.Launch(launch_info, error) 151 self.assertTrue(error.Success(), error.GetCString()) 152 self.assertTrue(process, PROCESS_IS_VALID) 153 self.assertEqual(process.GetProcessID(), 42) 154 155 self.assertEqual(process.GetNumThreads(), 1) 156 thread = process.GetSelectedThread() 157 self.assertTrue(thread, "Invalid thread.") 158 self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-1") 159 160 self.assertEqual(thread.GetNumFrames(), 3) 161 frame = thread.GetSelectedFrame() 162 self.assertTrue(frame, "Invalid frame.") 163 self.assertEqual(frame.GetFunctionName(), "bar") 164 self.assertEqual(int(frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42) 165 self.assertEqual(int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42) 166