diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -259,6 +259,8 @@ PacketResult Handle_g(StringExtractorGDBRemote &packet); + PacketResult Handle_G(StringExtractorGDBRemote &packet); + PacketResult Handle_qMemTags(StringExtractorGDBRemote &packet); PacketResult Handle_QMemTags(StringExtractorGDBRemote &packet); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -216,6 +216,8 @@ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g, &GDBRemoteCommunicationServerLLGS::Handle_g); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_G, + &GDBRemoteCommunicationServerLLGS::Handle_G); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qMemTags, @@ -2110,6 +2112,18 @@ return SendPacketNoLock("l"); } +static size_t GetGPacketSize(NativeRegisterContext &ctx) { + size_t result = 0; + for (uint32_t idx = 0; idx < ctx.GetUserRegisterCount(); ++idx) { + const RegisterInfo *info = ctx.GetRegisterInfoAtIndex(idx); + assert(info != nullptr); + if (info->value_regs != nullptr) + continue; // skip registers that are contained in other registers + result = std::max(result, info->byte_size + info->byte_offset); + } + return result; +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_g(StringExtractorGDBRemote &packet) { Log *log = GetLog(LLDBLog::Thread); @@ -2127,16 +2141,11 @@ // Get the thread's register context. NativeRegisterContext ®_ctx = thread->GetRegisterContext(); - std::vector regs_buffer; + std::vector regs_buffer(GetGPacketSize(reg_ctx), 0); for (uint32_t reg_num = 0; reg_num < reg_ctx.GetUserRegisterCount(); ++reg_num) { const RegisterInfo *reg_info = reg_ctx.GetRegisterInfoAtIndex(reg_num); - - if (reg_info == nullptr) { - LLDB_LOG(log, "failed to get register info for register index {0}", - reg_num); - return SendErrorResponse(0x15); - } + assert(reg_info); if (reg_info->value_regs != nullptr) continue; // skip registers that are contained in other registers @@ -2148,11 +2157,6 @@ return SendErrorResponse(0x15); } - if (reg_info->byte_offset + reg_info->byte_size >= regs_buffer.size()) - // Resize the buffer to guarantee it can store the register offsetted - // data. - regs_buffer.resize(reg_info->byte_offset + reg_info->byte_size); - // Copy the register offsetted data to the buffer. memcpy(regs_buffer.data() + reg_info->byte_offset, reg_value.GetBytes(), reg_info->byte_size); @@ -2165,6 +2169,48 @@ return SendPacketNoLock(response.GetString()); } +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_G(StringExtractorGDBRemote &packet) { + // Move past packet name. + packet.SetFilePos(strlen("G")); + + std::vector regs_buffer(packet.GetBytesLeft() / 2, 0); + regs_buffer.resize(packet.GetHexBytesAvail(regs_buffer)); + + // Get the thread to use. + NativeThreadProtocol *thread = GetThreadFromSuffix(packet); + if (!thread) + return SendErrorResponse(Status("No thread available")); + + NativeRegisterContext ®_ctx = thread->GetRegisterContext(); + + if (regs_buffer.size() != GetGPacketSize(reg_ctx)) + return SendErrorResponse(Status("Unexpected packet size")); + + for (uint32_t reg_num = 0; reg_num < reg_ctx.GetUserRegisterCount(); + ++reg_num) { + const RegisterInfo *reg_info = reg_ctx.GetRegisterInfoAtIndex(reg_num); + assert(reg_info); + + if (reg_info->value_regs != nullptr) + continue; // skip registers that are contained in other registers + + RegisterValue reg_value; + Status error; + reg_value.SetFromMemoryData( + *reg_info, regs_buffer.data() + reg_info->byte_offset, + reg_info->byte_size, + m_current_process->GetArchitecture().GetByteOrder(), error); + if (error.Fail()) + return SendErrorResponse(error); + error = reg_ctx.WriteRegister(reg_info, reg_value); + if (error.Fail()) + return SendErrorResponse(error); + } + + return SendOKResponse(); +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { Log *log = GetLog(LLDBLog::Thread); diff --git a/lldb/test/API/tools/lldb-server/register-reading/TestGdbRemoteGPacket.py b/lldb/test/API/tools/lldb-server/register-reading/TestGdbRemoteGPacket.py --- a/lldb/test/API/tools/lldb-server/register-reading/TestGdbRemoteGPacket.py +++ b/lldb/test/API/tools/lldb-server/register-reading/TestGdbRemoteGPacket.py @@ -25,7 +25,6 @@ class TestGdbRemoteGPacket(gdbremote_testcase.GdbRemoteTestCaseBase): @skipIfOutOfTreeDebugserver - @skipUnlessDarwin # G packet not supported def test_g_packet(self): self.build() self.prep_debug_monitor_and_inferior() @@ -128,7 +127,6 @@ @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr48420") @expectedFailureNetBSD - @skipIfDarwin # g packet not supported def test_g_returns_correct_data_with_suffix(self): self.build() self.set_inferior_startup_launch() @@ -136,7 +134,6 @@ @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr48420") @expectedFailureNetBSD - @skipIfDarwin # g packet not supported def test_g_returns_correct_data_no_suffix(self): self.build() self.set_inferior_startup_launch()