Moved the execution context that was in the Debugger into
the CommandInterpreter where it was always being used.

Make sure that Modules can track their object file offsets correctly to
allow opening of sub object files (like the "__commpage" on darwin).

Modified the Platforms to be able to launch processes. The first part of this
move is the platform soon will become the entity that launches your program
and when it does, it uses a new ProcessLaunchInfo class which encapsulates
all process launching settings. This simplifies the internal APIs needed for
launching. I want to slowly phase out process launching from the process
classes, so for now we can still launch just as we used to, but eventually
the platform is the object that should do the launching.

Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able
to launch processes with all of the new eLaunchFlag settings. Modified any
code that was manually launching processes to use the Host::LaunchProcess
functions.

Fixed an issue where lldb_private::Args had implicitly defined copy 
constructors that could do the wrong thing. This has now been fixed by adding
an appropriate copy constructor and assignment operator.

Make sure we don't add empty ModuleSP entries to a module list.

Fixed the commpage module creation on MacOSX, but we still need to train
the MacOSX dynamic loader to not get rid of it when it doesn't have an entry
in the all image infos.

Abstracted many more calls from in ProcessGDBRemote down into the 
GDBRemoteCommunicationClient subclass to make the classes cleaner and more
efficient.

Fixed the default iOS ARM register context to be correct and also added support
for targets that don't support the qThreadStopInfo packet by selecting the
current thread (only if needed) and then sending a stop reply packet.

Debugserver can now start up with a --unix-socket (-u for short) and can 
then bind to port zero and send the port it bound to to a listening process
on the other end. This allows the GDB remote platform to spawn new GDB server
instances (debugserver) to allow platform debugging.







git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@129351 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 3b8d605..93e4166 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -17,25 +17,33 @@
 // Other libraries and framework includes
 #include "lldb/Core/Log.h"
 #include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
 #include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Process.h"
 
 // Project includes
 #include "ProcessGDBRemoteLog.h"
 
+#define DEBUGSERVER_BASENAME    "debugserver"
+
 using namespace lldb;
 using namespace lldb_private;
 
 //----------------------------------------------------------------------
 // GDBRemoteCommunication constructor
 //----------------------------------------------------------------------
-GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, const char *listener_name) :
+GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, 
+                                               const char *listener_name, 
+                                               bool is_platform) :
     Communication(comm_name),
     m_packet_timeout (60),
     m_rx_packet_listener (listener_name),
     m_sequence_mutex (Mutex::eMutexTypeRecursive),
     m_public_is_running (false),
     m_private_is_running (false),
-    m_send_acks (true)
+    m_send_acks (true),
+    m_is_platform (is_platform)
 {
     m_rx_packet_listener.StartListeningForEvents(this,
                                                  Communication::eBroadcastBitPacketAvailable  |
@@ -328,3 +336,131 @@
     }
 }
 
+Error
+GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
+                                                 const char *unix_socket_name,  // For handshaking
+                                                 lldb_private::ProcessLaunchInfo &launch_info)
+{
+    Error error;
+    // If we locate debugserver, keep that located version around
+    static FileSpec g_debugserver_file_spec;
+    
+    // This function will fill in the launch information for the debugserver
+    // instance that gets launched.
+    launch_info.Clear();
+    
+    char debugserver_path[PATH_MAX];
+    FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
+    
+    // Always check to see if we have an environment override for the path
+    // to the debugserver to use and use it if we do.
+    const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
+    if (env_debugserver_path)
+        debugserver_file_spec.SetFile (env_debugserver_path, false);
+    else
+        debugserver_file_spec = g_debugserver_file_spec;
+    bool debugserver_exists = debugserver_file_spec.Exists();
+    if (!debugserver_exists)
+    {
+        // The debugserver binary is in the LLDB.framework/Resources
+        // directory. 
+        if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
+        {
+            debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
+            debugserver_exists = debugserver_file_spec.Exists();
+            if (debugserver_exists)
+            {
+                g_debugserver_file_spec = debugserver_file_spec;
+            }
+            else
+            {
+                g_debugserver_file_spec.Clear();
+                debugserver_file_spec.Clear();
+            }
+        }
+    }
+    
+    if (debugserver_exists)
+    {
+        debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
+
+        Args &debugserver_args = launch_info.GetArguments();
+        debugserver_args.Clear();
+        char arg_cstr[PATH_MAX];
+        
+        // Start args with "debugserver /file/path -r --"
+        debugserver_args.AppendArgument(debugserver_path);
+        debugserver_args.AppendArgument(debugserver_url);
+        // use native registers, not the GDB registers
+        debugserver_args.AppendArgument("--native-regs");   
+        // make debugserver run in its own session so signals generated by 
+        // special terminal key sequences (^C) don't affect debugserver
+        debugserver_args.AppendArgument("--setsid");
+        
+        if (unix_socket_name && unix_socket_name[0])
+        {
+            debugserver_args.AppendArgument("--unix-socket");
+            debugserver_args.AppendArgument(unix_socket_name);
+        }
+
+        const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
+        if (env_debugserver_log_file)
+        {
+            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
+            debugserver_args.AppendArgument(arg_cstr);
+        }
+        
+        const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
+        if (env_debugserver_log_flags)
+        {
+            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
+            debugserver_args.AppendArgument(arg_cstr);
+        }
+        //            debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
+        //            debugserver_args.AppendArgument("--log-flags=0x802e0e");
+        
+        // We currently send down all arguments, attach pids, or attach 
+        // process names in dedicated GDB server packets, so we don't need
+        // to pass them as arguments. This is currently because of all the
+        // things we need to setup prior to launching: the environment,
+        // current working dir, file actions, etc.
+#if 0
+        // Now append the program arguments
+        if (inferior_argv)
+        {
+            // Terminate the debugserver args so we can now append the inferior args
+            debugserver_args.AppendArgument("--");
+            
+            for (int i = 0; inferior_argv[i] != NULL; ++i)
+                debugserver_args.AppendArgument (inferior_argv[i]);
+        }
+        else if (attach_pid != LLDB_INVALID_PROCESS_ID)
+        {
+            ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
+            debugserver_args.AppendArgument (arg_cstr);
+        }
+        else if (attach_name && attach_name[0])
+        {
+            if (wait_for_launch)
+                debugserver_args.AppendArgument ("--waitfor");
+            else
+                debugserver_args.AppendArgument ("--attach");
+            debugserver_args.AppendArgument (attach_name);
+        }
+#endif
+        
+        // Close STDIN, STDOUT and STDERR. We might need to redirect them
+        // to "/dev/null" if we run into any problems.
+//        launch_info.AppendCloseFileAction (STDIN_FILENO);
+//        launch_info.AppendCloseFileAction (STDOUT_FILENO);
+//        launch_info.AppendCloseFileAction (STDERR_FILENO);
+        
+        error = Host::LaunchProcess(launch_info);
+    }
+    else
+    {
+        error.SetErrorStringWithFormat ("Unable to locate " DEBUGSERVER_BASENAME ".\n");
+    }
+    return error;
+}
+
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index f53d036..77e3e1a 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -37,7 +37,9 @@
     //------------------------------------------------------------------
     // Constructors and Destructors
     //------------------------------------------------------------------
-    GDBRemoteCommunication(const char *comm_name, const char *listener_name);
+    GDBRemoteCommunication(const char *comm_name, 
+                           const char *listener_name,
+                           bool is_platform);
 
     virtual
     ~GDBRemoteCommunication();
@@ -119,6 +121,15 @@
         return old_packet_timeout;
     }
 
+    //------------------------------------------------------------------
+    // Start a debugserver instance on the current host using the
+    // supplied connection URL.
+    //------------------------------------------------------------------
+    lldb_private::Error
+    StartDebugserverProcess (const char *connect_url,
+                             const char *unix_socket_name,
+                             lldb_private::ProcessLaunchInfo &launch_info); 
+
 protected:
     typedef std::list<std::string> packet_collection;
 
@@ -142,10 +153,13 @@
     lldb_private::Predicate<bool> m_public_is_running;
     lldb_private::Predicate<bool> m_private_is_running;
     bool m_send_acks;
-
+    bool m_is_platform; // Set to true if this class represents a platform,
+                        // false if this class represents a debug session for
+                        // a single process
     
 
 
+
 private:
     //------------------------------------------------------------------
     // For GDBRemoteCommunication only
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 2cebb10..d4f6592 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -34,8 +34,8 @@
 //----------------------------------------------------------------------
 // GDBRemoteCommunicationClient constructor
 //----------------------------------------------------------------------
-GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() :
-    GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"),
+GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
+    GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet", is_platform),
     m_supports_not_sending_acks (eLazyBoolCalculate),
     m_supports_thread_suffix (eLazyBoolCalculate),
     m_supports_vCont_all (eLazyBoolCalculate),
@@ -49,6 +49,14 @@
     m_supports_qfProcessInfo (true),
     m_supports_qUserName (true),
     m_supports_qGroupName (true),
+    m_supports_qThreadStopInfo (true),
+    m_supports_z0 (true),
+    m_supports_z1 (true),
+    m_supports_z2 (true),
+    m_supports_z3 (true),
+    m_supports_z4 (true),
+    m_curr_tid (LLDB_INVALID_THREAD_ID),
+    m_curr_tid_run (LLDB_INVALID_THREAD_ID),
     m_async_mutex (Mutex::eMutexTypeRecursive),
     m_async_packet_predicate (false),
     m_async_packet (),
@@ -126,6 +134,12 @@
     m_supports_qfProcessInfo = true;
     m_supports_qUserName = true;
     m_supports_qGroupName = true;
+    m_supports_qThreadStopInfo = true;
+    m_supports_z0 = true;
+    m_supports_z1 = true;
+    m_supports_z2 = true;
+    m_supports_z3 = true;
+    m_supports_z4 = true;
     m_host_arch.Clear();
 }
 
@@ -1119,7 +1133,7 @@
 }
 
 bool
-GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInfo &process_info)
+GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info)
 {
     if (response.IsNormalResponse())
     {
@@ -1139,7 +1153,7 @@
             }
             else if (name.compare("uid") == 0)
             {
-                process_info.SetRealUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
+                process_info.SetUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
             }
             else if (name.compare("euid") == 0)
             {
@@ -1147,7 +1161,7 @@
             }
             else if (name.compare("gid") == 0)
             {
-                process_info.SetRealGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
+                process_info.SetGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
             }
             else if (name.compare("egid") == 0)
             {
@@ -1180,7 +1194,7 @@
 }
 
 bool
-GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
+GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
 {
     process_info.Clear();
     
@@ -1205,8 +1219,8 @@
 }
 
 uint32_t
-GDBRemoteCommunicationClient::FindProcesses (const ProcessInfoMatch &match_info,
-                                             ProcessInfoList &process_infos)
+GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+                                             ProcessInstanceInfoList &process_infos)
 {
     process_infos.Clear();
     
@@ -1261,10 +1275,10 @@
                 packet.Printf("pid:%u;",match_info.GetProcessInfo().GetProcessID());
             if (match_info.GetProcessInfo().ParentProcessIDIsValid())
                 packet.Printf("parent_pid:%u;",match_info.GetProcessInfo().GetParentProcessID());
-            if (match_info.GetProcessInfo().RealUserIDIsValid())
-                packet.Printf("uid:%u;",match_info.GetProcessInfo().GetRealUserID());
-            if (match_info.GetProcessInfo().RealGroupIDIsValid())
-                packet.Printf("gid:%u;",match_info.GetProcessInfo().GetRealGroupID());
+            if (match_info.GetProcessInfo().UserIDIsValid())
+                packet.Printf("uid:%u;",match_info.GetProcessInfo().GetUserID());
+            if (match_info.GetProcessInfo().GroupIDIsValid())
+                packet.Printf("gid:%u;",match_info.GetProcessInfo().GetGroupID());
             if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
                 packet.Printf("euid:%u;",match_info.GetProcessInfo().GetEffectiveUserID());
             if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
@@ -1291,7 +1305,7 @@
 
             do
             {
-                ProcessInfo process_info;
+                ProcessInstanceInfo process_info;
                 if (!DecodeProcessInfoResponse (response, process_info))
                     break;
                 process_infos.Append(process_info);
@@ -1447,3 +1461,154 @@
     }
     return false;
 }
+
+uint16_t
+GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
+{
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse("qLaunchGDBServer", strlen("qLaunchGDBServer"), response, false))
+    {
+        std::string name;
+        std::string value;
+        uint16_t port = 0;
+        lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+        while (response.GetNameColonValue(name, value))
+        {
+            if (name.size() == 4 && name.compare("port") == 0)
+                port = Args::StringToUInt32(value.c_str(), 0, 0);
+            if (name.size() == 3 && name.compare("pid") == 0)
+                pid = Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
+        }
+        return port;
+    }
+    return 0;
+}
+
+bool
+GDBRemoteCommunicationClient::SetCurrentThread (int tid)
+{
+    if (m_curr_tid == tid)
+        return true;
+    
+    char packet[32];
+    int packet_len;
+    if (tid <= 0)
+        packet_len = ::snprintf (packet, sizeof(packet), "Hg%i", tid);
+    else
+        packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
+    assert (packet_len + 1 < sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+    {
+        if (response.IsOKResponse())
+        {
+            m_curr_tid = tid;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::SetCurrentThreadForRun (int tid)
+{
+    if (m_curr_tid_run == tid)
+        return true;
+    
+    char packet[32];
+    int packet_len;
+    if (tid <= 0)
+        packet_len = ::snprintf (packet, sizeof(packet), "Hc%i", tid);
+    else
+        packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid);
+    
+    assert (packet_len + 1 < sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+    {
+        if (response.IsOKResponse())
+        {
+            m_curr_tid_run = tid;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetStopReply (StringExtractorGDBRemote &response)
+{
+    if (SendPacketAndWaitForResponse("?", 1, response, false))
+        return response.IsNormalResponse();
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetThreadStopInfo (uint32_t tid, StringExtractorGDBRemote &response)
+{
+    if (m_supports_qThreadStopInfo)
+    {
+        char packet[256];
+        int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%x", tid);
+        assert (packet_len < sizeof(packet));
+        if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+        {
+            if (response.IsUnsupportedResponse())
+                m_supports_qThreadStopInfo = false;
+            else if (response.IsNormalResponse())
+                return true;
+            else
+                return false;
+        }
+    }
+    if (SetCurrentThread (tid))
+        return GetStopReply (response);
+    return false;
+}
+
+
+uint8_t
+GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert,  addr_t addr, uint32_t length)
+{
+    switch (type)
+    {
+    case eBreakpointSoftware:   if (!m_supports_z0) return UINT8_MAX; break;
+    case eBreakpointHardware:   if (!m_supports_z1) return UINT8_MAX; break;
+    case eWatchpointWrite:      if (!m_supports_z2) return UINT8_MAX; break;
+    case eWatchpointRead:       if (!m_supports_z3) return UINT8_MAX; break;
+    case eWatchpointReadWrite:  if (!m_supports_z4) return UINT8_MAX; break;
+    default:                    return UINT8_MAX;
+    }
+
+    char packet[64];
+    const int packet_len = ::snprintf (packet, 
+                                       sizeof(packet), 
+                                       "%c%i,%llx,%x", 
+                                       insert ? 'Z' : 'z', 
+                                       type, 
+                                       addr, 
+                                       length);
+
+    assert (packet_len + 1 < sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse(packet, packet_len, response, true))
+    {
+        if (response.IsOKResponse())
+            return 0;
+        if (response.IsUnsupportedResponse())
+        {
+            switch (type)
+            {
+                case eBreakpointSoftware:   m_supports_z0 = false; break;
+                case eBreakpointHardware:   m_supports_z1 = false; break;
+                case eWatchpointWrite:      m_supports_z2 = false; break;
+                case eWatchpointRead:       m_supports_z3 = false; break;
+                case eWatchpointReadWrite:  m_supports_z4 = false; break;
+                default:                    break;
+            }
+        }
+        else if (response.IsErrorResponse())
+            return response.GetError();
+    }
+    return UINT8_MAX;
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index ae1674a..5c24d64 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -18,13 +18,22 @@
 
 #include "GDBRemoteCommunication.h"
 
+typedef enum 
+{
+    eBreakpointSoftware = 0,
+    eBreakpointHardware,
+    eWatchpointWrite,
+    eWatchpointRead,
+    eWatchpointReadWrite
+} GDBStoppointType;
+
 class GDBRemoteCommunicationClient : public GDBRemoteCommunication
 {
 public:
     //------------------------------------------------------------------
     // Constructors and Destructors
     //------------------------------------------------------------------
-    GDBRemoteCommunicationClient();
+    GDBRemoteCommunicationClient(bool is_platform);
 
     virtual
     ~GDBRemoteCommunicationClient();
@@ -74,6 +83,9 @@
     bool
     GetLaunchSuccess (std::string &error_str);
 
+    uint16_t
+    LaunchGDBserverAndGetPort ();
+
     //------------------------------------------------------------------
     /// Sends a GDB remote protocol 'A' packet that delivers program
     /// arguments to the remote server.
@@ -214,11 +226,11 @@
 
     bool
     GetProcessInfo (lldb::pid_t pid, 
-                    lldb_private::ProcessInfo &process_info);
+                    lldb_private::ProcessInstanceInfo &process_info);
 
     uint32_t
-    FindProcesses (const lldb_private::ProcessInfoMatch &process_match_info,
-                   lldb_private::ProcessInfoList &process_infos);
+    FindProcesses (const lldb_private::ProcessInstanceInfoMatch &process_match_info,
+                   lldb_private::ProcessInstanceInfoList &process_infos);
 
     bool
     GetUserName (uint32_t uid, std::string &name);
@@ -246,6 +258,33 @@
         return old_packet_timeout;
     }
 
+    bool
+    GetStopReply (StringExtractorGDBRemote &response);
+
+    bool
+    GetThreadStopInfo (uint32_t tid, 
+                       StringExtractorGDBRemote &response);
+
+    bool
+    SupportsGDBStoppointPacket (GDBStoppointType type)
+    {
+        switch (type)
+        {
+        case eBreakpointSoftware:   return m_supports_z0;
+        case eBreakpointHardware:   return m_supports_z1;
+        case eWatchpointWrite:      return m_supports_z2;
+        case eWatchpointRead:       return m_supports_z3;
+        case eWatchpointReadWrite:  return m_supports_z4;
+        default:                    break;
+        }
+        return false;
+    }
+    uint8_t
+    SendGDBStoppointTypePacket (GDBStoppointType type,   // Type of breakpoint or watchpoint
+                                bool insert,              // Insert or remove?
+                                lldb::addr_t addr,        // Address of breakpoint or watchpoint
+                                uint32_t length);         // Byte Size of breakpoint or watchpoint
+
     void
     TestPacketSpeed (const uint32_t num_packets);
 
@@ -257,6 +296,13 @@
     bool
     SendSpeedTestPacket (uint32_t send_size, 
                          uint32_t recv_size);
+    
+    bool
+    SetCurrentThread (int tid);
+    
+    bool
+    SetCurrentThreadForRun (int tid);
+
 protected:
 
     //------------------------------------------------------------------
@@ -271,10 +317,21 @@
     lldb_private::LazyBool m_supports_vCont_s;
     lldb_private::LazyBool m_supports_vCont_S;
     lldb_private::LazyBool m_qHostInfo_is_valid;
-    bool m_supports_qProcessInfoPID;
-    bool m_supports_qfProcessInfo;
-    bool m_supports_qUserName;
-    bool m_supports_qGroupName;
+    bool
+        m_supports_qProcessInfoPID:1,
+        m_supports_qfProcessInfo:1,
+        m_supports_qUserName:1,
+        m_supports_qGroupName:1,
+        m_supports_qThreadStopInfo:1,
+        m_supports_z0:1,
+        m_supports_z1:1,
+        m_supports_z2:1,
+        m_supports_z3:1,
+        m_supports_z4:1;
+
+    lldb::tid_t m_curr_tid;         // Current gdb remote protocol thread index for all other operations
+    lldb::tid_t m_curr_tid_run;     // Current gdb remote protocol thread index for continue, step, etc
+
 
     // If we need to send a packet while the target is running, the m_async_XXX
     // member variables take care of making this happen.
@@ -294,7 +351,7 @@
     
     bool
     DecodeProcessInfoResponse (StringExtractorGDBRemote &response, 
-                               lldb_private::ProcessInfo &process_info);
+                               lldb_private::ProcessInstanceInfo &process_info);
 private:
     //------------------------------------------------------------------
     // For GDBRemoteCommunicationClient only
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index c243138..9379077 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -21,6 +21,7 @@
 #include "lldb/Core/StreamString.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Process.h"
 
 // Project includes
 #include "Utility/StringExtractorGDBRemote.h"
@@ -33,9 +34,15 @@
 //----------------------------------------------------------------------
 // GDBRemoteCommunicationServer constructor
 //----------------------------------------------------------------------
-GDBRemoteCommunicationServer::GDBRemoteCommunicationServer() :
-    GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet"),
-    m_async_thread (LLDB_INVALID_HOST_THREAD)
+GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
+    GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
+    m_async_thread (LLDB_INVALID_HOST_THREAD),
+    m_process_launch_info (),
+    m_process_launch_error (),
+    m_proc_infos (),
+    m_proc_infos_index (0),
+    m_lo_port_num (0),
+    m_hi_port_num (0)
 {
 }
 
@@ -82,45 +89,76 @@
         const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
         switch (packet_type)
         {
-        case StringExtractorGDBRemote::eServerPacketType_nack:
-        case StringExtractorGDBRemote::eServerPacketType_ack:
-            break;
+            case StringExtractorGDBRemote::eServerPacketType_nack:
+            case StringExtractorGDBRemote::eServerPacketType_ack:
+                break;
 
-        case StringExtractorGDBRemote::eServerPacketType_invalid:
-            error.SetErrorString("invalid packet");
-            quit = true;
-            break;
+            case StringExtractorGDBRemote::eServerPacketType_invalid:
+                error.SetErrorString("invalid packet");
+                quit = true;
+                break;
 
-        case StringExtractorGDBRemote::eServerPacketType_interrupt:
-            error.SetErrorString("interrupt received");
-            interrupt = true;
-            break;
-        
-        case StringExtractorGDBRemote::eServerPacketType_unimplemented:
-            return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
+            case StringExtractorGDBRemote::eServerPacketType_interrupt:
+                error.SetErrorString("interrupt received");
+                interrupt = true;
+                break;
+            
+            case StringExtractorGDBRemote::eServerPacketType_unimplemented:
+                return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
 
-        case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
-            return Handle_qHostInfo (packet);
+            case StringExtractorGDBRemote::eServerPacketType_A:
+                return Handle_A (packet);
 
-        case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
-            return Handle_qProcessInfoPID (packet);
+            case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
+                return Handle_qfProcessInfo (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
+                return Handle_qsProcessInfo (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qC:
+                return Handle_qC (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
+                return Handle_qHostInfo (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
+                return Handle_qLaunchGDBServer (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
+                return Handle_qLaunchSuccess (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qGroupName:
+                return Handle_qGroupName (packet);
 
-        case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
-            return Handle_qfProcessInfo (packet);
+            case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
+                return Handle_qProcessInfoPID (packet);
 
-        case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
-            return Handle_qsProcessInfo (packet);
-        
-        case StringExtractorGDBRemote::eServerPacketType_qUserName:
-            return Handle_qUserName (packet);
+            case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
+                return Handle_qSpeedTest (packet);
 
-        case StringExtractorGDBRemote::eServerPacketType_qGroupName:
-            return Handle_qGroupName (packet);
+            case StringExtractorGDBRemote::eServerPacketType_qUserName:
+                return Handle_qUserName (packet);
 
-        case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
-            return Handle_qSpeedTest (packet);
-        case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
-            return Handle_QStartNoAckMode (packet);
+            case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
+                return Handle_QEnvironment (packet);
+            
+            case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
+                return Handle_QSetDisableASLR (packet);
+            
+            case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
+                return Handle_QSetSTDIN (packet);
+            
+            case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
+                return Handle_QSetSTDOUT (packet);
+            
+            case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
+                return Handle_QSetSTDERR (packet);
+            
+            case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
+                return Handle_QSetWorkingDir (packet);
+
+            case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
+                return Handle_QStartNoAckMode (packet);
         }
         return true;
     }
@@ -236,13 +274,13 @@
 }
 
 static void
-CreateProcessInfoResponse (const ProcessInfo &proc_info, StreamString &response)
+CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
 {
     response.Printf ("pid:%i;ppid:%i;uid:%i;gid:%i;euid:%i;egid:%i;", 
                      proc_info.GetProcessID(),
                      proc_info.GetParentProcessID(),
-                     proc_info.GetRealUserID(),
-                     proc_info.GetRealGroupID(),
+                     proc_info.GetUserID(),
+                     proc_info.GetGroupID(),
                      proc_info.GetEffectiveUserID(),
                      proc_info.GetEffectiveGroupID());
     response.PutCString ("name:");
@@ -262,11 +300,11 @@
 GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
 {
     // Packet format: "qProcessInfoPID:%i" where %i is the pid
-    packet.SetFilePos(strlen ("qProcessInfoPID:"));
+    packet.SetFilePos(::strlen ("qProcessInfoPID:"));
     lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
     if (pid != LLDB_INVALID_PROCESS_ID)
     {
-        ProcessInfo proc_info;
+        ProcessInstanceInfo proc_info;
         if (Host::GetProcessInfo(pid, proc_info))
         {
             StreamString response;
@@ -283,8 +321,8 @@
     m_proc_infos_index = 0;
     m_proc_infos.Clear();
 
-    ProcessInfoMatch match_info;
-    packet.SetFilePos(strlen ("qfProcessInfo"));
+    ProcessInstanceInfoMatch match_info;
+    packet.SetFilePos(::strlen ("qfProcessInfo"));
     if (packet.GetChar() == ':')
     {
     
@@ -337,11 +375,11 @@
             }
             else if (key.compare("uid") == 0)
             {
-                match_info.GetProcessInfo().SetRealUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+                match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
             }
             else if (key.compare("gid") == 0)
             {
-                match_info.GetProcessInfo().SetRealGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+                match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
             }
             else if (key.compare("euid") == 0)
             {
@@ -395,7 +433,7 @@
 GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
 {
     // Packet format: "qUserName:%i" where %i is the uid
-    packet.SetFilePos(strlen ("qUserName:"));
+    packet.SetFilePos(::strlen ("qUserName:"));
     uint32_t uid = packet.GetU32 (UINT32_MAX);
     if (uid != UINT32_MAX)
     {
@@ -415,7 +453,7 @@
 GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
 {
     // Packet format: "qGroupName:%i" where %i is the gid
-    packet.SetFilePos(strlen ("qGroupName:"));
+    packet.SetFilePos(::strlen ("qGroupName:"));
     uint32_t gid = packet.GetU32 (UINT32_MAX);
     if (gid != UINT32_MAX)
     {
@@ -433,7 +471,7 @@
 bool
 GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
 {
-    packet.SetFilePos(strlen ("qSpeedTest:"));
+    packet.SetFilePos(::strlen ("qSpeedTest:"));
 
     std::string key;
     std::string value;
@@ -466,6 +504,327 @@
     }
     return SendErrorResponse (7);
 }
+
+
+static void *
+AcceptPortFromInferior (void *arg)
+{
+    const char *connect_url = (const char *)arg;
+    ConnectionFileDescriptor file_conn;
+    Error error;
+    if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
+    {
+        char pid_str[256];
+        ::memset (pid_str, 0, sizeof(pid_str));
+        ConnectionStatus status;
+        const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL);
+        if (pid_str_len > 0)
+        {
+            int pid = atoi (pid_str);
+            return (void *)(intptr_t)pid;
+        }
+    }
+    return NULL;
+}
+//
+//static bool
+//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
+//{
+//    const int time_delta_usecs = 100000;
+//    const int num_retries = timeout_in_seconds/time_delta_usecs;
+//    for (int i=0; i<num_retries; i++)
+//    {
+//        struct proc_bsdinfo bsd_info;
+//        int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO, 
+//                                    (uint64_t) 0, 
+//                                    &bsd_info, 
+//                                    PROC_PIDTBSDINFO_SIZE);
+//        
+//        switch (error)
+//        {
+//            case EINVAL:
+//            case ENOTSUP:
+//            case ESRCH:
+//            case EPERM:
+//                return false;
+//                
+//            default:
+//                break;
+//                
+//            case 0:
+//                if (bsd_info.pbi_status == SSTOP)
+//                    return true;
+//        }
+//        ::usleep (time_delta_usecs);
+//    }
+//    return false;
+//}
+
+bool
+GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
+{
+    // The 'A' packet is the most over designed packet ever here with 
+    // redundant argument indexes, redundant argument lengths and needed hex 
+    // encoded argument string values. Really all that is needed is a comma 
+    // separated hex encoded argument value list, but we will stay true to the
+    // documented version of the 'A' packet here...
+
+    packet.SetFilePos(1); // Skip the 'A'
+    bool success = true;
+    while (success && packet.GetBytesLeft() > 0)
+    {
+        // Decode the decimal argument string length. This length is the
+        // number of hex nibbles in the argument string value.
+        const uint32_t arg_len = packet.GetU32(UINT32_MAX);
+        if (arg_len == UINT32_MAX)
+            success = false;
+        else
+        {
+            // Make sure the argument hex string length is followed by a comma
+            if (packet.GetChar() != ',')
+                success = false;
+            else
+            {
+                // Decode the argument index. We ignore this really becuase
+                // who would really send down the arguments in a random order???
+                const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
+                if (arg_idx == UINT32_MAX)
+                    success = false;
+                else
+                {
+                    // Make sure the argument index is followed by a comma
+                    if (packet.GetChar() != ',')
+                        success = false;
+                    else
+                    {
+                        // Decode the argument string value from hex bytes
+                        // back into a UTF8 string and make sure the length
+                        // matches the one supplied in the packet
+                        std::string arg;
+                        if (packet.GetHexByteString(arg) != (arg_len / 2))
+                            success = false;
+                        else
+                        {
+                            // If there are any bytes lft
+                            if (packet.GetBytesLeft())
+                            {
+                                if (packet.GetChar() != ',')
+                                    success = false;
+                            }
+                            
+                            if (success)
+                            {
+                                if (arg_idx == 0)
+                                    m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
+                                m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (success)
+    {
+        m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
+        m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
+        if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
+        {
+            return SendOKResponse ();
+        }
+    }
+    return SendErrorResponse (8);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
+{
+    lldb::pid_t pid = m_process_launch_info.GetProcessID();
+    StreamString response;
+    response.Printf("QC%x", pid);
+    if (m_is_platform)
+    {
+        // If we launch a process and this GDB server is acting as a platform, 
+        // then we need to clear the process launch state so we can start 
+        // launching another process. In order to launch a process a bunch or
+        // packets need to be sent: environment packets, working directory,
+        // disable ASLR, and many more settings. When we launch a process we 
+        // then need to know when to clear this information. Currently we are
+        // selecting the 'qC' packet as that packet which seems to make the most
+        // sense.
+        if (pid != LLDB_INVALID_PROCESS_ID)
+        {
+            m_process_launch_info.Clear();
+        }
+    }
+    return SendPacket (response);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
+{
+    // Spawn a local debugserver as a platform so we can then attach or launch
+    // a process...
+
+    if (m_is_platform)
+    {
+        // Sleep and wait a bit for debugserver to start to listen...
+        ConnectionFileDescriptor file_conn;
+        char connect_url[PATH_MAX];
+        Error error;
+        char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";    
+        if (::mktemp (unix_socket_name) == NULL)
+        {
+            error.SetErrorString ("failed to make temporary path for a unix socket");
+        }
+        else
+        {
+            ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
+            // Spawn a new thread to accept the port that gets bound after
+            // binding to port 0 (zero).
+            lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
+                                                               AcceptPortFromInferior,
+                                                               connect_url,
+                                                               &error);
+            
+            if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
+            {
+                // Spawn a debugserver and try to get
+                ProcessLaunchInfo debugserver_launch_info;
+                error = StartDebugserverProcess ("localhost:0", 
+                                                 unix_socket_name, 
+                                                 debugserver_launch_info);
+                
+                lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+                if (error.Success())
+                {
+                    bool success = false;
+                    
+                    thread_result_t accept_thread_result = NULL;
+                    if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
+                    {
+                        if (accept_thread_result)
+                        {
+                            uint16_t port = (intptr_t)accept_thread_result;
+                            char response[256];
+                            const int response_len = ::snprintf (response, sizeof(response), "pid:%u;port:%u;", debugserver_pid, port);
+                            assert (response_len < sizeof(response));
+                            //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+                            success = SendPacket (response, response_len) > 0;
+                        }
+                    }
+                    ::unlink (unix_socket_name);
+                    
+                    if (!success)
+                    {
+                        if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+                            ::kill (debugserver_pid, SIGINT);
+                    }
+                    return success;
+                }
+            }
+        }
+    }
+    return SendErrorResponse (13);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
+{
+    if (m_process_launch_error.Success())
+        return SendOKResponse();
+    StreamString response;    
+    response.PutChar('E');
+    response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
+    return SendPacket (response);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QEnvironment  (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QEnvironment:"));
+    const uint32_t bytes_left = packet.GetBytesLeft();
+    if (bytes_left > 0)
+    {
+        m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
+        return SendOKResponse ();
+    }
+    return SendErrorResponse (9);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QSetDisableASLR:"));
+    if (packet.GetU32(0))
+        m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
+    else
+        m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
+    return SendOKResponse ();
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QSetWorkingDir:"));
+    std::string path;
+    packet.GetHexByteString(path);
+    m_process_launch_info.SwapWorkingDirectory (path);
+    return SendOKResponse ();
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QSetSTDIN:"));
+    ProcessLaunchInfo::FileAction file_action;
+    std::string path;
+    packet.GetHexByteString(path);
+    const bool read = false;
+    const bool write = true;
+    if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
+    {
+        m_process_launch_info.AppendFileAction(file_action);
+        return SendOKResponse ();
+    }
+    return SendErrorResponse (10);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QSetSTDOUT:"));
+    ProcessLaunchInfo::FileAction file_action;
+    std::string path;
+    packet.GetHexByteString(path);
+    const bool read = true;
+    const bool write = false;
+    if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
+    {
+        m_process_launch_info.AppendFileAction(file_action);
+        return SendOKResponse ();
+    }
+    return SendErrorResponse (11);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QSetSTDERR:"));
+    ProcessLaunchInfo::FileAction file_action;
+    std::string path;
+    packet.GetHexByteString(path);
+    const bool read = true;
+    const bool write = true;
+    if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
+    {
+        m_process_launch_info.AppendFileAction(file_action);
+        return SendOKResponse ();
+    }
+    return SendErrorResponse (12);
+}
+
 bool
 GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
 {
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 02440a2..1fddaeb 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -31,7 +31,7 @@
     //------------------------------------------------------------------
     // Constructors and Destructors
     //------------------------------------------------------------------
-    GDBRemoteCommunicationServer();
+    GDBRemoteCommunicationServer(bool is_platform);
 
     virtual
     ~GDBRemoteCommunicationServer();
@@ -53,10 +53,26 @@
     bool
     HandshakeWithClient (lldb_private::Error *error_ptr);
 
+    // Set both ports to zero to let the platform automatically bind to 
+    // a port chosen by the OS.
+    void
+    SetPortRange (uint16_t lo_port_num, uint16_t hi_port_num)
+    {
+        m_lo_port_num = lo_port_num;
+        m_hi_port_num = hi_port_num;
+    }
+
 protected:
+    //typedef std::map<uint16_t, lldb::pid_t> PortToPIDMap;
+
     lldb::thread_t m_async_thread;
-    lldb_private::ProcessInfoList m_proc_infos;
+    lldb_private::ProcessLaunchInfo m_process_launch_info;
+    lldb_private::Error m_process_launch_error;
+    lldb_private::ProcessInstanceInfoList m_proc_infos;
     uint32_t m_proc_infos_index;
+    uint16_t m_lo_port_num;
+    uint16_t m_hi_port_num;
+    //PortToPIDMap m_port_to_pid_map;
 
     size_t
     SendUnimplementedResponse (const char *packet);
@@ -68,9 +84,18 @@
     SendOKResponse ();
 
     bool
+    Handle_A (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_qLaunchSuccess (StringExtractorGDBRemote &packet);
+
+    bool
     Handle_qHostInfo (StringExtractorGDBRemote &packet);
     
     bool
+    Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
+
+    bool
     Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
     
     bool
@@ -79,6 +104,9 @@
     bool 
     Handle_qsProcessInfo (StringExtractorGDBRemote &packet);
 
+    bool
+    Handle_qC (StringExtractorGDBRemote &packet);
+
     bool 
     Handle_qUserName (StringExtractorGDBRemote &packet);
 
@@ -89,8 +117,26 @@
     Handle_qSpeedTest (StringExtractorGDBRemote &packet);
 
     bool
+    Handle_QEnvironment  (StringExtractorGDBRemote &packet);
+    
+    bool
+    Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
+
+    bool
     Handle_QStartNoAckMode (StringExtractorGDBRemote &packet);
 
+    bool
+    Handle_QSetSTDIN (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_QSetSTDOUT (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
+    
 private:
     //------------------------------------------------------------------
     // For GDBRemoteCommunicationServer only
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 0a1f872..841efa2 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -220,7 +220,7 @@
         if (gdb_comm.GetSequenceMutex (locker))
         {
             const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
-            if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+            if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
             {
                 char packet[64];
                 StringExtractorGDBRemote response;
@@ -329,7 +329,7 @@
         if (gdb_comm.GetSequenceMutex (locker))
         {
             const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
-            if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+            if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
             {
                 uint32_t offset, end_offset;
                 StreamString packet;
@@ -407,7 +407,7 @@
     {
         char packet[32];
         const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
-        if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+        if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
         {
             int packet_len = 0;
             if (thread_suffix_supported)
@@ -449,7 +449,7 @@
     if (gdb_comm.GetSequenceMutex (locker))
     {
         const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
-        if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+        if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
         {
             if (gdb_comm.SendPacketAndWaitForResponse((const char *)data_sp->GetBytes(), 
                                                       data_sp->GetByteSize(), 
@@ -474,91 +474,102 @@
 void
 GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters()
 {
-    static RegisterInfo
-    g_register_infos[] =
-    {
-        //  NAME        ALT     SZ  OFF   ENCODING           FORMAT            COMPILER              DWARF               GENERIC              GDB                    LLDB NATIVE
-        //  ======      ======= ==  ====  =============      ============    ===============         ===============     =========             =====                   ===========
-        {   "r0",       NULL,   4,    0,  eEncodingUint,     eFormatHex,     { gcc_r0,               dwarf_r0,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    0  }},
-        {   "r1",       NULL,   4,    4,  eEncodingUint,     eFormatHex,     { gcc_r1,               dwarf_r1,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    1 }},
-        {   "r2",       NULL,   4,    8,  eEncodingUint,     eFormatHex,     { gcc_r2,               dwarf_r2,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    2 }},
-        {   "r3",       NULL,   4,   12,  eEncodingUint,     eFormatHex,     { gcc_r3,               dwarf_r3,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    3 }},
-        {   "r4",       NULL,   4,   16,  eEncodingUint,     eFormatHex,     { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    4 }},
-        {   "r5",       NULL,   4,   20,  eEncodingUint,     eFormatHex,     { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    5 }},
-        {   "r6",       NULL,   4,   24,  eEncodingUint,     eFormatHex,     { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    6 }},
-        {   "r7",       NULL,   4,   28,  eEncodingUint,     eFormatHex,     { gcc_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP,  LLDB_INVALID_REGNUM, 7 }},
-        {   "r8",       NULL,   4,   32,  eEncodingUint,     eFormatHex,     { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    8 }},
-        {   "r9",       NULL,   4,   36,  eEncodingUint,     eFormatHex,     { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    9 }},
-        {   "r10",      NULL,   4,   40,  eEncodingUint,     eFormatHex,     { gcc_r10,              dwarf_r10,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    10 }},
-        {   "r11",      NULL,   4,   44,  eEncodingUint,     eFormatHex,     { gcc_r11,              dwarf_r11,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    11 }},
-        {   "r12",      NULL,   4,   48,  eEncodingUint,     eFormatHex,     { gcc_r12,              dwarf_r12,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    12 }},
-        {   "sp",      "r13",   4,   52,  eEncodingUint,     eFormatHex,     { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP,  LLDB_INVALID_REGNUM, 13 }},
-        {   "lr",      "r14",   4,   56,  eEncodingUint,     eFormatHex,     { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA,  LLDB_INVALID_REGNUM, 14 }},
-        {   "pc",      "r15",   4,   60,  eEncodingUint,     eFormatHex,     { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC,  LLDB_INVALID_REGNUM, 15 }},
-//        {   NULL,       NULL,  12,   64,  eEncodingIEEE754,  eFormatFloat,   { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM, 16 }},
-//        {   NULL,       NULL,  12,   76,  eEncodingIEEE754,  eFormatFloat,   { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM, 17 }},
-//        {   NULL,       NULL,  12,   88,  eEncodingIEEE754,  eFormatFloat,   { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM, 18 }},
-//        {   NULL,       NULL,  12,  100,  eEncodingIEEE754,  eFormatFloat,   { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM, 19 }},
-//        {   NULL,       NULL,  12,  112,  eEncodingIEEE754,  eFormatFloat,   { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM, 20 }},
-//        {   NULL,       NULL,  12,  124,  eEncodingIEEE754,  eFormatFloat,   { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM, 21 }},
-//        {   NULL,       NULL,  12,  136,  eEncodingIEEE754,  eFormatFloat,   { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM, 22 }},
-//        {   NULL,       NULL,  12,  148,  eEncodingIEEE754,  eFormatFloat,   { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM, 23 }},
-//        {   NULL,       NULL,  12,  160,  eEncodingIEEE754,  eFormatFloat,   { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM, 24 }},
-        {   "cpsr",     "psr",  4,  172,  eEncodingUint,     eFormatHex,     { gcc_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,  25 }},
-        {   "s0",       NULL,   4,  176,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     26 }},
-        {   "s1",       NULL,   4,  180,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     27 }},
-        {   "s2",       NULL,   4,  184,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     28 }},
-        {   "s3",       NULL,   4,  188,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     29 }},
-        {   "s4",       NULL,   4,  192,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     30 }},
-        {   "s5",       NULL,   4,  196,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     31 }},
-        {   "s6",       NULL,   4,  200,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     32 }},
-        {   "s7",       NULL,   4,  204,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     33 }},
-        {   "s8",       NULL,   4,  208,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     34 }},
-        {   "s9",       NULL,   4,  212,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     35 }},
-        {   "s10",      NULL,   4,  216,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     36 }},
-        {   "s11",      NULL,   4,  220,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     37 }},
-        {   "s12",      NULL,   4,  224,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     38 }},
-        {   "s13",      NULL,   4,  228,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     39 }},
-        {   "s14",      NULL,   4,  232,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     40 }},
-        {   "s15",      NULL,   4,  236,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     41 }},
-        {   "s16",      NULL,   4,  240,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     42 }},
-        {   "s17",      NULL,   4,  244,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     43 }},
-        {   "s18",      NULL,   4,  248,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     44 }},
-        {   "s19",      NULL,   4,  252,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     45 }},
-        {   "s20",      NULL,   4,  256,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     46 }},
-        {   "s21",      NULL,   4,  260,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     47 }},
-        {   "s22",      NULL,   4,  264,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     48 }},
-        {   "s23",      NULL,   4,  268,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     49 }},
-        {   "s24",      NULL,   4,  272,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     50 }},
-        {   "s25",      NULL,   4,  276,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     51 }},
-        {   "s26",      NULL,   4,  280,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     52 }},
-        {   "s27",      NULL,   4,  284,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     53 }},
-        {   "s28",      NULL,   4,  288,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     54 }},
-        {   "s29",      NULL,   4,  292,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     55 }},
-        {   "s30",      NULL,   4,  296,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     56 }},
-        {   "s31",      NULL,   4,  300,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     57 }},
-        {   "fpscr",    NULL,   4,  304,  eEncodingUint,     eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     58 }},
-        {   "d16",      NULL,   8,  308,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d16,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     59 }},
-        {   "d17",      NULL,   8,  316,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d17,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     60 }},
-        {   "d18",      NULL,   8,  324,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d18,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     61 }},
-        {   "d19",      NULL,   8,  332,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d19,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     62 }},
-        {   "d20",      NULL,   8,  340,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d20,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     63 }},
-        {   "d21",      NULL,   8,  348,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d21,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     64 }},
-        {   "d22",      NULL,   8,  356,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d22,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     65 }},
-        {   "d23",      NULL,   8,  364,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d23,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     66 }},
-        {   "d24",      NULL,   8,  372,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d24,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     67 }},
-        {   "d25",      NULL,   8,  380,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d25,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     68 }},
-        {   "d26",      NULL,   8,  388,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d26,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     69 }},
-        {   "d27",      NULL,   8,  396,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d27,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     70 }},
-        {   "d28",      NULL,   8,  404,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d28,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     71 }},
-        {   "d29",      NULL,   8,  412,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d29,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     72 }},
-        {   "d30",      NULL,   8,  420,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d30,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     73 }},
-        {   "d31",      NULL,   8,  428,  eEncodingIEEE754,  eFormatFloat,   { LLDB_INVALID_REGNUM,  dwarf_d31,          LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,     74 }},
+    static RegisterInfo g_register_infos[] = {
+//   NAME    ALT    SZ  OFF  ENCODING          FORMAT          COMPILER             DWARF                GENERIC                 GDB    LLDB
+//   ======  ====== === ===  =============     ============    ===================  ===================  ======================  ===    ====
+    { "r0",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r0,              dwarf_r0,            LLDB_INVALID_REGNUM,     0,      0 }},
+    { "r1",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r1,              dwarf_r1,            LLDB_INVALID_REGNUM,     1,      1 }},
+    { "r2",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r2,              dwarf_r2,            LLDB_INVALID_REGNUM,     2,      2 }},
+    { "r3",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r3,              dwarf_r3,            LLDB_INVALID_REGNUM,     3,      3 }},
+    { "r4",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r4,              dwarf_r4,            LLDB_INVALID_REGNUM,     4,      4 }},
+    { "r5",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r5,              dwarf_r5,            LLDB_INVALID_REGNUM,     5,      5 }},
+    { "r6",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r6,              dwarf_r6,            LLDB_INVALID_REGNUM,     6,      6 }},
+    { "r7",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r7,              dwarf_r7,            LLDB_REGNUM_GENERIC_FP,  7,      7 }},
+    { "r8",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r8,              dwarf_r8,            LLDB_INVALID_REGNUM,     8,      8 }},
+    { "r9",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r9,              dwarf_r9,            LLDB_INVALID_REGNUM,     9,      9 }},
+    { "r10",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r10,             dwarf_r10,           LLDB_INVALID_REGNUM,    10,     10 }},
+    { "r11",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r11,             dwarf_r11,           LLDB_INVALID_REGNUM,    11,     11 }},
+    { "r12",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r12,             dwarf_r12,           LLDB_INVALID_REGNUM,    12,     12 }},
+    { "sp",   "r13",  4,   0, eEncodingUint,    eFormatHex,   { gcc_sp,              dwarf_sp,            LLDB_REGNUM_GENERIC_SP, 13,     13 }},
+    { "lr",   "r14",  4,   0, eEncodingUint,    eFormatHex,   { gcc_lr,              dwarf_lr,            LLDB_REGNUM_GENERIC_RA, 14,     14 }},
+    { "pc",   "r15",  4,   0, eEncodingUint,    eFormatHex,   { gcc_pc,              dwarf_pc,            LLDB_REGNUM_GENERIC_PC, 15,     15 }},
+    { "f0",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    16,     16 }},
+    { "f1",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    17,     17 }},
+    { "f2",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    18,     18 }},
+    { "f3",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    19,     19 }},
+    { "f4",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    20,     20 }},
+    { "f5",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    21,     21 }},
+    { "f6",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    22,     22 }},
+    { "f7",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    23,     23 }},
+    { "fps",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    24,     24 }},
+    { "cpsr", "psr",  4,   0, eEncodingUint,    eFormatHex,   { gcc_cpsr,            dwarf_cpsr,          LLDB_INVALID_REGNUM,    25,     25 }},
+    { "s0",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s0,            LLDB_INVALID_REGNUM,    26,     26 }},
+    { "s1",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s1,            LLDB_INVALID_REGNUM,    27,     27 }},
+    { "s2",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s2,            LLDB_INVALID_REGNUM,    28,     28 }},
+    { "s3",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s3,            LLDB_INVALID_REGNUM,    29,     29 }},
+    { "s4",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s4,            LLDB_INVALID_REGNUM,    30,     30 }},
+    { "s5",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s5,            LLDB_INVALID_REGNUM,    31,     31 }},
+    { "s6",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s6,            LLDB_INVALID_REGNUM,    32,     32 }},
+    { "s7",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s7,            LLDB_INVALID_REGNUM,    33,     33 }},
+    { "s8",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s8,            LLDB_INVALID_REGNUM,    34,     34 }},
+    { "s9",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s9,            LLDB_INVALID_REGNUM,    35,     35 }},
+    { "s10",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s10,           LLDB_INVALID_REGNUM,    36,     36 }},
+    { "s11",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s11,           LLDB_INVALID_REGNUM,    37,     37 }},
+    { "s12",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s12,           LLDB_INVALID_REGNUM,    38,     38 }},
+    { "s13",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s13,           LLDB_INVALID_REGNUM,    39,     39 }},
+    { "s14",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s14,           LLDB_INVALID_REGNUM,    40,     40 }},
+    { "s15",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s15,           LLDB_INVALID_REGNUM,    41,     41 }},
+    { "s16",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s16,           LLDB_INVALID_REGNUM,    42,     42 }},
+    { "s17",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s17,           LLDB_INVALID_REGNUM,    43,     43 }},
+    { "s18",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s18,           LLDB_INVALID_REGNUM,    44,     44 }},
+    { "s19",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s19,           LLDB_INVALID_REGNUM,    45,     45 }},
+    { "s20",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s20,           LLDB_INVALID_REGNUM,    46,     46 }},
+    { "s21",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s21,           LLDB_INVALID_REGNUM,    47,     47 }},
+    { "s22",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s22,           LLDB_INVALID_REGNUM,    48,     48 }},
+    { "s23",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s23,           LLDB_INVALID_REGNUM,    49,     49 }},
+    { "s24",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s24,           LLDB_INVALID_REGNUM,    50,     50 }},
+    { "s25",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s25,           LLDB_INVALID_REGNUM,    51,     51 }},
+    { "s26",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s26,           LLDB_INVALID_REGNUM,    52,     52 }},
+    { "s27",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s27,           LLDB_INVALID_REGNUM,    53,     53 }},
+    { "s28",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s28,           LLDB_INVALID_REGNUM,    54,     54 }},
+    { "s29",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s29,           LLDB_INVALID_REGNUM,    55,     55 }},
+    { "s30",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s30,           LLDB_INVALID_REGNUM,    56,     56 }},
+    { "s31",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s31,           LLDB_INVALID_REGNUM,    57,     57 }},
+    { "fpscr",NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    58,     58 }},
+    { "d16",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d16,           LLDB_INVALID_REGNUM,    59,     59 }},
+    { "d17",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d17,           LLDB_INVALID_REGNUM,    60,     60 }},
+    { "d18",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d18,           LLDB_INVALID_REGNUM,    61,     61 }},
+    { "d19",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d19,           LLDB_INVALID_REGNUM,    62,     62 }},
+    { "d20",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d20,           LLDB_INVALID_REGNUM,    63,     63 }},
+    { "d21",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d21,           LLDB_INVALID_REGNUM,    64,     64 }},
+    { "d22",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d22,           LLDB_INVALID_REGNUM,    65,     65 }},
+    { "d23",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d23,           LLDB_INVALID_REGNUM,    66,     66 }},
+    { "d24",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d24,           LLDB_INVALID_REGNUM,    67,     67 }},
+    { "d25",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d25,           LLDB_INVALID_REGNUM,    68,     68 }},
+    { "d26",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d26,           LLDB_INVALID_REGNUM,    69,     69 }},
+    { "d27",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d27,           LLDB_INVALID_REGNUM,    70,     70 }},
+    { "d28",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d28,           LLDB_INVALID_REGNUM,    71,     71 }},
+    { "d29",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d29,           LLDB_INVALID_REGNUM,    72,     72 }},
+    { "d30",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d30,           LLDB_INVALID_REGNUM,    73,     73 }},
+    { "d31",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d31,           LLDB_INVALID_REGNUM,    74,     74 }},
     };
+
     static const uint32_t num_registers = sizeof (g_register_infos)/sizeof (RegisterInfo);
     static ConstString gpr_reg_set ("General Purpose Registers");
+    static ConstString sfp_reg_set ("Software Floating Point Registers");
     static ConstString vfp_reg_set ("Floating Point Registers");
-    for (uint32_t i=0; i<num_registers; ++i)
+    uint32_t i;
+    // Calculate the offsets of the registers
+    if (g_register_infos[2].byte_offset == 0)
+    {
+        uint32_t byte_offset = 0;
+        for (i=0; i<num_registers; ++i)
+        {
+            g_register_infos[i].byte_offset = byte_offset;
+            byte_offset += g_register_infos[i].byte_size;
+        }
+    }
+    for (i=0; i<num_registers; ++i)
     {
         ConstString name;
         ConstString alt_name;
@@ -566,8 +577,13 @@
             name.SetCString(g_register_infos[i].name);
         if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0])
             alt_name.SetCString(g_register_infos[i].alt_name);
-
-        AddRegister (g_register_infos[i], name, alt_name, i < 26 ? gpr_reg_set : vfp_reg_set);
+        
+        if (i <= 15 || i == 25)
+            AddRegister (g_register_infos[i], name, alt_name, gpr_reg_set);
+        else if (i <= 24)
+            AddRegister (g_register_infos[i], name, alt_name, sfp_reg_set);
+        else
+            AddRegister (g_register_infos[i], name, alt_name, vfp_reg_set);
     }
 }
 
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index ec07fbe..79f77e2 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -114,16 +114,13 @@
     Process (target, listener),
     m_flags (0),
     m_stdio_mutex (Mutex::eMutexTypeRecursive),
-    m_gdb_comm(),
+    m_gdb_comm(false),
     m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
     m_debugserver_thread (LLDB_INVALID_HOST_THREAD),
     m_last_stop_packet (),
     m_register_info (),
     m_async_broadcaster ("lldb.process.gdb-remote.async-broadcaster"),
     m_async_thread (LLDB_INVALID_HOST_THREAD),
-    m_curr_tid (LLDB_INVALID_THREAD_ID),
-    m_curr_tid_run (LLDB_INVALID_THREAD_ID),
-    m_z0_supported (1),
     m_continue_c_tids (),
     m_continue_C_tids (),
     m_continue_s_tids (),
@@ -430,7 +427,6 @@
     ObjectFile * object_file = module->GetObjectFile();
     if (object_file)
     {
-        ArchSpec inferior_arch(module->GetArchitecture());
         char host_port[128];
         snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
         char connect_url[128];
@@ -439,13 +435,7 @@
         // Make sure we aren't already connected?
         if (!m_gdb_comm.IsConnected())
         {
-            error = StartDebugserverProcess (host_port,
-                                             NULL,
-                                             NULL,
-                                             LLDB_INVALID_PROCESS_ID,
-                                             NULL, 
-                                             false,
-                                             inferior_arch);
+            error = StartDebugserverProcess (host_port);
             if (error.Fail())
                 return error;
 
@@ -700,8 +690,6 @@
     Error error;
     // Clear out and clean up from any current state
     Clear();
-    const ArchSpec &arch_spec = GetTarget().GetArchitecture();
-
     if (attach_pid != LLDB_INVALID_PROCESS_ID)
     {
         // Make sure we aren't already connected?
@@ -712,13 +700,7 @@
             char connect_url[128];
             snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
 
-            error = StartDebugserverProcess (host_port,                 // debugserver_url
-                                             NULL,                      // inferior_argv
-                                             NULL,                      // inferior_envp
-                                             LLDB_INVALID_PROCESS_ID,   // Don't send any attach to pid options to debugserver
-                                             NULL,                      // Don't send any attach by process name option to debugserver
-                                             false,                     // Don't send any attach wait_for_launch flag as an option to debugserver
-                                             arch_spec);
+            error = StartDebugserverProcess (host_port);
             
             if (error.Fail())
             {
@@ -778,21 +760,12 @@
         // Make sure we aren't already connected?
         if (!m_gdb_comm.IsConnected())
         {
-
-            const ArchSpec &arch_spec = GetTarget().GetArchitecture();
-
             char host_port[128];
             snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
             char connect_url[128];
             snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
 
-            error = StartDebugserverProcess (host_port,                 // debugserver_url
-                                             NULL,                      // inferior_argv
-                                             NULL,                      // inferior_envp
-                                             LLDB_INVALID_PROCESS_ID,   // Don't send any attach to pid options to debugserver
-                                             NULL,                      // Don't send any attach by process name option to debugserver
-                                             false,                     // Don't send any attach wait_for_launch flag as an option to debugserver
-                                             arch_spec);
+            error = StartDebugserverProcess (host_port);
             if (error.Fail())
             {
                 const char *error_string = error.AsCString();
@@ -925,7 +898,7 @@
                 if (num_continue_c_tids == num_threads)
                 {
                     // All threads are resuming...
-                    SetCurrentGDBRemoteThreadForRun (-1);
+                    m_gdb_comm.SetCurrentThreadForRun (-1);
                     continue_packet.PutChar ('c');                
                 }
                 else if (num_continue_c_tids == 1 &&
@@ -934,7 +907,7 @@
                          num_continue_S_tids == 0 )
                 {
                     // Only one thread is continuing
-                    SetCurrentGDBRemoteThreadForRun (m_continue_c_tids.front());
+                    m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front());
                     continue_packet.PutChar ('c');                
                 }
                 else
@@ -960,7 +933,7 @@
                     if (!continue_packet_error)
                     {
                         // Add threads continuing with the same signo...
-                        SetCurrentGDBRemoteThreadForRun (-1);
+                        m_gdb_comm.SetCurrentThreadForRun (-1);
                         continue_packet.Printf("C%2.2x", continue_signo);
                     }
                 }
@@ -970,7 +943,7 @@
                          num_continue_S_tids == 0 )
                 {
                     // Only one thread is continuing with signal
-                    SetCurrentGDBRemoteThreadForRun (m_continue_C_tids.front().first);
+                    m_gdb_comm.SetCurrentThreadForRun (m_continue_C_tids.front().first);
                     continue_packet.Printf("C%2.2x", m_continue_C_tids.front().second);
                 }
                 else
@@ -985,7 +958,7 @@
                 if (num_continue_s_tids == num_threads)
                 {
                     // All threads are resuming...
-                    SetCurrentGDBRemoteThreadForRun (-1);
+                    m_gdb_comm.SetCurrentThreadForRun (-1);
                     continue_packet.PutChar ('s');                
                 }
                 else if (num_continue_c_tids == 0 &&
@@ -994,7 +967,7 @@
                          num_continue_S_tids == 0 )
                 {
                     // Only one thread is stepping
-                    SetCurrentGDBRemoteThreadForRun (m_continue_s_tids.front());
+                    m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front());
                     continue_packet.PutChar ('s');                
                 }
                 else
@@ -1021,7 +994,7 @@
                     if (!continue_packet_error)
                     {
                         // Add threads stepping with the same signo...
-                        SetCurrentGDBRemoteThreadForRun (-1);
+                        m_gdb_comm.SetCurrentThreadForRun (-1);
                         continue_packet.Printf("S%2.2x", step_signo);
                     }
                 }
@@ -1031,7 +1004,7 @@
                          num_continue_S_tids == 1 )
                 {
                     // Only one thread is stepping with signal
-                    SetCurrentGDBRemoteThreadForRun (m_continue_S_tids.front().first);
+                    m_gdb_comm.SetCurrentThreadForRun (m_continue_S_tids.front().first);
                     continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
                 }
                 else
@@ -1667,40 +1640,28 @@
         {
             // Try and set hardware breakpoint, and if that fails, fall through
             // and set a software breakpoint?
-        }
-
-        if (m_z0_supported)
-        {
-            char packet[64];
-            const int packet_len = ::snprintf (packet, sizeof(packet), "Z0,%llx,%zx", addr, bp_op_size);
-            assert (packet_len + 1 < sizeof(packet));
-            StringExtractorGDBRemote response;
-            if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
+            if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointHardware))
             {
-                if (response.IsUnsupportedResponse())
-                {
-                    // Disable z packet support and try again
-                    m_z0_supported = 0;
-                    return EnableBreakpoint (bp_site);
-                }
-                else if (response.IsOKResponse())
+                if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0)
                 {
                     bp_site->SetEnabled(true);
-                    bp_site->SetType (BreakpointSite::eExternal);
+                    bp_site->SetType (BreakpointSite::eHardware);
                     return error;
                 }
-                else
-                {
-                    uint8_t error_byte = response.GetError();
-                    if (error_byte)
-                        error.SetErrorStringWithFormat("%x packet failed with error: %i (0x%2.2x).\n", packet, error_byte, error_byte);
-                }
             }
         }
-        else
+
+        if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
         {
-            return EnableSoftwareBreakpoint (bp_site);
+            if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
+            {
+                bp_site->SetEnabled(true);
+                bp_site->SetType (BreakpointSite::eExternal);
+                return error;
+            }
         }
+
+        return EnableSoftwareBreakpoint (bp_site);
     }
 
     if (log)
@@ -1731,44 +1692,25 @@
     {
         const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
 
-        if (bp_site->IsHardware())
+        BreakpointSite::Type bp_type = bp_site->GetType();
+        switch (bp_type)
         {
-            // TODO: disable hardware breakpoint...
+        case BreakpointSite::eSoftware:
+            error = DisableSoftwareBreakpoint (bp_site);
+            break;
+
+        case BreakpointSite::eHardware:
+            if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
+                error.SetErrorToGenericError();
+            break;
+
+        case BreakpointSite::eExternal:
+            if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
+                error.SetErrorToGenericError();
+            break;
         }
-        else
-        {
-            if (m_z0_supported)
-            {
-                char packet[64];
-                const int packet_len = ::snprintf (packet, sizeof(packet), "z0,%llx,%zx", addr, bp_op_size);
-                assert (packet_len + 1 < sizeof(packet));
-                StringExtractorGDBRemote response;
-                if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
-                {
-                    if (response.IsUnsupportedResponse())
-                    {
-                        error.SetErrorString("Breakpoint site was set with Z packet, yet remote debugserver states z packets are not supported.");
-                    }
-                    else if (response.IsOKResponse())
-                    {
-                        if (log)
-                            log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx -- SUCCESS", site_id, (uint64_t)addr);
-                        bp_site->SetEnabled(false);
-                        return error;
-                    }
-                    else
-                    {
-                        uint8_t error_byte = response.GetError();
-                        if (error_byte)
-                            error.SetErrorStringWithFormat("%x packet failed with error: %i (0x%2.2x).\n", packet, error_byte, error_byte);
-                    }
-                }
-            }
-            else
-            {
-                return DisableSoftwareBreakpoint (bp_site);
-            }
-        }
+        if (error.Success())
+            bp_site->SetEnabled(false);
     }
     else
     {
@@ -1869,16 +1811,7 @@
 }
 
 Error
-ProcessGDBRemote::StartDebugserverProcess
-(
-    const char *debugserver_url,    // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
-    char const *inferior_argv[],    // Arguments for the inferior program including the path to the inferior itself as the first argument
-    char const *inferior_envp[],    // Environment to pass along to the inferior program
-    lldb::pid_t attach_pid,         // If inferior inferior_argv == NULL, and attach_pid != LLDB_INVALID_PROCESS_ID send this pid as an argument to debugserver
-    const char *attach_name,        // Wait for the next process to launch whose basename matches "attach_name"
-    bool wait_for_launch,           // Wait for the process named "attach_name" to launch
-    const ArchSpec& inferior_arch   // The arch of the inferior that we will launch
-)
+ProcessGDBRemote::StartDebugserverProcess (const char *debugserver_url)    // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
 {
     Error error;
     if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
@@ -1886,8 +1819,9 @@
         // If we locate debugserver, keep that located version around
         static FileSpec g_debugserver_file_spec;
 
-        FileSpec debugserver_file_spec;
+        ProcessLaunchInfo launch_info;
         char debugserver_path[PATH_MAX];
+        FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
 
         // Always check to see if we have an environment override for the path
         // to the debugserver to use and use it if we do.
@@ -1922,25 +1856,10 @@
             debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
 
             m_stdio_communication.Clear();
-            posix_spawnattr_t attr;
 
             LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
 
-            Error local_err;    // Errors that don't affect the spawning.
-            if (log)
-                log->Printf ("%s ( path='%s', argv=%p, envp=%p, arch=%s )", 
-                             __FUNCTION__, 
-                             debugserver_path, 
-                             inferior_argv, 
-                             inferior_envp, 
-                             inferior_arch.GetArchitectureName());
-            error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
-            if (error.Fail() || log)
-                error.PutToLog(log.get(), "::posix_spawnattr_init ( &attr )");
-            if (error.Fail())
-                return error;
-
-            Args debugserver_args;
+            Args &debugserver_args = launch_info.GetArguments();
             char arg_cstr[PATH_MAX];
 
             // Start args with "debugserver /file/path -r --"
@@ -1968,6 +1887,12 @@
 //            debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
 //            debugserver_args.AppendArgument("--log-flags=0x802e0e");
 
+            // We currently send down all arguments, attach pids, or attach 
+            // process names in dedicated GDB server packets, so we don't need
+            // to pass them as arguments. This is currently because of all the
+            // things we need to setup prior to launching: the environment,
+            // current working dir, file actions, etc.
+#if 0
             // Now append the program arguments
             if (inferior_argv)
             {
@@ -1990,20 +1915,18 @@
                     debugserver_args.AppendArgument ("--attach");
                 debugserver_args.AppendArgument (attach_name);
             }
-
-            Error file_actions_err;
-            posix_spawn_file_actions_t file_actions;
-#if DONT_CLOSE_DEBUGSERVER_STDIO
-            file_actions_err.SetErrorString ("Remove this after uncommenting the code block below.");
-#else
-            file_actions_err.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
-            if (file_actions_err.Success())
-            {
-                ::posix_spawn_file_actions_addclose (&file_actions, STDIN_FILENO);
-                ::posix_spawn_file_actions_addclose (&file_actions, STDOUT_FILENO);
-                ::posix_spawn_file_actions_addclose (&file_actions, STDERR_FILENO);
-            }
 #endif
+            
+            ProcessLaunchInfo::FileAction file_action;
+            
+            // Close STDIN, STDOUT and STDERR. We might need to redirect them
+            // to "/dev/null" if we run into any problems.
+            file_action.Close (STDIN_FILENO);
+            launch_info.AppendFileAction (file_action);
+            file_action.Close (STDOUT_FILENO);
+            launch_info.AppendFileAction (file_action);
+            file_action.Close (STDERR_FILENO);
+            launch_info.AppendFileAction (file_action);
 
             if (log)
             {
@@ -2012,28 +1935,15 @@
                 log->Printf("%s arguments:\n%s", debugserver_args.GetArgumentAtIndex(0), strm.GetData());
             }
 
-            error.SetError (::posix_spawnp (&m_debugserver_pid,
-                                            debugserver_path,
-                                            file_actions_err.Success() ? &file_actions : NULL,
-                                            &attr,
-                                            debugserver_args.GetArgumentVector(),
-                                            (char * const*)inferior_envp),
-                            eErrorTypePOSIX);
-            
+            error = Host::LaunchProcess(launch_info);
 
-            ::posix_spawnattr_destroy (&attr);
-
-            if (file_actions_err.Success())
-                ::posix_spawn_file_actions_destroy (&file_actions);
-
-            // We have seen some cases where posix_spawnp was returning a valid
-            // looking pid even when an error was returned, so clear it out
-            if (error.Fail())
+            if (error.Success ())
+                m_debugserver_pid = launch_info.GetProcessID();
+            else
                 m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
 
             if (error.Fail() || log)
-                error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", m_debugserver_pid, debugserver_path, NULL, &attr, inferior_argv, inferior_envp);
-
+                error.PutToLog(log.get(), "Host::LaunchProcess (launch_info) => pid=%i, path='%s'", m_debugserver_pid, debugserver_path);
         }
         else
         {
@@ -2143,71 +2053,8 @@
 }
 
 bool
-ProcessGDBRemote::SetCurrentGDBRemoteThread (int tid)
-{
-    if (m_curr_tid == tid)
-        return true;
-
-    char packet[32];
-    int packet_len;
-    if (tid <= 0)
-        packet_len = ::snprintf (packet, sizeof(packet), "Hg%i", tid);
-    else
-        packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
-    assert (packet_len + 1 < sizeof(packet));
-    StringExtractorGDBRemote response;
-    if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
-    {
-        if (response.IsOKResponse())
-        {
-            m_curr_tid = tid;
-            return true;
-        }
-    }
-    return false;
-}
-
-bool
-ProcessGDBRemote::SetCurrentGDBRemoteThreadForRun (int tid)
-{
-    if (m_curr_tid_run == tid)
-        return true;
-
-    char packet[32];
-    int packet_len;
-    if (tid <= 0)
-        packet_len = ::snprintf (packet, sizeof(packet), "Hc%i", tid);
-    else
-        packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid);
-
-    assert (packet_len + 1 < sizeof(packet));
-    StringExtractorGDBRemote response;
-    if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
-    {
-        if (response.IsOKResponse())
-        {
-            m_curr_tid_run = tid;
-            return true;
-        }
-    }
-    return false;
-}
-
-void
-ProcessGDBRemote::ResetGDBRemoteState ()
-{
-    // Reset and GDB remote state
-    m_curr_tid = LLDB_INVALID_THREAD_ID;
-    m_curr_tid_run = LLDB_INVALID_THREAD_ID;
-    m_z0_supported = 1;
-}
-
-
-bool
 ProcessGDBRemote::StartAsyncThread ()
 {
-    ResetGDBRemoteState ();
-
     LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
 
     if (log)
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index e9ab4df..cf03604 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -215,12 +215,6 @@
     friend class GDBRemoteCommunicationClient;
     friend class GDBRemoteRegisterContext;
 
-    bool
-    SetCurrentGDBRemoteThread (int tid);
-
-    bool
-    SetCurrentGDBRemoteThreadForRun (int tid);
-
     //----------------------------------------------------------------------
     // Accessors
     //----------------------------------------------------------------------
@@ -275,13 +269,7 @@
     UpdateThreadListIfNeeded ();
 
     lldb_private::Error
-    StartDebugserverProcess (const char *debugserver_url,   // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
-                             char const *inferior_argv[],
-                             char const *inferior_envp[],
-                             lldb::pid_t attach_pid,        // If inferior inferior_argv == NULL, then attach to this pid
-                             const char *attach_pid_name,   // Wait for the next process to launch whose basename matches "attach_wait_name"
-                             bool wait_for_launch,          // Wait for the process named "attach_wait_name" to launch
-                             const lldb_private::ArchSpec& arch_spec);
+    StartDebugserverProcess (const char *debugserver_url);
 
     void
     KillDebugserverProcess ();
@@ -313,11 +301,6 @@
     GDBRemoteDynamicRegisterInfo m_register_info;
     lldb_private::Broadcaster m_async_broadcaster;
     lldb::thread_t m_async_thread;
-    // Current GDB remote state. Any members added here need to be reset to
-    // proper default values in ResetGDBRemoteState ().
-    lldb::tid_t m_curr_tid;         // Current gdb remote protocol thread index for all other operations
-    lldb::tid_t m_curr_tid_run;     // Current gdb remote protocol thread index for continue, step, etc
-    uint32_t m_z0_supported:1;      // Set to non-zero if Z0 and z0 packets are supported
     typedef std::vector<lldb::tid_t> tid_collection;
     typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
     tid_collection m_continue_c_tids;                  // 'c' for continue
@@ -330,9 +313,6 @@
     bool m_local_debugserver;  // Is the debugserver process we are talking to local or on another machine.
     std::vector<lldb::user_id_t>  m_thread_observation_bps;
 
-    void
-    ResetGDBRemoteState ();
-
     bool
     StartAsyncThread ();
 
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 9955409..351b6eb 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -261,13 +261,10 @@
         m_thread_stop_reason_stop_id = process_stop_id;
         m_actual_stop_info_sp.reset();
 
-        char packet[256];
-        ::snprintf(packet, sizeof(packet), "qThreadStopInfo%x", GetID());
         StringExtractorGDBRemote stop_packet;
-        if (GetGDBProcess().GetGDBRemote().SendPacketAndWaitForResponse(packet, stop_packet, false))
-        {
-            GetGDBProcess().SetThreadStopInfo (stop_packet);
-        }
+        ProcessGDBRemote &gdb_process = GetGDBProcess();
+        if (gdb_process.GetGDBRemote().GetThreadStopInfo(GetID(), stop_packet))
+            gdb_process.SetThreadStopInfo (stop_packet);
     }
     return m_actual_stop_info_sp;
 }