https://github.com/charles-zablit created https://github.com/llvm/llvm-project/pull/206117
Enumerate the loaded modules with `EnumProcessModulesEx` / `GetModuleFileNameExW` instead of the Toolhelp32 snapshot APIs, whose `MODULEENTRY32W::szExePath` is a fixed `MAX_PATH`. A truncated path never matches the module's real FileSpec, so `GetFileLoadAddress()` fails to find modules loaded from deep directories and breakpoints in them never resolve. >From 14ca60bfacc07d7764991caec9b9f5ef68702199 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Fri, 26 Jun 2026 16:52:40 +0100 Subject: [PATCH] [lldb][windows] support long path in loaded modules cache --- .../Windows/Common/NativeProcessWindows.cpp | 65 ++++++++++++++----- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp index 889a2e743c07f..b96d1eec24bab 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" @@ -357,27 +358,57 @@ Status NativeProcessWindows::CacheLoadedModules() { if (!m_loaded_modules.empty()) 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[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); + + std::vector<HMODULE> modules(256); + DWORD bytes_needed = 0; + while (true) { + if (!::EnumProcessModulesEx( + process.get(), modules.data(), + static_cast<DWORD>(modules.size() * sizeof(HMODULE)), &bytes_needed, + LIST_MODULES_ALL)) + return Status(::GetLastError(), eErrorTypeWin32); + size_t count = bytes_needed / sizeof(HMODULE); + if (count <= modules.size()) { + modules.resize(count); + break; } + modules.resize(count); + } - if (!m_loaded_modules.empty()) - return Status(); + for (HMODULE hmod : modules) { + std::vector<wchar_t> name(MAX_PATH); + DWORD len = 0; + while (name.size() <= PATHCCH_MAX_CCH) { + len = ::GetModuleFileNameExW(process.get(), hmod, name.data(), + static_cast<DWORD>(name.size())); + if (len == 0 || len < name.size()) + break; + name.resize(name.size() * 2); + } + if (len == 0) + continue; + + std::string path; + if (!llvm::convertWideToUTF8(std::wstring(name.data(), len), path)) + continue; + + MODULEINFO mi = {}; + if (!::GetModuleInformation(process.get(), hmod, &mi, sizeof(mi))) + continue; + + FileSpec file_spec(path); + FileSystem::Instance().Resolve(file_spec); + m_loaded_modules[file_spec] = reinterpret_cast<addr_t>(mi.lpBaseOfDll); } + if (!m_loaded_modules.empty()) + return Status(); + error = Status(::GetLastError(), lldb::ErrorType::eErrorTypeWin32); return error; } _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
