diff options
Diffstat (limited to 'source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp')
| -rw-r--r-- | source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp | 641 | 
1 files changed, 398 insertions, 243 deletions
| diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 7cc3a05304d4..df95542d2c0f 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -25,6 +25,7 @@  #include "lldb/Host/File.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/TimeValue.h" +#include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h"  // Project includes @@ -40,6 +41,7 @@ using namespace lldb_private;  //----------------------------------------------------------------------  GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :      GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform), +    m_platform_sp (Platform::GetDefaultPlatform ()),      m_async_thread (LLDB_INVALID_HOST_THREAD),      m_process_launch_info (),      m_process_launch_error (), @@ -52,6 +54,23 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :  {  } +GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform, +                                                           const lldb::PlatformSP& platform_sp) : +    GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform), +    m_platform_sp (platform_sp), +    m_async_thread (LLDB_INVALID_HOST_THREAD), +    m_process_launch_info (), +    m_process_launch_error (), +    m_spawned_pids (), +    m_spawned_pids_mutex (Mutex::eMutexTypeRecursive), +    m_proc_infos (), +    m_proc_infos_index (0), +    m_port_map (), +    m_port_offset(0) +{ +    assert(platform_sp); +} +  //----------------------------------------------------------------------  // Destructor  //---------------------------------------------------------------------- @@ -90,154 +109,249 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,                                                          bool &quit)  {      StringExtractorGDBRemote packet; -    if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec)) +    PacketResult packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec); +    if (packet_result == PacketResult::Success)      {          const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();          switch (packet_type)          { -            case StringExtractorGDBRemote::eServerPacketType_nack: -            case StringExtractorGDBRemote::eServerPacketType_ack: -                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_nack: +        case StringExtractorGDBRemote::eServerPacketType_ack: +            break; + +        case StringExtractorGDBRemote::eServerPacketType_invalid: +            error.SetErrorString("invalid packet"); +            quit = true; +            break; + +        case StringExtractorGDBRemote::eServerPacketType_interrupt: +            error.SetErrorString("interrupt received"); +            interrupt = true; +            break; + +        default: +        case StringExtractorGDBRemote::eServerPacketType_unimplemented: +            packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str()); +            break; -            case StringExtractorGDBRemote::eServerPacketType_unimplemented: -                return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0; +        case StringExtractorGDBRemote::eServerPacketType_A: +            packet_result = Handle_A (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_A: -                return Handle_A (packet); +        case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo: +            packet_result = Handle_qfProcessInfo (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo: -                return Handle_qfProcessInfo (packet); +        case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo: +            packet_result = Handle_qsProcessInfo (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo: -                return Handle_qsProcessInfo (packet); +        case StringExtractorGDBRemote::eServerPacketType_qC: +            packet_result = Handle_qC (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qC: -                return Handle_qC (packet); +        case StringExtractorGDBRemote::eServerPacketType_qHostInfo: +            packet_result = Handle_qHostInfo (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qHostInfo: -                return Handle_qHostInfo (packet); +        case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer: +            packet_result = Handle_qLaunchGDBServer (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer: -                return Handle_qLaunchGDBServer (packet); +        case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess: +            packet_result = Handle_qKillSpawnedProcess (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess: -                return Handle_qKillSpawnedProcess (packet); +        case StringExtractorGDBRemote::eServerPacketType_k: +            packet_result = Handle_k (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess: -                return Handle_qLaunchSuccess (packet); +        case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess: +            packet_result = Handle_qLaunchSuccess (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qGroupName: -                return Handle_qGroupName (packet); +        case StringExtractorGDBRemote::eServerPacketType_qGroupName: +            packet_result = Handle_qGroupName (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID: +            packet_result = Handle_qProcessInfoPID (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_qSpeedTest: +            packet_result = Handle_qSpeedTest (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_qUserName: +            packet_result = Handle_qUserName (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir: +            packet_result = Handle_qGetWorkingDir(packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_QEnvironment: +            packet_result = Handle_QEnvironment (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_QLaunchArch: +            packet_result = Handle_QLaunchArch (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR: +            packet_result = Handle_QSetDisableASLR (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN: +            packet_result = Handle_QSetSTDIN (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT: +            packet_result = Handle_QSetSTDOUT (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR: +            packet_result = Handle_QSetSTDERR (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir: +            packet_result = Handle_QSetWorkingDir (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: +            packet_result = Handle_QStartNoAckMode (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir: +            packet_result = Handle_qPlatform_mkdir (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod: +            packet_result = Handle_qPlatform_chmod (packet); +            break; + +        case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell: +            packet_result = Handle_qPlatform_shell (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID: -                return Handle_qProcessInfoPID (packet); +        case StringExtractorGDBRemote::eServerPacketType_vFile_open: +            packet_result = Handle_vFile_Open (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qSpeedTest: -                return Handle_qSpeedTest (packet); - -            case StringExtractorGDBRemote::eServerPacketType_qUserName: -                return Handle_qUserName (packet); - -            case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir: -                return Handle_qGetWorkingDir(packet); -     -            case StringExtractorGDBRemote::eServerPacketType_QEnvironment: -                return Handle_QEnvironment (packet); +        case StringExtractorGDBRemote::eServerPacketType_vFile_close: +            packet_result = Handle_vFile_Close (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_QLaunchArch: -                return Handle_QLaunchArch (packet); +        case StringExtractorGDBRemote::eServerPacketType_vFile_pread: +            packet_result = Handle_vFile_pRead (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR: -                return Handle_QSetDisableASLR (packet); +        case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite: +            packet_result = Handle_vFile_pWrite (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN: -                return Handle_QSetSTDIN (packet); +        case StringExtractorGDBRemote::eServerPacketType_vFile_size: +            packet_result = Handle_vFile_Size (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT: -                return Handle_QSetSTDOUT (packet); +        case StringExtractorGDBRemote::eServerPacketType_vFile_mode: +            packet_result = Handle_vFile_Mode (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR: -                return Handle_QSetSTDERR (packet); +        case StringExtractorGDBRemote::eServerPacketType_vFile_exists: +            packet_result = Handle_vFile_Exists (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir: -                return Handle_QSetWorkingDir (packet); +        case StringExtractorGDBRemote::eServerPacketType_vFile_stat: +            packet_result = Handle_vFile_Stat (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: -                return Handle_QStartNoAckMode (packet); +        case StringExtractorGDBRemote::eServerPacketType_vFile_md5: +            packet_result = Handle_vFile_MD5 (packet); +            break; -            case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir: -                return Handle_qPlatform_mkdir (packet); - -            case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod: -                return Handle_qPlatform_chmod (packet); - -            case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell: -                return Handle_qPlatform_shell (packet); - -            case StringExtractorGDBRemote::eServerPacketType_vFile_open: -                return Handle_vFile_Open (packet); - -            case StringExtractorGDBRemote::eServerPacketType_vFile_close: -                return Handle_vFile_Close (packet); +        case StringExtractorGDBRemote::eServerPacketType_vFile_symlink: +            packet_result = Handle_vFile_symlink (packet); +            break; +             +        case StringExtractorGDBRemote::eServerPacketType_vFile_unlink: +            packet_result = Handle_vFile_unlink (packet); +            break; +        } +    } +    else +    { +        if (!IsConnected()) +        { +            error.SetErrorString("lost connection"); +            quit = true; +        } +        else +        { +            error.SetErrorString("timeout"); +        } +    } +    return packet_result == PacketResult::Success; +} -            case StringExtractorGDBRemote::eServerPacketType_vFile_pread: -                return Handle_vFile_pRead (packet); +lldb_private::Error +GDBRemoteCommunicationServer::SetLaunchArguments (const char *const args[], int argc) +{ +    if ((argc < 1) || !args || !args[0] || !args[0][0]) +        return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__); -            case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite: -                return Handle_vFile_pWrite (packet); +    m_process_launch_info.SetArguments (const_cast<const char**> (args), true); +    return lldb_private::Error (); +} -            case StringExtractorGDBRemote::eServerPacketType_vFile_size: -                return Handle_vFile_Size (packet); +lldb_private::Error +GDBRemoteCommunicationServer::SetLaunchFlags (unsigned int launch_flags) +{ +    m_process_launch_info.GetFlags ().Set (launch_flags); +    return lldb_private::Error (); +} -            case StringExtractorGDBRemote::eServerPacketType_vFile_mode: -                return Handle_vFile_Mode (packet); +lldb_private::Error +GDBRemoteCommunicationServer::LaunchProcess () +{ +    if (!m_process_launch_info.GetArguments ().GetArgumentCount ()) +        return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__); -            case StringExtractorGDBRemote::eServerPacketType_vFile_exists: -                return Handle_vFile_Exists (packet); +    // specify the process monitor if not already set.  This should +    // generally be what happens since we need to reap started +    // processes. +    if (!m_process_launch_info.GetMonitorProcessCallback ()) +        m_process_launch_info.SetMonitorProcessCallback(ReapDebuggedProcess, this, false); -            case StringExtractorGDBRemote::eServerPacketType_vFile_stat: -                return Handle_vFile_Stat (packet); +    lldb_private::Error error = m_platform_sp->LaunchProcess (m_process_launch_info); +    if (!error.Success ()) +    { +        fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0)); +        return error; +    } -            case StringExtractorGDBRemote::eServerPacketType_vFile_md5: -                return Handle_vFile_MD5 (packet); +    printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID()); -            case StringExtractorGDBRemote::eServerPacketType_vFile_symlink: -                return Handle_vFile_symlink (packet); -                 -            case StringExtractorGDBRemote::eServerPacketType_vFile_unlink: -                return Handle_vFile_unlink (packet); -        } -        return true; -    } -    else +    // add to list of spawned processes.  On an lldb-gdbserver, we +    // would expect there to be only one. +    lldb::pid_t pid; +    if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID )      { -        if (!IsConnected()) -            error.SetErrorString("lost connection"); -        else -            error.SetErrorString("timeout"); +        Mutex::Locker locker (m_spawned_pids_mutex); +        m_spawned_pids.insert(pid);      } -    return false; +    return error;  } -size_t +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)  {      // TODO: Log the packet we aren't handling...      return SendPacketNoLock ("", 0);  } -size_t +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)  {      char packet[16]; @@ -247,7 +361,7 @@ GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)  } -size_t +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::SendOKResponse ()  {      return SendPacketNoLock ("OK", 2); @@ -256,10 +370,10 @@ GDBRemoteCommunicationServer::SendOKResponse ()  bool  GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)  { -    return GetAck(); +    return GetAck() == PacketResult::Success;  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)  {      StreamString response; @@ -272,6 +386,14 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet      response.PutCStringAsRawHex8(host_triple.getTriple().c_str());      response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); +    const char* distribution_id = host_arch.GetDistributionId ().AsCString (); +    if (distribution_id) +    { +        response.PutCString("distribution_id:"); +        response.PutCStringAsRawHex8(distribution_id); +        response.PutCString(";"); +    } +      uint32_t cpu = host_arch.GetMachOCPUType();      uint32_t sub = host_arch.GetMachOCPUSubType();      if (cpu != LLDB_INVALID_CPUTYPE) @@ -351,7 +473,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet      }  #endif  // #if defined(__APPLE__) -    return SendPacketNoLock (response.GetData(), response.GetSize()) > 0; +    return SendPacketNoLock (response.GetData(), response.GetSize());  }  static void @@ -377,7 +499,7 @@ CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &r      }  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)  {      // Packet format: "qProcessInfoPID:%i" where %i is the pid @@ -396,7 +518,7 @@ GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &      return SendErrorResponse (1);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)  {      m_proc_infos_index = 0; @@ -497,7 +619,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa      return SendErrorResponse (3);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)  {      if (m_proc_infos_index < m_proc_infos.GetSize()) @@ -510,7 +632,7 @@ GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &pa      return SendErrorResponse (4);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)  {      // Packet format: "qUserName:%i" where %i is the uid @@ -530,7 +652,7 @@ GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)  {      // Packet format: "qGroupName:%i" where %i is the gid @@ -549,7 +671,7 @@ GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packe      return SendErrorResponse (6);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen ("qSpeedTest:")); @@ -641,7 +763,7 @@ AcceptPortFromInferior (void *arg)  //    return false;  //} -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)  {      // The 'A' packet is the most over designed packet ever here with @@ -708,8 +830,11 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)      if (success)      { +        // FIXME: remove linux restriction once eLaunchFlagDebug is supported +#if !defined (__linux__)          m_process_launch_info.GetFlags().Set (eLaunchFlagDebug); -        m_process_launch_error = Host::LaunchProcess (m_process_launch_info); +#endif +        m_process_launch_error = LaunchProcess ();          if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)          {              return SendOKResponse (); @@ -718,7 +843,7 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)      return SendErrorResponse (8);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)  {      lldb::pid_t pid = m_process_launch_info.GetProcessID(); @@ -762,11 +887,30 @@ GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,  }  bool +GDBRemoteCommunicationServer::DebuggedProcessReaped (lldb::pid_t pid) +{ +    // reap a process that we were debugging (but not debugserver) +    Mutex::Locker locker (m_spawned_pids_mutex); +    return m_spawned_pids.erase(pid) > 0; +} + +bool +GDBRemoteCommunicationServer::ReapDebuggedProcess (void *callback_baton, +                                                   lldb::pid_t pid, +                                                   bool exited, +                                                   int signal,    // Zero for no signal +                                                   int status)    // Exit value of process if signal is zero +{ +    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton; +    server->DebuggedProcessReaped (pid); +    return true; +} + +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)  {  #ifdef _WIN32 -    // No unix sockets on windows -    return false; +    return SendErrorResponse(9);  #else      // Spawn a local debugserver as a platform so we can then attach or launch      // a process... @@ -775,7 +919,6 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote      {          // Sleep and wait a bit for debugserver to start to listen...          ConnectionFileDescriptor file_conn; -        char connect_url[PATH_MAX];          Error error;          std::string hostname;          // TODO: /tmp/ should not be hardcoded. User might want to override /tmp @@ -796,45 +939,23 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote          // Spawn a new thread to accept the port that gets bound after          // binding to port 0 (zero). -        lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD; -        const char *unix_socket_name = NULL; -        char unix_socket_name_buf[PATH_MAX] = "/tmp/XXXXXXXXX"; - -        if (port == 0) -        { -            if (::mkstemp (unix_socket_name_buf) == 0) -            { -                unix_socket_name = unix_socket_name_buf; -                ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name); -                accept_thread = Host::ThreadCreate (unix_socket_name, -                                                    AcceptPortFromInferior, -                                                    connect_url, -                                                    &error); -            } -            else -            { -                error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno)); -            } -        }          if (error.Success())          {              // Spawn a debugserver and try to get the port it listens to.              ProcessLaunchInfo debugserver_launch_info; -            StreamString host_and_port;              if (hostname.empty())                  hostname = "localhost"; -            host_and_port.Printf("%s:%u", hostname.c_str(), port); -            const char *host_and_port_cstr = host_and_port.GetString().c_str();              Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));              if (log) -                log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr); +                log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);              debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); -            error = StartDebugserverProcess (host_and_port_cstr, -                                             unix_socket_name, -                                             debugserver_launch_info); +            error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(), +                                             port, +                                             debugserver_launch_info, +                                             port);              lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); @@ -854,45 +975,17 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote              if (error.Success())              { -                bool success = false; +                char response[256]; +                const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); +                assert (response_len < sizeof(response)); +                PacketResult packet_result = SendPacketNoLock (response, response_len); -                if (IS_VALID_LLDB_HOST_THREAD(accept_thread)) -                { -                    thread_result_t accept_thread_result = NULL; -                    if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error)) -                    { -                        if (accept_thread_result) -                        { -                            port = (intptr_t)accept_thread_result; -                            char response[256]; -                            const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); -                            assert (response_len < sizeof(response)); -                            //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID(); -                            success = SendPacketNoLock (response, response_len) > 0; -                        } -                    } -                } -                else -                { -                    char response[256]; -                    const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); -                    assert (response_len < sizeof(response)); -                    //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID(); -                    success = SendPacketNoLock (response, response_len) > 0; - -                } -                Host::Unlink (unix_socket_name); - -                if (!success) +                if (packet_result != PacketResult::Success)                  {                      if (debugserver_pid != LLDB_INVALID_PROCESS_ID)                          ::kill (debugserver_pid, SIGINT);                  } -                return success; -            } -            else if (accept_thread) -            { -                Host::Unlink (unix_socket_name); +                return packet_result;              }          }      } @@ -901,59 +994,124 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote  }  bool -GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) +GDBRemoteCommunicationServer::KillSpawnedProcess (lldb::pid_t pid)  { -    // Spawn a local debugserver as a platform so we can then attach or launch -    // a process... - -    if (m_is_platform) +    // make sure we know about this process      { -        packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            return false; +    } -        lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); +    // first try a SIGTERM (standard kill) +    Host::Kill (pid, SIGTERM); -        // Scope for locker +    // check if that worked +    for (size_t i=0; i<10; ++i) +    {          {              Mutex::Locker locker (m_spawned_pids_mutex);              if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -                return SendErrorResponse (10); +            { +                // it is now killed +                return true; +            }          } -        Host::Kill (pid, SIGTERM); +        usleep (10000); +    } + +    // check one more time after the final usleep +    { +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            return true; +    } + +    // the launched process still lives.  Now try killling it again, +    // this time with an unblockable signal. +    Host::Kill (pid, SIGKILL); -        for (size_t i=0; i<10; ++i) +    for (size_t i=0; i<10; ++i) +    {          { -            // Scope for locker +            Mutex::Locker locker (m_spawned_pids_mutex); +            if (m_spawned_pids.find(pid) == m_spawned_pids.end())              { -                Mutex::Locker locker (m_spawned_pids_mutex); -                if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -                    return SendOKResponse(); +                // it is now killed +                return true;              } -            usleep (10000);          } +        usleep (10000); +    } + +    // check one more time after the final usleep +    // Scope for locker +    { +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            return true; +    } + +    // no luck - the process still lives +    return false; +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) +{ +    packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); + +    lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); -        // Scope for locker +    // verify that we know anything about this pid. +    // Scope for locker +    { +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end())          { -            Mutex::Locker locker (m_spawned_pids_mutex); -            if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -                return SendOKResponse(); +            // not a pid we know about +            return SendErrorResponse (10);          } -        Host::Kill (pid, SIGKILL); +    } + +    // go ahead and attempt to kill the spawned process +    if (KillSpawnedProcess (pid)) +        return SendOKResponse (); +    else +        return SendErrorResponse (11); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::Handle_k (StringExtractorGDBRemote &packet) +{ +    // ignore for now if we're lldb_platform +    if (m_is_platform) +        return SendUnimplementedResponse (packet.GetStringRef().c_str()); -        for (size_t i=0; i<10; ++i) +    // shutdown all spawned processes +    std::set<lldb::pid_t> spawned_pids_copy; + +    // copy pids +    { +        Mutex::Locker locker (m_spawned_pids_mutex); +        spawned_pids_copy.insert (m_spawned_pids.begin (), m_spawned_pids.end ()); +    } + +    // nuke the spawned processes +    for (auto it = spawned_pids_copy.begin (); it != spawned_pids_copy.end (); ++it) +    { +        lldb::pid_t spawned_pid = *it; +        if (!KillSpawnedProcess (spawned_pid))          { -            // Scope for locker -            { -                Mutex::Locker locker (m_spawned_pids_mutex); -                if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -                    return SendOKResponse(); -            } -            usleep (10000); +            fprintf (stderr, "%s: failed to kill spawned pid %" PRIu64 ", ignoring.\n", __FUNCTION__, spawned_pid);          }      } -    return SendErrorResponse (11); + +    // TODO figure out how to shut down gracefully at this point +    return SendOKResponse ();  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)  {      if (m_process_launch_error.Success()) @@ -964,7 +1122,7 @@ GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &p      return SendPacketNoLock (response.GetData(), response.GetSize());  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_QEnvironment  (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen ("QEnvironment:")); @@ -977,7 +1135,7 @@ GDBRemoteCommunicationServer::Handle_QEnvironment  (StringExtractorGDBRemote &pa      return SendErrorResponse (12);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen ("QLaunchArch:")); @@ -992,7 +1150,7 @@ GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &pack      return SendErrorResponse(13);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen ("QSetDisableASLR:")); @@ -1003,7 +1161,7 @@ GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &      return SendOKResponse ();  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen ("QSetWorkingDir:")); @@ -1027,7 +1185,7 @@ GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &p      return SendOKResponse ();  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)  {      StreamString response; @@ -1043,8 +1201,7 @@ GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &p          else          {              response.PutBytesAsRawHex8(cwd, strlen(cwd)); -            SendPacketNoLock(response.GetData(), response.GetSize()); -            return true; +            return SendPacketNoLock(response.GetData(), response.GetSize());          }      }      else @@ -1053,8 +1210,7 @@ GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &p          if (working_dir && working_dir[0])          {              response.PutBytesAsRawHex8(working_dir, strlen(working_dir)); -            SendPacketNoLock(response.GetData(), response.GetSize()); -            return true; +            return SendPacketNoLock(response.GetData(), response.GetSize());          }          else          { @@ -1063,7 +1219,7 @@ GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &p      }  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen ("QSetSTDIN:")); @@ -1080,7 +1236,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet      return SendErrorResponse (15);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen ("QSetSTDOUT:")); @@ -1097,7 +1253,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packe      return SendErrorResponse (16);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen ("QSetSTDERR:")); @@ -1114,16 +1270,16 @@ GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packe      return SendErrorResponse (17);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)  {      // Send response first before changing m_send_acks to we ack this packet -    SendOKResponse (); +    PacketResult packet_result = SendOKResponse ();      m_send_acks = false; -    return true; +    return packet_result;  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("qPlatform_mkdir:")); @@ -1141,7 +1297,7 @@ GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &      return SendErrorResponse(20);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("qPlatform_chmod:")); @@ -1160,7 +1316,7 @@ GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &      return SendErrorResponse(19);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("vFile:open:")); @@ -1176,7 +1332,6 @@ GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packe                  mode_t mode = packet.GetHexMaxU32(false, 0600);                  Error error;                  int fd = ::open (path.c_str(), flags, mode); -                printf ("open('%s', flags=0x%x, mode=%o) fd = %i (%s)\n", path.c_str(), flags, mode, fd, fd == -1 ? strerror(errno) : "<success>");                  const int save_errno = fd == -1 ? errno : 0;                  StreamString response;                  response.PutChar('F'); @@ -1190,7 +1345,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packe      return SendErrorResponse(18);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("vFile:close:")); @@ -1215,7 +1370,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &pack      return SendPacketNoLock(response.GetData(), response.GetSize());  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)  {  #ifdef _WIN32 @@ -1257,7 +1412,7 @@ GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &pack  #endif  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)  {  #ifdef _WIN32 @@ -1294,7 +1449,7 @@ GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &pac  #endif  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("vFile:size:")); @@ -1316,7 +1471,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packe      return SendErrorResponse(22);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("vFile:mode:")); @@ -1335,7 +1490,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packe      return SendErrorResponse(23);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("vFile:exists:")); @@ -1356,7 +1511,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &pac      return SendErrorResponse(24);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("vFile:symlink:")); @@ -1370,7 +1525,7 @@ GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &pa      return SendPacketNoLock(response.GetData(), response.GetSize());  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("vFile:unlink:")); @@ -1382,7 +1537,7 @@ GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &pac      return SendPacketNoLock(response.GetData(), response.GetSize());  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("qPlatform_shell:")); @@ -1424,13 +1579,13 @@ GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &      return SendErrorResponse(24);  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)  {      return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_Stat() unimplemented");  } -bool +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("vFile:MD5:")); | 
