Adding Support for Error Strings in Remote Packets

Summary:
This patch adds support for sending strings along with
error codes in the reply packets. The implementation is
based on the feedback recieved in the lldb-dev mailing
list. The patch also adds an extra packet for the client
to query if the server has the capability to provide
strings along with error replys.

Reviewers: labath, jingham, sas, lldb-commits, clayborg

Reviewed By: labath, clayborg

Differential Revision: https://reviews.llvm.org/D34945

llvm-svn: 307768
diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp
index 3473a9e..8174c15 100644
--- a/lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -19,8 +19,18 @@
 
   switch (m_packet[0]) {
   case 'E':
-    if (m_packet.size() == 3 && isxdigit(m_packet[1]) && isxdigit(m_packet[2]))
-      return eError;
+    if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) {
+      if (m_packet.size() == 3)
+        return eError;
+      llvm::StringRef packet_ref(m_packet);
+      if (packet_ref[3] == ';') {
+        auto err_string = packet_ref.substr(4);
+        for (auto e : err_string)
+          if (!isxdigit(e))
+            return eResponse;
+        return eError;
+      }
+    }
     break;
 
   case 'O':
@@ -86,6 +96,8 @@
         return eServerPacketType_QEnvironment;
       if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:"))
         return eServerPacketType_QEnvironmentHexEncoded;
+      if (PACKET_STARTS_WITH("QEnableErrorStrings"))
+        return eServerPacketType_QEnableErrorStrings;
       break;
 
     case 'P':
@@ -438,8 +450,8 @@
 }
 
 bool StringExtractorGDBRemote::IsErrorResponse() const {
-  return GetResponseType() == eError && m_packet.size() == 3 &&
-         isxdigit(m_packet[1]) && isxdigit(m_packet[2]);
+  return GetResponseType() == eError && isxdigit(m_packet[1]) &&
+         isxdigit(m_packet[2]);
 }
 
 uint8_t StringExtractorGDBRemote::GetError() {
@@ -450,6 +462,23 @@
   return 0;
 }
 
+lldb_private::Status StringExtractorGDBRemote::GetStatus() {
+  lldb_private::Status error;
+  if (GetResponseType() == eError) {
+    SetFilePos(1);
+    uint8_t errc = GetHexU8(255);
+    error.SetError(errc, lldb::eErrorTypeGeneric);
+
+    std::string error_messg("Error ");
+    error_messg += std::to_string(errc);
+    if (GetChar() == ';')
+      GetHexByteString(error_messg);
+
+    error.SetErrorString(error_messg);
+  }
+  return error;
+}
+
 size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
   // Just get the data bytes in the string as
   // GDBRemoteCommunication::CheckForPacket()