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)
 {