Author: Charles Zablit Date: 2026-05-13T16:16:19+02:00 New Revision: 4a8900ff41ca51528d44bc384a9b8dc327ccf8ae
URL: https://github.com/llvm/llvm-project/commit/4a8900ff41ca51528d44bc384a9b8dc327ccf8ae DIFF: https://github.com/llvm/llvm-project/commit/4a8900ff41ca51528d44bc384a9b8dc327ccf8ae.diff LOG: [lldb][windows] add sibling-import fallback to LoadImage helper (#197218) `PlatformWindows::DoLoadImage` injects `__lldb_LoadLibraryHelper` which registers each caller-supplied search path via `AddDllDirectory()` and calls `LoadLibraryExW(name, nullptr, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)`. In practice however, this flow fails for a common layout where a DLL lives next to its sibling imports. LoadLibraryExW returns ERROR_CANT_RESOLVE_FILENAME and the load is reported as unrecoverable, even though every required DLL is present in one of the search paths. This patch adds a fallback after the first `LoadLibraryExW(name, nullptr, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)` call: if it fails, iterate the caller-provided search paths and try `LoadLibraryExW(path, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH)`. `LOAD_WITH_ALTERED_SEARCH_PATH` instructs the Windows loader to add the DLL's own directory to the dependency search. See https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa. --------- Co-authored-by: Nerixyz <[email protected]> Added: Modified: lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp Removed: ################################################################################ diff --git a/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp b/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp index c82841ab029aa..eecbe53d46c24 100644 --- a/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp +++ b/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp @@ -645,6 +645,11 @@ extern "C" { // application should include in its DLL search path. #define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000 +// If this value is used, and lpFileName specifies an absolute path, the system +// uses the alternate file search strategy to find associated executable +// modules. +#define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008 + // WINBASEAPI DWORD WINAPI GetLastError(VOID); /* __declspec(dllimport) */ uint32_t __stdcall GetLastError(); @@ -688,6 +693,32 @@ void * __lldb_LoadLibraryHelper(const wchar_t *name, const wchar_t *paths, result->ImageBase = LoadLibraryExW(name, nullptr, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + + // Fallback: if the AddDllDirectory + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS path + // failed to find the library, iterate the search paths ourselves and + // load by absolute path using LOAD_WITH_ALTERED_SEARCH_PATH, which makes + // Windows use the loaded DLL's own directory to resolve its sibling imports. + if (result->ImageBase == nullptr) { + wchar_t full[4096]; + for (const wchar_t *path = paths; path && *path; path += wcslen(path) + 1) { + size_t plen = wcslen(path); + size_t nlen = wcslen(name); + // Need room for: path + '\\' + name + '\0' + if (plen + 1 + nlen + 1 > 4096) + continue; + wchar_t *p = full; + for (size_t i = 0; i < plen; ++i) + *p++ = path[i]; + *p++ = L'\\'; + for (size_t i = 0; i <= nlen; ++i) // Copy name including trailing '\0'. + *p++ = name[i]; + result->ImageBase = LoadLibraryExW(full, nullptr, + LOAD_WITH_ALTERED_SEARCH_PATH); + if (result->ImageBase != nullptr) + break; + } + } + if (result->ImageBase == nullptr) result->ErrorCode = GetLastError(); else _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
