brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.4 KiB · 5916e62 Raw
290 lines · python
1"""2Test python scripted process in lldb3"""4 5import os, shutil6 7import lldb8from lldbsuite.test.decorators import *9from lldbsuite.test.lldbtest import *10from lldbsuite.test import lldbutil11from lldbsuite.test import lldbtest12 13import dummy_scripted_process14 15 16class ScriptedProcesTestCase(TestBase):17    NO_DEBUG_INFO_TESTCASE = True18 19    @skipUnlessDarwin20    def test_python_plugin_package(self):21        """Test that the lldb python module has a `plugins.scripted_process`22        package."""23        self.expect(24            "script import lldb.plugins",25            substrs=["ModuleNotFoundError"],26            matching=False,27        )28 29        self.expect("script dir(lldb.plugins)", substrs=["scripted_process"])30 31        self.expect(32            "script import lldb.plugins.scripted_process",33            substrs=["ModuleNotFoundError"],34            matching=False,35        )36 37        self.expect(38            "script dir(lldb.plugins.scripted_process)", substrs=["ScriptedProcess"]39        )40 41        self.expect(42            "script from lldb.plugins.scripted_process import ScriptedProcess",43            substrs=["ImportError"],44            matching=False,45        )46 47        self.expect("script dir(ScriptedProcess)", substrs=["launch"])48 49    def move_blueprint_to_dsym(self, blueprint_name):50        blueprint_origin_path = os.path.join(self.getSourceDir(), blueprint_name)51        dsym_bundle = self.getBuildArtifact("a.out.dSYM")52        blueprint_destination_path = os.path.join(53            dsym_bundle, "Contents", "Resources", "Python"54        )55        if not os.path.exists(blueprint_destination_path):56            os.mkdir(blueprint_destination_path)57 58        blueprint_destination_path = os.path.join(59            blueprint_destination_path, "a_out.py"60        )61        shutil.copy(blueprint_origin_path, blueprint_destination_path)62 63    # No dylib on Windows.64    @skipIfWindows65    def test_missing_methods_scripted_register_context(self):66        """Test that we only instanciate scripted processes if they implement67        all the required abstract methods."""68        self.build()69 70        os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1"71 72        def cleanup():73            del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]74 75        self.addTearDownHook(cleanup)76 77        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))78        self.assertTrue(target, VALID_TARGET)79        log_file = self.getBuildArtifact("script.log")80        self.runCmd("log enable lldb script -f " + log_file)81        self.assertTrue(os.path.isfile(log_file))82        script_path = os.path.join(83            self.getSourceDir(), "missing_methods_scripted_process.py"84        )85        self.runCmd("command script import " + script_path)86 87        launch_info = lldb.SBLaunchInfo(None)88        launch_info.SetProcessPluginName("ScriptedProcess")89        launch_info.SetScriptedProcessClassName(90            "missing_methods_scripted_process.MissingMethodsScriptedProcess"91        )92        error = lldb.SBError()93 94        process = target.Launch(launch_info, error)95 96        self.assertFailure(error)97 98        with open(log_file, "r") as f:99            log = f.read()100 101        self.assertIn(102            "Abstract method MissingMethodsScriptedProcess.read_memory_at_address not implemented",103            log,104        )105        self.assertIn(106            "Abstract method MissingMethodsScriptedProcess.is_alive not implemented",107            log,108        )109        self.assertIn(110            "Abstract method MissingMethodsScriptedProcess.get_scripted_thread_plugin not implemented",111            log,112        )113 114    @skipUnlessDarwin115    def test_invalid_scripted_register_context(self):116        """Test that we can launch an lldb scripted process with an invalid117        Scripted Thread, with invalid register context."""118        self.build()119 120        os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1"121 122        def cleanup():123            del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]124 125        self.addTearDownHook(cleanup)126 127        self.runCmd("settings set target.load-script-from-symbol-file true")128        self.move_blueprint_to_dsym("invalid_scripted_process.py")129        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))130        self.assertTrue(target, VALID_TARGET)131        log_file = self.getBuildArtifact("thread.log")132        self.runCmd("log enable lldb thread -f " + log_file)133        self.assertTrue(os.path.isfile(log_file))134 135        launch_info = lldb.SBLaunchInfo(None)136        launch_info.SetProcessPluginName("ScriptedProcess")137        launch_info.SetScriptedProcessClassName("a_out.InvalidScriptedProcess")138        error = lldb.SBError()139 140        process = target.Launch(launch_info, error)141 142        self.assertSuccess(error)143        self.assertTrue(process, PROCESS_IS_VALID)144        self.assertEqual(process.GetProcessID(), 666)145        self.assertEqual(process.GetNumThreads(), 0)146 147        impl = process.GetScriptedImplementation()148        self.assertTrue(impl)149        impl = process.GetScriptedImplementation()150        self.assertTrue(impl)151        impl = process.GetScriptedImplementation()152        self.assertTrue(impl)153        impl = process.GetScriptedImplementation()154        self.assertTrue(impl)155 156        addr = 0x500000000157        buff = process.ReadMemory(addr, 4, error)158        self.assertEqual(buff, None)159        self.assertTrue(error.Fail())160        self.assertEqual(error.GetCString(), "This is an invalid scripted process!")161 162        with open(log_file, "r") as f:163            log = f.read()164 165        self.assertIn("Failed to get scripted thread registers data.", log)166 167    @skipUnlessDarwin168    def test_scripted_process_and_scripted_thread(self):169        """Test that we can launch an lldb scripted process using the SBAPI,170        check its process ID, read string from memory, check scripted thread171        id, name stop reason and register context.172        """173        self.build()174        target_0 = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))175        self.assertTrue(target_0, VALID_TARGET)176 177        os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1"178 179        def cleanup():180            del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]181 182        self.addTearDownHook(cleanup)183 184        scripted_process_example_relpath = "dummy_scripted_process.py"185        self.runCmd(186            "command script import "187            + os.path.join(self.getSourceDir(), scripted_process_example_relpath)188        )189 190        self.runCmd(191            "target stop-hook add -k first -v 1 -k second -v 2 -P dummy_scripted_process.DummyStopHook"192        )193 194        launch_info = lldb.SBLaunchInfo(None)195        launch_info.SetProcessPluginName("ScriptedProcess")196        launch_info.SetScriptedProcessClassName(197            "dummy_scripted_process.DummyScriptedProcess"198        )199 200        error = lldb.SBError()201        process_0 = target_0.Launch(launch_info, error)202        self.assertTrue(process_0 and process_0.IsValid(), PROCESS_IS_VALID)203        self.assertEqual(process_0.GetProcessID(), 42)204        self.assertEqual(process_0.GetNumThreads(), 1)205 206        py_impl = process_0.GetScriptedImplementation()207        self.assertTrue(py_impl)208        self.assertIsInstance(py_impl, dummy_scripted_process.DummyScriptedProcess)209        self.assertFalse(hasattr(py_impl, "my_super_secret_member"))210        py_impl.my_super_secret_member = 42211        self.assertTrue(hasattr(py_impl, "my_super_secret_member"))212        self.assertEqual(py_impl.my_super_secret_method(), 42)213 214        self.assertTrue(hasattr(py_impl, "handled_stop"))215        self.assertTrue(py_impl.handled_stop)216 217        # Try reading from target #0 process ...218        addr = 0x500000000219        message = "Hello, target 0"220        buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error)221        self.assertSuccess(error)222        self.assertEqual(buff, message)223 224        target_1 = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))225        self.assertTrue(target_1, VALID_TARGET)226 227        # We still need to specify a PID when attaching even for scripted processes228        attach_info = lldb.SBAttachInfo(42)229        attach_info.SetProcessPluginName("ScriptedProcess")230        attach_info.SetScriptedProcessClassName(231            "dummy_scripted_process.DummyScriptedProcess"232        )233 234        error = lldb.SBError()235        process_1 = target_1.Attach(attach_info, error)236        self.assertTrue(process_1 and process_1.IsValid(), PROCESS_IS_VALID)237        self.assertEqual(process_1.GetProcessID(), 42)238        self.assertEqual(process_1.GetNumThreads(), 1)239 240        # ... then try reading from target #1 process ...241        message = "Hello, target 1"242        buff = process_1.ReadCStringFromMemory(addr, len(message) + 1, error)243        self.assertSuccess(error)244        self.assertEqual(buff, message)245 246        # ... now, reading again from target #0 process to make sure the call247        # gets dispatched to the right target.248        message = "Hello, target 0"249        buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error)250        self.assertSuccess(error)251        self.assertEqual(buff, message)252 253        # Let's write some memory.254        message = "Hello, world!"255        bytes_written = process_0.WriteMemoryAsCString(addr, message, error)256        self.assertSuccess(error)257        self.assertEqual(bytes_written, len(message) + 1)258 259        # ... and check if that memory was saved properly.260        buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error)261        self.assertSuccess(error)262        self.assertEqual(buff, message)263 264        thread = process_0.GetSelectedThread()265        self.assertTrue(thread, "Invalid thread.")266        self.assertEqual(thread.GetThreadID(), 0x19)267        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")268        self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonTrace)269 270        self.assertGreater(thread.GetNumFrames(), 0)271 272        frame = thread.GetFrameAtIndex(0)273        GPRs = None274        register_set = frame.registers  # Returns an SBValueList.275        for regs in register_set:276            if "general purpose" in regs.name.lower():277                GPRs = regs278                break279 280        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")281        self.assertGreater(GPRs.GetNumChildren(), 0)282        for idx, reg in enumerate(GPRs, start=1):283            if idx > 21:284                break285            self.assertEqual(idx, int(reg.value, 16))286 287        self.assertTrue(frame.IsSynthetic(), "Frame is not synthetic")288        pc = frame.GetPCAddress().GetLoadAddress(target_0)289        self.assertEqual(pc, 0x0100001B00)290