Bug 1586939 - Skip LoadLibraryEx if we're likely to hit the crash in nvd3d9wrap{,x}.dll - r=gregtatum a=reland CLOSED TREE

This is a port of bugs 1607574, 1617188, 1635823 to the Base Profiler.

Differential Revision: https://phabricator.services.mozilla.com/D77014
This commit is contained in:
Gerald Squelart 2020-05-28 03:39:07 +00:00
Родитель c7d245ef9a
Коммит 26045e2d2c
1 изменённых файлов: 47 добавлений и 10 удалений

Просмотреть файл

@ -12,7 +12,9 @@
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "mozilla/WindowsVersion.h"
#include <cctype>
#include <string> #include <string>
#define CV_SIGNATURE 0x53445352 // 'SDSR' #define CV_SIGNATURE 0x53445352 // 'SDSR'
@ -163,11 +165,7 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
} }
for (unsigned int i = 0; i < modulesNum; i++) { for (unsigned int i = 0; i < modulesNum; i++) {
std::string pdbPathStr;
std::string pdbNameStr;
char* pdbName = NULL;
char modulePath[MAX_PATH + 1]; char modulePath[MAX_PATH + 1];
if (!GetModuleFileNameEx(hProcess, hMods[i], modulePath, if (!GetModuleFileNameEx(hProcess, hMods[i], modulePath,
sizeof(modulePath) / sizeof(char))) { sizeof(modulePath) / sizeof(char))) {
continue; continue;
@ -179,6 +177,48 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
continue; continue;
} }
std::string modulePathStr(modulePath);
size_t pos = modulePathStr.find_last_of("\\/");
std::string moduleNameStr = (pos != std::string::npos)
? modulePathStr.substr(pos + 1)
: modulePathStr;
// Hackaround for Bug 1607574. Nvidia's shim driver nvd3d9wrap[x].dll
// detours LoadLibraryExW when it's loaded and the detour function causes
// AV when the code tries to access data pointing to an address within
// unloaded nvinit[x].dll.
// The crashing code is executed when a given parameter is "detoured.dll"
// and OS version is older than 6.2. We hit that crash at the following
// call to LoadLibraryEx even if we specify LOAD_LIBRARY_AS_DATAFILE.
// We work around it by skipping LoadLibraryEx, and add a library info with
// a dummy breakpad id instead.
#if !defined(_M_ARM64)
# if defined(_M_AMD64)
LPCSTR kNvidiaShimDriver = "nvd3d9wrapx.dll";
LPCSTR kNvidiaInitDriver = "nvinitx.dll";
# elif defined(_M_IX86)
LPCSTR kNvidiaShimDriver = "nvd3d9wrap.dll";
LPCSTR kNvidiaInitDriver = "nvinit.dll";
# endif
constexpr std::string_view detoured_dll = "detoured.dll";
if (std::equal(moduleNameStr.cbegin(), moduleNameStr.cend(),
detoured_dll.cbegin(), detoured_dll.cend(),
[](char aModuleChar, char aDetouredChar) {
return std::tolower(aModuleChar) == aDetouredChar;
}) &&
!mozilla::IsWin8OrLater() && ::GetModuleHandle(kNvidiaShimDriver) &&
!::GetModuleHandle(kNvidiaInitDriver)) {
const std::string pdbNameStr = "detoured.pdb";
SharedLibrary shlib((uintptr_t)module.lpBaseOfDll,
(uintptr_t)module.lpBaseOfDll + module.SizeOfImage,
0, // DLLs are always mapped at offset 0 on Windows
"000000000000000000000000000000000", moduleNameStr,
modulePathStr, pdbNameStr, pdbNameStr, "", "");
sharedLibraryInfo.AddSharedLibrary(shlib);
continue;
}
#endif // !defined(_M_ARM64)
std::string breakpadId; std::string breakpadId;
// Load the module again to make sure that its handle will remain // Load the module again to make sure that its handle will remain
// valid as we attempt to read the PDB information from it. We load the // valid as we attempt to read the PDB information from it. We load the
@ -197,6 +237,9 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
MEMORY_BASIC_INFORMATION vmemInfo = {0}; MEMORY_BASIC_INFORMATION vmemInfo = {0};
std::string pdbSig; std::string pdbSig;
uint32_t pdbAge; uint32_t pdbAge;
std::string pdbPathStr;
std::string pdbNameStr;
char* pdbName = nullptr;
if (handleLock && if (handleLock &&
sizeof(vmemInfo) == sizeof(vmemInfo) ==
VirtualQuery(module.lpBaseOfDll, &vmemInfo, sizeof(vmemInfo)) && VirtualQuery(module.lpBaseOfDll, &vmemInfo, sizeof(vmemInfo)) &&
@ -212,12 +255,6 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
(pos != std::string::npos) ? pdbPathStr.substr(pos + 1) : pdbPathStr; (pos != std::string::npos) ? pdbPathStr.substr(pos + 1) : pdbPathStr;
} }
std::string modulePathStr(modulePath);
size_t pos = modulePathStr.find_last_of("\\/");
std::string moduleNameStr = (pos != std::string::npos)
? modulePathStr.substr(pos + 1)
: modulePathStr;
SharedLibrary shlib((uintptr_t)module.lpBaseOfDll, SharedLibrary shlib((uintptr_t)module.lpBaseOfDll,
(uintptr_t)module.lpBaseOfDll + module.SizeOfImage, (uintptr_t)module.lpBaseOfDll + module.SizeOfImage,
0, // DLLs are always mapped at offset 0 on Windows 0, // DLLs are always mapped at offset 0 on Windows