Move packet construction from GDBRemoteRegisterContext go the communication class
Summary:
When saving/restoring registers the GDBRemoteRegisterContext class was manually constructing
the register save/restore packets. This creates appropriate helper functions in
GDBRemoteCommunicationClient, and switches the class to use those. It also removes what a
duplicate packet send in some of those functions, a thing that I can only attribute to a bad
merge artefact.
I also add a test framework for testing gdb-remote client functionality and add tests for the new
functions I introduced. I'd like to be able to test the register context changes in isolation as
well, but currently there doesn't seem to be a way to reasonably construct a standalone register
context object, so we'll have to rely on the end-to-end tests to verify that.
Reviewers: clayborg
Subscribers: lldb-commits
Differential Revision: https://reviews.llvm.org/D23553
llvm-svn: 278915
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 0933ada..bfc2d4a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -3526,6 +3526,57 @@
}
return false;
}
+
+bool
+GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid, uint32_t reg_num, llvm::StringRef data)
+{
+ Lock lock(*this, false);
+ if (!lock)
+ {
+ if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
+ log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex for P packet.", __FUNCTION__);
+ return false;
+ }
+
+ const bool thread_suffix_supported = GetThreadSuffixSupported();
+ if (!thread_suffix_supported && !SetCurrentThread(tid))
+ return false;
+
+ StreamString packet;
+ packet.Printf("P%x=", reg_num);
+ packet.PutBytesAsRawHex8(data.data(), data.size(), endian::InlHostByteOrder(), endian::InlHostByteOrder());
+ if (thread_suffix_supported)
+ packet.Printf(";thread:%4.4" PRIx64 ";", tid);
+ StringExtractorGDBRemote response;
+ return SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success &&
+ response.IsOKResponse();
+}
+
+bool
+GDBRemoteCommunicationClient::WriteAllRegisters(lldb::tid_t tid, llvm::StringRef data)
+{
+ Lock lock(*this, false);
+ if (!lock)
+ {
+ if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
+ log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex for G packet.", __FUNCTION__);
+ return false;
+ }
+
+ const bool thread_suffix_supported = GetThreadSuffixSupported();
+ if (!thread_suffix_supported && !SetCurrentThread(tid))
+ return false;
+
+ StreamString packet;
+ packet.PutChar('G');
+ packet.Write(data.data(), data.size());
+ if (thread_suffix_supported)
+ packet.Printf(";thread:%4.4" PRIx64 ";", tid);
+ StringExtractorGDBRemote response;
+ return SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success &&
+ response.IsOKResponse();
+}
+
bool
GDBRemoteCommunicationClient::SaveRegisterState (lldb::tid_t tid, uint32_t &save_id)
{