From 9d9302bb020e24455412595ee516f123a58c3444 Mon Sep 17 00:00:00 2001 From: Scott Graham Date: Wed, 30 Sep 2015 17:20:23 -0700 Subject: [PATCH] win: fix VirtualQueryEx on < win10 On Win10, VirtualQueryEx supports querying the x64 part of WOW64 processes. However, on lower OSs it errors past 2/3G. There's no direct way to retrieve to maximum memory address for processes other than yourself, but fortunately, VirtualQueryEx sets a distinct error code when `lpAddress` exceeds the maximum accessible address, so we can just terminate successfully in that case. R=mark@chromium.org BUG=crashpad:20, crashpad:46 Review URL: https://codereview.chromium.org/1376353002 . --- util/win/process_info.cc | 22 ++++++++++++++-------- util/win/process_info.h | 4 +++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/util/win/process_info.cc b/util/win/process_info.cc index ed5262c7..6d70fa0d 100644 --- a/util/win/process_info.cc +++ b/util/win/process_info.cc @@ -16,6 +16,8 @@ #include +#include + #include "base/logging.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" @@ -253,15 +255,17 @@ bool ReadProcessData(HANDLE process, return true; } -bool ReadMemoryInfo(HANDLE process, ProcessInfo* process_info) { +bool ReadMemoryInfo(HANDLE process, bool is_64_bit, ProcessInfo* process_info) { DCHECK(process_info->memory_info_.empty()); - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - const WinVMAddress min_address = - reinterpret_cast(system_info.lpMinimumApplicationAddress); - const WinVMAddress max_address = - reinterpret_cast(system_info.lpMaximumApplicationAddress); + const WinVMAddress min_address = 0; + // We can't use GetSystemInfo() to get the address space range for another + // process. VirtualQueryEx() will fail with ERROR_INVALID_PARAMETER if the + // address is above the highest memory address accessible to the process, so + // we just probe the entire potential range (2^32 for x86, or 2^64 for x64). + const WinVMAddress max_address = is_64_bit + ? std::numeric_limits::max() + : std::numeric_limits::max(); MEMORY_BASIC_INFORMATION memory_basic_information; for (WinVMAddress address = min_address; address <= max_address; address += memory_basic_information.RegionSize) { @@ -270,6 +274,8 @@ bool ReadMemoryInfo(HANDLE process, ProcessInfo* process_info) { &memory_basic_information, sizeof(memory_basic_information)); if (result == 0) { + if (GetLastError() == ERROR_INVALID_PARAMETER) + break; PLOG(ERROR) << "VirtualQueryEx"; return false; } @@ -367,7 +373,7 @@ bool ProcessInfo::Initialize(HANDLE process) { return false; } - if (!ReadMemoryInfo(process, this)) { + if (!ReadMemoryInfo(process, is_64_bit_, this)) { LOG(ERROR) << "ReadMemoryInfo failed"; return false; } diff --git a/util/win/process_info.h b/util/win/process_info.h index 5af28bd7..c8bac702 100644 --- a/util/win/process_info.h +++ b/util/win/process_info.h @@ -141,7 +141,9 @@ class ProcessInfo { WinVMAddress peb_address_vmaddr, ProcessInfo* process_info); - friend bool ReadMemoryInfo(HANDLE process, ProcessInfo* process_info); + friend bool ReadMemoryInfo(HANDLE process, + bool is_64_bit, + ProcessInfo* process_info); pid_t process_id_; pid_t inherited_from_process_id_;