зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1603974 - Part 1: Implement nt::VirtualQuery consuming only ntdll.dll. r=mhowell
This patch introduces `nt::VirtualQuery` which consumes only ntdll's functions to reduce dependency in `MMPolicy` on kernel32.dll. With this, `MMPolicy` still depends on kernel32.dll, that will be solved by a coming patch. Differential Revision: https://phabricator.services.mozilla.com/D68342 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
d7147ca5b6
Коммит
8bb38652d4
|
@ -48,6 +48,10 @@ if CONFIG['OS_ARCH'] == 'WINNT':
|
|||
'winmm.dll',
|
||||
'user32.dll',
|
||||
]
|
||||
|
||||
OS_LIBS += [
|
||||
'ntdll',
|
||||
]
|
||||
|
||||
DELAYLOAD_DLLS += [
|
||||
'xul.dll',
|
||||
|
|
|
@ -50,6 +50,10 @@ if CONFIG['OS_ARCH'] == 'WINNT':
|
|||
'user32.dll',
|
||||
]
|
||||
|
||||
OS_LIBS += [
|
||||
'ntdll',
|
||||
]
|
||||
|
||||
DELAYLOAD_DLLS += [
|
||||
'xul.dll',
|
||||
]
|
||||
|
|
|
@ -89,6 +89,9 @@ VOID NTAPI RtlAcquireSRWLockShared(PSRWLOCK aLock);
|
|||
VOID NTAPI RtlReleaseSRWLockExclusive(PSRWLOCK aLock);
|
||||
VOID NTAPI RtlReleaseSRWLockShared(PSRWLOCK aLock);
|
||||
|
||||
ULONG NTAPI RtlNtStatusToDosError(NTSTATUS aStatus);
|
||||
VOID NTAPI RtlSetLastWin32Error(DWORD aError);
|
||||
|
||||
NTSTATUS NTAPI NtReadVirtualMemory(HANDLE aProcessHandle, PVOID aBaseAddress,
|
||||
PVOID aBuffer, SIZE_T aNumBytesToRead,
|
||||
PSIZE_T aNumBytesRead);
|
||||
|
@ -1099,6 +1102,8 @@ inline DWORD RtlGetCurrentThreadId() {
|
|||
0xFFFFFFFFUL);
|
||||
}
|
||||
|
||||
const HANDLE kCurrentProcess = reinterpret_cast<HANDLE>(-1);
|
||||
|
||||
inline LauncherResult<DWORD> GetParentProcessId() {
|
||||
struct PROCESS_BASIC_INFORMATION {
|
||||
NTSTATUS ExitStatus;
|
||||
|
@ -1109,7 +1114,6 @@ inline LauncherResult<DWORD> GetParentProcessId() {
|
|||
ULONG_PTR InheritedFromUniqueProcessId;
|
||||
};
|
||||
|
||||
const HANDLE kCurrentProcess = reinterpret_cast<HANDLE>(-1);
|
||||
ULONG returnLength;
|
||||
PROCESS_BASIC_INFORMATION pbi = {};
|
||||
NTSTATUS status =
|
||||
|
@ -1122,6 +1126,30 @@ inline LauncherResult<DWORD> GetParentProcessId() {
|
|||
return static_cast<DWORD>(pbi.InheritedFromUniqueProcessId & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
inline SIZE_T WINAPI VirtualQueryEx(HANDLE aProcess, LPCVOID aAddress,
|
||||
PMEMORY_BASIC_INFORMATION aMemInfo,
|
||||
SIZE_T aMemInfoLen) {
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
return ::VirtualQueryEx(aProcess, aAddress, aMemInfo, aMemInfoLen);
|
||||
#else
|
||||
SIZE_T returnedLength;
|
||||
NTSTATUS status = ::NtQueryVirtualMemory(
|
||||
aProcess, const_cast<PVOID>(aAddress), MemoryBasicInformation, aMemInfo,
|
||||
aMemInfoLen, &returnedLength);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
::RtlSetLastWin32Error(::RtlNtStatusToDosError(status));
|
||||
returnedLength = 0;
|
||||
}
|
||||
return returnedLength;
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
}
|
||||
|
||||
inline SIZE_T WINAPI VirtualQuery(LPCVOID aAddress,
|
||||
PMEMORY_BASIC_INFORMATION aMemInfo,
|
||||
SIZE_T aMemInfoLen) {
|
||||
return nt::VirtualQueryEx(kCurrentProcess, aAddress, aMemInfo, aMemInfoLen);
|
||||
}
|
||||
|
||||
struct DataDirectoryEntry : public _IMAGE_DATA_DIRECTORY {
|
||||
DataDirectoryEntry() : _IMAGE_DATA_DIRECTORY() {}
|
||||
|
||||
|
|
|
@ -74,6 +74,19 @@ PVOID WINAPI MapViewOfFile3(HANDLE FileMapping, HANDLE Process,
|
|||
extern "C" errno_t rand_s(unsigned int* randomValue);
|
||||
#endif // !defined(_CRT_RAND_S)
|
||||
|
||||
// Declaring only the functions we need in NativeNt.h. To include the entire
|
||||
// NativeNt.h causes circular dependency.
|
||||
namespace mozilla {
|
||||
namespace nt {
|
||||
SIZE_T WINAPI VirtualQueryEx(HANDLE aProcess, LPCVOID aAddress,
|
||||
PMEMORY_BASIC_INFORMATION aMemInfo,
|
||||
SIZE_T aMemInfoLen);
|
||||
|
||||
SIZE_T WINAPI VirtualQuery(LPCVOID aAddress, PMEMORY_BASIC_INFORMATION aMemInfo,
|
||||
SIZE_T aMemInfoLen);
|
||||
} // namespace nt
|
||||
} // namespace mozilla
|
||||
|
||||
namespace mozilla {
|
||||
namespace interceptor {
|
||||
|
||||
|
@ -276,7 +289,7 @@ class MOZ_TRIVIAL_CTOR_DTOR MMPolicyBase {
|
|||
// Scan the range for a free chunk that is at least as large as
|
||||
// aDesiredBytesLen
|
||||
while (address <= kMaxPtr &&
|
||||
::VirtualQueryEx(aProcess, address, &mbi, len)) {
|
||||
nt::VirtualQueryEx(aProcess, address, &mbi, len)) {
|
||||
if (mbi.State == MEM_FREE && mbi.RegionSize >= aDesiredBytesLen) {
|
||||
return mbi.BaseAddress;
|
||||
}
|
||||
|
@ -424,7 +437,7 @@ class MOZ_TRIVIAL_CTOR_DTOR MMPolicyInProcess : public MMPolicyBase {
|
|||
*/
|
||||
bool IsPageAccessible(void* aVAddress) const {
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
SIZE_T result = ::VirtualQuery(aVAddress, &mbi, sizeof(mbi));
|
||||
SIZE_T result = nt::VirtualQuery(aVAddress, &mbi, sizeof(mbi));
|
||||
|
||||
return result && mbi.AllocationProtect && (mbi.Type & MEM_IMAGE) &&
|
||||
mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS;
|
||||
|
@ -696,7 +709,7 @@ class MMPolicyOutOfProcess : public MMPolicyBase {
|
|||
*/
|
||||
bool IsPageAccessible(void* aVAddress) const {
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
SIZE_T result = ::VirtualQueryEx(mProcess, aVAddress, &mbi, sizeof(mbi));
|
||||
SIZE_T result = nt::VirtualQueryEx(mProcess, aVAddress, &mbi, sizeof(mbi));
|
||||
|
||||
return result && mbi.AllocationProtect && (mbi.Type & MEM_IMAGE) &&
|
||||
mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS;
|
||||
|
|
|
@ -41,6 +41,29 @@ const char kFailFmt[] =
|
|||
using namespace mozilla;
|
||||
using namespace mozilla::nt;
|
||||
|
||||
bool TestVirtualQuery(HANDLE aProcess, LPCVOID aAddress) {
|
||||
MEMORY_BASIC_INFORMATION info1 = {}, info2 = {};
|
||||
SIZE_T result1 = ::VirtualQueryEx(aProcess, aAddress, &info1, sizeof(info1)),
|
||||
result2 = mozilla::nt::VirtualQueryEx(aProcess, aAddress, &info2,
|
||||
sizeof(info2));
|
||||
if (result1 != result2) {
|
||||
printf("TEST-FAILED | NativeNt | The returned values mismatch\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!result1) {
|
||||
// Both APIs failed.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (memcmp(&info1, &info2, result1) != 0) {
|
||||
printf("TEST-FAILED | NativeNt | The returned structures mismatch\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Need a non-inline function to bypass compiler optimization that the thread
|
||||
// local storage pointer is cached in a register before accessing a thread-local
|
||||
// variable.
|
||||
|
@ -226,6 +249,23 @@ int wmain(int argc, wchar_t* argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
// To test the Ex version of API, we purposely get a real handle
|
||||
// instead of a pseudo handle.
|
||||
nsAutoHandle process(
|
||||
::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId()));
|
||||
if (!process) {
|
||||
printf("TEST-FAILED | NativeNt | OpenProcess() failed - %08lx\n",
|
||||
::GetLastError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test Null page, Heap, Mapped image, and Invalid handle
|
||||
if (!TestVirtualQuery(process, nullptr) || !TestVirtualQuery(process, argv) ||
|
||||
!TestVirtualQuery(process, kNormal) ||
|
||||
!TestVirtualQuery(nullptr, kNormal)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("TEST-PASS | NativeNt | All tests ran successfully\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче