Chromium Code Reviews| Index: util/win/process_info.cc |
| diff --git a/util/win/process_info.cc b/util/win/process_info.cc |
| index ed5262c7f7cc9d7f2d2958d3c7c74a1b69a7b9a6..d983a7233e1f4e42b9b8e963840731d67253ca46 100644 |
| --- a/util/win/process_info.cc |
| +++ b/util/win/process_info.cc |
| @@ -16,6 +16,8 @@ |
| #include <winternl.h> |
| +#include <algorithm> |
| + |
| #include "base/logging.h" |
| #include "base/strings/stringprintf.h" |
| #include "build/build_config.h" |
| @@ -104,6 +106,13 @@ bool ReadStruct(HANDLE process, WinVMAddress at, T* into) { |
| return true; |
| } |
| +bool PageIsReadable(const ProcessInfo::MemoryInfo& memory_info) { |
|
Mark Mentovai
2015/10/01 17:38:58
The function name, PageIsReadable(), doesn’t match
Mark Mentovai
2015/10/01 17:38:58
This operates on MemoryInfo objects, which represe
scottmg
2015/10/01 18:10:02
Done.
scottmg
2015/10/01 18:10:02
Done.
|
| + return memory_info.state == MEM_FREE || |
| + (memory_info.state == MEM_COMMIT && |
| + ((memory_info.protect & PAGE_NOACCESS) || |
| + (memory_info.protect & PAGE_GUARD))); |
| +} |
| + |
| } // namespace |
| template <class Traits> |
| @@ -292,6 +301,16 @@ ProcessInfo::Module::Module() : name(), dll_base(0), size(0), timestamp() { |
| ProcessInfo::Module::~Module() { |
| } |
| +ProcessInfo::MemoryInfo::MemoryInfo() |
| + : base_address(0), |
| + region_size(0), |
| + allocation_base(0), |
| + state(0), |
| + allocation_protect(0), |
| + protect(0), |
| + type(0) { |
| +} |
| + |
| ProcessInfo::MemoryInfo::MemoryInfo(const MEMORY_BASIC_INFORMATION& mbi) |
| : base_address(reinterpret_cast<WinVMAddress>(mbi.BaseAddress)), |
| region_size(mbi.RegionSize), |
| @@ -415,7 +434,70 @@ bool ProcessInfo::Modules(std::vector<Module>* modules) const { |
| const std::vector<ProcessInfo::MemoryInfo>& ProcessInfo::MemoryInformation() |
| const { |
| + INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| return memory_info_; |
| } |
| +std::vector<CheckedRange<WinVMAddress, WinVMSize>> |
| +ProcessInfo::GetReadableRanges( |
| + const CheckedRange<WinVMAddress, WinVMSize>& range) const { |
| + return GetReadableRangesOfMemoryMap(range, MemoryInformation()); |
| +} |
| + |
| +std::vector<CheckedRange<WinVMAddress, WinVMSize>> GetReadableRangesOfMemoryMap( |
| + const CheckedRange<WinVMAddress, WinVMSize>& range, |
| + const std::vector<ProcessInfo::MemoryInfo>& memory_info) { |
| + using Range = CheckedRange<WinVMAddress, WinVMSize>; |
| + |
| + // Find all the ranges that overlap the target range, maintaining their order. |
| + std::vector<ProcessInfo::MemoryInfo> overlapping; |
| + for (const auto& mi : memory_info) { |
| + if (range.OverlapsRange(Range(mi.base_address, mi.region_size))) |
| + overlapping.push_back(mi); |
| + } |
| + if (overlapping.empty()) |
| + return std::vector<Range>(); |
| + |
| + // For the first and last, trim to the boundary of the incoming range. |
| + ProcessInfo::MemoryInfo& front = overlapping.front(); |
| + WinVMAddress original_base = front.base_address; |
|
Mark Mentovai
2015/10/01 17:38:58
Since there are several ranges in play here, this
scottmg
2015/10/01 18:10:02
Done.
|
| + front.base_address = range.base(); |
|
Mark Mentovai
2015/10/01 17:38:59
Since this requires that front.base_address <= ran
scottmg
2015/10/01 18:10:02
Good catch. Done and added test.
|
| + front.region_size = (original_base + front.region_size) - range.base(); |
|
Mark Mentovai
2015/10/01 17:38:58
and then this one will need to become - front.base
scottmg
2015/10/01 18:10:02
Done.
|
| + |
| + ProcessInfo::MemoryInfo& back = overlapping.back(); |
| + back.region_size = range.end() - back.base_address; |
|
Mark Mentovai
2015/10/01 17:38:58
The same kind of problem might show up here if the
scottmg
2015/10/01 18:10:02
Done and added test.
|
| + |
| + // Discard all non-accessible. |
| + overlapping.erase(std::remove_if(overlapping.begin(), |
| + overlapping.end(), |
| + [](const ProcessInfo::MemoryInfo& mi) { |
| + return PageIsReadable(mi); |
| + }), |
| + overlapping.end()); |
| + if (overlapping.empty()) |
| + return std::vector<Range>(); |
| + |
| + // Convert to return type. |
| + std::vector<Range> as_ranges; |
| + for (const auto& mi : overlapping) { |
| + as_ranges.push_back(Range(mi.base_address, mi.region_size)); |
| + DCHECK(as_ranges.back().IsValid()); |
| + } |
| + |
| + // Coalesce remaining regions. |
| + std::vector<Range> result; |
| + result.push_back(as_ranges[0]); |
| + for (size_t i = 1; i < as_ranges.size(); ++i) { |
| + if (result.back().end() == as_ranges[i].base()) { |
| + result.back().SetRange(result.back().base(), |
| + result.back().size() + as_ranges[i].size()); |
| + } else { |
| + result.push_back(as_ranges[i]); |
| + } |
| + DCHECK(result.back().IsValid()); |
| + } |
| + |
| + return result; |
| +} |
| + |
| } // namespace crashpad |