diff options
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote')
7 files changed, 149 insertions, 64 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 0bbee854dc4..ea95298dd5c 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -1112,17 +1112,15 @@ GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg) } Error -GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, - uint16_t in_port, +GDBRemoteCommunication::StartDebugserverProcess (const char *url, Platform *platform, ProcessLaunchInfo &launch_info, - uint16_t &out_port) + uint16_t *port) { Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); if (log) - log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port); + log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16, __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0)); - out_port = in_port; Error error; // If we locate debugserver, keep that located version around static FileSpec g_debugserver_file_spec; @@ -1193,17 +1191,9 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, debugserver_args.AppendArgument("gdbserver"); #endif - // If a host and port is supplied then use it - char host_and_port[128]; - if (hostname) - { - snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port); - debugserver_args.AppendArgument(host_and_port); - } - else - { - host_and_port[0] = '\0'; - } + // If a url is supplied then use it + if (url) + debugserver_args.AppendArgument(url); // use native registers, not the GDB registers debugserver_args.AppendArgument("--native-regs"); @@ -1214,11 +1204,18 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, } llvm::SmallString<PATH_MAX> named_pipe_path; - Pipe port_pipe; - - if (in_port == 0) + // socket_pipe is used by debug server to communicate back either + // TCP port or domain socket name which it listens on. + // The second purpose of the pipe to serve as a synchronization point - + // once data is written to the pipe, debug server is up and running. + Pipe socket_pipe; + + // port is null when debug server should listen on domain socket - + // we're not interested in port value but rather waiting for debug server + // to become available. + if ((port != nullptr && *port == 0) || port == nullptr) { - if (host_and_port[0]) + if (url) { // Create a temporary file to get the stdout/stderr and redirect the // output of the command into this file. We will later read this file @@ -1227,7 +1224,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, #if defined(__APPLE__) // Binding to port zero, we need to figure out what port it ends up // using using a named pipe... - error = port_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); + error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); if (error.Fail()) { if (log) @@ -1241,7 +1238,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, #else // Binding to port zero, we need to figure out what port it ends up // using using an unnamed pipe... - error = port_pipe.CreateNew(true); + error = socket_pipe.CreateNew(true); if (error.Fail()) { if (log) @@ -1250,10 +1247,10 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, __FUNCTION__, error.AsCString()); return error; } - int write_fd = port_pipe.GetWriteFileDescriptor(); + int write_fd = socket_pipe.GetWriteFileDescriptor(); debugserver_args.AppendArgument("--pipe"); debugserver_args.AppendArgument(std::to_string(write_fd).c_str()); - launch_info.AppendCloseFileAction(port_pipe.GetReadFileDescriptor()); + launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor()); #endif } else @@ -1270,11 +1267,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection (); // Wait for 10 seconds to resolve the bound port - out_port = connection->GetListeningPort(10); - if (out_port > 0) + *port = connection->GetListeningPort(10); + if (*port > 0) { char port_cstr[32]; - snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port); + snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", *port); // Send the host and port down that debugserver and specify an option // so that it connects back to the port we are listening to in this process debugserver_args.AppendArgument("--reverse-connect"); @@ -1343,11 +1340,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, error = Host::LaunchProcess(launch_info); - if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) + if (error.Success() && + launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { if (named_pipe_path.size() > 0) { - error = port_pipe.OpenAsReader(named_pipe_path, false); + error = socket_pipe.OpenAsReader(named_pipe_path, false); if (error.Fail()) if (log) log->Printf("GDBRemoteCommunication::%s() " @@ -1355,24 +1353,24 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } - if (port_pipe.CanWrite()) - port_pipe.CloseWriteFileDescriptor(); - if (port_pipe.CanRead()) + if (socket_pipe.CanWrite()) + socket_pipe.CloseWriteFileDescriptor(); + if (socket_pipe.CanRead()) { - char port_cstr[256]; + char port_cstr[PATH_MAX] = {0}; port_cstr[0] = '\0'; size_t num_bytes = sizeof(port_cstr); // Read port from pipe with 10 second timeout. - error = port_pipe.ReadWithTimeout(port_cstr, num_bytes, + error = socket_pipe.ReadWithTimeout(port_cstr, num_bytes, std::chrono::seconds{10}, num_bytes); - if (error.Success()) + if (error.Success() && (port != nullptr)) { assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); - out_port = StringConvert::ToUInt32(port_cstr, 0); + *port = StringConvert::ToUInt32(port_cstr, 0); if (log) log->Printf("GDBRemoteCommunication::%s() " - "debugserver listens %u port", - __FUNCTION__, out_port); + "debugserver listens %u port", + __FUNCTION__, *port); } else { @@ -1382,12 +1380,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } - port_pipe.Close(); + socket_pipe.Close(); } if (named_pipe_path.size() > 0) { - const auto err = port_pipe.Delete(named_pipe_path); + const auto err = socket_pipe.Delete(named_pipe_path); if (err.Fail()) { if (log) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 94ffa512884..dee3528463f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -167,11 +167,10 @@ public: // supplied connection URL. //------------------------------------------------------------------ Error - StartDebugserverProcess (const char *hostname, - uint16_t in_port, // If set to zero, then out_port will contain the bound port on exit + StartDebugserverProcess (const char *url, Platform *platform, // If non NULL, then check with the platform for the GDB server binary if it can't be located ProcessLaunchInfo &launch_info, - uint16_t &out_port); + uint16_t *port); void DumpHistory(Stream &strm); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 42eb0a1d2ac..a6fcd14cba4 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -3315,10 +3315,16 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success; } -uint16_t -GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname) +bool +GDBRemoteCommunicationClient::LaunchGDBServer (const char *remote_accept_hostname, + lldb::pid_t &pid, + uint16_t &port, + std::string &socket_name) { pid = LLDB_INVALID_PROCESS_ID; + port = 0; + socket_name.clear(); + StringExtractorGDBRemote response; StreamString stream; stream.PutCString("qLaunchGDBServer;"); @@ -3343,22 +3349,30 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const // give the process a few seconds to startup GDBRemoteCommunication::ScopedTimeout timeout (*this, 10); - + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) { std::string name; std::string value; - uint16_t port = 0; + StringExtractor extractor; while (response.GetNameColonValue(name, value)) { if (name.compare("port") == 0) port = StringConvert::ToUInt32(value.c_str(), 0, 0); else if (name.compare("pid") == 0) pid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0); + else if (name.compare("socket_name") == 0) + { + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString(value); + + socket_name = value; + } } - return port; + return true; } - return 0; + return false; } bool diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index b08ff064779..4847aad52f2 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -114,8 +114,11 @@ public: bool GetLaunchSuccess (std::string &error_str); - uint16_t - LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname); + bool + LaunchGDBServer (const char *remote_accept_hostname, + lldb::pid_t &pid, + uint16_t &port, + std::string &socket_name); bool KillSpawnedProcess (lldb::pid_t pid); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 592d7f7f27c..54aad1022f1 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -15,14 +15,20 @@ // C++ Includes #include <cstring> #include <chrono> +#include <mutex> +#include <sstream> // Other libraries and framework includes +#include "llvm/Support/FileSystem.h" + #include "lldb/Core/Log.h" +#include "lldb/Core/StreamGDBRemote.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/StructuredData.h" #include "lldb/Host/Config.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Host/StringConvert.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" @@ -40,8 +46,9 @@ using namespace lldb_private::process_gdb_remote; //---------------------------------------------------------------------- // GDBRemoteCommunicationServerPlatform constructor //---------------------------------------------------------------------- -GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform() : +GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol) : GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"), + m_socket_protocol(socket_protocol), m_spawned_pids_mutex (Mutex::eMutexTypeRecursive), m_platform_sp (Platform::GetHostPlatform ()), m_port_map (), @@ -138,11 +145,24 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path); UNUSED_IF_ASSERT_DISABLED(ok); assert(ok); - Error error = StartDebugserverProcess (platform_ip.c_str(), - port, + + std::string socket_name; + std::ostringstream url; + + uint16_t* port_ptr = &port; + if (m_socket_protocol == Socket::ProtocolTcp) + url << platform_ip << ":" << port; + else + { + socket_name = GetDomainSocketPath("gdbserver").GetPath(); + url << socket_name; + port_ptr = nullptr; + } + + Error error = StartDebugserverProcess (url.str().c_str(), nullptr, debugserver_launch_info, - port); + port_ptr); lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); @@ -165,11 +185,16 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD if (log) log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid); - char response[256]; - const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); - assert (response_len < (int)sizeof(response)); - PacketResult packet_result = SendPacketNoLock (response, response_len); + StreamGDBRemote response; + response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); + if (!socket_name.empty()) + { + response.PutCString("socket_name:"); + response.PutCStringAsRawHex8(socket_name.c_str()); + response.PutChar(';'); + } + PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize()); if (packet_result != PacketResult::Success) { if (debugserver_pid != LLDB_INVALID_PROCESS_ID) @@ -494,6 +519,36 @@ GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid) return false; } +const FileSpec& +GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() +{ + static FileSpec g_domainsocket_dir; + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, []() { + const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR"); + if (domainsocket_dir_env != nullptr) + g_domainsocket_dir = FileSpec(domainsocket_dir_env, false); + else + HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir); + }); + + return g_domainsocket_dir; +} + +FileSpec +GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix) +{ + llvm::SmallString<PATH_MAX> socket_path; + llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str()); + + FileSpec socket_path_spec(GetDomainSocketDir()); + socket_path_spec.AppendPathComponent(socket_name.c_str()); + + llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path); + return FileSpec(socket_path.c_str(), false); +} + void GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset) { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index f507a085cdb..e34189f9ec1 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -12,6 +12,8 @@ #include "GDBRemoteCommunicationServerCommon.h" +#include "lldb/Host/Socket.h" + #include <set> namespace lldb_private { @@ -23,7 +25,7 @@ class GDBRemoteCommunicationServerPlatform : public: typedef std::map<uint16_t, lldb::pid_t> PortMap; - GDBRemoteCommunicationServerPlatform(); + GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol); virtual ~GDBRemoteCommunicationServerPlatform(); @@ -61,6 +63,7 @@ public: SetPortOffset (uint16_t port_offset); protected: + const Socket::SocketProtocol m_socket_protocol; Mutex m_spawned_pids_mutex; std::set<lldb::pid_t> m_spawned_pids; lldb::PlatformSP m_platform_sp; @@ -103,6 +106,12 @@ private: int signal, int status); + static const FileSpec& + GetDomainSocketDir(); + + static FileSpec + GetDomainSocketPath(const char* prefix); + //------------------------------------------------------------------ // For GDBRemoteCommunicationServerPlatform only //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 5b6f9794f5a..8ed7e45f1a2 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -3562,15 +3562,22 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info // Set hostname being NULL to do the reverse connect where debugserver // will bind to port zero and it will communicate back to us the port // that we will connect to - const char *hostname = NULL; + const char *hostname = nullptr; uint16_t port = 0; #endif - error = m_gdb_comm.StartDebugserverProcess (hostname, - port, + StreamString url_str; + const char* url = nullptr; + if (hostname != nullptr) + { + url_str.Printf("%s:%u", hostname, port); + url = url_str.GetData(); + } + + error = m_gdb_comm.StartDebugserverProcess (url, GetTarget().GetPlatform().get(), debugserver_launch_info, - port); + &port); if (error.Success ()) m_debugserver_pid = debugserver_launch_info.GetProcessID(); |