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