https://github.com/charles-zablit updated 
https://github.com/llvm/llvm-project/pull/206985

>From 8b897129938714430e907c8e7780c8df622b0f87 Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Wed, 1 Jul 2026 14:44:35 +0100
Subject: [PATCH 1/7] [lldb] Extract URI schemes manually to support Windows
 paths

---
 .../gdb-server/PlatformRemoteGDBServer.cpp    | 24 ++++++++++++++-----
 .../GDBRemoteCommunicationServerLLGS.cpp      | 12 ++++++----
 2 files changed, 25 insertions(+), 11 deletions(-)

diff --git 
a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp 
b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 1f69ef5f3f6ca..55fdc94df4b99 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -19,6 +19,7 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Host/PosixApi.h"
+#include "lldb/Host/Socket.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/FileSpec.h"
@@ -226,13 +227,24 @@ Status PlatformRemoteGDBServer::ConnectRemote(Args &args) 
{
   if (!url)
     return Status::FromErrorString("URL is null.");
 
-  std::optional<URI> parsed_url = URI::Parse(url);
-  if (!parsed_url)
-    return Status::FromErrorStringWithFormat("Invalid URL: %s", url);
+  // Parse the scheme manually because URI::parse does not handle Windows 
paths.
+  llvm::StringRef scheme = llvm::StringRef(url).split("://").first;
+  std::optional<Socket::ProtocolModePair> protocol_and_mode =
+      Socket::GetProtocolAndMode(scheme);
+  if (protocol_and_mode &&
+      (protocol_and_mode->first == Socket::ProtocolUnixDomain ||
+       protocol_and_mode->first == Socket::ProtocolUnixAbstract)) {
+    m_platform_scheme = scheme.str();
+    m_platform_hostname = "";
+  } else {
+    std::optional<URI> parsed_url = URI::Parse(url);
+    if (!parsed_url)
+      return Status::FromErrorStringWithFormat("Invalid URL: %s", url);
 
-  // We're going to reuse the hostname when we connect to the debugserver.
-  m_platform_scheme = parsed_url->scheme.str();
-  m_platform_hostname = parsed_url->hostname.str();
+    // We're going to reuse the hostname when we connect to the debugserver.
+    m_platform_scheme = parsed_url->scheme.str();
+    m_platform_hostname = parsed_url->hostname.str();
+  }
 
   auto client_up =
       std::make_unique<process_gdb_remote::GDBRemoteCommunicationClient>();
diff --git 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 769705588fbdf..948e939a02613 100644
--- 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -4560,20 +4560,22 @@ void 
GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse(
 std::string
 lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg,
                                                bool reverse_connect) {
-  // Try parsing the argument as URL.
-  if (std::optional<URI> url = URI::Parse(url_arg)) {
+  // Parse the scheme manually because URI::parse does not handle Windows 
paths.
+  constexpr llvm::StringRef kSchemeSep = "://";
+  if (size_t pos = url_arg.find(kSchemeSep); pos != llvm::StringRef::npos) {
     if (reverse_connect)
       return url_arg.str();
 
     // Translate the scheme from LLGS notation to ConnectionFileDescriptor.
     // If the scheme doesn't match any, pass it through to support using CFD
     // schemes directly.
-    std::string new_url = llvm::StringSwitch<std::string>(url->scheme)
+    llvm::StringRef scheme = url_arg.substr(0, pos);
+    std::string new_url = llvm::StringSwitch<std::string>(scheme)
                               .Case("tcp", "listen")
                               .Case("unix", "unix-accept")
                               .Case("unix-abstract", "unix-abstract-accept")
-                              .Default(url->scheme.str());
-    llvm::append_range(new_url, url_arg.substr(url->scheme.size()));
+                              .Default(scheme.str());
+    llvm::append_range(new_url, url_arg.substr(scheme.size()));
     return new_url;
   }
 

>From 52b7d2cf85f6ffaaacf5d61720c9fd4d40a93d11 Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Wed, 1 Jul 2026 16:38:40 +0100
Subject: [PATCH 2/7] inline variable

---
 .../Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp    | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 948e939a02613..f550c82d0885f 100644
--- 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -4561,8 +4561,7 @@ std::string
 lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg,
                                                bool reverse_connect) {
   // Parse the scheme manually because URI::parse does not handle Windows 
paths.
-  constexpr llvm::StringRef kSchemeSep = "://";
-  if (size_t pos = url_arg.find(kSchemeSep); pos != llvm::StringRef::npos) {
+  if (size_t pos = url_arg.find("://"); pos != llvm::StringRef::npos) {
     if (reverse_connect)
       return url_arg.str();
 

>From b58e5d550d04029a021e9b728408f75df77db57a Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Wed, 1 Jul 2026 17:00:55 +0100
Subject: [PATCH 3/7] add comment

---
 .../Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp      | 1 +
 1 file changed, 1 insertion(+)

diff --git 
a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp 
b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 55fdc94df4b99..22d30d660d9c3 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -235,6 +235,7 @@ Status PlatformRemoteGDBServer::ConnectRemote(Args &args) {
       (protocol_and_mode->first == Socket::ProtocolUnixDomain ||
        protocol_and_mode->first == Socket::ProtocolUnixAbstract)) {
     m_platform_scheme = scheme.str();
+    // The URI contains a filepath, the hostname is empty.
     m_platform_hostname = "";
   } else {
     std::optional<URI> parsed_url = URI::Parse(url);

>From 46672423e0c244d84a47dd360e2fb50ffd1f3cfd Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Fri, 17 Jul 2026 10:56:32 +0100
Subject: [PATCH 4/7] use the RFC 8089 form

---
 lldb/include/lldb/Host/common/DomainSocket.h  | 11 +++++
 lldb/source/Host/common/DomainSocket.cpp      | 42 +++++++++++++++----
 .../gdb-server/PlatformRemoteGDBServer.cpp    | 25 +++--------
 .../GDBRemoteCommunicationServerLLGS.cpp      | 11 +++--
 lldb/unittests/Host/SocketTest.cpp            | 29 +++++++++++--
 .../GDBRemoteCommunicationServerLLGSTest.cpp  |  5 +++
 lldb/unittests/Utility/UriParserTest.cpp      |  5 +++
 7 files changed, 92 insertions(+), 36 deletions(-)

diff --git a/lldb/include/lldb/Host/common/DomainSocket.h 
b/lldb/include/lldb/Host/common/DomainSocket.h
index 4d2b657cf88e4..fa96d38316851 100644
--- a/lldb/include/lldb/Host/common/DomainSocket.h
+++ b/lldb/include/lldb/Host/common/DomainSocket.h
@@ -45,6 +45,17 @@ class DomainSocket : public Socket {
   static llvm::Expected<std::unique_ptr<DomainSocket>>
   FromBoundNativeSocket(NativeSocket sockfd, bool should_close);
 
+  /// Convert between a native filesystem path and the path component of a
+  /// domain-socket URI.
+  /// On Windows a drive-letter path (e.g. "C:\\dir\\sock") is not a valid URI
+  /// authority, so it is carried in the RFC 8089 file-URI form "/C:/dir/sock"
+  /// (leading slash, forward slashes). On other platforms the path is already 
a
+  /// valid URI path and is returned unchanged.
+  /// @{
+  static std::string NativePathToURIPath(llvm::StringRef path);
+  static std::string URIPathToNativePath(llvm::StringRef path);
+  /// @}
+
 protected:
   DomainSocket(SocketProtocol protocol);
   DomainSocket(SocketProtocol protocol, NativeSocket socket, bool 
should_close);
diff --git a/lldb/source/Host/common/DomainSocket.cpp 
b/lldb/source/Host/common/DomainSocket.cpp
index 988b8238a3cce..13b4a8650a6cd 100644
--- a/lldb/source/Host/common/DomainSocket.cpp
+++ b/lldb/source/Host/common/DomainSocket.cpp
@@ -12,10 +12,12 @@
 #include <lldb/Host/linux/AbstractSocket.h>
 #endif
 
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Errno.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 
+#include <algorithm>
 #include <cstddef>
 #include <memory>
 
@@ -32,6 +34,29 @@ using namespace lldb_private;
 static const int kDomain = AF_UNIX;
 static const int kType = SOCK_STREAM;
 
+std::string DomainSocket::NativePathToURIPath(llvm::StringRef path) {
+#ifdef _WIN32
+  if (path.size() >= 2 && llvm::isAlpha(path[0]) && path[1] == ':') {
+    std::string uri_path = "/" + path.str();
+    std::replace(uri_path.begin(), uri_path.end(), '\\', '/');
+    return uri_path;
+  }
+#endif
+  return path.str();
+}
+
+std::string DomainSocket::URIPathToNativePath(llvm::StringRef path) {
+#ifdef _WIN32
+  if (path.size() >= 3 && path[0] == '/' && llvm::isAlpha(path[1]) &&
+      path[2] == ':') {
+    std::string native = path.drop_front().str();
+    std::replace(native.begin(), native.end(), '/', '\\');
+    return native;
+  }
+#endif
+  return path.str();
+}
+
 static bool SetSockAddr(llvm::StringRef name, const size_t name_offset,
                         sockaddr_un *saddr_un, socklen_t &saddr_un_len) {
   if (name.size() + name_offset > sizeof(saddr_un->sun_path))
@@ -79,9 +104,10 @@ DomainSocket::DomainSocket(SocketProtocol protocol, 
NativeSocket socket,
 }
 
 Status DomainSocket::Connect(llvm::StringRef name) {
+  std::string native_name = URIPathToNativePath(name);
   sockaddr_un saddr_un;
   socklen_t saddr_un_len;
-  if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
+  if (!SetSockAddr(native_name, GetNameOffset(), &saddr_un, saddr_un_len))
     return Status::FromErrorString("Failed to set socket address");
 
   Status error;
@@ -97,12 +123,13 @@ Status DomainSocket::Connect(llvm::StringRef name) {
 }
 
 Status DomainSocket::Listen(llvm::StringRef name, int backlog) {
+  std::string native_name = URIPathToNativePath(name);
   sockaddr_un saddr_un;
   socklen_t saddr_un_len;
-  if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
+  if (!SetSockAddr(native_name, GetNameOffset(), &saddr_un, saddr_un_len))
     return Status::FromErrorString("Failed to set socket address");
 
-  DeleteSocketFile(name);
+  DeleteSocketFile(native_name);
 
   Status error;
   m_socket = CreateSocket(kDomain, kType, 0, error);
@@ -175,9 +202,9 @@ std::string DomainSocket::GetRemoteConnectionURI() const {
   if (name.empty())
     return name;
 
-  return llvm::formatv(
-      "{0}://{1}",
-      GetNameOffset() == 0 ? "unix-connect" : "unix-abstract-connect", name);
+  if (GetNameOffset() == 0)
+    return llvm::formatv("unix-connect://{0}", NativePathToURIPath(name));
+  return llvm::formatv("unix-abstract-connect://{0}", name);
 }
 
 std::vector<std::string> DomainSocket::GetListeningConnectionURI() const {
@@ -191,7 +218,8 @@ std::vector<std::string> 
DomainSocket::GetListeningConnectionURI() const {
   if (::getsockname(m_socket, (struct sockaddr *)&addr, &addr_len) != 0)
     return {};
 
-  return {llvm::formatv("unix-connect://{0}", addr.sun_path)};
+  return {
+      llvm::formatv("unix-connect://{0}", NativePathToURIPath(addr.sun_path))};
 }
 
 llvm::Expected<std::unique_ptr<DomainSocket>>
diff --git 
a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp 
b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 22d30d660d9c3..1f69ef5f3f6ca 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -19,7 +19,6 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Host/PosixApi.h"
-#include "lldb/Host/Socket.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/FileSpec.h"
@@ -227,25 +226,13 @@ Status PlatformRemoteGDBServer::ConnectRemote(Args &args) 
{
   if (!url)
     return Status::FromErrorString("URL is null.");
 
-  // Parse the scheme manually because URI::parse does not handle Windows 
paths.
-  llvm::StringRef scheme = llvm::StringRef(url).split("://").first;
-  std::optional<Socket::ProtocolModePair> protocol_and_mode =
-      Socket::GetProtocolAndMode(scheme);
-  if (protocol_and_mode &&
-      (protocol_and_mode->first == Socket::ProtocolUnixDomain ||
-       protocol_and_mode->first == Socket::ProtocolUnixAbstract)) {
-    m_platform_scheme = scheme.str();
-    // The URI contains a filepath, the hostname is empty.
-    m_platform_hostname = "";
-  } else {
-    std::optional<URI> parsed_url = URI::Parse(url);
-    if (!parsed_url)
-      return Status::FromErrorStringWithFormat("Invalid URL: %s", url);
+  std::optional<URI> parsed_url = URI::Parse(url);
+  if (!parsed_url)
+    return Status::FromErrorStringWithFormat("Invalid URL: %s", url);
 
-    // We're going to reuse the hostname when we connect to the debugserver.
-    m_platform_scheme = parsed_url->scheme.str();
-    m_platform_hostname = parsed_url->hostname.str();
-  }
+  // We're going to reuse the hostname when we connect to the debugserver.
+  m_platform_scheme = parsed_url->scheme.str();
+  m_platform_hostname = parsed_url->hostname.str();
 
   auto client_up =
       std::make_unique<process_gdb_remote::GDBRemoteCommunicationClient>();
diff --git 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index f550c82d0885f..769705588fbdf 100644
--- 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -4560,21 +4560,20 @@ void 
GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse(
 std::string
 lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg,
                                                bool reverse_connect) {
-  // Parse the scheme manually because URI::parse does not handle Windows 
paths.
-  if (size_t pos = url_arg.find("://"); pos != llvm::StringRef::npos) {
+  // Try parsing the argument as URL.
+  if (std::optional<URI> url = URI::Parse(url_arg)) {
     if (reverse_connect)
       return url_arg.str();
 
     // Translate the scheme from LLGS notation to ConnectionFileDescriptor.
     // If the scheme doesn't match any, pass it through to support using CFD
     // schemes directly.
-    llvm::StringRef scheme = url_arg.substr(0, pos);
-    std::string new_url = llvm::StringSwitch<std::string>(scheme)
+    std::string new_url = llvm::StringSwitch<std::string>(url->scheme)
                               .Case("tcp", "listen")
                               .Case("unix", "unix-accept")
                               .Case("unix-abstract", "unix-abstract-accept")
-                              .Default(scheme.str());
-    llvm::append_range(new_url, url_arg.substr(scheme.size()));
+                              .Default(url->scheme.str());
+    llvm::append_range(new_url, url_arg.substr(url->scheme.size()));
     return new_url;
   }
 
diff --git a/lldb/unittests/Host/SocketTest.cpp 
b/lldb/unittests/Host/SocketTest.cpp
index 45dcce83ca0a7..c7fdea2cc0d26 100644
--- a/lldb/unittests/Host/SocketTest.cpp
+++ b/lldb/unittests/Host/SocketTest.cpp
@@ -161,9 +161,12 @@ TEST_F(SocketTest, DomainListenGetListeningConnectionURI) {
   ASSERT_THAT_ERROR(error.ToError(), llvm::Succeeded());
   ASSERT_TRUE(listen_socket_up->IsValid());
 
-  ASSERT_THAT(
-      listen_socket_up->GetListeningConnectionURI(),
-      testing::ElementsAre(llvm::formatv("unix-connect://{0}", Path).str()));
+  std::string expected_uri =
+      llvm::formatv("unix-connect://{0}",
+                    DomainSocket::NativePathToURIPath(Path))
+          .str();
+  ASSERT_THAT(listen_socket_up->GetListeningConnectionURI(),
+              testing::ElementsAre(expected_uri));
 }
 
 TEST_F(SocketTest, DomainMainLoopAccept) {
@@ -392,12 +395,30 @@ TEST_F(SocketTest, DomainGetConnectURI) {
   CreateDomainConnectedSockets(domain_path, &socket_a_up, &socket_b_up);
 
   std::string uri(socket_a_up->GetRemoteConnectionURI());
-  EXPECT_EQ((URI{"unix-connect", "", std::nullopt, domain_path}),
+  std::string expected_path = DomainSocket::NativePathToURIPath(domain_path);
+  EXPECT_EQ((URI{"unix-connect", "", std::nullopt, expected_path}),
             URI::Parse(uri));
 
   EXPECT_EQ(socket_b_up->GetRemoteConnectionURI(), "");
 }
 
+TEST_F(SocketTest, DomainSocketPathURIConversion) {
+  // Paths that are already valid URI paths (no drive letter) are unchanged on
+  // every platform.
+  EXPECT_EQ(DomainSocket::NativePathToURIPath("/tmp/foo"), "/tmp/foo");
+  EXPECT_EQ(DomainSocket::URIPathToNativePath("/tmp/foo"), "/tmp/foo");
+
+#ifdef _WIN32
+  // A Windows drive-letter path round-trips through the RFC 8089 "/C:/..."
+  // URI form.
+  EXPECT_EQ(DomainSocket::NativePathToURIPath("C:\\dir\\sock"), 
"/C:/dir/sock");
+  EXPECT_EQ(DomainSocket::URIPathToNativePath("/C:/dir/sock"), 
"C:\\dir\\sock");
+  EXPECT_EQ(DomainSocket::URIPathToNativePath(
+                DomainSocket::NativePathToURIPath("C:\\dir\\sock")),
+            "C:\\dir\\sock");
+#endif
+}
+
 TEST_F(SocketTest, DomainSocketFromBoundNativeSocket) {
   if (!HostSupportsDomainSockets())
     GTEST_SKIP() << "Domain sockets unavailable";
diff --git 
a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationServerLLGSTest.cpp 
b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationServerLLGSTest.cpp
index b4704606e8692..d2cd5bf8df327 100644
--- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationServerLLGSTest.cpp
+++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationServerLLGSTest.cpp
@@ -31,6 +31,11 @@ TEST(GDBRemoteCommunicationServerLLGSTest, LLGSArgToURL) {
   EXPECT_EQ(LLGSArgToURL("unix-abstract://foo", false),
             "unix-abstract-accept://foo");
 
+  // LLGS legacy listen URLs carrying a Windows drive-letter path (in RFC 8089
+  // "/C:/..." form) should be converted, keeping the path intact.
+  EXPECT_EQ(LLGSArgToURL("unix:///C:/Users/a/foo", false),
+            "unix-accept:///C:/Users/a/foo");
+
   // LLGS listen host:port pairs should be converted to listen://
   EXPECT_EQ(LLGSArgToURL("127.0.0.1:1234", false), "listen://127.0.0.1:1234");
   EXPECT_EQ(LLGSArgToURL("[::1]:1234", false), "listen://[::1]:1234");
diff --git a/lldb/unittests/Utility/UriParserTest.cpp 
b/lldb/unittests/Utility/UriParserTest.cpp
index 9923d3a9af936..34ea314149660 100644
--- a/lldb/unittests/Utility/UriParserTest.cpp
+++ b/lldb/unittests/Utility/UriParserTest.cpp
@@ -24,6 +24,11 @@ TEST(UriParserTest, LongPath) {
             URI::Parse("x://y/abc/def/xyz"));
 }
 
+TEST(UriParserTest, WindowsDriveLetterPath) {
+  EXPECT_EQ((URI{"unix-connect", "", std::nullopt, "/C:/Users/a/sock"}),
+            URI::Parse("unix-connect:///C:/Users/a/sock"));
+}
+
 TEST(UriParserTest, TypicalPortPathIPv4) {
   EXPECT_EQ((URI{"connect", "192.168.100.132", 5432, "/"}),
             URI::Parse("connect://192.168.100.132:5432/"));

>From 39a477437c017e5d7c22ce3a6b9391c3390267e0 Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Fri, 17 Jul 2026 12:09:03 +0100
Subject: [PATCH 5/7] handle UNC paths in domain-socket URI conversion

---
 lldb/include/lldb/Host/common/DomainSocket.h |  6 ++++--
 lldb/source/Host/common/DomainSocket.cpp     | 16 ++++++++++++++++
 lldb/unittests/Host/SocketTest.cpp           |  9 +++++++++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/lldb/include/lldb/Host/common/DomainSocket.h 
b/lldb/include/lldb/Host/common/DomainSocket.h
index fa96d38316851..9a2aedc21e1f7 100644
--- a/lldb/include/lldb/Host/common/DomainSocket.h
+++ b/lldb/include/lldb/Host/common/DomainSocket.h
@@ -49,8 +49,10 @@ class DomainSocket : public Socket {
   /// domain-socket URI.
   /// On Windows a drive-letter path (e.g. "C:\\dir\\sock") is not a valid URI
   /// authority, so it is carried in the RFC 8089 file-URI form "/C:/dir/sock"
-  /// (leading slash, forward slashes). On other platforms the path is already 
a
-  /// valid URI path and is returned unchanged.
+  /// (leading slash, forward slashes). A UNC path (e.g. "\\\\server\\share")
+  /// only needs its backslashes replaced to become the URI path
+  /// "//server/share". On other platforms the path is already a valid URI path
+  /// and is returned unchanged.
   /// @{
   static std::string NativePathToURIPath(llvm::StringRef path);
   static std::string URIPathToNativePath(llvm::StringRef path);
diff --git a/lldb/source/Host/common/DomainSocket.cpp 
b/lldb/source/Host/common/DomainSocket.cpp
index 13b4a8650a6cd..666ec54046761 100644
--- a/lldb/source/Host/common/DomainSocket.cpp
+++ b/lldb/source/Host/common/DomainSocket.cpp
@@ -36,23 +36,39 @@ static const int kType = SOCK_STREAM;
 
 std::string DomainSocket::NativePathToURIPath(llvm::StringRef path) {
 #ifdef _WIN32
+  // A drive-letter path (e.g. "C:\\dir\\sock") is not a valid URI authority, 
so
+  // it is carried in the RFC 8089 URI form "/C:/dir/sock".
   if (path.size() >= 2 && llvm::isAlpha(path[0]) && path[1] == ':') {
     std::string uri_path = "/" + path.str();
     std::replace(uri_path.begin(), uri_path.end(), '\\', '/');
     return uri_path;
   }
+  // A UNC path (e.g. "\\\\server\\share") is already anchored by its leading
+  // slashes.
+  if (path.starts_with("\\\\")) {
+    std::string uri_path = path.str();
+    std::replace(uri_path.begin(), uri_path.end(), '\\', '/');
+    return uri_path;
+  }
 #endif
   return path.str();
 }
 
 std::string DomainSocket::URIPathToNativePath(llvm::StringRef path) {
 #ifdef _WIN32
+  // Reverse of the drive-letter mapping: "/C:/dir/sock" -> "C:\\dir\\sock".
   if (path.size() >= 3 && path[0] == '/' && llvm::isAlpha(path[1]) &&
       path[2] == ':') {
     std::string native = path.drop_front().str();
     std::replace(native.begin(), native.end(), '/', '\\');
     return native;
   }
+  // Reverse of the UNC mapping: "//server/share" -> "\\\\server\\share".
+  if (path.starts_with("//")) {
+    std::string native = path.str();
+    std::replace(native.begin(), native.end(), '/', '\\');
+    return native;
+  }
 #endif
   return path.str();
 }
diff --git a/lldb/unittests/Host/SocketTest.cpp 
b/lldb/unittests/Host/SocketTest.cpp
index c7fdea2cc0d26..5e40cdcd333f8 100644
--- a/lldb/unittests/Host/SocketTest.cpp
+++ b/lldb/unittests/Host/SocketTest.cpp
@@ -416,6 +416,15 @@ TEST_F(SocketTest, DomainSocketPathURIConversion) {
   EXPECT_EQ(DomainSocket::URIPathToNativePath(
                 DomainSocket::NativePathToURIPath("C:\\dir\\sock")),
             "C:\\dir\\sock");
+
+  // A Windows UNC path round-trips by swapping backslashes for forward 
slashes.
+  EXPECT_EQ(DomainSocket::NativePathToURIPath("\\\\server\\share\\sock"),
+            "//server/share/sock");
+  EXPECT_EQ(DomainSocket::URIPathToNativePath("//server/share/sock"),
+            "\\\\server\\share\\sock");
+  
EXPECT_EQ(DomainSocket::URIPathToNativePath(DomainSocket::NativePathToURIPath(
+                "\\\\server\\share\\sock")),
+            "\\\\server\\share\\sock");
 #endif
 }
 

>From 29da0dba645ae8b9a8b1ffc86f0120a58070c8c0 Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Fri, 17 Jul 2026 15:27:44 +0100
Subject: [PATCH 6/7] make domain-socket path/URI conversion host-independent

---
 lldb/include/lldb/Host/common/DomainSocket.h | 15 ++++++++-------
 lldb/source/Host/common/DomainSocket.cpp     |  4 ----
 lldb/unittests/Host/SocketTest.cpp           |  9 +++------
 3 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/lldb/include/lldb/Host/common/DomainSocket.h 
b/lldb/include/lldb/Host/common/DomainSocket.h
index 9a2aedc21e1f7..65850e6777593 100644
--- a/lldb/include/lldb/Host/common/DomainSocket.h
+++ b/lldb/include/lldb/Host/common/DomainSocket.h
@@ -46,13 +46,14 @@ class DomainSocket : public Socket {
   FromBoundNativeSocket(NativeSocket sockfd, bool should_close);
 
   /// Convert between a native filesystem path and the path component of a
-  /// domain-socket URI.
-  /// On Windows a drive-letter path (e.g. "C:\\dir\\sock") is not a valid URI
-  /// authority, so it is carried in the RFC 8089 file-URI form "/C:/dir/sock"
-  /// (leading slash, forward slashes). A UNC path (e.g. "\\\\server\\share")
-  /// only needs its backslashes replaced to become the URI path
-  /// "//server/share". On other platforms the path is already a valid URI path
-  /// and is returned unchanged.
+  /// domain-socket URI. This is a pure, content-driven string transformation
+  /// (independent of the build host) so that, for example, a Unix build of
+  /// LLDB remote debugging a Windows target can still interpret Windows paths.
+  /// A drive-letter path (e.g. "C:\\dir\\sock") is not a valid URI authority,
+  /// so it is carried in the RFC 8089 file-URI form "/C:/dir/sock" (leading
+  /// slash, forward slashes). A UNC path (e.g. "\\\\server\\share") only needs
+  /// its backslashes replaced to become the URI path "//server/share". Any
+  /// other path is already a valid URI path and is returned unchanged.
   /// @{
   static std::string NativePathToURIPath(llvm::StringRef path);
   static std::string URIPathToNativePath(llvm::StringRef path);
diff --git a/lldb/source/Host/common/DomainSocket.cpp 
b/lldb/source/Host/common/DomainSocket.cpp
index 666ec54046761..28ec1b7d25dae 100644
--- a/lldb/source/Host/common/DomainSocket.cpp
+++ b/lldb/source/Host/common/DomainSocket.cpp
@@ -35,7 +35,6 @@ static const int kDomain = AF_UNIX;
 static const int kType = SOCK_STREAM;
 
 std::string DomainSocket::NativePathToURIPath(llvm::StringRef path) {
-#ifdef _WIN32
   // A drive-letter path (e.g. "C:\\dir\\sock") is not a valid URI authority, 
so
   // it is carried in the RFC 8089 URI form "/C:/dir/sock".
   if (path.size() >= 2 && llvm::isAlpha(path[0]) && path[1] == ':') {
@@ -50,12 +49,10 @@ std::string 
DomainSocket::NativePathToURIPath(llvm::StringRef path) {
     std::replace(uri_path.begin(), uri_path.end(), '\\', '/');
     return uri_path;
   }
-#endif
   return path.str();
 }
 
 std::string DomainSocket::URIPathToNativePath(llvm::StringRef path) {
-#ifdef _WIN32
   // Reverse of the drive-letter mapping: "/C:/dir/sock" -> "C:\\dir\\sock".
   if (path.size() >= 3 && path[0] == '/' && llvm::isAlpha(path[1]) &&
       path[2] == ':') {
@@ -69,7 +66,6 @@ std::string DomainSocket::URIPathToNativePath(llvm::StringRef 
path) {
     std::replace(native.begin(), native.end(), '/', '\\');
     return native;
   }
-#endif
   return path.str();
 }
 
diff --git a/lldb/unittests/Host/SocketTest.cpp 
b/lldb/unittests/Host/SocketTest.cpp
index 5e40cdcd333f8..cdc02e96f40b7 100644
--- a/lldb/unittests/Host/SocketTest.cpp
+++ b/lldb/unittests/Host/SocketTest.cpp
@@ -403,12 +403,10 @@ TEST_F(SocketTest, DomainGetConnectURI) {
 }
 
 TEST_F(SocketTest, DomainSocketPathURIConversion) {
-  // Paths that are already valid URI paths (no drive letter) are unchanged on
-  // every platform.
+  // Paths that are already valid URI paths (no drive letter) are unchanged.
   EXPECT_EQ(DomainSocket::NativePathToURIPath("/tmp/foo"), "/tmp/foo");
   EXPECT_EQ(DomainSocket::URIPathToNativePath("/tmp/foo"), "/tmp/foo");
 
-#ifdef _WIN32
   // A Windows drive-letter path round-trips through the RFC 8089 "/C:/..."
   // URI form.
   EXPECT_EQ(DomainSocket::NativePathToURIPath("C:\\dir\\sock"), 
"/C:/dir/sock");
@@ -422,10 +420,9 @@ TEST_F(SocketTest, DomainSocketPathURIConversion) {
             "//server/share/sock");
   EXPECT_EQ(DomainSocket::URIPathToNativePath("//server/share/sock"),
             "\\\\server\\share\\sock");
-  
EXPECT_EQ(DomainSocket::URIPathToNativePath(DomainSocket::NativePathToURIPath(
-                "\\\\server\\share\\sock")),
+  EXPECT_EQ(DomainSocket::URIPathToNativePath(
+                DomainSocket::NativePathToURIPath("\\\\server\\share\\sock")),
             "\\\\server\\share\\sock");
-#endif
 }
 
 TEST_F(SocketTest, DomainSocketFromBoundNativeSocket) {

>From 78d1c7b28801bb476771904ea135da54d5b93778 Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Fri, 17 Jul 2026 15:30:14 +0100
Subject: [PATCH 7/7] add UNC path tests for URI parsing and LLGS URL
 conversion

---
 .../gdb-remote/GDBRemoteCommunicationServerLLGSTest.cpp      | 4 ++++
 lldb/unittests/Utility/UriParserTest.cpp                     | 5 +++++
 2 files changed, 9 insertions(+)

diff --git 
a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationServerLLGSTest.cpp 
b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationServerLLGSTest.cpp
index d2cd5bf8df327..9018cbc83f5d5 100644
--- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationServerLLGSTest.cpp
+++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationServerLLGSTest.cpp
@@ -36,6 +36,10 @@ TEST(GDBRemoteCommunicationServerLLGSTest, LLGSArgToURL) {
   EXPECT_EQ(LLGSArgToURL("unix:///C:/Users/a/foo", false),
             "unix-accept:///C:/Users/a/foo");
 
+  // Same for a Windows UNC path (in "//server/share/..." form).
+  EXPECT_EQ(LLGSArgToURL("unix:////server/share/foo", false),
+            "unix-accept:////server/share/foo");
+
   // LLGS listen host:port pairs should be converted to listen://
   EXPECT_EQ(LLGSArgToURL("127.0.0.1:1234", false), "listen://127.0.0.1:1234");
   EXPECT_EQ(LLGSArgToURL("[::1]:1234", false), "listen://[::1]:1234");
diff --git a/lldb/unittests/Utility/UriParserTest.cpp 
b/lldb/unittests/Utility/UriParserTest.cpp
index 34ea314149660..da3f5a978dcea 100644
--- a/lldb/unittests/Utility/UriParserTest.cpp
+++ b/lldb/unittests/Utility/UriParserTest.cpp
@@ -29,6 +29,11 @@ TEST(UriParserTest, WindowsDriveLetterPath) {
             URI::Parse("unix-connect:///C:/Users/a/sock"));
 }
 
+TEST(UriParserTest, WindowsUNCPath) {
+  EXPECT_EQ((URI{"unix-connect", "", std::nullopt, "//server/share/sock"}),
+            URI::Parse("unix-connect:////server/share/sock"));
+}
+
 TEST(UriParserTest, TypicalPortPathIPv4) {
   EXPECT_EQ((URI{"connect", "192.168.100.132", 5432, "/"}),
             URI::Parse("connect://192.168.100.132:5432/"));

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to