diff options
Diffstat (limited to 'lldb/source')
15 files changed, 263 insertions, 158 deletions
diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index cb69b6b2850..54cb7c22330 100644 --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -50,8 +50,6 @@ #include "lldb/Host/common/TCPSocket.h" #include "lldb/Interpreter/Args.h" -#include "Utility/UriParser.h" - using namespace lldb; using namespace lldb_private; @@ -171,20 +169,6 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) // unix://SOCKNAME return NamedSocketAccept(s + strlen("unix-accept://"), error_ptr); } - else if (strstr(s, "adb://") == s) - { - int port = -1; - std::string scheme, host, path; - if (!UriParser::Parse(s, scheme, host, port, path)) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("Failed to parse URL '%s'", s); - return eConnectionStatusError; - } - std::ostringstream host_and_port; - host_and_port << "localhost:" << port; - return ConnectTCP(host_and_port.str().c_str(), error_ptr); - } else if (strstr(s, "connect://") == s) { return ConnectTCP(s + strlen("connect://"), error_ptr); @@ -197,6 +181,11 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) { return ConnectUDP(s + strlen("udp://"), error_ptr); } + else if (strstr(s, "unix-connect://") == s) + { + // unix-connect://SOCKNAME + return NamedSocketConnect(s + strlen("unix-connect://"), error_ptr); + } #ifndef LLDB_DISABLE_POSIX else if (strstr(s, "fd://") == s) { diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.cpp b/lldb/source/Plugins/Platform/Android/AdbClient.cpp index 17fccb38937..f57e8c3faf2 100644 --- a/lldb/source/Plugins/Platform/Android/AdbClient.cpp +++ b/lldb/source/Plugins/Platform/Android/AdbClient.cpp @@ -145,6 +145,19 @@ AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_p } Error +AdbClient::SetPortForwarding (const uint16_t local_port, const char* remote_socket_name) +{ + char message[PATH_MAX]; + snprintf (message, sizeof (message), "forward:tcp:%d;localfilesystem:%s", local_port, remote_socket_name); + + const auto error = SendDeviceMessage (message); + if (error.Fail ()) + return error; + + return ReadResponseStatus (); +} + +Error AdbClient::DeletePortForwarding (const uint16_t local_port) { char message[32]; diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.h b/lldb/source/Plugins/Platform/Android/AdbClient.h index 25a72640c6c..43aa1db678f 100644 --- a/lldb/source/Plugins/Platform/Android/AdbClient.h +++ b/lldb/source/Plugins/Platform/Android/AdbClient.h @@ -51,6 +51,9 @@ public: SetPortForwarding (const uint16_t local_port, const uint16_t remote_port); Error + SetPortForwarding (const uint16_t local_port, const char* remote_socket_name); + + Error DeletePortForwarding (const uint16_t local_port); Error diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp index 403e641952c..0706c9bafa8 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -196,8 +196,7 @@ PlatformAndroid::ConnectRemote(Args& args) return Error("URL is null."); if (!UriParser::Parse(url, scheme, host, port, path)) return Error("Invalid URL: %s", url); - if (scheme == "adb") - m_device_id = host; + m_device_id = host; auto error = PlatformLinux::ConnectRemote(args); if (error.Success()) diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp index 3e07442994b..1abc708cb83 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp @@ -24,7 +24,10 @@ using namespace platform_android; static const lldb::pid_t g_remote_platform_pid = 0; // Alias for the process id of lldb-platform static Error -ForwardPortWithAdb (const uint16_t local_port, const uint16_t remote_port, std::string& device_id) +ForwardPortWithAdb (const uint16_t local_port, + const uint16_t remote_port, + const char* remote_socket_name, + std::string& device_id) { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); @@ -37,7 +40,16 @@ ForwardPortWithAdb (const uint16_t local_port, const uint16_t remote_port, std:: if (log) log->Printf("Connected to Android device \"%s\"", device_id.c_str ()); - return adb.SetPortForwarding(local_port, remote_port); + if (remote_port != 0) + { + if (log) + log->Printf("Forwarding remote TCP port %d to local TCP port %d", remote_port, local_port); + return adb.SetPortForwarding(local_port, remote_port); + } + + if (log) + log->Printf("Forwarding remote socket \"%s\" to local TCP port %d", remote_socket_name, local_port); + return adb.SetPortForwarding(local_port, remote_socket_name); } static Error @@ -72,16 +84,24 @@ PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer () DeleteForwardPortWithAdb(it.second, m_device_id); } -uint16_t -PlatformAndroidRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid) +bool +PlatformAndroidRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) { - uint16_t remote_port = m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1"); - if (remote_port == 0) - return remote_port; + uint16_t remote_port = 0; + std::string socket_name; + if (!m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, remote_port, socket_name)) + return false; - uint16_t local_port = 0; - auto error = SetPortForwarding (pid, remote_port, local_port); - return error.Success() ? local_port : 0; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + + auto error = MakeConnectURL (pid, + remote_port, + socket_name.c_str (), + connect_url); + if (error.Success() && log) + log->Printf("gdbserver connect URL: %s", connect_url.c_str()); + + return error.Success(); } bool @@ -106,21 +126,22 @@ PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args) return Error("URL is null."); if (!UriParser::Parse (url, scheme, host, remote_port, path)) return Error("Invalid URL: %s", url); - if (scheme == "adb") - m_device_id = host; + m_device_id = host; + + std::string connect_url; + auto error = MakeConnectURL (g_remote_platform_pid, + (remote_port < 0) ? 0 : remote_port, + path.c_str (), + connect_url); - uint16_t local_port = 0; - auto error = SetPortForwarding (g_remote_platform_pid, remote_port, local_port); if (error.Fail ()) return error; - const std::string new_url = MakeUrl( - scheme.c_str(), host.c_str(), local_port, path.c_str()); - args.ReplaceArgumentAtIndex (0, new_url.c_str ()); + args.ReplaceArgumentAtIndex (0, connect_url.c_str ()); Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (log) - log->Printf("Rewritten URL: %s", new_url.c_str()); + log->Printf("Rewritten platform connect URL: %s", connect_url.c_str()); error = PlatformRemoteGDBServer::ConnectRemote(args); if (error.Fail ()) @@ -156,9 +177,10 @@ PlatformAndroidRemoteGDBServer::DeleteForwardPort (lldb::pid_t pid) } Error -PlatformAndroidRemoteGDBServer::SetPortForwarding(const lldb::pid_t pid, - const uint16_t remote_port, - uint16_t &local_port) +PlatformAndroidRemoteGDBServer::MakeConnectURL(const lldb::pid_t pid, + const uint16_t remote_port, + const char* remote_socket_name, + std::string& connect_url) { static const int kAttempsNum = 5; @@ -168,35 +190,21 @@ PlatformAndroidRemoteGDBServer::SetPortForwarding(const lldb::pid_t pid, // adding the loop to mitigate such problem. for (auto i = 0; i < kAttempsNum; ++i) { + uint16_t local_port = 0; error = FindUnusedPort(local_port); if (error.Fail()) return error; - error = ForwardPortWithAdb(local_port, remote_port, m_device_id); + error = ForwardPortWithAdb(local_port, remote_port, remote_socket_name, m_device_id); if (error.Success()) { m_port_forwards[pid] = local_port; + std::ostringstream url_str; + url_str << "connect://localhost:" << local_port; + connect_url = url_str.str(); break; } } return error; } - -std::string -PlatformAndroidRemoteGDBServer::MakeUrl(const char* scheme, - const char* hostname, - uint16_t port, - const char* path) -{ - std::ostringstream hostname_str; - if (!strcmp(scheme, "adb")) - hostname_str << "[" << hostname << "]"; - else - hostname_str << hostname; - - return PlatformRemoteGDBServer::MakeUrl(scheme, - hostname_str.str().c_str(), - port, - path); -} diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h index a6dccb8cfcd..9555c73a29a 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h @@ -40,8 +40,8 @@ protected: std::string m_device_id; std::map<lldb::pid_t, uint16_t> m_port_forwards; - uint16_t - LaunchGDBserverAndGetPort (lldb::pid_t &pid) override; + bool + LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) override; bool KillSpawnedProcess (lldb::pid_t pid) override; @@ -49,14 +49,11 @@ protected: void DeleteForwardPort (lldb::pid_t pid); - std::string - MakeUrl(const char* scheme, - const char* hostname, - uint16_t port, - const char* path) override; - Error - SetPortForwarding(const lldb::pid_t pid, const uint16_t remote_port, uint16_t &local_port); + MakeConnectURL(const lldb::pid_t pid, + const uint16_t remote_port, + const char* remote_socket_name, + std::string& connect_url); private: DISALLOW_COPY_AND_ASSIGN (PlatformAndroidRemoteGDBServer); diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index bf5c328f866..ea83027bfe5 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -573,9 +573,8 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info, if (IsConnected()) { lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; - uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid); - - if (port == 0) + std::string connect_url; + if (!LaunchGDBServer(debugserver_pid, connect_url)) { error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); } @@ -606,8 +605,6 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info, if (process_sp) { - std::string connect_url = - MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port); error = process_sp->ConnectRemote (nullptr, connect_url.c_str()); // Retry the connect remote one time... if (error.Fail()) @@ -632,23 +629,36 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info, } -uint16_t -PlatformRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid) +bool +PlatformRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) { ArchSpec remote_arch = GetRemoteSystemArchitecture (); llvm::Triple &remote_triple = remote_arch.GetTriple (); + + uint16_t port = 0; + std::string socket_name; + bool launch_result = false; if (remote_triple.getVendor () == llvm::Triple::Apple && remote_triple.getOS () == llvm::Triple::IOS) { // When remote debugging to iOS, we use a USB mux that always talks // to localhost, so we will need the remote debugserver to accept connections // only from localhost, no matter what our current hostname is - return m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1"); + launch_result = m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, port, socket_name); } else { // All other hosts should use their actual hostname - return m_gdb_client.LaunchGDBserverAndGetPort (pid, NULL); + launch_result = m_gdb_client.LaunchGDBServer (nullptr, pid, port, socket_name); } + + if (!launch_result) + return false; + + connect_url = MakeGdbServerUrl(m_platform_scheme, + m_platform_hostname, + port, + (socket_name.empty()) ? nullptr : socket_name.c_str()); + return true; } bool @@ -669,9 +679,8 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info, if (IsConnected()) { lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; - uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid); - - if (port == 0) + std::string connect_url; + if (!LaunchGDBServer(debugserver_pid, connect_url)) { error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); } @@ -699,11 +708,8 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info, // The darwin always currently uses the GDB remote debugger plug-in // so even when debugging locally we are debugging remotely! process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); - if (process_sp) { - std::string connect_url = - MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port); error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); if (error.Success()) { @@ -950,7 +956,8 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals() std::string PlatformRemoteGDBServer::MakeGdbServerUrl(const std::string &platform_scheme, const std::string &platform_hostname, - uint16_t port) + uint16_t port, + const char* socket_name) { const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME"); const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME"); @@ -960,17 +967,19 @@ PlatformRemoteGDBServer::MakeGdbServerUrl(const std::string &platform_scheme, return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(), override_hostname ? override_hostname : platform_hostname.c_str(), port + port_offset, - nullptr); + socket_name); } std::string PlatformRemoteGDBServer::MakeUrl(const char* scheme, - const char* hostname, - uint16_t port, - const char* path) + const char* hostname, + uint16_t port, + const char* path) { StreamString result; - result.Printf("%s://%s:%u", scheme, hostname, port); + result.Printf("%s://%s", scheme, hostname); + if (port != 0) + result.Printf(":%u", port); if (path) result.Write(path, strlen(path)); return result.GetString(); diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 7b997e8c561..ffba509bbfb 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -225,11 +225,12 @@ protected: lldb::UnixSignalsSP m_remote_signals_sp; - // Launch the lldb-gdbserver on the remote host and return the port it is listening on or 0 on - // failure. Subclasses should override this method if they want to do extra actions before or - // after launching the lldb-gdbserver. - virtual uint16_t - LaunchGDBserverAndGetPort (lldb::pid_t &pid); + // Launch the debug server on the remote host - caller connects to launched + // debug server using connect_url. + // Subclasses should override this method if they want to do extra actions before or + // after launching the debug server. + virtual bool + LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url); virtual bool KillSpawnedProcess (lldb::pid_t pid); @@ -244,7 +245,8 @@ private: std::string MakeGdbServerUrl(const std::string &platform_scheme, const std::string &platform_hostname, - uint16_t port); + uint16_t port, + const char* socket_name); DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer); 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(); |