[Lldb-commits] [lldb] 43bd07b - [lldb][Windows] Strip the extended-length prefix from host and process paths (#227373)

via lldb-commits lldb-commits at lists.llvm.org
Wed Sep 30 03:58:42 PDT 2026


Author: Charles Zablit
Date: 2026-09-30T11:58:35+01:00
New Revision: 43bd07b665ec5496750fe12011af5f9d317b22ab

URL: https://github.com/llvm/llvm-project/commit/43bd07b665ec5496750fe12011af5f9d317b22ab
DIFF: https://github.com/llvm/llvm-project/commit/43bd07b665ec5496750fe12011af5f9d317b22ab.diff

LOG: [lldb][Windows] Strip the extended-length prefix from host and process paths (#227373)

This patch introduces a helper function to strip the extended-length
path prefix from windows paths.

Added: 
    lldb/include/lldb/Host/windows/PathUtils.h
    lldb/unittests/Host/windows/PathUtilsTest.cpp

Modified: 
    lldb/source/Host/windows/FileSystem.cpp
    lldb/source/Host/windows/Host.cpp
    lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
    lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
    lldb/unittests/Host/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Host/windows/PathUtils.h b/lldb/include/lldb/Host/windows/PathUtils.h
new file mode 100644
index 0000000000000..2678bd17f8bdb
--- /dev/null
+++ b/lldb/include/lldb/Host/windows/PathUtils.h
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_HOST_WINDOWS_PATHUTILS_H
+#define LLDB_HOST_WINDOWS_PATHUTILS_H
+
+#include "llvm/ADT/StringRef.h"
+
+#include <string>
+
+namespace lldb_private {
+
+/// Convert an extended-length path to a regular DOS path: "\\?\C:\a" becomes
+/// "C:\a" and "\\?\UNC\server\share" becomes "\\server\share". Other paths are
+/// returned unchanged.
+inline std::string StripExtendedLengthPrefix(llvm::StringRef path) {
+  if (path.consume_front("\\\\?\\UNC\\"))
+    return "\\\\" + path.str();
+  path.consume_front("\\\\?\\");
+  return path.str();
+}
+
+} // namespace lldb_private
+
+#endif // LLDB_HOST_WINDOWS_PATHUTILS_H

diff  --git a/lldb/source/Host/windows/FileSystem.cpp b/lldb/source/Host/windows/FileSystem.cpp
index 26e2fdc2a7aa5..f070364151b3f 100644
--- a/lldb/source/Host/windows/FileSystem.cpp
+++ b/lldb/source/Host/windows/FileSystem.cpp
@@ -15,6 +15,7 @@
 
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/windows/AutoHandle.h"
+#include "lldb/Host/windows/PathUtils.h"
 #include "lldb/Host/windows/PosixApi.h"
 
 #include "llvm/Support/ConvertUTF.h"
@@ -66,7 +67,7 @@ Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) {
 
   std::vector<wchar_t> buf(PATH_MAX + 1);
   // Subtract 1 from the path length since this function does not add a null
-  // terminator.
+  // terminator. The result is an extended-length ("\\?\") path.
   DWORD result = ::GetFinalPathNameByHandleW(
       h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
   std::string path;
@@ -75,7 +76,7 @@ Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) {
   else if (!llvm::convertWideToUTF8(buf.data(), path))
     error = Status::FromErrorString(PATH_CONVERSION_ERROR);
   else
-    dst.SetFile(path, FileSpec::Style::native);
+    dst.SetFile(StripExtendedLengthPrefix(path), FileSpec::Style::native);
 
   ::CloseHandle(h);
   return error;

diff  --git a/lldb/source/Host/windows/Host.cpp b/lldb/source/Host/windows/Host.cpp
index eb297df90b928..a9f6e65e38c10 100644
--- a/lldb/source/Host/windows/Host.cpp
+++ b/lldb/source/Host/windows/Host.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Host/windows/AutoHandle.h"
+#include "lldb/Host/windows/PathUtils.h"
 #include "lldb/Host/windows/windows.h"
 #include <cstdio>
 
@@ -77,7 +78,11 @@ static bool GetExecutableForProcess(const AutoHandle &handle,
   DWORD dwSize = buffer.size();
   if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize))
     return false;
-  return llvm::convertWideToUTF8(buffer.data(), path);
+  if (!llvm::convertWideToUTF8(buffer.data(), path))
+    return false;
+  // A process launched through an extended-length path has the "\\?\" prefix.
+  path = StripExtendedLengthPrefix(path);
+  return true;
 }
 
 static void GetProcessExecutableAndTriple(const AutoHandle &handle,

diff  --git a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
index 51d47751ed05d..346e9517f16c6 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
@@ -17,6 +17,7 @@
 #include "lldb/Host/HostProcess.h"
 #include "lldb/Host/HostThread.h"
 #include "lldb/Host/ProcessLaunchInfo.h"
+#include "lldb/Host/windows/PathUtils.h"
 #include "lldb/Target/MemoryRegionInfo.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Utility/FileSpec.h"
@@ -59,7 +60,9 @@ bool ProcessDebugger::IsSystemDLL(llvm::StringRef path) {
   if (windows_prefix.empty())
     return false;
 
-  std::string normalized = path.str();
+  // A module loaded through an extended-length path has the "\\?\" prefix,
+  // which would not match the Windows directory.
+  std::string normalized = StripExtendedLengthPrefix(path);
   NormalizeWindowsPathSeparators(normalized);
   return llvm::StringRef(normalized).starts_with_insensitive(windows_prefix);
 }

diff  --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index d72856bdc8d2c..0490b4ba2573b 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -30,6 +30,7 @@
 #include "lldb/Host/PseudoTerminal.h"
 #include "lldb/Host/windows/ConnectionConPTYWindows.h"
 #include "lldb/Host/windows/HostThreadWindows.h"
+#include "lldb/Host/windows/PathUtils.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/MemoryRegionInfo.h"
@@ -72,7 +73,8 @@ std::string GetProcessExecutableName(HANDLE process_handle) {
   file_name.resize(copied);
   std::string result;
   llvm::convertWideToUTF8(file_name.data(), result);
-  return result;
+  // A process launched through an extended-length path has the "\\?\" prefix.
+  return StripExtendedLengthPrefix(result);
 }
 
 std::string GetProcessExecutableName(DWORD pid) {

diff  --git a/lldb/unittests/Host/CMakeLists.txt b/lldb/unittests/Host/CMakeLists.txt
index 6bbbd4461ff50..285f93de58c60 100644
--- a/lldb/unittests/Host/CMakeLists.txt
+++ b/lldb/unittests/Host/CMakeLists.txt
@@ -38,6 +38,7 @@ endif()
 
 if (CMAKE_SYSTEM_NAME MATCHES "Windows")
   list(APPEND FILES
+    windows/PathUtilsTest.cpp
     windows/StripConPTYSequencesTest.cpp
   )
 endif()

diff  --git a/lldb/unittests/Host/windows/PathUtilsTest.cpp b/lldb/unittests/Host/windows/PathUtilsTest.cpp
new file mode 100644
index 0000000000000..0f11371dec904
--- /dev/null
+++ b/lldb/unittests/Host/windows/PathUtilsTest.cpp
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/windows/PathUtils.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+
+TEST(PathUtilsTest, StripExtendedLengthPrefixDrive) {
+  EXPECT_EQ("C:\\a\\b.exe", StripExtendedLengthPrefix("\\\\?\\C:\\a\\b.exe"));
+}
+
+TEST(PathUtilsTest, StripExtendedLengthPrefixUNC) {
+  EXPECT_EQ("\\\\server\\share\\a.dll",
+            StripExtendedLengthPrefix("\\\\?\\UNC\\server\\share\\a.dll"));
+}
+
+TEST(PathUtilsTest, StripExtendedLengthPrefixUnchanged) {
+  EXPECT_EQ("C:\\a\\b.exe", StripExtendedLengthPrefix("C:\\a\\b.exe"));
+  EXPECT_EQ("\\\\server\\share\\a.dll",
+            StripExtendedLengthPrefix("\\\\server\\share\\a.dll"));
+  EXPECT_EQ("", StripExtendedLengthPrefix(""));
+}


        


More information about the lldb-commits mailing list