Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions onnxruntime/core/platform/windows/dll_load_error.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
Comment thread Fixed
// Licensed under the MIT License.

#include <windows.h>
#include <dbghelp.h>
#include <iostream>
#include <string>
#pragma comment(lib, "dbghelp.lib")

struct HMODULE_Deleter {
typedef HMODULE pointer;
void operator()(HMODULE h) { FreeLibrary(h); }
};

using ModulePtr = std::unique_ptr<HMODULE, HMODULE_Deleter>;

// If a DLL fails to load, this will try loading the DLL and then its dependencies recursively
// until it finds a missing file, then will report which file is missing and what the dependency
// chain is.
std::wstring DetermineLoadLibraryError(const wchar_t* filename_in) {
std::wstring error(L"Error loading");

std::wstring filename{filename_in};
while (filename.size()) {
error += std::wstring(L" \"") + filename + L"\"";

ModulePtr hModule = ModulePtr{LoadLibraryExW(filename.c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES)};
Comment thread
tianleiwu marked this conversation as resolved.
Outdated
if (!hModule) {
error += L" which is missing.";
return error;
}

// Get the address of the Import Directory
ULONG size;
PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hModule.get(), TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size);
if (!importDesc) {
error += L" No import directory found."; // This is unexpected, and I'm not sure how it could happen but we handle it just in case.
return error;
}

// Iterate through the import descriptors to see which dependent DLL can't load
filename.clear();
for (; importDesc->Characteristics; importDesc++) {
Comment thread
tianleiwu marked this conversation as resolved.
Outdated
char* dllName = (char*)((BYTE*)(hModule.get()) + importDesc->Name);
ModulePtr hDepModule{LoadLibrary(dllName)};
if (!hDepModule) {
filename = std::wstring(dllName, dllName + strlen(dllName));
Comment thread
tianleiwu marked this conversation as resolved.
Outdated
error += L" which depends on";
break;
}
}
}
error += L" But no dependency issue could be determined.";
return error;
}
1 change: 1 addition & 0 deletions onnxruntime/core/platform/windows/dll_load_error.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
std::wstring DetermineLoadLibraryError(const wchar_t* filename);
11 changes: 6 additions & 5 deletions onnxruntime/core/platform/windows/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ limitations under the License.
#include <wil/Resource.h>

#include "core/platform/path_lib.h" // for LoopDir()
#include "dll_load_error.h"

EXTERN_C IMAGE_DOS_HEADER __ImageBase;

Expand Down Expand Up @@ -704,17 +705,17 @@ Status WindowsEnv::LoadDynamicLibrary(const PathString& wlibrary_filename, bool
static constexpr DWORD bufferLength = 64 * 1024;
std::wstring s(bufferLength, '\0');
FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error_code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)s.data(),
0, NULL);
bufferLength, NULL);
s.erase(std::remove(s.begin(), s.end(), L'\r'), s.end());
s.erase(std::remove(s.begin(), s.end(), L'\n'), s.end());
std::wostringstream oss;
oss << L"LoadLibrary failed with error " << error_code << L" \"" << s.c_str() << L"\" when trying to load \"" << wlibrary_filename << L"\"";
oss << DetermineLoadLibraryError(wlibrary_filename.c_str()) << L" (Error " << error_code << ": \"" << s.c_str() << "\")";
std::wstring errmsg = oss.str();
// TODO: trim the ending '\r' and/or '\n'
common::Status status(common::ONNXRUNTIME, common::FAIL, ToUTF8String(errmsg));
return status;
}
Expand Down