https://github.com/charles-zablit created https://github.com/llvm/llvm-project/pull/205618
Windows 10 1803+ provides `AF_UNIX` sockets via `<afunix.h>`. This patch compiles `DomainSocket.cpp` on Windows and port it to the Win32 `sockaddr_un`. There is no `sun_len` and no `SUN_LEN` macro, so lldb must compute the address length explicitly. It must also emulate the missing `socketpair()` in `DomainSocket::CreatePair` Also remove the gate on the `ProtocolUnixDomain` paths in `Socket::Create/CreatePair` and the lldb-platform child-socket path so they build with `LLDB_ENABLE_POSIX` off on Windows. This is part of a longer set of patches to fix tests on `LLDB_USE_LLDB_SERVER=1`. >From 1ecdcb57a873070e2e19e6d41a978405ae5db9da Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Wed, 24 Jun 2026 18:49:32 +0100 Subject: [PATCH] [lldb][Windows] Support AF_UNIX domain sockets --- lldb/source/Host/CMakeLists.txt | 2 +- lldb/source/Host/common/Socket.cpp | 13 +++-- lldb/source/Host/posix/DomainSocket.cpp | 51 +++++++++++++++---- lldb/tools/lldb-server/lldb-platform.cpp | 4 +- lldb/unittests/Host/SocketTest.cpp | 11 +++- .../Host/SocketTestUtilities.cpp | 7 +-- .../TestingSupport/Host/SocketTestUtilities.h | 6 +-- 7 files changed, 70 insertions(+), 24 deletions(-) diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index 28c639ee38215..c4836adb8f59b 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -73,6 +73,7 @@ endif() add_host_subdirectory(posix posix/ConnectionFileDescriptorPosix.cpp + posix/DomainSocket.cpp ) if (CMAKE_SYSTEM_NAME MATCHES "Windows") @@ -100,7 +101,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") endif() else() add_host_subdirectory(posix - posix/DomainSocket.cpp posix/FilePosix.cpp posix/FileSystemPosix.cpp posix/HostInfoPosix.cpp diff --git a/lldb/source/Host/common/Socket.cpp b/lldb/source/Host/common/Socket.cpp index 810d63fc0390d..6c15d5ebf5ed4 100644 --- a/lldb/source/Host/common/Socket.cpp +++ b/lldb/source/Host/common/Socket.cpp @@ -24,9 +24,9 @@ #include "llvm/Support/Regex.h" #include "llvm/Support/WindowsError.h" -#if LLDB_ENABLE_POSIX #include "lldb/Host/posix/DomainSocket.h" +#if LLDB_ENABLE_POSIX #include <arpa/inet.h> #include <netdb.h> #include <netinet/in.h> @@ -211,7 +211,7 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, socket_up = std::make_unique<UDPSocket>(should_close); break; case ProtocolUnixDomain: -#if LLDB_ENABLE_POSIX +#if LLDB_ENABLE_POSIX || defined(_WIN32) socket_up = std::make_unique<DomainSocket>(should_close); #else error = Status::FromErrorString( @@ -241,10 +241,17 @@ Socket::CreatePair(std::optional<SocketProtocol> protocol) { switch (protocol.value_or(kBestProtocol)) { case ProtocolTcp: return TCPSocket::CreatePair(); -#if LLDB_ENABLE_POSIX case ProtocolUnixDomain: +#if LLDB_ENABLE_POSIX || defined(_WIN32) + return DomainSocket::CreatePair(); +#else + return llvm::createStringError("unsupported protocol"); +#endif case ProtocolUnixAbstract: +#if LLDB_ENABLE_POSIX return DomainSocket::CreatePair(); +#else + return llvm::createStringError("unsupported protocol"); #endif default: return llvm::createStringError("unsupported protocol"); diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp index 4f08c372d43cf..1893b4aa9de59 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -15,12 +15,23 @@ #include "llvm/Support/Errno.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include <chrono> #include <cstddef> -#include <fcntl.h> #include <memory> + +#ifdef _WIN32 +// DomainSocket.h pulls in Socket.h, which includes winsock2.h on Windows. +// afunix.h must be included after winsock2.h. +// clang-format off +#include <afunix.h> +// clang-format on +#else +#include <fcntl.h> #include <sys/socket.h> #include <sys/un.h> +#endif using namespace lldb; using namespace lldb_private; @@ -38,14 +49,8 @@ static bool SetSockAddr(llvm::StringRef name, const size_t name_offset, memcpy(saddr_un->sun_path + name_offset, name.data(), name.size()); - // For domain sockets we can use SUN_LEN in order to calculate size of - // sockaddr_un, but for abstract sockets we have to calculate size manually - // because of leading null symbol. - if (name_offset == 0) - saddr_un_len = SUN_LEN(saddr_un); - else - saddr_un_len = - offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); + saddr_un_len = + offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ defined(__OpenBSD__) @@ -79,6 +84,7 @@ DomainSocket::DomainSocket(SocketProtocol protocol, NativeSocket socket, } llvm::Expected<DomainSocket::Pair> DomainSocket::CreatePair() { +#ifndef _WIN32 int sockets[2]; int type = SOCK_STREAM; #ifdef SOCK_CLOEXEC @@ -111,6 +117,33 @@ llvm::Expected<DomainSocket::Pair> DomainSocket::CreatePair() { std::unique_ptr<DomainSocket>( new DomainSocket(ProtocolUnixDomain, sockets[1], /*should_close=*/true))); +#else // _WIN32 + llvm::SmallString<128> model; + llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/true, model); + llvm::sys::path::append(model, "lldb-domain-socketpair-%%%%%%%%.sock"); + llvm::SmallString<128> path; + llvm::sys::fs::createUniquePath(model, path, /*MakeAbsolute=*/false); + + auto listen_socket = std::make_unique<DomainSocket>(/*should_close=*/true); + if (Status error = listen_socket->Listen(path, /*backlog=*/1); error.Fail()) + return error.takeError(); + + auto connect_socket = std::make_unique<DomainSocket>(/*should_close=*/true); + if (Status error = connect_socket->Connect(path); error.Fail()) + return error.takeError(); + + // The connection is already queued, so a short timeout is sufficient. + Socket *accept_socket = nullptr; + Status error = listen_socket->Accept(std::chrono::seconds(1), accept_socket); + // Once both ends are connected the bound socket file is no longer needed. + llvm::sys::fs::remove(path); + if (error.Fail()) + return error.takeError(); + + return Pair(std::move(connect_socket), + std::unique_ptr<DomainSocket>( + static_cast<DomainSocket *>(accept_socket))); +#endif // _WIN32 } Status DomainSocket::Connect(llvm::StringRef name) { diff --git a/lldb/tools/lldb-server/lldb-platform.cpp b/lldb/tools/lldb-server/lldb-platform.cpp index ec2ef053241ca..5e1bf651cfd67 100644 --- a/lldb/tools/lldb-server/lldb-platform.cpp +++ b/lldb/tools/lldb-server/lldb-platform.cpp @@ -40,9 +40,7 @@ #include "lldb/Host/OptionParser.h" #include "lldb/Host/Socket.h" #include "lldb/Host/common/TCPSocket.h" -#if LLDB_ENABLE_POSIX #include "lldb/Host/posix/DomainSocket.h" -#endif #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Status.h" @@ -539,7 +537,7 @@ int main_platform(int argc, char *argv[]) { if (gdbserver_port) { socket = std::make_unique<TCPSocket>(sockfd, /*should_close=*/true); } else { -#if LLDB_ENABLE_POSIX +#if LLDB_ENABLE_POSIX || defined(_WIN32) llvm::Expected<std::unique_ptr<DomainSocket>> domain_socket = DomainSocket::FromBoundNativeSocket(sockfd, /*should_close=*/true); if (!domain_socket) { diff --git a/lldb/unittests/Host/SocketTest.cpp b/lldb/unittests/Host/SocketTest.cpp index 45dcce83ca0a7..d080946108028 100644 --- a/lldb/unittests/Host/SocketTest.cpp +++ b/lldb/unittests/Host/SocketTest.cpp @@ -93,6 +93,11 @@ TEST_F(SocketTest, CreatePair) { functional_protocols.push_back(Socket::ProtocolUnixDomain); functional_protocols.push_back(Socket::ProtocolUnixAbstract); } +#elif defined(_WIN32) + // Windows supports AF_UNIX domain sockets (Windows 10 1803+) but not the + // Linux abstract-namespace variant. + if (HostSupportsDomainSockets()) + functional_protocols.push_back(Socket::ProtocolUnixDomain); #endif for (auto p : functional_protocols) { @@ -111,7 +116,7 @@ TEST_F(SocketTest, CreatePair) { std::vector<Socket::SocketProtocol> erroring_protocols = { #if !LLDB_ENABLE_POSIX - Socket::ProtocolUnixDomain, + // Windows has AF_UNIX domain sockets but no abstract-namespace sockets. Socket::ProtocolUnixAbstract, #endif }; @@ -121,7 +126,7 @@ TEST_F(SocketTest, CreatePair) { } } -#if LLDB_ENABLE_POSIX +#if LLDB_ENABLE_POSIX || defined(_WIN32) TEST_F(SocketTest, DomainListenConnectAccept) { if (!HostSupportsDomainSockets()) GTEST_SKIP() << "Domain sockets unavailable"; @@ -397,7 +402,9 @@ TEST_F(SocketTest, DomainGetConnectURI) { EXPECT_EQ(socket_b_up->GetRemoteConnectionURI(), ""); } +#endif +#if LLDB_ENABLE_POSIX || defined(_WIN32) TEST_F(SocketTest, DomainSocketFromBoundNativeSocket) { if (!HostSupportsDomainSockets()) GTEST_SKIP() << "Domain sockets unavailable"; diff --git a/lldb/unittests/TestingSupport/Host/SocketTestUtilities.cpp b/lldb/unittests/TestingSupport/Host/SocketTestUtilities.cpp index 2c5e310ea9a9b..5b66004a7a33e 100644 --- a/lldb/unittests/TestingSupport/Host/SocketTestUtilities.cpp +++ b/lldb/unittests/TestingSupport/Host/SocketTestUtilities.cpp @@ -71,7 +71,7 @@ bool lldb_private::CreateTCPConnectedSockets( return true; } -#if LLDB_ENABLE_POSIX +#if LLDB_ENABLE_POSIX || defined(_WIN32) void lldb_private::CreateDomainConnectedSockets( llvm::StringRef path, std::unique_ptr<DomainSocket> *socket_a_up, std::unique_ptr<DomainSocket> *socket_b_up) { @@ -148,16 +148,17 @@ llvm::Expected<std::string> lldb_private::GetLocalhostIP() { "Neither IPv4 nor IPv6 appear to be supported"); } -#if LLDB_ENABLE_POSIX +#if LLDB_ENABLE_POSIX || defined(_WIN32) bool lldb_private::HostSupportsDomainSockets() { llvm::SmallString<64> Path; if (llvm::sys::fs::createUniqueDirectory("SocketTestCanary", Path)) return false; + auto cleanup_dir = Path; llvm::sys::path::append(Path, "test"); DomainSocket sock(true); Status status = sock.Listen(Path, 1); llvm::sys::fs::remove(Path); - llvm::sys::fs::remove(Path.str().rsplit('/').first); + llvm::sys::fs::remove(cleanup_dir); return status.Success(); } #endif diff --git a/lldb/unittests/TestingSupport/Host/SocketTestUtilities.h b/lldb/unittests/TestingSupport/Host/SocketTestUtilities.h index a7c9aee162e65..1dc57b7992863 100644 --- a/lldb/unittests/TestingSupport/Host/SocketTestUtilities.h +++ b/lldb/unittests/TestingSupport/Host/SocketTestUtilities.h @@ -21,7 +21,7 @@ #include "llvm/Support/Path.h" #include "llvm/Testing/Support/Error.h" -#if LLDB_ENABLE_POSIX +#if LLDB_ENABLE_POSIX || defined(_WIN32) #include "lldb/Host/posix/DomainSocket.h" #endif @@ -34,7 +34,7 @@ void CreateConnectedSockets( bool CreateTCPConnectedSockets(std::string listen_remote_ip, std::unique_ptr<TCPSocket> *a_up, std::unique_ptr<TCPSocket> *b_up); -#if LLDB_ENABLE_POSIX +#if LLDB_ENABLE_POSIX || defined(_WIN32) void CreateDomainConnectedSockets(llvm::StringRef path, std::unique_ptr<DomainSocket> *a_up, std::unique_ptr<DomainSocket> *b_up); @@ -42,7 +42,7 @@ void CreateDomainConnectedSockets(llvm::StringRef path, bool HostSupportsIPv6(); bool HostSupportsIPv4(); -#if LLDB_ENABLE_POSIX +#if LLDB_ENABLE_POSIX || defined(_WIN32) bool HostSupportsDomainSockets(); #endif _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
