mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-28 15:50:26 +08:00
win: Add memory map range intersection helper
To be used for improved version of ReadMemory() that is memory-map aware, in particular for reading the environment block in https://codereview.chromium.org/1360863006/. R=mark@chromium.org BUG=crashpad:20, crashpad:46 Review URL: https://codereview.chromium.org/1372183002 .
This commit is contained in:
parent
7942b87fcb
commit
4df538f283
@ -104,11 +104,31 @@ class CheckedRange {
|
|||||||
return that.base() >= base() && that.end() <= end();
|
return that.base() >= base() && that.end() <= end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! \brief Returns whether the range overlaps another range.
|
||||||
|
//!
|
||||||
|
//! \param[in] that The (possibly) overlapping range.
|
||||||
|
//!
|
||||||
|
//! \return `true` if `this` range, the first range, overlaps \a that,
|
||||||
|
//! the provided range. `false` otherwise.
|
||||||
|
//!
|
||||||
|
//! Ranges are considered to be closed-open [base, end) for this test. Zero
|
||||||
|
//! length ranges are never considered to overlap another range.
|
||||||
|
//!
|
||||||
|
//! This method must only be called if IsValid() would return `true` for both
|
||||||
|
//! CheckedRange objects involved.
|
||||||
|
bool OverlapsRange(const CheckedRange<ValueType, SizeType>& that) const {
|
||||||
|
DCHECK(IsValid());
|
||||||
|
DCHECK(that.IsValid());
|
||||||
|
|
||||||
|
if (size() == 0 || that.size() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return base() < that.end() && that.base() < end();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ValueType base_;
|
ValueType base_;
|
||||||
SizeType size_;
|
SizeType size_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CheckedRange);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -155,7 +155,7 @@ TEST(CheckedRange, IsValid) {
|
|||||||
TEST(CheckedRange, ContainsValue) {
|
TEST(CheckedRange, ContainsValue) {
|
||||||
const struct TestData {
|
const struct TestData {
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
bool valid;
|
bool contains;
|
||||||
} kTestData[] = {
|
} kTestData[] = {
|
||||||
{0, false},
|
{0, false},
|
||||||
{1, false},
|
{1, false},
|
||||||
@ -190,7 +190,7 @@ TEST(CheckedRange, ContainsValue) {
|
|||||||
SCOPED_TRACE(base::StringPrintf(
|
SCOPED_TRACE(base::StringPrintf(
|
||||||
"index %" PRIuS ", value 0x%x", index, testcase.value));
|
"index %" PRIuS ", value 0x%x", index, testcase.value));
|
||||||
|
|
||||||
EXPECT_EQ(testcase.valid, parent_range.ContainsValue(testcase.value));
|
EXPECT_EQ(testcase.contains, parent_range.ContainsValue(testcase.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ TEST(CheckedRange, ContainsRange) {
|
|||||||
const struct TestData {
|
const struct TestData {
|
||||||
uint32_t base;
|
uint32_t base;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
bool valid;
|
bool contains;
|
||||||
} kTestData[] = {
|
} kTestData[] = {
|
||||||
{0, 0, false},
|
{0, 0, false},
|
||||||
{0, 1, false},
|
{0, 1, false},
|
||||||
@ -242,7 +242,60 @@ TEST(CheckedRange, ContainsRange) {
|
|||||||
|
|
||||||
CheckedRange<uint32_t> child_range(testcase.base, testcase.size);
|
CheckedRange<uint32_t> child_range(testcase.base, testcase.size);
|
||||||
ASSERT_TRUE(child_range.IsValid());
|
ASSERT_TRUE(child_range.IsValid());
|
||||||
EXPECT_EQ(testcase.valid, parent_range.ContainsRange(child_range));
|
EXPECT_EQ(testcase.contains, parent_range.ContainsRange(child_range));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CheckedRange, OverlapsRange) {
|
||||||
|
const struct TestData {
|
||||||
|
uint32_t base;
|
||||||
|
uint32_t size;
|
||||||
|
bool overlaps;
|
||||||
|
} kTestData[] = {
|
||||||
|
{0, 0, false},
|
||||||
|
{0, 1, false},
|
||||||
|
{0x2000, 0x1000, true},
|
||||||
|
{0, 0x2000, false},
|
||||||
|
{0x3000, 0x1000, false},
|
||||||
|
{0x1800, 0x1000, true},
|
||||||
|
{0x1800, 0x2000, true},
|
||||||
|
{0x2800, 0x1000, true},
|
||||||
|
{0x2000, 0x800, true},
|
||||||
|
{0x2800, 0x800, true},
|
||||||
|
{0x2400, 0x800, true},
|
||||||
|
{0x2800, 0, false},
|
||||||
|
{0x2000, 0xffffdfff, true},
|
||||||
|
{0x2800, 0xffffd7ff, true},
|
||||||
|
{0x3000, 0xffffcfff, false},
|
||||||
|
{0xfffffffe, 1, false},
|
||||||
|
{0xffffffff, 0, false},
|
||||||
|
{0x1fff, 0, false},
|
||||||
|
{0x2000, 0, false},
|
||||||
|
{0x2001, 0, false},
|
||||||
|
{0x2fff, 0, false},
|
||||||
|
{0x3000, 0, false},
|
||||||
|
{0x3001, 0, false},
|
||||||
|
{0x1fff, 1, false},
|
||||||
|
{0x2000, 1, true},
|
||||||
|
{0x2001, 1, true},
|
||||||
|
{0x2fff, 1, true},
|
||||||
|
{0x3000, 1, false},
|
||||||
|
{0x3001, 1, false},
|
||||||
|
};
|
||||||
|
|
||||||
|
CheckedRange<uint32_t> first_range(0x2000, 0x1000);
|
||||||
|
ASSERT_TRUE(first_range.IsValid());
|
||||||
|
|
||||||
|
for (size_t index = 0; index < arraysize(kTestData); ++index) {
|
||||||
|
const TestData& testcase = kTestData[index];
|
||||||
|
SCOPED_TRACE(base::StringPrintf("index %" PRIuS ", base 0x%x, size 0x%x",
|
||||||
|
index,
|
||||||
|
testcase.base,
|
||||||
|
testcase.size));
|
||||||
|
|
||||||
|
CheckedRange<uint32_t> second_range(testcase.base, testcase.size);
|
||||||
|
ASSERT_TRUE(second_range.IsValid());
|
||||||
|
EXPECT_EQ(testcase.overlaps, first_range.OverlapsRange(second_range));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
@ -106,6 +107,13 @@ bool ReadStruct(HANDLE process, WinVMAddress at, T* into) {
|
|||||||
return true;
|
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
|
} // namespace
|
||||||
|
|
||||||
template <class Traits>
|
template <class Traits>
|
||||||
@ -421,7 +429,72 @@ bool ProcessInfo::Modules(std::vector<Module>* modules) const {
|
|||||||
|
|
||||||
const std::vector<ProcessInfo::MemoryInfo>& ProcessInfo::MemoryInformation()
|
const std::vector<ProcessInfo::MemoryInfo>& ProcessInfo::MemoryInformation()
|
||||||
const {
|
const {
|
||||||
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||||
return memory_info_;
|
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
|
} // namespace crashpad
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
#include "util/misc/initialization_state_dcheck.h"
|
#include "util/misc/initialization_state_dcheck.h"
|
||||||
|
#include "util/numeric/checked_range.h"
|
||||||
#include "util/win/address_types.h"
|
#include "util/win/address_types.h"
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
@ -129,6 +130,16 @@ class ProcessInfo {
|
|||||||
//! \brief Retrieves information about all pages mapped into the process.
|
//! \brief Retrieves information about all pages mapped into the process.
|
||||||
const std::vector<MemoryInfo>& MemoryInformation() const;
|
const std::vector<MemoryInfo>& MemoryInformation() const;
|
||||||
|
|
||||||
|
//! \brief Given a range to be read from the target process, returns a vector
|
||||||
|
//! of ranges, representing the readable portions of the original range.
|
||||||
|
//!
|
||||||
|
//! \param[in] range The range being identified.
|
||||||
|
//!
|
||||||
|
//! \return A vector of ranges corresponding to the portion of \a range that
|
||||||
|
//! is readable based on the memory map.
|
||||||
|
std::vector<CheckedRange<WinVMAddress, WinVMSize>> GetReadableRanges(
|
||||||
|
const CheckedRange<WinVMAddress, WinVMSize>& range) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class Traits>
|
template <class Traits>
|
||||||
friend bool GetProcessBasicInformation(HANDLE process,
|
friend bool GetProcessBasicInformation(HANDLE process,
|
||||||
@ -159,6 +170,16 @@ class ProcessInfo {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
|
DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! \brief Given a memory map of a process, and a range to be read from the
|
||||||
|
//! target process, returns a vector of ranges, representing the readable
|
||||||
|
//! portions of the original range.
|
||||||
|
//!
|
||||||
|
//! This is a free function for testing, but prefer
|
||||||
|
//! ProcessInfo::GetReadableRanges().
|
||||||
|
std::vector<CheckedRange<WinVMAddress, WinVMSize>> GetReadableRangesOfMemoryMap(
|
||||||
|
const CheckedRange<WinVMAddress, WinVMSize>& range,
|
||||||
|
const std::vector<ProcessInfo::MemoryInfo>& memory_info);
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
|
||||||
#endif // CRASHPAD_UTIL_WIN_PROCESS_INFO_H_
|
#endif // CRASHPAD_UTIL_WIN_PROCESS_INFO_H_
|
||||||
|
@ -199,6 +199,180 @@ TEST(ProcessInfo, OtherProcessWOW64) {
|
|||||||
}
|
}
|
||||||
#endif // ARCH_CPU_64_BITS
|
#endif // ARCH_CPU_64_BITS
|
||||||
|
|
||||||
|
TEST(ProcessInfo, AccessibleRangesNone) {
|
||||||
|
std::vector<ProcessInfo::MemoryInfo> memory_info;
|
||||||
|
MEMORY_BASIC_INFORMATION mbi = {0};
|
||||||
|
|
||||||
|
mbi.BaseAddress = 0;
|
||||||
|
mbi.RegionSize = 10;
|
||||||
|
mbi.State = MEM_FREE;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
|
||||||
|
GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(2, 4),
|
||||||
|
memory_info);
|
||||||
|
|
||||||
|
EXPECT_TRUE(result.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ProcessInfo, AccessibleRangesOneInside) {
|
||||||
|
std::vector<ProcessInfo::MemoryInfo> memory_info;
|
||||||
|
MEMORY_BASIC_INFORMATION mbi = {0};
|
||||||
|
|
||||||
|
mbi.BaseAddress = 0;
|
||||||
|
mbi.RegionSize = 10;
|
||||||
|
mbi.State = MEM_COMMIT;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
|
||||||
|
GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(2, 4),
|
||||||
|
memory_info);
|
||||||
|
|
||||||
|
ASSERT_EQ(result.size(), 1u);
|
||||||
|
EXPECT_EQ(2, result[0].base());
|
||||||
|
EXPECT_EQ(4, result[0].size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ProcessInfo, AccessibleRangesOneTruncatedSize) {
|
||||||
|
std::vector<ProcessInfo::MemoryInfo> memory_info;
|
||||||
|
MEMORY_BASIC_INFORMATION mbi = {0};
|
||||||
|
|
||||||
|
mbi.BaseAddress = 0;
|
||||||
|
mbi.RegionSize = 10;
|
||||||
|
mbi.State = MEM_COMMIT;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
mbi.BaseAddress = reinterpret_cast<void*>(10);
|
||||||
|
mbi.RegionSize = 20;
|
||||||
|
mbi.State = MEM_FREE;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
|
||||||
|
GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
|
||||||
|
memory_info);
|
||||||
|
|
||||||
|
ASSERT_EQ(result.size(), 1u);
|
||||||
|
EXPECT_EQ(5, result[0].base());
|
||||||
|
EXPECT_EQ(5, result[0].size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ProcessInfo, AccessibleRangesOneMovedStart) {
|
||||||
|
std::vector<ProcessInfo::MemoryInfo> memory_info;
|
||||||
|
MEMORY_BASIC_INFORMATION mbi = {0};
|
||||||
|
|
||||||
|
mbi.BaseAddress = 0;
|
||||||
|
mbi.RegionSize = 10;
|
||||||
|
mbi.State = MEM_FREE;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
mbi.BaseAddress = reinterpret_cast<void*>(10);
|
||||||
|
mbi.RegionSize = 20;
|
||||||
|
mbi.State = MEM_COMMIT;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
|
||||||
|
GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
|
||||||
|
memory_info);
|
||||||
|
|
||||||
|
ASSERT_EQ(result.size(), 1u);
|
||||||
|
EXPECT_EQ(10, result[0].base());
|
||||||
|
EXPECT_EQ(5, result[0].size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ProcessInfo, AccessibleRangesCoalesced) {
|
||||||
|
std::vector<ProcessInfo::MemoryInfo> memory_info;
|
||||||
|
MEMORY_BASIC_INFORMATION mbi = {0};
|
||||||
|
|
||||||
|
mbi.BaseAddress = 0;
|
||||||
|
mbi.RegionSize = 10;
|
||||||
|
mbi.State = MEM_FREE;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
mbi.BaseAddress = reinterpret_cast<void*>(10);
|
||||||
|
mbi.RegionSize = 2;
|
||||||
|
mbi.State = MEM_COMMIT;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
mbi.BaseAddress = reinterpret_cast<void*>(12);
|
||||||
|
mbi.RegionSize = 5;
|
||||||
|
mbi.State = MEM_RESERVE;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
|
||||||
|
GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(11, 4),
|
||||||
|
memory_info);
|
||||||
|
|
||||||
|
ASSERT_EQ(result.size(), 1u);
|
||||||
|
EXPECT_EQ(11, result[0].base());
|
||||||
|
EXPECT_EQ(4, result[0].size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ProcessInfo, AccessibleRangesMiddleUnavailable) {
|
||||||
|
std::vector<ProcessInfo::MemoryInfo> memory_info;
|
||||||
|
MEMORY_BASIC_INFORMATION mbi = {0};
|
||||||
|
|
||||||
|
mbi.BaseAddress = 0;
|
||||||
|
mbi.RegionSize = 10;
|
||||||
|
mbi.State = MEM_COMMIT;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
mbi.BaseAddress = reinterpret_cast<void*>(10);
|
||||||
|
mbi.RegionSize = 5;
|
||||||
|
mbi.State = MEM_FREE;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
mbi.BaseAddress = reinterpret_cast<void*>(15);
|
||||||
|
mbi.RegionSize = 100;
|
||||||
|
mbi.State = MEM_COMMIT;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
|
||||||
|
GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 45),
|
||||||
|
memory_info);
|
||||||
|
|
||||||
|
ASSERT_EQ(result.size(), 2u);
|
||||||
|
EXPECT_EQ(5, result[0].base());
|
||||||
|
EXPECT_EQ(5, result[0].size());
|
||||||
|
EXPECT_EQ(15, result[1].base());
|
||||||
|
EXPECT_EQ(35, result[1].size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ProcessInfo, RequestedBeforeMap) {
|
||||||
|
std::vector<ProcessInfo::MemoryInfo> memory_info;
|
||||||
|
MEMORY_BASIC_INFORMATION mbi = {0};
|
||||||
|
|
||||||
|
mbi.BaseAddress = reinterpret_cast<void*>(10);
|
||||||
|
mbi.RegionSize = 10;
|
||||||
|
mbi.State = MEM_COMMIT;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
|
||||||
|
GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
|
||||||
|
memory_info);
|
||||||
|
|
||||||
|
ASSERT_EQ(result.size(), 1u);
|
||||||
|
EXPECT_EQ(10, result[0].base());
|
||||||
|
EXPECT_EQ(5, result[0].size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ProcessInfo, RequestedAfterMap) {
|
||||||
|
std::vector<ProcessInfo::MemoryInfo> memory_info;
|
||||||
|
MEMORY_BASIC_INFORMATION mbi = {0};
|
||||||
|
|
||||||
|
mbi.BaseAddress = reinterpret_cast<void*>(10);
|
||||||
|
mbi.RegionSize = 10;
|
||||||
|
mbi.State = MEM_COMMIT;
|
||||||
|
memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
|
||||||
|
|
||||||
|
std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
|
||||||
|
GetReadableRangesOfMemoryMap(
|
||||||
|
CheckedRange<WinVMAddress, WinVMSize>(15, 100), memory_info);
|
||||||
|
|
||||||
|
ASSERT_EQ(result.size(), 1u);
|
||||||
|
EXPECT_EQ(15, result[0].base());
|
||||||
|
EXPECT_EQ(5, result[0].size());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
Loading…
x
Reference in New Issue
Block a user