diff options
Diffstat (limited to 'lldb/tools')
| -rw-r--r-- | lldb/tools/lldb-server/Acceptor.cpp | 98 | ||||
| -rw-r--r-- | lldb/tools/lldb-server/Acceptor.h | 63 | ||||
| -rw-r--r-- | lldb/tools/lldb-server/CMakeLists.txt | 14 | ||||
| -rw-r--r-- | lldb/tools/lldb-server/lldb-gdbserver.cpp | 156 | ||||
| -rw-r--r-- | lldb/tools/lldb-server/lldb-platform.cpp | 62 |
5 files changed, 234 insertions, 159 deletions
diff --git a/lldb/tools/lldb-server/Acceptor.cpp b/lldb/tools/lldb-server/Acceptor.cpp new file mode 100644 index 00000000000..c3cea7f9b19 --- /dev/null +++ b/lldb/tools/lldb-server/Acceptor.cpp @@ -0,0 +1,98 @@ +//===-- Acceptor.cpp --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Acceptor.h" + +#include "llvm/ADT/StringRef.h" + +#include "lldb/Core/StreamString.h" +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Host/posix/DomainSocket.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::lldb_server; +using namespace llvm; + +Error +Acceptor::Listen(int backlog) +{ + return m_listener_socket_up->Listen(StringRef(m_name.c_str()), + backlog); +} + +Error +Acceptor::Accept(const bool child_processes_inherit, Connection *&conn) +{ + Socket* conn_socket = nullptr; + auto error = m_listener_socket_up->Accept(StringRef(m_name.c_str()), + child_processes_inherit, + conn_socket); + if (error.Success()) + conn = new ConnectionFileDescriptor(conn_socket); + + return error; +} + +Socket::SocketProtocol +Acceptor::GetSocketProtocol() const +{ + return m_listener_socket_up->GetSocketProtocol(); +} + +std::string +Acceptor::GetLocalSocketId() const +{ + return m_local_socket_id(); +} + +std::unique_ptr<Acceptor> +Acceptor::Create(StringRef name, const bool child_processes_inherit, Error &error) +{ + error.Clear(); + + LocalSocketIdFunc local_socket_id; + std::unique_ptr<Socket> listener_socket = nullptr; + std::string host_str; + std::string port_str; + int32_t port = INT32_MIN; + if (Socket::DecodeHostAndPort (name, host_str, port_str, port, &error)) + { + auto tcp_socket = new TCPSocket(child_processes_inherit, error); + local_socket_id = [tcp_socket]() { + auto local_port = tcp_socket->GetLocalPortNumber(); + return (local_port != 0) ? std::to_string(local_port) : ""; + }; + listener_socket.reset(tcp_socket); + } + else + { + const std::string socket_name = name; + local_socket_id = [socket_name](){ + return socket_name; + }; + listener_socket.reset(new DomainSocket(child_processes_inherit, error)); + } + + if (error.Success()) + return std::unique_ptr<Acceptor>( + new Acceptor(std::move(listener_socket), name, local_socket_id)); + + return std::unique_ptr<Acceptor>(); +} + +Acceptor::Acceptor(std::unique_ptr<Socket> &&listener_socket, + StringRef name, + const LocalSocketIdFunc &local_socket_id) + : m_listener_socket_up(std::move(listener_socket)), + m_name(name.str()), + m_local_socket_id(local_socket_id) +{ +} diff --git a/lldb/tools/lldb-server/Acceptor.h b/lldb/tools/lldb-server/Acceptor.h new file mode 100644 index 00000000000..fca5108f02d --- /dev/null +++ b/lldb/tools/lldb-server/Acceptor.h @@ -0,0 +1,63 @@ +//===-- Acceptor.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef lldb_server_Acceptor_h_ +#define lldb_server_Acceptor_h_ + +#include "lldb/Core/Connection.h" +#include "lldb/Core/Error.h" +#include "lldb/Host/Socket.h" + +#include <functional> +#include <memory> +#include <string> + +namespace llvm +{ + class StringRef; +} + +namespace lldb_private { +namespace lldb_server { + +class Acceptor +{ +public: + virtual ~Acceptor() = default; + + Error + Listen(int backlog); + + Error + Accept(const bool child_processes_inherit, Connection *&conn); + + static std::unique_ptr<Acceptor> + Create(llvm::StringRef name, const bool child_processes_inherit, Error &error); + + Socket::SocketProtocol GetSocketProtocol() const; + + // Returns either TCP port number as string or domain socket path. + // Empty string is returned in case of error. + std::string GetLocalSocketId() const; + +private: + typedef std::function<std::string()> LocalSocketIdFunc; + + Acceptor(std::unique_ptr<Socket> &&listener_socket, + llvm::StringRef name, + const LocalSocketIdFunc &local_socket_id); + + const std::unique_ptr<Socket> m_listener_socket_up; + const std::string m_name; + const LocalSocketIdFunc m_local_socket_id; +}; + +} // namespace lldb_server +} // namespace lldb_private + +#endif // lldb_server_Acceptor_h_ diff --git a/lldb/tools/lldb-server/CMakeLists.txt b/lldb/tools/lldb-server/CMakeLists.txt index f8d2e0ecb16..55af04c9c7d 100644 --- a/lldb/tools/lldb-server/CMakeLists.txt +++ b/lldb/tools/lldb-server/CMakeLists.txt @@ -18,24 +18,18 @@ include_directories(../../source) include(../../cmake/LLDBDependencies.cmake) -if (BUILD_SHARED_LIBS ) - add_lldb_executable(lldb-server +add_lldb_executable(lldb-server + Acceptor.cpp lldb-gdbserver.cpp lldb-platform.cpp lldb-server.cpp LLDBServerUtilities.cpp - ) +) +if (BUILD_SHARED_LIBS ) target_link_libraries(lldb-server liblldb) target_link_libraries(lldb-server ${LLDB_SYSTEM_LIBS}) else() - add_lldb_executable(lldb-server - lldb-gdbserver.cpp - lldb-platform.cpp - lldb-server.cpp - LLDBServerUtilities.cpp - ) - # The Darwin linker doesn't understand --start-group/--end-group. if (LLDB_LINKER_SUPPORTS_GROUPS) target_link_libraries(lldb-server diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp index a754cfd3343..18938ce7e3b 100644 --- a/lldb/tools/lldb-server/lldb-gdbserver.cpp +++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp @@ -24,18 +24,16 @@ // Other libraries and framework includes #include "llvm/ADT/StringRef.h" -#include "lldb/Core/ConnectionMachPort.h" #include "lldb/Core/Error.h" #include "lldb/Core/PluginManager.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostGetOpt.h" -#include "lldb/Host/HostThread.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/Socket.h" #include "lldb/Host/StringConvert.h" -#include "lldb/Host/ThreadLauncher.h" #include "lldb/Target/Platform.h" +#include "Acceptor.h" #include "LLDBServerUtilities.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" @@ -54,15 +52,6 @@ using namespace lldb_private; using namespace lldb_private::lldb_server; using namespace lldb_private::process_gdb_remote; -// lldb-gdbserver state - -namespace -{ -HostThread s_listen_thread; - std::unique_ptr<ConnectionFileDescriptor> s_listen_connection_up; - std::string s_listen_url; -} - //---------------------------------------------------------------------- // option descriptors for getopt_long_only() //---------------------------------------------------------------------- @@ -263,64 +252,16 @@ handle_launch (GDBRemoteCommunicationServerLLGS &gdb_server, int argc, const cha } } -static lldb::thread_result_t -ListenThread (lldb::thread_arg_t /* arg */) -{ - Error error; - - if (s_listen_connection_up) - { - // Do the listen on another thread so we can continue on... - if (s_listen_connection_up->Connect(s_listen_url.c_str(), &error) != eConnectionStatusSuccess) - s_listen_connection_up.reset(); - } - return nullptr; -} - -static Error -StartListenThread (const char *hostname, uint16_t port) -{ - Error error; - if (s_listen_thread.IsJoinable()) - { - error.SetErrorString("listen thread already running"); - } - else - { - char listen_url[512]; - if (hostname && hostname[0]) - snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, port); - else - snprintf(listen_url, sizeof(listen_url), "listen://%i", port); - - s_listen_url = listen_url; - s_listen_connection_up.reset (new ConnectionFileDescriptor ()); - s_listen_thread = ThreadLauncher::LaunchThread(listen_url, ListenThread, nullptr, &error); - } - return error; -} - -static bool -JoinListenThread () -{ - if (s_listen_thread.IsJoinable()) - s_listen_thread.Join(nullptr); - return true; -} - Error -WritePortToPipe(Pipe &port_pipe, const uint16_t port) +writeSocketIdToPipe(Pipe &port_pipe, const std::string &socket_id) { - char port_str[64]; - const auto port_str_len = ::snprintf(port_str, sizeof(port_str), "%u", port); - size_t bytes_written = 0; // Write the port number as a C string with the NULL terminator. - return port_pipe.Write(port_str, port_str_len + 1, bytes_written); + return port_pipe.Write(socket_id.c_str(), socket_id.size(), bytes_written); } Error -writePortToPipe(const char *const named_pipe_path, const uint16_t port) +writeSocketIdToPipe(const char *const named_pipe_path, const std::string &socket_id) { Pipe port_name_pipe; // Wait for 10 seconds for pipe to be opened. @@ -328,17 +269,17 @@ writePortToPipe(const char *const named_pipe_path, const uint16_t port) std::chrono::seconds{10}); if (error.Fail()) return error; - return WritePortToPipe(port_name_pipe, port); + return writeSocketIdToPipe(port_name_pipe, socket_id); } Error -writePortToPipe(int unnamed_pipe_fd, const uint16_t port) +writeSocketIdToPipe(int unnamed_pipe_fd, const std::string &socket_id) { #if defined(_WIN32) return Error("Unnamed pipes are not supported on Windows."); #else Pipe port_pipe{Pipe::kInvalidDescriptor, unnamed_pipe_fd}; - return WritePortToPipe(port_pipe, port); + return writeSocketIdToPipe(port_pipe, socket_id); #endif } @@ -370,14 +311,8 @@ ConnectToRemote(MainLoop &mainloop, GDBRemoteCommunicationServerLLGS &gdb_server connection_port = final_host_and_port.substr (colon_pos + 1); connection_portno = StringConvert::ToUInt32 (connection_port.c_str (), 0); } - else - { - fprintf (stderr, "failed to parse host and port from connection string '%s'\n", final_host_and_port.c_str ()); - display_usage (progname, subcommand); - exit (1); - } - std::unique_ptr<ConnectionFileDescriptor> connection_up; + std::unique_ptr<Connection> connection_up; if (reverse_connect) { @@ -410,66 +345,51 @@ ConnectToRemote(MainLoop &mainloop, GDBRemoteCommunicationServerLLGS &gdb_server } else { - // llgs will listen for connections on the given port from the given address. - // Start the listener on a new thread. We need to do this so we can resolve the - // bound listener port. - StartListenThread(connection_host.c_str (), static_cast<uint16_t> (connection_portno)); - printf ("Listening to port %s for a connection from %s...\n", connection_port.c_str (), connection_host.c_str ()); - - // If we have a named pipe to write the port number back to, do that now. - if (named_pipe_path && named_pipe_path[0] && connection_portno == 0) + std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(final_host_and_port, false, error)); + if (error.Fail()) + { + fprintf(stderr, "failed to create acceptor: %s", error.AsCString()); + exit(1); + } + error = acceptor_up->Listen(1); + if (error.Fail()) { - const uint16_t bound_port = s_listen_connection_up->GetListeningPort (10); - if (bound_port > 0) + fprintf(stderr, "failed to listen: %s\n", error.AsCString()); + exit(1); + } + const std::string socket_id = acceptor_up->GetLocalSocketId(); + if (!socket_id.empty()) + { + // If we have a named pipe to write the socket id back to, do that now. + if (named_pipe_path && named_pipe_path[0]) { - error = writePortToPipe (named_pipe_path, bound_port); + error = writeSocketIdToPipe (named_pipe_path, socket_id); if (error.Fail ()) - { - fprintf (stderr, "failed to write to the named pipe \'%s\': %s", named_pipe_path, error.AsCString()); - } + fprintf (stderr, "failed to write to the named pipe \'%s\': %s", + named_pipe_path, error.AsCString()); } - else + // If we have an unnamed pipe to write the socket id back to, do that now. + else if (unnamed_pipe_fd >= 0) { - fprintf (stderr, "unable to get the bound port for the listening connection\n"); - } - } - - // If we have an unnamed pipe to write the port number back to, do that now. - if (unnamed_pipe_fd >= 0 && connection_portno == 0) - { - const uint16_t bound_port = s_listen_connection_up->GetListeningPort(10); - if (bound_port > 0) - { - error = writePortToPipe(unnamed_pipe_fd, bound_port); + error = writeSocketIdToPipe(unnamed_pipe_fd, socket_id); if (error.Fail()) - { fprintf(stderr, "failed to write to the unnamed pipe: %s", error.AsCString()); - } - } - else - { - fprintf(stderr, "unable to get the bound port for the listening connection\n"); } } - - // Join the listener thread. - if (!JoinListenThread ()) + else { - fprintf (stderr, "failed to join the listener thread\n"); - display_usage (progname, subcommand); - exit (1); + fprintf (stderr, "unable to get the socket id for the listening connection\n"); } - // Ensure we connected. - if (s_listen_connection_up) - connection_up = std::move(s_listen_connection_up); - else + Connection* conn = nullptr; + error = acceptor_up->Accept(false, conn); + if (error.Fail()) { - fprintf (stderr, "failed to connect to '%s': %s\n", final_host_and_port.c_str (), error.AsCString ()); - display_usage (progname, subcommand); - exit (1); + printf ("failed to accept new connection: %s\n", error.AsCString()); + exit(1); } + connection_up.reset(conn); } error = gdb_server.InitializeConnection (std::move(connection_up)); if (error.Fail()) diff --git a/lldb/tools/lldb-server/lldb-platform.cpp b/lldb/tools/lldb-server/lldb-platform.cpp index df9b6bb2543..be34f49ea4f 100644 --- a/lldb/tools/lldb-server/lldb-platform.cpp +++ b/lldb/tools/lldb-server/lldb-platform.cpp @@ -23,6 +23,9 @@ #include <fstream> // Other libraries and framework includes +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" + #include "lldb/Core/Error.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" @@ -30,8 +33,7 @@ #include "lldb/Host/HostGetOpt.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/common/TCPSocket.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/FileUtilities.h" +#include "Acceptor.h" #include "LLDBServerUtilities.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" @@ -61,7 +63,7 @@ static struct option g_long_options[] = { "gdbserver-port", required_argument, NULL, 'P' }, { "min-gdbserver-port", required_argument, NULL, 'm' }, { "max-gdbserver-port", required_argument, NULL, 'M' }, - { "port-file", required_argument, NULL, 'f' }, + { "socket-file", required_argument, NULL, 'f' }, { "server", no_argument, &g_server, 1 }, { NULL, 0, NULL, 0 } }; @@ -100,9 +102,9 @@ display_usage (const char *progname, const char *subcommand) } static Error -save_port_to_file(const uint16_t port, const FileSpec &port_file_spec) +save_socket_id_to_file(const std::string &socket_id, const FileSpec &file_spec) { - FileSpec temp_file_spec(port_file_spec.GetDirectory().AsCString(), false); + FileSpec temp_file_spec(file_spec.GetDirectory().AsCString(), false); auto error = FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault); if (error.Fail()) return Error("Failed to create directory %s: %s", temp_file_spec.GetCString(), error.AsCString()); @@ -119,13 +121,13 @@ save_port_to_file(const uint16_t port, const FileSpec &port_file_spec) std::ofstream temp_file(temp_file_path.c_str(), std::ios::out); if (!temp_file.is_open()) return Error("Failed to open temp file %s", temp_file_path.c_str()); - temp_file << port; + temp_file << socket_id; } - err_code = llvm::sys::fs::rename(temp_file_path.c_str(), port_file_spec.GetPath().c_str()); + err_code = llvm::sys::fs::rename(temp_file_path.c_str(), file_spec.GetPath().c_str()); if (err_code) return Error("Failed to rename file %s to %s: %s", - temp_file_path.c_str(), port_file_spec.GetPath().c_str(), err_code.message().c_str()); + temp_file_path.c_str(), file_spec.GetPath().c_str(), err_code.message().c_str()); tmp_file_remover.releaseFile(); return Error(); @@ -156,7 +158,7 @@ main_platform (int argc, char *argv[]) int max_gdbserver_port = 0; uint16_t port_offset = 0; - FileSpec port_file; + FileSpec socket_file; bool show_usage = false; int option_error = 0; int socket_error = -1; @@ -191,9 +193,9 @@ main_platform (int argc, char *argv[]) log_channels = StringRef(optarg); break; - case 'f': // Port file + case 'f': // Socket file if (optarg && optarg[0]) - port_file.SetFile(optarg, false); + socket_file.SetFile(optarg, false); break; case 'p': @@ -282,39 +284,38 @@ main_platform (int argc, char *argv[]) display_usage(progname, subcommand); exit(option_error); } - - Socket *socket = nullptr; - const bool children_inherit_listen_socket = false; + const bool children_inherit_listen_socket = false; // the test suite makes many connections in parallel, let's not miss any. - // The highest this should get reasonably is a function of the number - // of target CPUs. For now, let's just use 100 + // The highest this should get reasonably is a function of the number + // of target CPUs. For now, let's just use 100. const int backlog = 100; - std::unique_ptr<TCPSocket> listening_socket_up(new TCPSocket(children_inherit_listen_socket, error)); + + std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(listen_host_port, children_inherit_listen_socket, error)); if (error.Fail()) { - fprintf(stderr, "failed to create socket: %s", error.AsCString()); + fprintf(stderr, "failed to create acceptor: %s", error.AsCString()); exit(socket_error); } - error = listening_socket_up->Listen(listen_host_port.c_str(), backlog); + error = acceptor_up->Listen(backlog); if (error.Fail()) { - printf("error: %s\n", error.AsCString()); + printf("failed to listen: %s\n", error.AsCString()); exit(socket_error); } - if (port_file) + if (socket_file) { - error = save_port_to_file(listening_socket_up->GetLocalPortNumber(), port_file); + error = save_socket_id_to_file(acceptor_up->GetLocalSocketId(), socket_file); if (error.Fail()) { - fprintf(stderr, "failed to write port to %s: %s", port_file.GetPath().c_str(), error.AsCString()); + fprintf(stderr, "failed to write socket id to %s: %s", socket_file.GetPath().c_str(), error.AsCString()); return 1; } } do { - GDBRemoteCommunicationServerPlatform platform; + GDBRemoteCommunicationServerPlatform platform(acceptor_up->GetSocketProtocol()); if (port_offset > 0) platform.SetPortOffset(port_offset); @@ -325,8 +326,8 @@ main_platform (int argc, char *argv[]) } const bool children_inherit_accept_socket = true; - socket = nullptr; - error = listening_socket_up->Accept(listen_host_port.c_str(), children_inherit_accept_socket, socket); + Connection* conn = nullptr; + error = acceptor_up->Accept(children_inherit_accept_socket, conn); if (error.Fail()) { printf ("error: %s\n", error.AsCString()); @@ -340,8 +341,7 @@ main_platform (int argc, char *argv[]) if (fork()) { // Parent doesn't need a connection to the lldb client - delete socket; - socket = nullptr; + delete conn; // Parent will continue to listen for new connections. continue; @@ -351,16 +351,16 @@ main_platform (int argc, char *argv[]) // Child process will handle the connection and exit. g_server = 0; // Listening socket is owned by parent process. - listening_socket_up.release(); + acceptor_up.release(); } } else { // If not running as a server, this process will not accept // connections while a connection is active. - listening_socket_up.reset(); + acceptor_up.reset(); } - platform.SetConnection (new ConnectionFileDescriptor(socket)); + platform.SetConnection (conn); if (platform.IsConnected()) { |

