Index: include/lldb/Host/Socket.h =================================================================== --- include/lldb/Host/Socket.h +++ include/lldb/Host/Socket.h @@ -45,7 +45,8 @@ { ProtocolTcp, ProtocolUdp, - ProtocolUnixDomain + ProtocolUnixDomain, + ProtocolUnixAbstract } SocketProtocol; static const NativeSocket kInvalidSocketValue; @@ -69,6 +70,8 @@ static Error UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket); static Error UnixDomainConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); static Error UnixDomainAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); + static Error UnixAbstractConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); + static Error UnixAbstractAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); int GetOption (int level, int option_name, int &option_value); int SetOption (int level, int option_name, int option_value); Index: include/lldb/Host/linux/AbstractSocket.h =================================================================== --- /dev/null +++ include/lldb/Host/linux/AbstractSocket.h @@ -0,0 +1,28 @@ +//===-- AbstractSocket.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_AbstractSocket_h_ +#define liblldb_AbstractSocket_h_ + +#include "lldb/Host/posix/DomainSocket.h" + +namespace lldb_private +{ + class AbstractSocket: public DomainSocket + { + public: + AbstractSocket(bool child_processes_inherit, Error &error); + + protected: + size_t GetNameOffset() const override; + void DeleteSocketFile(llvm::StringRef name) override; + }; +} + +#endif // ifndef liblldb_AbstractSocket_h_ Index: include/lldb/Host/posix/ConnectionFileDescriptorPosix.h =================================================================== --- include/lldb/Host/posix/ConnectionFileDescriptorPosix.h +++ include/lldb/Host/posix/ConnectionFileDescriptorPosix.h @@ -84,6 +84,8 @@ lldb::ConnectionStatus NamedSocketAccept(const char *socket_name, Error *error_ptr); + lldb::ConnectionStatus UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr); + lldb::IOObjectSP m_read_sp; lldb::IOObjectSP m_write_sp; Index: include/lldb/Host/posix/DomainSocket.h =================================================================== --- include/lldb/Host/posix/DomainSocket.h +++ include/lldb/Host/posix/DomainSocket.h @@ -22,6 +22,13 @@ Error Connect(llvm::StringRef name) override; Error Listen(llvm::StringRef name, int backlog) override; Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) override; + + protected: + DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error); + + virtual size_t GetNameOffset() const; + virtual void DeleteSocketFile(llvm::StringRef name); + private: DomainSocket(NativeSocket socket); }; Index: source/Host/CMakeLists.txt =================================================================== --- source/Host/CMakeLists.txt +++ source/Host/CMakeLists.txt @@ -121,6 +121,7 @@ android/HostInfoAndroid.cpp android/LibcGlue.cpp android/ProcessLauncherAndroid.cpp + linux/AbstractSocket.cpp linux/Host.cpp linux/HostInfoLinux.cpp linux/HostThreadLinux.cpp @@ -129,6 +130,7 @@ ) else() add_host_subdirectory(linux + linux/AbstractSocket.cpp linux/Host.cpp linux/HostInfoLinux.cpp linux/HostThreadLinux.cpp Index: source/Host/common/Socket.cpp =================================================================== --- source/Host/common/Socket.cpp +++ source/Host/common/Socket.cpp @@ -30,6 +30,10 @@ #include #endif +#ifdef __linux__ +#include "lldb/Host/linux/AbstractSocket.h" +#endif + #ifdef __ANDROID_NDK__ #include #include @@ -190,6 +194,44 @@ return error; } +Error +Socket::UnixAbstractConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +{ + Error error; +#ifdef __linux__ + std::unique_ptr connect_socket(new AbstractSocket(child_processes_inherit, error)); + if (error.Fail()) + return error; + + error = connect_socket->Connect(name); + if (error.Success()) + socket = connect_socket.release(); +#else + error.SetErrorString("Abstract domain sockets are not supported on this platform."); +#endif + return error; +} + +Error +Socket::UnixAbstractAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +{ + Error error; +#ifdef __linux__ + std::unique_ptr listen_socket(new AbstractSocket(child_processes_inherit, error)); + if (error.Fail()) + return error; + + error = listen_socket->Listen(name, 5); + if (error.Fail()) + return error; + + error = listen_socket->Accept(name, child_processes_inherit, socket); +#else + error.SetErrorString("Abstract domain sockets are not supported on this platform."); +#endif + return error; +} + bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, std::string &host_str, Index: source/Host/linux/AbstractSocket.cpp =================================================================== --- /dev/null +++ source/Host/linux/AbstractSocket.cpp @@ -0,0 +1,31 @@ +//===-- AbstractSocket.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/linux/AbstractSocket.h" + +#include "llvm/ADT/StringRef.h" + +using namespace lldb; +using namespace lldb_private; + +AbstractSocket::AbstractSocket(bool child_processes_inherit, Error &error) + : DomainSocket(ProtocolUnixAbstract, child_processes_inherit, error) +{ +} + +size_t +AbstractSocket::GetNameOffset() const +{ + return 1; +} + +void +AbstractSocket::DeleteSocketFile(llvm::StringRef name) +{ +} Index: source/Host/posix/ConnectionFileDescriptorPosix.cpp =================================================================== --- source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -186,6 +186,11 @@ // unix-connect://SOCKNAME return NamedSocketConnect(s + strlen("unix-connect://"), error_ptr); } + else if (strstr(s, "unix-abstract-connect://") == s) + { + // unix-abstract-connect://SOCKNAME + return UnixAbstractSocketConnect(s + strlen("unix-abstract-connect://"), error_ptr); + } #ifndef LLDB_DISABLE_POSIX else if (strstr(s, "fd://") == s) { @@ -763,6 +768,23 @@ return eConnectionStatusSuccess; } +lldb::ConnectionStatus +ConnectionFileDescriptor::UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr) +{ + Socket *socket = nullptr; + Error error = Socket::UnixAbstractConnect(socket_name, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + if (error.Fail()) + { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; +} + ConnectionStatus ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr) { Index: source/Host/posix/DomainSocket.cpp =================================================================== --- source/Host/posix/DomainSocket.cpp +++ source/Host/posix/DomainSocket.cpp @@ -29,14 +29,19 @@ const int kDomain = AF_UNIX; const int kType = SOCK_STREAM; -void SetSockAddr(llvm::StringRef name, sockaddr_un* saddr_un) +bool SetSockAddr(llvm::StringRef name, const size_t name_offset, sockaddr_un* saddr_un) { + if (name.size() + name_offset > sizeof(saddr_un->sun_path)) + return false; + saddr_un->sun_family = kDomain; - ::strncpy(saddr_un->sun_path, name.data(), sizeof(saddr_un->sun_path) - 1); - saddr_un->sun_path[sizeof(saddr_un->sun_path) - 1] = '\0'; + memset(saddr_un->sun_path, 0, sizeof(saddr_un->sun_path)); + + strncpy(&saddr_un->sun_path[name_offset], name.data(), name.size()); #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) saddr_un->sun_len = SUN_LEN (saddr_un); #endif + return true; } } @@ -51,14 +56,20 @@ { } +DomainSocket::DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error) + : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), protocol, true) +{ +} + Error DomainSocket::Connect(llvm::StringRef name) { sockaddr_un saddr_un; - SetSockAddr(name, &saddr_un); + if (!SetSockAddr(name, GetNameOffset(), &saddr_un)) + return Error("Failed to set socket address"); Error error; - if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0) + if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, sizeof(saddr_un)) < 0) SetLastError (error); return error; @@ -68,12 +79,13 @@ DomainSocket::Listen(llvm::StringRef name, int backlog) { sockaddr_un saddr_un; - SetSockAddr(name, &saddr_un); + if (!SetSockAddr(name, GetNameOffset(), &saddr_un)) + return Error("Failed to set socket address"); - FileSystem::Unlink(FileSpec{name, true}); + DeleteSocketFile(name); Error error; - if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0) + if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, sizeof(saddr_un)) == 0) if (::listen(GetNativeSocket(), backlog) == 0) return error; @@ -91,3 +103,15 @@ return error; } + +size_t +DomainSocket::GetNameOffset() const +{ + return 0; +} + +void +DomainSocket::DeleteSocketFile(llvm::StringRef name) +{ + FileSystem::Unlink(FileSpec{name, true}); +}