Author: Emre Kultursay Date: 2025-04-25T14:11:19-07:00 New Revision: 488eeb3ae508221f8e476bbc9d2e9f014542862e
URL: https://github.com/llvm/llvm-project/commit/488eeb3ae508221f8e476bbc9d2e9f014542862e DIFF: https://github.com/llvm/llvm-project/commit/488eeb3ae508221f8e476bbc9d2e9f014542862e.diff LOG: Fix connecting via abstract socket (#136466) Commit 82ee31f and Commit 2e893124 added socket sharing, but only for unix domain sockets. That broke Android, which uses unix-abstract sockets. Added: Modified: lldb/include/lldb/Host/linux/AbstractSocket.h lldb/include/lldb/Host/posix/DomainSocket.h lldb/source/Host/linux/AbstractSocket.cpp lldb/source/Host/posix/DomainSocket.cpp lldb/tools/lldb-server/lldb-platform.cpp lldb/unittests/Host/SocketTest.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Host/linux/AbstractSocket.h b/lldb/include/lldb/Host/linux/AbstractSocket.h index accfd01457a5e..c6a0e2f8af63b 100644 --- a/lldb/include/lldb/Host/linux/AbstractSocket.h +++ b/lldb/include/lldb/Host/linux/AbstractSocket.h @@ -15,6 +15,7 @@ namespace lldb_private { class AbstractSocket : public DomainSocket { public: AbstractSocket(); + AbstractSocket(NativeSocket socket, bool should_close); protected: size_t GetNameOffset() const override; diff --git a/lldb/include/lldb/Host/posix/DomainSocket.h b/lldb/include/lldb/Host/posix/DomainSocket.h index 3dbe6206da2c5..a840d474429ec 100644 --- a/lldb/include/lldb/Host/posix/DomainSocket.h +++ b/lldb/include/lldb/Host/posix/DomainSocket.h @@ -31,8 +31,12 @@ class DomainSocket : public Socket { std::vector<std::string> GetListeningConnectionURI() const override; + static llvm::Expected<std::unique_ptr<DomainSocket>> + FromBoundNativeSocket(NativeSocket sockfd, bool should_close); + protected: DomainSocket(SocketProtocol protocol); + DomainSocket(SocketProtocol protocol, NativeSocket socket, bool should_close); virtual size_t GetNameOffset() const; virtual void DeleteSocketFile(llvm::StringRef name); diff --git a/lldb/source/Host/linux/AbstractSocket.cpp b/lldb/source/Host/linux/AbstractSocket.cpp index 8393a80e86e72..681aa2d1ebc72 100644 --- a/lldb/source/Host/linux/AbstractSocket.cpp +++ b/lldb/source/Host/linux/AbstractSocket.cpp @@ -15,6 +15,9 @@ using namespace lldb_private; AbstractSocket::AbstractSocket() : DomainSocket(ProtocolUnixAbstract) {} +AbstractSocket::AbstractSocket(NativeSocket socket, bool should_close) + : DomainSocket(ProtocolUnixAbstract, socket, should_close) {} + size_t AbstractSocket::GetNameOffset() const { return 1; } void AbstractSocket::DeleteSocketFile(llvm::StringRef name) {} diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp index 6c490cdda47ed..4f76e0c16d4c7 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -8,6 +8,9 @@ #include "lldb/Host/posix/DomainSocket.h" #include "lldb/Utility/LLDBLog.h" +#ifdef __linux__ +#include <lldb/Host/linux/AbstractSocket.h> +#endif #include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" @@ -67,6 +70,12 @@ DomainSocket::DomainSocket(NativeSocket socket, m_socket = socket; } +DomainSocket::DomainSocket(SocketProtocol protocol, NativeSocket socket, + bool should_close) + : Socket(protocol, should_close) { + m_socket = socket; +} + Status DomainSocket::Connect(llvm::StringRef name) { sockaddr_un saddr_un; socklen_t saddr_un_len; @@ -182,3 +191,20 @@ std::vector<std::string> DomainSocket::GetListeningConnectionURI() const { return {llvm::formatv("unix-connect://{0}", addr.sun_path)}; } + +llvm::Expected<std::unique_ptr<DomainSocket>> +DomainSocket::FromBoundNativeSocket(NativeSocket sockfd, bool should_close) { + // Check if fd represents domain socket or abstract socket. + struct sockaddr_un addr; + socklen_t addr_len = sizeof(addr); + if (getsockname(sockfd, (struct sockaddr *)&addr, &addr_len) == -1) + return llvm::createStringError("not a socket or error occurred"); + if (addr.sun_family != AF_UNIX) + return llvm::createStringError("Bad socket type"); +#ifdef __linux__ + if (addr_len > offsetof(struct sockaddr_un, sun_path) && + addr.sun_path[0] == '\0') + return std::make_unique<AbstractSocket>(sockfd, should_close); +#endif + return std::make_unique<DomainSocket>(sockfd, should_close); +} diff --git a/lldb/tools/lldb-server/lldb-platform.cpp b/lldb/tools/lldb-server/lldb-platform.cpp index 23d36ffb4cb66..b9a85370d649c 100644 --- a/lldb/tools/lldb-server/lldb-platform.cpp +++ b/lldb/tools/lldb-server/lldb-platform.cpp @@ -455,15 +455,9 @@ int main_platform(int argc, char *argv[]) { lldb_private::Args inferior_arguments; inferior_arguments.SetArguments(argc, const_cast<const char **>(argv)); - Socket::SocketProtocol protocol = Socket::ProtocolUnixDomain; - + Log *log = GetLog(LLDBLog::Platform); if (fd != SharedSocket::kInvalidFD) { // Child process will handle the connection and exit. - if (gdbserver_port) - protocol = Socket::ProtocolTcp; - - Log *log = GetLog(LLDBLog::Platform); - NativeSocket sockfd; error = SharedSocket::GetNativeSocket(fd, sockfd); if (error.Fail()) { @@ -471,21 +465,24 @@ int main_platform(int argc, char *argv[]) { return socket_error; } - GDBRemoteCommunicationServerPlatform platform(protocol, gdbserver_port); - Socket *socket; - if (protocol == Socket::ProtocolTcp) - socket = new TCPSocket(sockfd, /*should_close=*/true); - else { -#if LLDB_ENABLE_POSIX - socket = new DomainSocket(sockfd, /*should_close=*/true); -#else - WithColor::error() << "lldb-platform child: Unix domain sockets are not " - "supported on this platform."; - return socket_error; -#endif + std::unique_ptr<Socket> socket; + if (gdbserver_port) { + socket = std::make_unique<TCPSocket>(sockfd, /*should_close=*/true); + } else { + llvm::Expected<std::unique_ptr<DomainSocket>> domain_socket = + DomainSocket::FromBoundNativeSocket(sockfd, /*should_close=*/true); + if (!domain_socket) { + LLDB_LOG_ERROR(log, domain_socket.takeError(), + "Failed to create socket: {0}"); + return socket_error; + } + socket = std::move(domain_socket.get()); } - platform.SetConnection( - std::unique_ptr<Connection>(new ConnectionFileDescriptor(socket))); + + GDBRemoteCommunicationServerPlatform platform(socket->GetSocketProtocol(), + gdbserver_port); + platform.SetConnection(std::unique_ptr<Connection>( + new ConnectionFileDescriptor(socket.release()))); client_handle(platform, inferior_arguments); return 0; } @@ -498,6 +495,7 @@ int main_platform(int argc, char *argv[]) { return 1; } + Socket::SocketProtocol protocol = Socket::ProtocolUnixDomain; std::string address; std::string gdb_address; uint16_t platform_port = 0; diff --git a/lldb/unittests/Host/SocketTest.cpp b/lldb/unittests/Host/SocketTest.cpp index 9cbf3e26b0883..5bfb48b52f7e7 100644 --- a/lldb/unittests/Host/SocketTest.cpp +++ b/lldb/unittests/Host/SocketTest.cpp @@ -15,6 +15,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include <chrono> +#if __linux__ +#include <lldb/Host/linux/AbstractSocket.h> +#endif using namespace lldb_private; @@ -337,6 +340,47 @@ TEST_F(SocketTest, DomainGetConnectURI) { EXPECT_EQ(socket_b_up->GetRemoteConnectionURI(), ""); } + +TEST_F(SocketTest, DomainSocketFromBoundNativeSocket) { + // Generate a name for the domain socket. + llvm::SmallString<64> name; + std::error_code EC = llvm::sys::fs::createUniqueDirectory( + "DomainSocketFromBoundNativeSocket", name); + ASSERT_FALSE(EC); + llvm::sys::path::append(name, "test"); + + DomainSocket socket(true); + Status error = socket.Listen(name, /*backlog=*/10); + ASSERT_THAT_ERROR(error.takeError(), llvm::Succeeded()); + NativeSocket native_socket = socket.GetNativeSocket(); + + llvm::Expected<std::unique_ptr<DomainSocket>> sock = + DomainSocket::FromBoundNativeSocket(native_socket, + /*should_close=*/false); + ASSERT_THAT_EXPECTED(sock, llvm::Succeeded()); + ASSERT_EQ(Socket::ProtocolUnixDomain, sock->get()->GetSocketProtocol()); +} +#endif + +#if __linux__ +TEST_F(SocketTest, AbstractSocketFromBoundNativeSocket) { + // Generate a name for the abstract socket. + llvm::SmallString<100> name; + llvm::sys::fs::createUniquePath("AbstractSocketFromBoundNativeSocket", name, + true); + llvm::sys::path::append(name, "test"); + + AbstractSocket socket; + Status error = socket.Listen(name, /*backlog=*/10); + ASSERT_THAT_ERROR(error.takeError(), llvm::Succeeded()); + NativeSocket native_socket = socket.GetNativeSocket(); + + llvm::Expected<std::unique_ptr<DomainSocket>> sock = + DomainSocket::FromBoundNativeSocket(native_socket, + /*should_close=*/false); + ASSERT_THAT_EXPECTED(sock, llvm::Succeeded()); + ASSERT_EQ(Socket::ProtocolUnixAbstract, sock->get()->GetSocketProtocol()); +} #endif INSTANTIATE_TEST_SUITE_P( _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits