Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -202,8 +202,9 @@ PacketResult Handle_interrupt (StringExtractorGDBRemote &packet); + // Handles $m and $x packets. PacketResult - Handle_m (StringExtractorGDBRemote &packet); + Handle_memory_read (StringExtractorGDBRemote &packet); PacketResult Handle_M (StringExtractorGDBRemote &packet); Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -113,7 +113,7 @@ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_interrupt, &GDBRemoteCommunicationServerLLGS::Handle_interrupt); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_m, - &GDBRemoteCommunicationServerLLGS::Handle_m); + &GDBRemoteCommunicationServerLLGS::Handle_memory_read); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M, &GDBRemoteCommunicationServerLLGS::Handle_M); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p, @@ -164,6 +164,8 @@ &GDBRemoteCommunicationServerLLGS::Handle_vCont); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vCont_actions, &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_x, + &GDBRemoteCommunicationServerLLGS::Handle_memory_read); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z, &GDBRemoteCommunicationServerLLGS::Handle_Z); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, @@ -1975,7 +1977,7 @@ } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet) +GDBRemoteCommunicationServerLLGS::Handle_memory_read(StringExtractorGDBRemote &packet) { Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -2008,7 +2010,7 @@ { if (log) log->Printf ("GDBRemoteCommunicationServerLLGS::%s nothing to read: zero-length packet", __FUNCTION__); - return PacketResult::Success; + return SendOKResponse(); } // Allocate the response buffer. @@ -2035,8 +2037,16 @@ } StreamGDBRemote response; - for (size_t i = 0; i < bytes_read; ++i) - response.PutHex8(buf[i]); + packet.SetFilePos(0); + char kind = packet.GetChar('?'); + if (kind == 'x') + response.PutEscapedBytes(buf.data(), byte_count); + else + { + assert(kind == 'm'); + for (size_t i = 0; i < bytes_read; ++i) + response.PutHex8(buf[i]); + } return SendPacketNoLock(response.GetData(), response.GetSize()); } Index: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -3043,14 +3043,8 @@ char packet[64]; int packet_len; bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); - if (binary_memory_read) - { - packet_len = ::snprintf (packet, sizeof(packet), "x0x%" PRIx64 ",0x%" PRIx64, (uint64_t)addr, (uint64_t)size); - } - else - { - packet_len = ::snprintf (packet, sizeof(packet), "m%" PRIx64 ",%" PRIx64, (uint64_t)addr, (uint64_t)size); - } + packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64, + binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size); assert (packet_len + 1 < (int)sizeof(packet)); StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success) Index: lldb/trunk/source/Utility/StringExtractorGDBRemote.h =================================================================== --- lldb/trunk/source/Utility/StringExtractorGDBRemote.h +++ lldb/trunk/source/Utility/StringExtractorGDBRemote.h @@ -145,6 +145,8 @@ eServerPacketType_s, eServerPacketType_S, eServerPacketType_T, + eServerPacketType_x, + eServerPacketType_X, eServerPacketType_Z, eServerPacketType_z, Index: lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp =================================================================== --- lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp +++ lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp @@ -310,6 +310,12 @@ case 'S': return eServerPacketType_S; + case 'x': + return eServerPacketType_x; + + case 'X': + return eServerPacketType_X; + case 'T': return eServerPacketType_T; Index: lldb/trunk/test/tools/lldb-server/TestGDBRemoteMemoryRead.py =================================================================== --- lldb/trunk/test/tools/lldb-server/TestGDBRemoteMemoryRead.py +++ lldb/trunk/test/tools/lldb-server/TestGDBRemoteMemoryRead.py @@ -0,0 +1,45 @@ +""" +Tests the binary ($x) and hex ($m) memory read packets of the remote stub +""" + +import os +import unittest2 +import lldb +from lldbtest import * +import lldbutil +import binascii + + +class MemoryReadTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessPlatform(getDarwinOSTriples()+["linux"]) + def test_memory_read(self): + self.build() + exe = os.path.join (os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + lldbutil.run_break_set_by_symbol(self, "main") + + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetState(), lldb.eStateStopped, "Process is stopped") + + pc = process.GetSelectedThread().GetSelectedFrame().GetPC() + for size in [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]: + error = lldb.SBError() + memory = process.ReadMemory(pc, size, error) + self.assertTrue(error.Success()) + self.match("process plugin packet send x%x,%x" % (pc, size), ["response:", memory]) + self.match("process plugin packet send m%x,%x" % (pc, size), ["response:", binascii.hexlify(memory)]) + + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited, "Process exited") + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main()