| Index: util/win/process_info.cc
|
| diff --git a/util/win/process_info.cc b/util/win/process_info.cc
|
| index ed5262c7f7cc9d7f2d2958d3c7c74a1b69a7b9a6..c7901c27c2f4e5660087eeda27656a69284e1a99 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 RegionIsInaccessible(const ProcessInfo::MemoryInfo& memory_info) {
|
| + 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>
|
| @@ -415,7 +424,72 @@ 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_front_base_address = front.base_address;
|
| + front.base_address = std::max(front.base_address, range.base());
|
| + front.region_size =
|
| + (original_front_base_address + front.region_size) - front.base_address;
|
| +
|
| + ProcessInfo::MemoryInfo& back = overlapping.back();
|
| + WinVMAddress back_end = back.base_address + back.region_size;
|
| + back.region_size = std::min(range.end(), back_end) - back.base_address;
|
| +
|
| + // Discard all non-accessible.
|
| + overlapping.erase(std::remove_if(overlapping.begin(),
|
| + overlapping.end(),
|
| + [](const ProcessInfo::MemoryInfo& mi) {
|
| + return RegionIsInaccessible(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
|
|
|