[Lldb-commits] [lldb] 8167678 - [lldb][windows] support long path in loaded modules cache (#206117)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Sep 16 04:52:41 PDT 2026
Author: Charles Zablit
Date: 2026-09-16T12:52:35+01:00
New Revision: 8167678860e17c5c20aaaf0f863ef70861b3b9f1
URL: https://github.com/llvm/llvm-project/commit/8167678860e17c5c20aaaf0f863ef70861b3b9f1
DIFF: https://github.com/llvm/llvm-project/commit/8167678860e17c5c20aaaf0f863ef70861b3b9f1.diff
LOG: [lldb][windows] support long path in loaded modules cache (#206117)
`NativeProcessWindows::CacheLoadedModules` truncates paths longer than
260 characters.
This patch changes how modules are resolved:
- Query the untruncated image path with `GetModuleFileNameExW`.
- Canonicalize it through a handle to the image file with
`GetFinalPathNameByHandleW(FILE_NAME_NORMALIZED | VOLUME_NAME_DOS)`.
- Strip the extended length prefixes so the cached path matches the
ordinary Win32 form lldb produces elsewhere.
Added:
Modified:
lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
Removed:
################################################################################
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index 0fa3eae2c7ed6..849931eaec372 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -9,6 +9,7 @@
#include "lldb/Host/windows/windows.h"
#include <dbghelp.h>
#include <excpt.h>
+#include <pathcch.h>
#include <psapi.h>
#include "NativeProcessWindows.h"
@@ -359,32 +360,95 @@ Status NativeProcessWindows::RemoveBreakpoint(lldb::addr_t addr,
return RemoveSoftwareBreakpoint(addr);
}
+// Resolve the fully qualified, normalized on disk path of a module loaded in
+// the target process.
+static bool GetLoadedModulePath(HANDLE process, HMODULE module,
+ std::string &path) {
+ std::vector<wchar_t> name(MAX_PATH);
+ DWORD len = 0;
+ while (true) {
+ len = ::GetModuleFileNameExW(process, module, name.data(),
+ static_cast<DWORD>(name.size()));
+ if (len == 0)
+ return false;
+ if (len < name.size())
+ break;
+ if (name.size() >= PATHCCH_MAX_CCH)
+ return false;
+ name.resize(name.size() * 2);
+ }
+
+ std::wstring wpath(name.data(), len);
+
+ // Canonicalize through a handle to the image file so the reported path
+ // matches the on-disk name exactly.
+ AutoHandle file(::CreateFileW(
+ wpath.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
+
+ if (!file.IsValid())
+ return llvm::convertWideToUTF8(wpath, path);
+
+ // Unlike GetModuleFileNameExW, GetFinalPathNameByHandleW reports the buffer
+ // size it needs instead of truncating, so start empty and let the first call
+ // size the buffer rather than guessing.
+ std::vector<wchar_t> full;
+ while (true) {
+ DWORD needed = ::GetFinalPathNameByHandleW(
+ file.get(), full.data(), static_cast<DWORD>(full.size()),
+ FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
+ if (needed == 0)
+ break;
+ if (needed < full.size()) {
+ std::wstring canonical(full.data(), needed);
+ // GetFinalPathNameByHandleW returns an extended-length ("\\?\") path.
+ static const wchar_t kUNCPrefix[] = L"\\\\?\\UNC\\";
+ static const wchar_t kDOSPrefix[] = L"\\\\?\\";
+ if (canonical.rfind(kUNCPrefix, 0) == 0)
+ canonical.replace(0, wcslen(kUNCPrefix), L"\\\\");
+ else if (canonical.rfind(kDOSPrefix, 0) == 0)
+ canonical.erase(0, wcslen(kDOSPrefix));
+ wpath = std::move(canonical);
+ break;
+ }
+ full.resize(needed);
+ }
+
+ return llvm::convertWideToUTF8(wpath, path);
+}
+
Status NativeProcessWindows::CacheLoadedModules() {
Status error;
if (!m_loaded_modules.IsEmpty())
return Status();
- // Retrieve loaded modules by a Target/Module-free implementation.
- AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetID()));
- if (snapshot.IsValid()) {
- MODULEENTRY32W me;
- me.dwSize = sizeof(MODULEENTRY32W);
- if (Module32FirstW(snapshot.get(), &me)) {
- do {
- std::string path;
- if (!llvm::convertWideToUTF8(me.szExePath, path))
- continue;
-
- FileSpec file_spec(path);
- FileSystem::Instance().Resolve(file_spec);
- m_loaded_modules.Add(file_spec, (addr_t)me.modBaseAddr);
- } while (Module32Next(snapshot.get(), &me));
- }
+ AutoHandle process(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ FALSE, GetID()),
+ nullptr);
+ if (!process.IsValid())
+ return Status(::GetLastError(), eErrorTypeWin32);
+
+ AutoHandle snapshot(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetID()));
+ if (!snapshot.IsValid())
+ return Status(::GetLastError(), eErrorTypeWin32);
+
+ MODULEENTRY32W me;
+ me.dwSize = sizeof(MODULEENTRY32W);
+ if (::Module32FirstW(snapshot.get(), &me)) {
+ do {
+ std::string path;
+ if (!GetLoadedModulePath(process.get(), me.hModule, path))
+ continue;
- if (!m_loaded_modules.IsEmpty())
- return Status();
+ FileSpec file_spec(path);
+ FileSystem::Instance().Resolve(file_spec);
+ m_loaded_modules.Add(file_spec, reinterpret_cast<addr_t>(me.modBaseAddr));
+ } while (::Module32NextW(snapshot.get(), &me));
}
+ if (!m_loaded_modules.IsEmpty())
+ return Status();
+
error = Status(::GetLastError(), lldb::ErrorType::eErrorTypeWin32);
return error;
}
More information about the lldb-commits
mailing list