brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.3 KiB · 0b857fb Raw
514 lines · python
1"""2Test SBProcess APIs, including ReadMemory(), WriteMemory(), and others.3"""4 5import lldb6import sys7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test.lldbutil import get_stopped_thread, state_type_to_str10 11 12class ProcessAPITestCase(TestBase):13    def setUp(self):14        # Call super's setUp().15        TestBase.setUp(self)16        # Find the line number to break inside main().17        self.line = line_number(18            "main.cpp", "// Set break point at this line and check variable 'my_char'."19        )20 21    def test_scripted_implementation(self):22        self.build()23        exe = self.getBuildArtifact("a.out")24 25        (target, process, _, _) = lldbutil.run_to_source_breakpoint(26            self, "Set break point", lldb.SBFileSpec("main.cpp")27        )28 29        self.assertTrue(process, PROCESS_IS_VALID)30        self.assertEqual(process.GetScriptedImplementation(), None)31 32    def test_read_memory(self):33        """Test Python SBProcess.ReadMemory() API."""34        self.build()35        exe = self.getBuildArtifact("a.out")36 37        target = self.dbg.CreateTarget(exe)38        self.assertTrue(target, VALID_TARGET)39 40        breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)41        self.assertTrue(breakpoint, VALID_BREAKPOINT)42 43        # Launch the process, and do not stop at the entry point.44        process = target.LaunchSimple(None, None, self.get_process_working_directory())45 46        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)47        self.assertTrue(48            thread.IsValid(), "There should be a thread stopped due to breakpoint"49        )50        frame = thread.GetFrameAtIndex(0)51 52        # Get the SBValue for the file static variable 'my_char'.53        val = frame.FindValue("my_char", lldb.eValueTypeVariableStatic)54        self.DebugSBValue(val)55 56        # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and57        # expect to get a Python string as the result object!58        error = lldb.SBError()59        self.assertFalse(val.TypeIsPointerType())60        content = process.ReadMemory(val.AddressOf().GetValueAsUnsigned(), 1, error)61        if not error.Success():62            self.fail("SBProcess.ReadMemory() failed")63        if self.TraceOn():64            print("memory content:", content)65 66        self.expect(67            content,68            "Result from SBProcess.ReadMemory() matches our expected output: 'x'",69            exe=False,70            startstr=b"x",71        )72 73        # Read (char *)my_char_ptr.74        val = frame.FindValue("my_char_ptr", lldb.eValueTypeVariableGlobal)75        self.DebugSBValue(val)76        cstring = process.ReadCStringFromMemory(val.GetValueAsUnsigned(), 256, error)77        if not error.Success():78            self.fail("SBProcess.ReadCStringFromMemory() failed")79        if self.TraceOn():80            print("cstring read is:", cstring)81 82        self.expect(83            cstring,84            "Result from SBProcess.ReadCStringFromMemory() matches our expected output",85            exe=False,86            startstr="Does it work?",87        )88 89        # Get the SBValue for the global variable 'my_cstring'.90        val = frame.FindValue("my_cstring", lldb.eValueTypeVariableGlobal)91        self.DebugSBValue(val)92 93        # Due to the typemap magic (see lldb.swig), we pass in 256 to read at most 256 bytes94        # from the address, and expect to get a Python string as the result95        # object!96        self.assertFalse(val.TypeIsPointerType())97        cstring = process.ReadCStringFromMemory(98            val.AddressOf().GetValueAsUnsigned(), 256, error99        )100        if not error.Success():101            self.fail("SBProcess.ReadCStringFromMemory() failed")102        if self.TraceOn():103            print("cstring read is:", cstring)104 105        self.expect(106            cstring,107            "Result from SBProcess.ReadCStringFromMemory() matches our expected output",108            exe=False,109            startstr="lldb.SBProcess.ReadCStringFromMemory() works!",110        )111 112        # Get the SBValue for the global variable 'my_uint32'.113        val = frame.FindValue("my_uint32", lldb.eValueTypeVariableGlobal)114        self.DebugSBValue(val)115 116        # Due to the typemap magic (see lldb.swig), we pass in 4 to read 4 bytes117        # from the address, and expect to get an int as the result!118        self.assertFalse(val.TypeIsPointerType())119        my_uint32 = process.ReadUnsignedFromMemory(120            val.AddressOf().GetValueAsUnsigned(), 4, error121        )122        if not error.Success():123            self.fail("SBProcess.ReadCStringFromMemory() failed")124        if self.TraceOn():125            print("uint32 read is:", my_uint32)126 127        if my_uint32 != 12345:128            self.fail(129                "Result from SBProcess.ReadUnsignedFromMemory() does not match our expected output"130            )131 132    def test_write_memory(self):133        """Test Python SBProcess.WriteMemory() API."""134        self.build()135        exe = self.getBuildArtifact("a.out")136 137        target = self.dbg.CreateTarget(exe)138        self.assertTrue(target, VALID_TARGET)139 140        breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)141        self.assertTrue(breakpoint, VALID_BREAKPOINT)142 143        # Launch the process, and do not stop at the entry point.144        process = target.LaunchSimple(None, None, self.get_process_working_directory())145 146        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)147        self.assertTrue(148            thread.IsValid(), "There should be a thread stopped due to breakpoint"149        )150        frame = thread.GetFrameAtIndex(0)151 152        # Get the SBValue for the static variable 'my_char'.153        val = frame.FindValue("my_char", lldb.eValueTypeVariableStatic)154        self.DebugSBValue(val)155 156        # If the variable does not have a load address, there's no sense157        # continuing.158        if not val.GetLocation().startswith("0x"):159            return160 161        # OK, let's get the hex location of the variable.162        location = int(val.GetLocation(), 16)163 164        # The program logic makes the 'my_char' variable to have memory content as 'x'.165        # But we want to use the WriteMemory() API to assign 'a' to the166        # variable.167 168        # Now use WriteMemory() API to write 'a' into the global variable.169        error = lldb.SBError()170        result = process.WriteMemory(location, "a", error)171        if not error.Success() or result != 1:172            self.fail("SBProcess.WriteMemory() failed")173 174        # Read from the memory location.  This time it should be 'a'.175        # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and176        # expect to get a Python string as the result object!177        content = process.ReadMemory(location, 1, error)178        if not error.Success():179            self.fail("SBProcess.ReadMemory() failed")180        if self.TraceOn():181            print("memory content:", content)182 183        self.expect(184            content,185            "Result from SBProcess.ReadMemory() matches our expected output: 'a'",186            exe=False,187            startstr=b"a",188        )189 190        # Get the SBValue for the global variable 'my_cstring'.191        val = frame.FindValue("my_cstring", lldb.eValueTypeVariableGlobal)192        self.DebugSBValue(val)193 194        addr = val.AddressOf().GetValueAsUnsigned()195 196        # Write an empty string to memory197        bytes_written = process.WriteMemoryAsCString(addr, "", error)198        self.assertEqual(bytes_written, 0)199        if not error.Success():200            self.fail("SBProcess.WriteMemoryAsCString() failed")201 202        message = "Hello!"203        bytes_written = process.WriteMemoryAsCString(addr, message, error)204        self.assertEqual(bytes_written, len(message) + 1)205        if not error.Success():206            self.fail("SBProcess.WriteMemoryAsCString() failed")207 208        cstring = process.ReadCStringFromMemory(209            val.AddressOf().GetValueAsUnsigned(), 256, error210        )211        if not error.Success():212            self.fail("SBProcess.ReadCStringFromMemory() failed")213 214        self.assertEqual(cstring, message)215 216    def test_access_my_int(self):217        """Test access 'my_int' using Python SBProcess.GetByteOrder() and other APIs."""218        self.build()219        exe = self.getBuildArtifact("a.out")220 221        target = self.dbg.CreateTarget(exe)222        self.assertTrue(target, VALID_TARGET)223 224        breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)225        self.assertTrue(breakpoint, VALID_BREAKPOINT)226 227        # Launch the process, and do not stop at the entry point.228        process = target.LaunchSimple(None, None, self.get_process_working_directory())229 230        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)231        self.assertTrue(232            thread.IsValid(), "There should be a thread stopped due to breakpoint"233        )234        frame = thread.GetFrameAtIndex(0)235 236        # Get the SBValue for the global variable 'my_int'.237        val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal)238        self.DebugSBValue(val)239 240        # If the variable does not have a load address, there's no sense241        # continuing.242        if not val.GetLocation().startswith("0x"):243            return244 245        # OK, let's get the hex location of the variable.246        location = int(val.GetLocation(), 16)247 248        # Note that the canonical from of the bytearray is little endian.249        from lldbsuite.test.lldbutil import int_to_bytearray, bytearray_to_int250 251        byteSize = val.GetByteSize()252        bytes = int_to_bytearray(256, byteSize)253 254        byteOrder = process.GetByteOrder()255        if byteOrder == lldb.eByteOrderBig:256            bytes.reverse()257        elif byteOrder == lldb.eByteOrderLittle:258            pass259        else:260            # Neither big endian nor little endian?  Return for now.261            # Add more logic here if we want to handle other types.262            return263 264        # The program logic makes the 'my_int' variable to have int type and value of 0.265        # But we want to use the WriteMemory() API to assign 256 to the266        # variable.267 268        # Now use WriteMemory() API to write 256 into the global variable.269        error = lldb.SBError()270        result = process.WriteMemory(location, bytes, error)271        if not error.Success() or result != byteSize:272            self.fail("SBProcess.WriteMemory() failed")273 274        # Make sure that the val we got originally updates itself to notice the275        # change:276        self.expect(277            val.GetValue(),278            "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'",279            exe=False,280            startstr="256",281        )282 283        # And for grins, get the SBValue for the global variable 'my_int'284        # again, to make sure that also tracks the new value:285        val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal)286        self.expect(287            val.GetValue(),288            "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'",289            exe=False,290            startstr="256",291        )292 293        # Now read the memory content.  The bytearray should have (byte)1 as294        # the second element.295        content = process.ReadMemory(location, byteSize, error)296        if not error.Success():297            self.fail("SBProcess.ReadMemory() failed")298 299        # The bytearray_to_int utility function expects a little endian300        # bytearray.301        if byteOrder == lldb.eByteOrderBig:302            content = bytearray(content, "ascii")303            content.reverse()304 305        new_value = bytearray_to_int(content, byteSize)306        if new_value != 256:307            self.fail("Memory content read from 'my_int' does not match (int)256")308 309        # Dump the memory content....310        if self.TraceOn():311            for i in content:312                print("byte:", i)313 314    def test_remote_launch(self):315        """Test SBProcess.RemoteLaunch() API with a process not in eStateConnected, and it should fail."""316        self.build()317        exe = self.getBuildArtifact("a.out")318 319        target = self.dbg.CreateTarget(exe)320        self.assertTrue(target, VALID_TARGET)321 322        # Launch the process, and do not stop at the entry point.323        process = target.LaunchSimple(None, None, self.get_process_working_directory())324 325        if self.TraceOn():326            print("process state:", state_type_to_str(process.GetState()))327        self.assertNotEqual(process.GetState(), lldb.eStateConnected)328 329        error = lldb.SBError()330        success = process.RemoteLaunch(331            None, None, None, None, None, None, 0, False, error332        )333        self.assertTrue(334            not success,335            "RemoteLaunch() should fail for process state != eStateConnected",336        )337 338    def test_get_num_supported_hardware_watchpoints(self):339        """Test SBProcess.GetNumSupportedHardwareWatchpoints() API with a process."""340        self.build()341        exe = self.getBuildArtifact("a.out")342        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)343 344        target = self.dbg.CreateTarget(exe)345        self.assertTrue(target, VALID_TARGET)346 347        breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)348        self.assertTrue(breakpoint, VALID_BREAKPOINT)349 350        # Launch the process, and do not stop at the entry point.351        process = target.LaunchSimple(None, None, self.get_process_working_directory())352 353        error = lldb.SBError()354        num = process.GetNumSupportedHardwareWatchpoints(error)355        if self.TraceOn() and error.Success():356            print("Number of supported hardware watchpoints: %d" % num)357 358    @no_debug_info_test359    @skipIfRemote360    def test_get_process_info(self):361        """Test SBProcess::GetProcessInfo() API with a locally launched process."""362        self.build()363        exe = self.getBuildArtifact("a.out")364        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)365 366        target = self.dbg.CreateTarget(exe)367        self.assertTrue(target, VALID_TARGET)368 369        # Launch the process and stop at the entry point.370        launch_info = target.GetLaunchInfo()371        launch_info.SetWorkingDirectory(self.get_process_working_directory())372        launch_flags = launch_info.GetLaunchFlags()373        launch_flags |= lldb.eLaunchFlagStopAtEntry374        launch_info.SetLaunchFlags(launch_flags)375        error = lldb.SBError()376        process = target.Launch(launch_info, error)377 378        if not error.Success():379            self.fail("Failed to launch process")380 381        # Verify basic process info can be retrieved successfully382        process_info = process.GetProcessInfo()383        self.assertTrue(process_info.IsValid())384        file_spec = process_info.GetExecutableFile()385        self.assertTrue(file_spec.IsValid())386        process_name = process_info.GetName()387        self.assertIsNotNone(process_name, "Process has a name")388        self.assertGreater(len(process_name), 0, "Process name isn't blank")389        self.assertEqual(file_spec.GetFilename(), "a.out")390        self.assertNotEqual(391            process_info.GetProcessID(),392            lldb.LLDB_INVALID_PROCESS_ID,393            "Process ID is valid",394        )395        triple = process_info.GetTriple()396        self.assertIsNotNone(triple, "Process has a triple")397 398        # Additional process info varies by platform, so just check that399        # whatever info was retrieved is consistent and nothing blows up.400        if process_info.UserIDIsValid():401            self.assertNotEqual(402                process_info.GetUserID(), lldb.UINT32_MAX, "Process user ID is valid"403            )404        else:405            self.assertEqual(406                process_info.GetUserID(), lldb.UINT32_MAX, "Process user ID is invalid"407            )408 409        if process_info.GroupIDIsValid():410            self.assertNotEqual(411                process_info.GetGroupID(), lldb.UINT32_MAX, "Process group ID is valid"412            )413        else:414            self.assertEqual(415                process_info.GetGroupID(),416                lldb.UINT32_MAX,417                "Process group ID is invalid",418            )419 420        if process_info.EffectiveUserIDIsValid():421            self.assertNotEqual(422                process_info.GetEffectiveUserID(),423                lldb.UINT32_MAX,424                "Process effective user ID is valid",425            )426        else:427            self.assertEqual(428                process_info.GetEffectiveUserID(),429                lldb.UINT32_MAX,430                "Process effective user ID is invalid",431            )432 433        if process_info.EffectiveGroupIDIsValid():434            self.assertNotEqual(435                process_info.GetEffectiveGroupID(),436                lldb.UINT32_MAX,437                "Process effective group ID is valid",438            )439        else:440            self.assertEqual(441                process_info.GetEffectiveGroupID(),442                lldb.UINT32_MAX,443                "Process effective group ID is invalid",444            )445 446        process_info.GetParentProcessID()447 448    def test_allocate_deallocate_memory(self):449        """Test Python SBProcess.AllocateMemory() and SBProcess.DeallocateMemory() APIs."""450        self.build()451        (452            target,453            process,454            main_thread,455            main_breakpoint,456        ) = lldbutil.run_to_source_breakpoint(457            self, "// Set break point at this line", lldb.SBFileSpec("main.cpp")458        )459 460        # Allocate a block of memory in the target process461        error = lldb.SBError()462        addr = process.AllocateMemory(16384, lldb.ePermissionsReadable, error)463        if not error.Success() or addr == lldb.LLDB_INVALID_ADDRESS:464            self.fail("SBProcess.AllocateMemory() failed")465 466        # Now use WriteMemory() API to write 'a' into the allocated467        # memory. Note that the debugger can do this even though the468        # block is not set writable.469        result = process.WriteMemory(addr, "a", error)470        if not error.Success() or result != 1:471            self.fail("SBProcess.WriteMemory() failed")472 473        # Read from the memory location.  This time it should be 'a'.474        # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and475        # expect to get a Python string as the result object!476        content = process.ReadMemory(addr, 1, error)477        if not error.Success():478            self.fail("SBProcess.ReadMemory() failed")479        if self.TraceOn():480            print("memory content:", content)481 482        self.expect(483            content,484            "Result from SBProcess.ReadMemory() matches our expected output: 'a'",485            exe=False,486            startstr=b"a",487        )488 489        # Verify that the process itself can read the allocated memory490        frame = main_thread.GetFrameAtIndex(0)491        val = frame.EvaluateExpression(492            "test_read(reinterpret_cast<char *>({:#x}))".format(addr)493        )494        self.expect(495            val.GetValue(),496            "Result of test_read() matches expected output 'a'",497            exe=False,498            startstr="'a'",499        )500 501        # Verify that the process cannot write into the block502        val = frame.EvaluateExpression(503            "test_write(reinterpret_cast<char *>({:#x}), 'b')".format(addr)504        )505        if val.GetError().Success():506            self.fail(507                "test_write() to allocated memory without write permission unexpectedly succeeded"508            )509 510        # Deallocate the memory511        error = process.DeallocateMemory(addr)512        if not error.Success():513            self.fail("SBProcess.DeallocateMemory() failed")514