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 def test_launch_scripted_process_stack_frames(self): 108 """Test that we can launch an lldb scripted process from the command 109 line, check its process ID and read string from memory.""" 110 self.build() 111 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 112 self.assertTrue(target, VALID_TARGET) 113 114 for module in target.modules: 115 if 'a.out' in module.GetFileSpec().GetFilename(): 116 main_module = module 117 break 118 119 self.assertTrue(main_module, "Invalid main module.") 120 error = target.SetModuleLoadAddress(main_module, 0) 121 self.assertTrue(error.Success(), "Reloading main module at offset 0 failed.") 122 123 os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 124 def cleanup(): 125 del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 126 self.addTearDownHook(cleanup) 127 128 scripted_process_example_relpath = 'stack_core_scripted_process.py' 129 self.runCmd("command script import " + os.path.join(self.getSourceDir(), 130 scripted_process_example_relpath)) 131 132 corefile_process = None 133 with tempfile.NamedTemporaryFile() as file: 134 self.create_stack_skinny_corefile(file.name) 135 corefile_target = self.dbg.CreateTarget(None) 136 corefile_process = corefile_target.LoadCore(self.getBuildArtifact(file.name)) 137 self.assertTrue(corefile_process, PROCESS_IS_VALID) 138 139 structured_data = lldb.SBStructuredData() 140 structured_data.SetFromJSON(json.dumps({ 141 "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget()) 142 })) 143 launch_info = lldb.SBLaunchInfo(None) 144 launch_info.SetProcessPluginName("ScriptedProcess") 145 launch_info.SetScriptedProcessClassName("stack_core_scripted_process.StackCoreScriptedProcess") 146 launch_info.SetScriptedProcessDictionary(structured_data) 147 148 error = lldb.SBError() 149 process = target.Launch(launch_info, error) 150 self.assertTrue(error.Success(), error.GetCString()) 151 self.assertTrue(process, PROCESS_IS_VALID) 152 self.assertEqual(process.GetProcessID(), 42) 153 154 self.assertEqual(process.GetNumThreads(), 1) 155 thread = process.GetSelectedThread() 156 self.assertTrue(thread, "Invalid thread.") 157 self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-1") 158 159 self.assertEqual(thread.GetNumFrames(), 3) 160 frame = thread.GetSelectedFrame() 161 self.assertTrue(frame, "Invalid frame.") 162 self.assertEqual(frame.GetFunctionName(), "bar") 163 self.assertEqual(int(frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42) 164 self.assertEqual(int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42) 165