diff --git a/src/tools/windows/converter/ms_symbol_server_converter.cc b/src/tools/windows/converter/ms_symbol_server_converter.cc index 4b0dcf6e..2b40faee 100644 --- a/src/tools/windows/converter/ms_symbol_server_converter.cc +++ b/src/tools/windows/converter/ms_symbol_server_converter.cc @@ -36,6 +36,7 @@ #include #include +#include #include #include @@ -53,6 +54,31 @@ #define SYMOPT_NO_PROMPTS 0x00080000 #endif // SYMOPT_NO_PROMPTS +namespace { + +std::wstring GetExeDirectory() { + wchar_t directory[MAX_PATH]; + + // Get path to this process exe. + DWORD result = GetModuleFileName(/*hModule=*/nullptr, directory, MAX_PATH); + if (result <= 0 || result == MAX_PATH) { + fprintf(stderr, + "GetExeDirectory: failed to get path to process exe.\n"); + return L""; + } + HRESULT hr = PathCchRemoveFileSpec(directory, result + 1); + if (hr != S_OK) { + fprintf(stderr, + "GetExeDirectory: failed to remove basename from path '%ls'.\n", + directory); + return L""; + } + + return std::wstring(directory); +} + +} // namespace + namespace google_breakpad { // Use sscanf_s if it is available, to quench the warning about scanf being @@ -160,6 +186,34 @@ class AutoSymSrv { bool Initialize(HANDLE process, char *path, bool invade_process) { process_ = process; + + // TODO(nbilling): Figure out why dbghelp.dll is being loaded from + // system32/SysWOW64 before exe folder. + + // Attempt to locate and load dbghelp.dll beside the process exe. This is + // somewhat of a workaround to loader delay load behavior that is occurring + // when we call into symsrv APIs. dbghelp.dll must be loaded from beside + // the process exe so that we are guaranteed to find symsrv.dll alongside + // dbghelp.dll (a security requirement of dbghelp.dll) and so that the + // symsrv.dll file that is loaded has a symsrv.yes file alongside it (a + // requirement of symsrv.dll when accessing Microsoft-owned symbol + // servers). + // 'static local' because we don't care about the value but we need the + // initialization to happen exactly once. + static HMODULE dbghelp_module = [] () -> HMODULE { + std::wstring exe_directory = GetExeDirectory(); + if (exe_directory.empty()) { + return nullptr; + } + std::wstring dbghelp_path = exe_directory + L"\\dbghelp.dll"; + return LoadLibrary(dbghelp_path.c_str()); + }(); + if (dbghelp_module == nullptr) { + fprintf(stderr, + "AutoSymSrv::Initialize: failed to load dbghelp.dll beside exe."); + return false; + } + initialized_ = SymInitialize(process, path, invade_process) == TRUE; return initialized_; }