1d327108dSMed Ismail Bennani""" 2d327108dSMed Ismail BennaniTest python scripted process in lldb 3d327108dSMed Ismail Bennani""" 4d327108dSMed Ismail Bennani 5d327108dSMed Ismail Bennaniimport os, json, tempfile 6d327108dSMed Ismail Bennani 7d327108dSMed Ismail Bennaniimport lldb 8d327108dSMed Ismail Bennanifrom lldbsuite.test.decorators import * 9d327108dSMed Ismail Bennanifrom lldbsuite.test.lldbtest import * 10d327108dSMed Ismail Bennanifrom lldbsuite.test import lldbutil 11d327108dSMed Ismail Bennanifrom lldbsuite.test import lldbtest 12d327108dSMed Ismail Bennani 13d327108dSMed Ismail Bennaniclass StackCoreScriptedProcesTestCase(TestBase): 14d327108dSMed Ismail Bennani 15d327108dSMed Ismail Bennani NO_DEBUG_INFO_TESTCASE = True 16d327108dSMed Ismail Bennani 17d327108dSMed Ismail Bennani def setUp(self): 18d327108dSMed Ismail Bennani TestBase.setUp(self) 19d327108dSMed Ismail Bennani 20d327108dSMed Ismail Bennani def tearDown(self): 21d327108dSMed Ismail Bennani TestBase.tearDown(self) 22d327108dSMed Ismail Bennani 23d327108dSMed Ismail Bennani def create_stack_skinny_corefile(self, file): 24d327108dSMed Ismail Bennani self.build() 25d327108dSMed Ismail Bennani target, process, thread, _ = lldbutil.run_to_source_breakpoint(self, "// break here", 26680ca7f2SMed Ismail Bennani lldb.SBFileSpec("baz.c")) 27d327108dSMed Ismail Bennani self.assertTrue(process.IsValid(), "Process is invalid.") 28d327108dSMed Ismail Bennani # FIXME: Use SBAPI to save the process corefile. 29d327108dSMed Ismail Bennani self.runCmd("process save-core -s stack " + file) 30d327108dSMed Ismail Bennani self.assertTrue(os.path.exists(file), "No stack-only corefile found.") 31d327108dSMed Ismail Bennani self.assertTrue(self.dbg.DeleteTarget(target), "Couldn't delete target") 32d327108dSMed Ismail Bennani 33680ca7f2SMed Ismail Bennani def get_module_with_name(self, target, name): 34680ca7f2SMed Ismail Bennani for module in target.modules: 35680ca7f2SMed Ismail Bennani if name in module.GetFileSpec().GetFilename(): 36680ca7f2SMed Ismail Bennani return module 37680ca7f2SMed Ismail Bennani return None 38680ca7f2SMed Ismail Bennani 39d327108dSMed Ismail Bennani @skipUnlessDarwin 40d327108dSMed Ismail Bennani @skipIfOutOfTreeDebugserver 41*065e3c9aSJonas Devlieghere @skipIfRemote 42d327108dSMed Ismail Bennani def test_launch_scripted_process_stack_frames(self): 43d327108dSMed Ismail Bennani """Test that we can launch an lldb scripted process from the command 44d327108dSMed Ismail Bennani line, check its process ID and read string from memory.""" 45d327108dSMed Ismail Bennani self.build() 46d327108dSMed Ismail Bennani target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 47d327108dSMed Ismail Bennani self.assertTrue(target, VALID_TARGET) 48d327108dSMed Ismail Bennani 49680ca7f2SMed Ismail Bennani main_module = self.get_module_with_name(target, 'a.out') 50d327108dSMed Ismail Bennani self.assertTrue(main_module, "Invalid main module.") 51d327108dSMed Ismail Bennani error = target.SetModuleLoadAddress(main_module, 0) 52779bbbf2SDave Lee self.assertSuccess(error, "Reloading main module at offset 0 failed.") 53d327108dSMed Ismail Bennani 54680ca7f2SMed Ismail Bennani scripted_dylib = self.get_module_with_name(target, 'libbaz.dylib') 55680ca7f2SMed Ismail Bennani self.assertTrue(scripted_dylib, "Dynamic library libbaz.dylib not found.") 56680ca7f2SMed Ismail Bennani self.assertEqual(scripted_dylib.GetObjectFileHeaderAddress().GetLoadAddress(target), 0xffffffffffffffff) 57680ca7f2SMed Ismail Bennani 58d327108dSMed Ismail Bennani os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' 59d327108dSMed Ismail Bennani def cleanup(): 60d327108dSMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 61d327108dSMed Ismail Bennani self.addTearDownHook(cleanup) 62d327108dSMed Ismail Bennani 63d327108dSMed Ismail Bennani scripted_process_example_relpath = 'stack_core_scripted_process.py' 64d327108dSMed Ismail Bennani self.runCmd("command script import " + os.path.join(self.getSourceDir(), 65d327108dSMed Ismail Bennani scripted_process_example_relpath)) 66d327108dSMed Ismail Bennani 67d327108dSMed Ismail Bennani corefile_process = None 68d327108dSMed Ismail Bennani with tempfile.NamedTemporaryFile() as file: 69d327108dSMed Ismail Bennani self.create_stack_skinny_corefile(file.name) 70d327108dSMed Ismail Bennani corefile_target = self.dbg.CreateTarget(None) 71d327108dSMed Ismail Bennani corefile_process = corefile_target.LoadCore(self.getBuildArtifact(file.name)) 72d327108dSMed Ismail Bennani self.assertTrue(corefile_process, PROCESS_IS_VALID) 73d327108dSMed Ismail Bennani 74d327108dSMed Ismail Bennani structured_data = lldb.SBStructuredData() 75d327108dSMed Ismail Bennani structured_data.SetFromJSON(json.dumps({ 76680ca7f2SMed Ismail Bennani "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget()), 77680ca7f2SMed Ismail Bennani "libbaz_path" : self.getBuildArtifact("libbaz.dylib") 78d327108dSMed Ismail Bennani })) 79d327108dSMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 80d327108dSMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 81d327108dSMed Ismail Bennani launch_info.SetScriptedProcessClassName("stack_core_scripted_process.StackCoreScriptedProcess") 82d327108dSMed Ismail Bennani launch_info.SetScriptedProcessDictionary(structured_data) 83d327108dSMed Ismail Bennani 84d327108dSMed Ismail Bennani error = lldb.SBError() 85d327108dSMed Ismail Bennani process = target.Launch(launch_info, error) 86779bbbf2SDave Lee self.assertSuccess(error) 87d327108dSMed Ismail Bennani self.assertTrue(process, PROCESS_IS_VALID) 88d327108dSMed Ismail Bennani self.assertEqual(process.GetProcessID(), 42) 89d327108dSMed Ismail Bennani 90680ca7f2SMed Ismail Bennani self.assertEqual(process.GetNumThreads(), 2) 91d327108dSMed Ismail Bennani thread = process.GetSelectedThread() 92d327108dSMed Ismail Bennani self.assertTrue(thread, "Invalid thread.") 93680ca7f2SMed Ismail Bennani self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-1") 94d327108dSMed Ismail Bennani 95d327108dSMed Ismail Bennani self.assertTrue(target.triple, "Invalid target triple") 96d327108dSMed Ismail Bennani arch = target.triple.split('-')[0] 97d327108dSMed Ismail Bennani supported_arch = ['x86_64', 'arm64', 'arm64e'] 98d327108dSMed Ismail Bennani self.assertIn(arch, supported_arch) 99d327108dSMed Ismail Bennani # When creating a corefile of a arm process, lldb saves the exception 100d327108dSMed Ismail Bennani # that triggers the breakpoint in the LC_NOTES of the corefile, so they 101d327108dSMed Ismail Bennani # can be reloaded with the corefile on the next debug session. 102d327108dSMed Ismail Bennani if arch in 'arm64e': 103d327108dSMed Ismail Bennani self.assertTrue(thread.GetStopReason(), lldb.eStopReasonException) 104d327108dSMed Ismail Bennani # However, it's architecture specific, and corefiles made from intel 105d327108dSMed Ismail Bennani # process don't save any metadata to retrieve to stop reason. 106d327108dSMed Ismail Bennani # To mitigate this, the StackCoreScriptedProcess will report a 107d327108dSMed Ismail Bennani # eStopReasonSignal with a SIGTRAP, mimicking what debugserver does. 108d327108dSMed Ismail Bennani else: 109d327108dSMed Ismail Bennani self.assertTrue(thread.GetStopReason(), lldb.eStopReasonSignal) 110d327108dSMed Ismail Bennani 111680ca7f2SMed Ismail Bennani self.assertEqual(thread.GetNumFrames(), 5) 112d327108dSMed Ismail Bennani frame = thread.GetSelectedFrame() 113d327108dSMed Ismail Bennani self.assertTrue(frame, "Invalid frame.") 114680ca7f2SMed Ismail Bennani func = frame.GetFunction() 115680ca7f2SMed Ismail Bennani self.assertTrue(func, "Invalid function.") 116680ca7f2SMed Ismail Bennani 117680ca7f2SMed Ismail Bennani self.assertIn("baz", frame.GetFunctionName()) 118680ca7f2SMed Ismail Bennani self.assertEqual(frame.vars.GetSize(), 2) 119680ca7f2SMed Ismail Bennani self.assertEqual(int(frame.vars.GetFirstValueByName('j').GetValue()), 42 * 42) 120680ca7f2SMed Ismail Bennani self.assertEqual(int(frame.vars.GetFirstValueByName('k').GetValue()), 42) 121680ca7f2SMed Ismail Bennani 122999e7547SMed Ismail Bennani corefile_dylib = self.get_module_with_name(corefile_target, 'libbaz.dylib') 123999e7547SMed Ismail Bennani self.assertTrue(corefile_dylib, "Dynamic library libbaz.dylib not found.") 124680ca7f2SMed Ismail Bennani scripted_dylib = self.get_module_with_name(target, 'libbaz.dylib') 125680ca7f2SMed Ismail Bennani self.assertTrue(scripted_dylib, "Dynamic library libbaz.dylib not found.") 126999e7547SMed Ismail Bennani self.assertEqual(scripted_dylib.GetObjectFileHeaderAddress().GetLoadAddress(target), 127999e7547SMed Ismail Bennani corefile_dylib.GetObjectFileHeaderAddress().GetLoadAddress(target)) 128