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 Bennani 142238dcc3SJonas Devlieghereclass StackCoreScriptedProcesTestCase(TestBase): 15d327108dSMed Ismail Bennani NO_DEBUG_INFO_TESTCASE = True 16d327108dSMed Ismail Bennani 17d327108dSMed Ismail Bennani def create_stack_skinny_corefile(self, file): 18d327108dSMed Ismail Bennani self.build() 192238dcc3SJonas Devlieghere target, process, thread, _ = lldbutil.run_to_source_breakpoint( 202238dcc3SJonas Devlieghere self, "// break here", lldb.SBFileSpec("baz.cpp") 212238dcc3SJonas Devlieghere ) 22d327108dSMed Ismail Bennani self.assertTrue(process.IsValid(), "Process is invalid.") 23d327108dSMed Ismail Bennani # FIXME: Use SBAPI to save the process corefile. 24d327108dSMed Ismail Bennani self.runCmd("process save-core -s stack " + file) 25d327108dSMed Ismail Bennani self.assertTrue(os.path.exists(file), "No stack-only corefile found.") 26d327108dSMed Ismail Bennani self.assertTrue(self.dbg.DeleteTarget(target), "Couldn't delete target") 27d327108dSMed Ismail Bennani 28680ca7f2SMed Ismail Bennani def get_module_with_name(self, target, name): 29680ca7f2SMed Ismail Bennani for module in target.modules: 30680ca7f2SMed Ismail Bennani if name in module.GetFileSpec().GetFilename(): 31680ca7f2SMed Ismail Bennani return module 32680ca7f2SMed Ismail Bennani return None 33680ca7f2SMed Ismail Bennani 34d327108dSMed Ismail Bennani @skipUnlessDarwin 35d327108dSMed Ismail Bennani @skipIfOutOfTreeDebugserver 36065e3c9aSJonas Devlieghere @skipIfRemote 3740cef806SMed Ismail Bennani @skipIfAsan # On ASAN builds, this test times-out (rdar://98678134) 38*d10a61c8SMed Ismail Bennani @skipIfDarwin 39d327108dSMed Ismail Bennani def test_launch_scripted_process_stack_frames(self): 40d327108dSMed Ismail Bennani """Test that we can launch an lldb scripted process from the command 41d327108dSMed Ismail Bennani line, check its process ID and read string from memory.""" 42d327108dSMed Ismail Bennani self.build() 43d327108dSMed Ismail Bennani target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 44d327108dSMed Ismail Bennani self.assertTrue(target, VALID_TARGET) 45d327108dSMed Ismail Bennani 462238dcc3SJonas Devlieghere main_module = self.get_module_with_name(target, "a.out") 47d327108dSMed Ismail Bennani self.assertTrue(main_module, "Invalid main module.") 48d327108dSMed Ismail Bennani error = target.SetModuleLoadAddress(main_module, 0) 49779bbbf2SDave Lee self.assertSuccess(error, "Reloading main module at offset 0 failed.") 50d327108dSMed Ismail Bennani 512238dcc3SJonas Devlieghere scripted_dylib = self.get_module_with_name(target, "libbaz.dylib") 52680ca7f2SMed Ismail Bennani self.assertTrue(scripted_dylib, "Dynamic library libbaz.dylib not found.") 532238dcc3SJonas Devlieghere self.assertEqual( 542238dcc3SJonas Devlieghere scripted_dylib.GetObjectFileHeaderAddress().GetLoadAddress(target), 552238dcc3SJonas Devlieghere 0xFFFFFFFFFFFFFFFF, 562238dcc3SJonas Devlieghere ) 57680ca7f2SMed Ismail Bennani 582238dcc3SJonas Devlieghere os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1" 592238dcc3SJonas Devlieghere 60d327108dSMed Ismail Bennani def cleanup(): 61d327108dSMed Ismail Bennani del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] 622238dcc3SJonas Devlieghere 63d327108dSMed Ismail Bennani self.addTearDownHook(cleanup) 64d327108dSMed Ismail Bennani 652238dcc3SJonas Devlieghere scripted_process_example_relpath = "stack_core_scripted_process.py" 662238dcc3SJonas Devlieghere self.runCmd( 672238dcc3SJonas Devlieghere "command script import " 682238dcc3SJonas Devlieghere + os.path.join(self.getSourceDir(), scripted_process_example_relpath) 692238dcc3SJonas Devlieghere ) 70d327108dSMed Ismail Bennani 71d327108dSMed Ismail Bennani corefile_process = None 72d327108dSMed Ismail Bennani with tempfile.NamedTemporaryFile() as file: 73d327108dSMed Ismail Bennani self.create_stack_skinny_corefile(file.name) 74d327108dSMed Ismail Bennani corefile_target = self.dbg.CreateTarget(None) 752238dcc3SJonas Devlieghere corefile_process = corefile_target.LoadCore( 762238dcc3SJonas Devlieghere self.getBuildArtifact(file.name) 772238dcc3SJonas Devlieghere ) 78d327108dSMed Ismail Bennani self.assertTrue(corefile_process, PROCESS_IS_VALID) 79d327108dSMed Ismail Bennani 80d327108dSMed Ismail Bennani structured_data = lldb.SBStructuredData() 812238dcc3SJonas Devlieghere structured_data.SetFromJSON( 822238dcc3SJonas Devlieghere json.dumps( 832238dcc3SJonas Devlieghere { 842238dcc3SJonas Devlieghere "backing_target_idx": self.dbg.GetIndexOfTarget( 852238dcc3SJonas Devlieghere corefile_process.GetTarget() 862238dcc3SJonas Devlieghere ), 872238dcc3SJonas Devlieghere "libbaz_path": self.getBuildArtifact("libbaz.dylib"), 882238dcc3SJonas Devlieghere } 892238dcc3SJonas Devlieghere ) 902238dcc3SJonas Devlieghere ) 91d327108dSMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 92d327108dSMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 932238dcc3SJonas Devlieghere launch_info.SetScriptedProcessClassName( 942238dcc3SJonas Devlieghere "stack_core_scripted_process.StackCoreScriptedProcess" 952238dcc3SJonas Devlieghere ) 96d327108dSMed Ismail Bennani launch_info.SetScriptedProcessDictionary(structured_data) 97d327108dSMed Ismail Bennani 98d327108dSMed Ismail Bennani error = lldb.SBError() 99d327108dSMed Ismail Bennani process = target.Launch(launch_info, error) 100779bbbf2SDave Lee self.assertSuccess(error) 101d327108dSMed Ismail Bennani self.assertTrue(process, PROCESS_IS_VALID) 102d327108dSMed Ismail Bennani self.assertEqual(process.GetProcessID(), 42) 103d327108dSMed Ismail Bennani 104680ca7f2SMed Ismail Bennani self.assertEqual(process.GetNumThreads(), 2) 105d327108dSMed Ismail Bennani thread = process.GetSelectedThread() 106d327108dSMed Ismail Bennani self.assertTrue(thread, "Invalid thread.") 107680ca7f2SMed Ismail Bennani self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-1") 108d327108dSMed Ismail Bennani 109d327108dSMed Ismail Bennani self.assertTrue(target.triple, "Invalid target triple") 1102238dcc3SJonas Devlieghere arch = target.triple.split("-")[0] 1112238dcc3SJonas Devlieghere supported_arch = ["x86_64", "arm64", "arm64e"] 112d327108dSMed Ismail Bennani self.assertIn(arch, supported_arch) 113d327108dSMed Ismail Bennani # When creating a corefile of a arm process, lldb saves the exception 114d327108dSMed Ismail Bennani # that triggers the breakpoint in the LC_NOTES of the corefile, so they 115d327108dSMed Ismail Bennani # can be reloaded with the corefile on the next debug session. 1162238dcc3SJonas Devlieghere if arch in "arm64e": 117d327108dSMed Ismail Bennani self.assertTrue(thread.GetStopReason(), lldb.eStopReasonException) 118d327108dSMed Ismail Bennani # However, it's architecture specific, and corefiles made from intel 119d327108dSMed Ismail Bennani # process don't save any metadata to retrieve to stop reason. 120d327108dSMed Ismail Bennani # To mitigate this, the StackCoreScriptedProcess will report a 121d327108dSMed Ismail Bennani # eStopReasonSignal with a SIGTRAP, mimicking what debugserver does. 122d327108dSMed Ismail Bennani else: 123d327108dSMed Ismail Bennani self.assertTrue(thread.GetStopReason(), lldb.eStopReasonSignal) 124d327108dSMed Ismail Bennani 125680ca7f2SMed Ismail Bennani self.assertEqual(thread.GetNumFrames(), 5) 126d327108dSMed Ismail Bennani frame = thread.GetSelectedFrame() 127d327108dSMed Ismail Bennani self.assertTrue(frame, "Invalid frame.") 128680ca7f2SMed Ismail Bennani func = frame.GetFunction() 129680ca7f2SMed Ismail Bennani self.assertTrue(func, "Invalid function.") 130680ca7f2SMed Ismail Bennani 131680ca7f2SMed Ismail Bennani self.assertIn("baz", frame.GetFunctionName()) 1328f549c53SMed Ismail Bennani self.assertGreater(frame.vars.GetSize(), 0) 1332238dcc3SJonas Devlieghere self.assertEqual(int(frame.vars.GetFirstValueByName("k").GetValue()), 42) 1342238dcc3SJonas Devlieghere self.assertEqual( 1352238dcc3SJonas Devlieghere int(frame.vars.GetFirstValueByName("j").Dereference().GetValue()), 42 * 42 1362238dcc3SJonas Devlieghere ) 137680ca7f2SMed Ismail Bennani 1382238dcc3SJonas Devlieghere corefile_dylib = self.get_module_with_name(corefile_target, "libbaz.dylib") 139999e7547SMed Ismail Bennani self.assertTrue(corefile_dylib, "Dynamic library libbaz.dylib not found.") 1402238dcc3SJonas Devlieghere scripted_dylib = self.get_module_with_name(target, "libbaz.dylib") 141680ca7f2SMed Ismail Bennani self.assertTrue(scripted_dylib, "Dynamic library libbaz.dylib not found.") 1422238dcc3SJonas Devlieghere self.assertEqual( 1432238dcc3SJonas Devlieghere scripted_dylib.GetObjectFileHeaderAddress().GetLoadAddress(target), 1442238dcc3SJonas Devlieghere corefile_dylib.GetObjectFileHeaderAddress().GetLoadAddress(target), 1452238dcc3SJonas Devlieghere ) 146