Explicitly LoadLibrary dbghelp.dll in symbol converter.
- This is a workaround to an issue with gn/clang build of Windows symbol converter where dbghelp.dll is loaded from system32/syswow64 instead of alongside the process exe. - Why do we care where dbghelp.dll is loaded from? Two considerations: 1. dbghelp.dll will only load symsrv.dll from the directory where it resides. 2. symsrv.dll requires a file called "symsrv.yes" to be in the directory where it resides in order to work with MS symbol stores. Therefore if we load dbghelp.dll from syswow64, then we must also ensure there is a symsrv.dll and symsrv.yes file in syswow64. Change-Id: Ia283a2c11e276c855a48157aa7be77897af4b02e Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/1680670 Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Ivan Penkov <ivanpe@chromium.org>
This commit is contained in:
parent
a5a607b0b0
commit
9cafb376eb
1 changed files with 54 additions and 0 deletions
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
#include <pathcch.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
@ -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_;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue