Did a lot more work on abtracting and organizing the platforms. 

On Mac OS X we now have 3 platforms:
PlatformDarwin - must be subclassed to fill in the missing pure virtual funcs
                 but this implements all the common functionality between
                 remote-macosx and remote-ios. It also allows for another
                 platform to be used (remote-gdb-server for now) when doing
                 remote connections. Keeping this pluggable will allow for
                 flexibility.
PlatformMacOSX - Now implements both local and remote macosx desktop platforms.
PlatformRemoteiOS - Remote only iOS that knows how to locate SDK files in the
                    cached SDK locations on the host.

A new agnostic platform has been created:
PlatformRemoteGDBServer - this implements the platform using the GDB remote 
                          protocol and uses the built in lldb_private::Host
                          static functions to implement many queries.

llvm-svn: 128193
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 707fe46..15ab589 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -32,7 +32,8 @@
     m_rx_packet_listener (listener_name),
     m_sequence_mutex (Mutex::eMutexTypeRecursive),
     m_public_is_running (false),
-    m_private_is_running (false)
+    m_private_is_running (false),
+    m_send_acks (true)
 {
     m_rx_packet_listener.StartListeningForEvents(this,
                                                  Communication::eBroadcastBitPacketAvailable  |
@@ -127,7 +128,10 @@
             if (GetSendAcks ())
             {
                 if (GetAck () != '+')
+                {
+                    printf("get ack failed...");
                     return 0;
+                }
             }
         }
         else
@@ -238,9 +242,10 @@
                 }
             }
         }
-        else if (Communication::eBroadcastBitReadThreadDidExit)
+        else if (event_type | Communication::eBroadcastBitReadThreadDidExit)
         {
             // Our read thread exited on us so just fall through and return zero...
+            Disconnect();
         }
     }
     return 0;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 858f67c..e8129ce 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -88,15 +88,18 @@
         return m_public_is_running.GetValue();
     }
 
+    bool
+    GetSendAcks ()
+    {
+        return m_send_acks;
+    }
+
     //------------------------------------------------------------------
     // Client and server must implement these pure virtual functions
     //------------------------------------------------------------------
     virtual bool
     GetThreadSuffixSupported () = 0;
 
-    virtual bool
-    GetSendAcks () = 0;
-    
     //------------------------------------------------------------------
     // Set the global packet timeout.
     //
@@ -135,6 +138,10 @@
     lldb_private::Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time
     lldb_private::Predicate<bool> m_public_is_running;
     lldb_private::Predicate<bool> m_private_is_running;
+    bool m_send_acks;
+
+    
+
 
 private:
     //------------------------------------------------------------------
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 7700ab2..e158e5c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -50,7 +50,10 @@
     m_async_packet (),
     m_async_response (),
     m_async_signal (-1),
-    m_host_arch()
+    m_host_arch(),
+    m_os_version_major (UINT32_MAX),
+    m_os_version_minor (UINT32_MAX),
+    m_os_version_update (UINT32_MAX)
 {
     m_rx_packet_listener.StartListeningForEvents(this,
                                                  Communication::eBroadcastBitPacketAvailable  |
@@ -73,19 +76,36 @@
 }
 
 bool
-GDBRemoteCommunicationClient::GetSendAcks ()
+GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr)
+{
+    // Start the read thread after we send the handshake ack since if we
+    // fail to send the handshake ack, there is no reason to continue...
+    if (SendAck())
+        return StartReadThread (error_ptr);
+    
+    if (error_ptr)
+        error_ptr->SetErrorString("failed to send the handshake ack");
+    return false;
+}
+
+void
+GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
 {
     if (m_supports_not_sending_acks == eLazyBoolCalculate)
     {
-        StringExtractorGDBRemote response;
+        m_send_acks = true;
         m_supports_not_sending_acks = eLazyBoolNo;
+
+        StringExtractorGDBRemote response;
         if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false))
         {
             if (response.IsOKResponse())
+            {
+                m_send_acks = false;
                 m_supports_not_sending_acks = eLazyBoolYes;
+            }
         }
     }
-    return m_supports_not_sending_acks != eLazyBoolYes;
 }
 
 void
@@ -664,6 +684,79 @@
 }
 
 bool
+GDBRemoteCommunicationClient::GetOSVersion (uint32_t &major, 
+                                            uint32_t &minor, 
+                                            uint32_t &update)
+{
+    if (GetHostInfo ())
+    {
+        if (m_os_version_major != UINT32_MAX)
+        {
+            major = m_os_version_major;
+            minor = m_os_version_minor;
+            update = m_os_version_update;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetOSBuildString (std::string &s)
+{
+    if (GetHostInfo ())
+    {
+        if (!m_os_build.empty())
+        {
+            s = m_os_build;
+            return true;
+        }
+    }
+    s.clear();
+    return false;
+}
+
+
+bool
+GDBRemoteCommunicationClient::GetOSKernelDescription (std::string &s)
+{
+    if (GetHostInfo ())
+    {
+        if (!m_os_kernel.empty())
+        {
+            s = m_os_kernel;
+            return true;
+        }
+    }
+    s.clear();
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetHostname (std::string &s)
+{
+    if (GetHostInfo ())
+    {
+        if (!m_hostname.empty())
+        {
+            s = m_hostname;
+            return true;
+        }
+    }
+    s.clear();
+    return false;
+}
+
+ArchSpec
+GDBRemoteCommunicationClient::GetSystemArchitecture ()
+{
+    if (GetHostInfo ())
+        return m_host_arch;
+    return ArchSpec();
+}
+
+
+bool
 GDBRemoteCommunicationClient::GetHostInfo ()
 {
     if (m_supports_qHostInfo == eLazyBoolCalculate)
@@ -685,7 +778,9 @@
             std::string arch_name;
             std::string os_name;
             std::string vendor_name;
+            std::string triple;
             uint32_t pointer_byte_size = 0;
+            StringExtractor extractor;
             ByteOrder byte_order = eByteOrderInvalid;
             while (response.GetNameColonValue(name, value))
             {
@@ -703,6 +798,31 @@
                 {
                     arch_name.swap (value);
                 }
+                else if (name.compare("triple") == 0)
+                {
+                    // The triple comes as ASCII hex bytes since it contains '-' chars
+                    extractor.GetStringRef().swap(value);
+                    extractor.SetFilePos(0);
+                    extractor.GetHexByteString (triple);
+                }
+                else if (name.compare("os_build") == 0)
+                {
+                    extractor.GetStringRef().swap(value);
+                    extractor.SetFilePos(0);
+                    extractor.GetHexByteString (m_os_build);
+                }
+                else if (name.compare("hostname") == 0)
+                {
+                    extractor.GetStringRef().swap(value);
+                    extractor.SetFilePos(0);
+                    extractor.GetHexByteString (m_hostname);
+                }
+                else if (name.compare("os_kernel") == 0)
+                {
+                    extractor.GetStringRef().swap(value);
+                    extractor.SetFilePos(0);
+                    extractor.GetHexByteString (m_os_kernel);
+                }
                 else if (name.compare("ostype") == 0)
                 {
                     os_name.swap (value);
@@ -724,13 +844,52 @@
                 {
                     pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
                 }
+                else if (name.compare("os_version") == 0)
+                {
+                    Args::StringToVersion (value.c_str(), 
+                                           m_os_version_major,
+                                           m_os_version_minor,
+                                           m_os_version_update);
+                }
             }
             
-            if (arch_name.empty())
+            if (triple.empty())
             {
-                if (cpu != LLDB_INVALID_CPUTYPE)
+                if (arch_name.empty())
                 {
-                    m_host_arch.SetArchitecture (lldb::eArchTypeMachO, cpu, sub);
+                    if (cpu != LLDB_INVALID_CPUTYPE)
+                    {
+                        m_host_arch.SetArchitecture (lldb::eArchTypeMachO, cpu, sub);
+                        if (pointer_byte_size)
+                        {
+                            assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
+                        }
+                        if (byte_order != eByteOrderInvalid)
+                        {
+                            assert (byte_order == m_host_arch.GetByteOrder());
+                        }
+                        if (!vendor_name.empty())
+                            m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
+                        if (!os_name.empty())
+                            m_host_arch.GetTriple().setVendorName (llvm::StringRef (os_name));
+                            
+                    }
+                }
+                else
+                {
+                    std::string triple;
+                    triple += arch_name;
+                    triple += '-';
+                    if (vendor_name.empty())
+                        triple += "unknown";
+                    else
+                        triple += vendor_name;
+                    triple += '-';
+                    if (os_name.empty())
+                        triple += "unknown";
+                    else
+                        triple += os_name;
+                    m_host_arch.SetTriple (triple.c_str());
                     if (pointer_byte_size)
                     {
                         assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
@@ -739,29 +898,21 @@
                     {
                         assert (byte_order == m_host_arch.GetByteOrder());
                     }
-                    if (!vendor_name.empty())
-                        m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
-                    if (!os_name.empty())
-                        m_host_arch.GetTriple().setVendorName (llvm::StringRef (os_name));
-                        
+                    
                 }
             }
             else
             {
-                std::string triple;
-                triple += arch_name;
-                triple += '-';
-                if (vendor_name.empty())
-                    triple += "unknown";
-                else
-                    triple += vendor_name;
-                triple += '-';
-                if (os_name.empty())
-                    triple += "unknown";
-                else
-                    triple += os_name;
                 m_host_arch.SetTriple (triple.c_str());
-            }
+                if (pointer_byte_size)
+                {
+                    assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
+                }
+                if (byte_order != eByteOrderInvalid)
+                {
+                    assert (byte_order == m_host_arch.GetByteOrder());
+                }
+            }            
         }
     }
     return m_supports_qHostInfo == eLazyBoolYes;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index bcf23f2..410d80d 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -29,6 +29,13 @@
     virtual
     ~GDBRemoteCommunicationClient();
 
+    //------------------------------------------------------------------
+    // After connecting, send the handshake to the server to make sure
+    // we are communicating with it.
+    //------------------------------------------------------------------
+    bool
+    HandshakeWithServer (lldb_private::Error *error_ptr);
+
     size_t
     SendPacketAndWaitForResponse (const char *send_payload,
                                   StringExtractorGDBRemote &response,
@@ -49,8 +56,8 @@
     virtual bool
     GetThreadSuffixSupported ();
 
-    virtual bool
-    GetSendAcks ();
+    void
+    QueryNoAckModeSupported ();
 
     bool
     SendAsyncSignal (int signo);
@@ -186,6 +193,23 @@
     GetHostInfo ();
     
     bool
+    GetOSVersion (uint32_t &major, 
+                  uint32_t &minor, 
+                  uint32_t &update);
+
+    bool
+    GetOSBuildString (std::string &s);
+    
+    bool
+    GetOSKernelDescription (std::string &s);
+
+    lldb_private::ArchSpec
+    GetSystemArchitecture ();
+
+    bool
+    GetHostname (std::string &s);
+
+    bool
     GetSupportsThreadSuffix ();
 
     bool
@@ -232,7 +256,12 @@
     int m_async_signal; // We were asked to deliver a signal to the inferior process.
     
     lldb_private::ArchSpec m_host_arch;
-    uint32_t m_cpusubtype;
+    uint32_t m_os_version_major;
+    uint32_t m_os_version_minor;
+    uint32_t m_os_version_update;
+    std::string m_os_build;
+    std::string m_os_kernel;
+    std::string m_hostname;
     
 private:
     //------------------------------------------------------------------
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 18d6087..faee677 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -35,8 +35,7 @@
 //----------------------------------------------------------------------
 GDBRemoteCommunicationServer::GDBRemoteCommunicationServer() :
     GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet"),
-    m_async_thread (LLDB_INVALID_HOST_THREAD),
-    m_send_acks (true)
+    m_async_thread (LLDB_INVALID_HOST_THREAD)
 {
 }
 
@@ -73,6 +72,7 @@
 //
 bool
 GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_ptr, 
+                                                        Error &error,
                                                         bool &interrupt, 
                                                         bool &quit)
 {
@@ -87,10 +87,12 @@
             break;
 
         case StringExtractorGDBRemote::eServerPacketType_invalid:
+            error.SetErrorString("invalid packet");
             quit = true;
             break;
 
         case StringExtractorGDBRemote::eServerPacketType_interrupt:
+            error.SetErrorString("interrupt received");
             interrupt = true;
             break;
         
@@ -99,9 +101,20 @@
 
         case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
             return Handle_qHostInfo ();
+            
+        case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
+            return Handle_QStartNoAckMode ();
         }
         return true;
     }
+    else
+    {
+        if (!IsConnected())
+            error.SetErrorString("lost connection");
+        else
+            error.SetErrorString("timeout");
+    }
+
     return false;
 }
 
@@ -111,6 +124,19 @@
     return SendPacket ("");
 }
 
+size_t
+GDBRemoteCommunicationServer::SendOKResponse ()
+{
+    return SendPacket ("OK");
+}
+
+bool
+GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
+{
+    if (StartReadThread(error_ptr))
+        return GetAck();
+    return false;
+}
 
 bool
 GDBRemoteCommunicationServer::Handle_qHostInfo ()
@@ -120,17 +146,18 @@
     // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
 
     ArchSpec host_arch (Host::GetArchitecture ());
-    
     const llvm::Triple &host_triple = host_arch.GetTriple();
-    const llvm::StringRef arch_name (host_triple.getArchName());
-    const llvm::StringRef vendor_name (host_triple.getOSName());
-    const llvm::StringRef os_name (host_triple.getVendorName());
-    response.Printf ("arch:%.*s;ostype:%.*s;vendor:%.*s;ptrsize:%u", 
-                     (int)arch_name.size(), arch_name.data(),
-                     (int)os_name.size(), os_name.data(),
-                     (int)vendor_name.size(), vendor_name.data(),
-                     host_arch.GetAddressByteSize());
+    response.PutCString("triple:");
+    response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
+    response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
 
+    uint32_t cpu = host_arch.GetMachOCPUType();
+    uint32_t sub = host_arch.GetMachOCPUSubType();
+    if (cpu != LLDB_INVALID_CPUTYPE)
+        response.Printf ("cputype:%u;", cpu);
+    if (sub != LLDB_INVALID_CPUTYPE)
+        response.Printf ("cpusubtype:%u;", sub);
+    
     switch (lldb::endian::InlHostByteOrder())
     {
     case eByteOrderBig:     response.PutCString ("endian:big;"); break;
@@ -139,5 +166,52 @@
     default:                response.PutCString ("endian:unknown;"); break;
     }
     
+    uint32_t major = UINT32_MAX;
+    uint32_t minor = UINT32_MAX;
+    uint32_t update = UINT32_MAX;
+    if (Host::GetOSVersion (major, minor, update))
+    {
+        if (major != UINT32_MAX)
+        {
+            response.Printf("os_version:%u", major);
+            if (minor != UINT32_MAX)
+            {
+                response.Printf(".%u", minor);
+                if (update != UINT32_MAX)
+                    response.Printf(".%u", update);
+            }
+            response.PutChar(';');
+        }
+    }
+
+    std::string s;
+    if (Host::GetOSBuildString (s))
+    {
+        response.PutCString ("os_build:");
+        response.PutCStringAsRawHex8(s.c_str());
+        response.PutChar(';');
+    }
+    if (Host::GetOSKernelDescription (s))
+    {
+        response.PutCString ("os_kernel:");
+        response.PutCStringAsRawHex8(s.c_str());
+        response.PutChar(';');
+    }
+    if (Host::GetHostname (s))
+    {
+        response.PutCString ("hostname:");
+        response.PutCStringAsRawHex8(s.c_str());
+        response.PutChar(';');
+    }
+    
     return SendPacket (response.GetString().c_str(),response.GetString().size()) > 0;
 }
+
+
+bool
+GDBRemoteCommunicationServer::Handle_QStartNoAckMode ()
+{
+    SendOKResponse ();
+    m_send_acks = false;
+    return true;
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 4e0b24d..66ddc77 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -35,6 +35,7 @@
 
     bool
     GetPacketAndSendResponse (const lldb_private::TimeValue* timeout_ptr,
+                              lldb_private::Error &error,
                               bool &interrupt, 
                               bool &quit);
 
@@ -44,23 +45,26 @@
         return true;
     }
 
-    virtual bool
-    GetSendAcks ()
-    {
-        return m_send_acks;
-    }
+    // After connecting, do a little handshake with the client to make sure
+    // we are at least communicating
+    bool
+    HandshakeWithClient (lldb_private::Error *error_ptr);
 
 protected:
     lldb::thread_t m_async_thread;
-    bool m_send_acks;
 
     size_t
     SendUnimplementedResponse ();
 
+    size_t
+    SendOKResponse ();
 
     bool
     Handle_qHostInfo ();
 
+    bool
+    Handle_QStartNoAckMode ();
+
 private:
     //------------------------------------------------------------------
     // For GDBRemoteCommunicationServer only