<rdar://problem/15172417>

Added two new GDB server packets to debugserver: "QSaveRegisterState" and "QRestoreRegiterState".

"QSaveRegisterState" makes the remote GDB server save all register values and it returns a save identifier as an unsigned integer. This packet can be used prior to running expressions to save all registers.

All registers can them we later restored with "QRestoreRegiterState:SAVEID" what SAVEID is the integer identifier that was returned from the call to QSaveRegisterState.

Cleaned up redundant code in lldb_private::Thread, lldb_private::ThreadPlanCallFunction.
Moved the lldb_private::Thread::RegisterCheckpoint into its own header file and it is now in the lldb_private namespace. Trimmed down the RegisterCheckpoint class to omit stuff that wasn't used (the stack ID).

Added a few new virtual methods to lldb_private::RegisterContext that allow subclasses to efficiently save/restore register states and changed the RegisterContextGDBRemote to take advantage of these new calls.

llvm-svn: 194621
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 2ac7d20..da2299a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -65,6 +65,7 @@
     m_attach_or_wait_reply(eLazyBoolCalculate),
     m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
     m_supports_p (eLazyBoolCalculate),
+    m_supports_QSaveRegisterState (eLazyBoolCalculate),
     m_supports_qProcessInfoPID (true),
     m_supports_qfProcessInfo (true),
     m_supports_qUserName (true),
@@ -208,6 +209,7 @@
     m_supports_vCont_s = eLazyBoolCalculate;
     m_supports_vCont_S = eLazyBoolCalculate;
     m_supports_p = eLazyBoolCalculate;
+    m_supports_QSaveRegisterState = eLazyBoolCalculate;
     m_qHostInfo_is_valid = eLazyBoolCalculate;
     m_qProcessInfo_is_valid = eLazyBoolCalculate;
     m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
@@ -2809,3 +2811,134 @@
     }
     return false;
 }
+
+bool
+GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, uint32_t reg, StringExtractorGDBRemote &response)
+{
+    Mutex::Locker locker;
+    if (GetSequenceMutex (locker, "Didn't get sequence mutex for p packet."))
+    {
+        const bool thread_suffix_supported = GetThreadSuffixSupported();
+        
+        if (thread_suffix_supported || SetCurrentThread(tid))
+        {
+            char packet[64];
+            int packet_len = 0;
+            if (thread_suffix_supported)
+                packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4" PRIx64 ";", reg, tid);
+            else
+                packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
+            assert (packet_len < ((int)sizeof(packet) - 1));
+            return SendPacketAndWaitForResponse(packet, response, false);
+        }
+    }
+    return false;
+
+}
+
+
+bool
+GDBRemoteCommunicationClient::ReadAllRegisters (lldb::tid_t tid, StringExtractorGDBRemote &response)
+{
+    Mutex::Locker locker;
+    if (GetSequenceMutex (locker, "Didn't get sequence mutex for g packet."))
+    {
+        const bool thread_suffix_supported = GetThreadSuffixSupported();
+
+        if (thread_suffix_supported || SetCurrentThread(tid))
+        {
+            char packet[64];
+            int packet_len = 0;
+            // Get all registers in one packet
+            if (thread_suffix_supported)
+                packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64 ";", tid);
+            else
+                packet_len = ::snprintf (packet, sizeof(packet), "g");
+            assert (packet_len < ((int)sizeof(packet) - 1));
+            return SendPacketAndWaitForResponse(packet, response, false);
+        }
+    }
+    return false;
+}
+bool
+GDBRemoteCommunicationClient::SaveRegisterState (lldb::tid_t tid, uint32_t &save_id)
+{
+    save_id = 0; // Set to invalid save ID
+    if (m_supports_QSaveRegisterState == eLazyBoolNo)
+        return false;
+    
+    m_supports_QSaveRegisterState = eLazyBoolYes;
+    Mutex::Locker locker;
+    if (GetSequenceMutex (locker, "Didn't get sequence mutex for QSaveRegisterState."))
+    {
+        const bool thread_suffix_supported = GetThreadSuffixSupported();
+        if (thread_suffix_supported || SetCurrentThread(tid))
+        {
+            char packet[256];
+            if (thread_suffix_supported)
+                ::snprintf (packet, sizeof(packet), "QSaveRegisterState;thread:%4.4" PRIx64 ";", tid);
+            else
+                ::strncpy (packet, "QSaveRegisterState", sizeof(packet));
+            
+            StringExtractorGDBRemote response;
+
+            if (SendPacketAndWaitForResponse(packet, response, false))
+            {
+                if (response.IsUnsupportedResponse())
+                {
+                    // This packet isn't supported, don't try calling it again
+                    m_supports_QSaveRegisterState = eLazyBoolNo;
+                }
+                    
+                const uint32_t response_save_id = response.GetU32(0);
+                if (response_save_id != 0)
+                {
+                    save_id = response_save_id;
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::RestoreRegisterState (lldb::tid_t tid, uint32_t save_id)
+{
+    // We use the "m_supports_QSaveRegisterState" variable here becuase the
+    // QSaveRegisterState and QRestoreRegisterState packets must both be supported in
+    // order to be useful
+    if (m_supports_QSaveRegisterState == eLazyBoolNo)
+        return false;
+    
+    Mutex::Locker locker;
+    if (GetSequenceMutex (locker, "Didn't get sequence mutex for QRestoreRegisterState."))
+    {
+        const bool thread_suffix_supported = GetThreadSuffixSupported();
+        if (thread_suffix_supported || SetCurrentThread(tid))
+        {
+            char packet[256];
+            if (thread_suffix_supported)
+                ::snprintf (packet, sizeof(packet), "QRestoreRegisterState:%u;thread:%4.4" PRIx64 ";", save_id, tid);
+            else
+                ::snprintf (packet, sizeof(packet), "QRestoreRegisterState:%u" PRIx64 ";", save_id);
+            
+            StringExtractorGDBRemote response;
+            
+            if (SendPacketAndWaitForResponse(packet, response, false))
+            {
+                if (response.IsOKResponse())
+                {
+                    return true;
+                }
+                else if (response.IsUnsupportedResponse())
+                {
+                    // This packet isn't supported, don't try calling this packet or
+                    // QSaveRegisterState again...
+                    m_supports_QSaveRegisterState = eLazyBoolNo;
+                }
+            }
+        }
+    }
+    return false;
+}