mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-04-18 04:51:43 +00:00
Add MinidumpMemoryInfo / MinidumpMemoryInfoList classes to expose MDRawMemoryInfo / MDRawMemoryInfoList via the Minidump class
R=mark at http://breakpad.appspot.com/255001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@755 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
80745c59de
commit
7b8e2b7e09
|
@ -794,6 +794,76 @@ class MinidumpBreakpadInfo : public MinidumpStream {
|
||||||
MDRawBreakpadInfo breakpad_info_;
|
MDRawBreakpadInfo breakpad_info_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// MinidumpMemoryInfo wraps MDRawMemoryInfo, which provides information
|
||||||
|
// about mapped memory regions in a process, including their ranges
|
||||||
|
// and protection.
|
||||||
|
class MinidumpMemoryInfo : public MinidumpObject {
|
||||||
|
public:
|
||||||
|
const MDRawMemoryInfo* info() const { return valid_ ? &memory_info_ : NULL; }
|
||||||
|
|
||||||
|
// The address of the base of the memory region.
|
||||||
|
u_int64_t GetBase() const { return valid_ ? memory_info_.base_address : 0; }
|
||||||
|
|
||||||
|
// The size, in bytes, of the memory region.
|
||||||
|
u_int32_t GetSize() const { return valid_ ? memory_info_.region_size : 0; }
|
||||||
|
|
||||||
|
// Return true if the memory protection allows execution.
|
||||||
|
bool IsExecutable() const;
|
||||||
|
|
||||||
|
// Return true if the memory protection allows writing.
|
||||||
|
bool IsWritable() const;
|
||||||
|
|
||||||
|
// Print a human-readable representation of the object to stdout.
|
||||||
|
void Print();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// These objects are managed by MinidumpMemoryInfoList.
|
||||||
|
friend class MinidumpMemoryInfoList;
|
||||||
|
|
||||||
|
explicit MinidumpMemoryInfo(Minidump* minidump);
|
||||||
|
|
||||||
|
// This works like MinidumpStream::Read, but is driven by
|
||||||
|
// MinidumpMemoryInfoList. No size checking is done, because
|
||||||
|
// MinidumpMemoryInfoList handles that directly.
|
||||||
|
bool Read();
|
||||||
|
|
||||||
|
MDRawMemoryInfo memory_info_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// MinidumpMemoryInfoList contains a list of information about
|
||||||
|
// mapped memory regions for a process in the form of MDRawMemoryInfo.
|
||||||
|
// It maintains a map of these structures so that it may easily provide
|
||||||
|
// info corresponding to a specific address.
|
||||||
|
class MinidumpMemoryInfoList : public MinidumpStream {
|
||||||
|
public:
|
||||||
|
virtual ~MinidumpMemoryInfoList();
|
||||||
|
|
||||||
|
unsigned int info_count() const { return valid_ ? info_count_ : 0; }
|
||||||
|
|
||||||
|
const MinidumpMemoryInfo* GetMemoryInfoForAddress(u_int64_t address) const;
|
||||||
|
const MinidumpMemoryInfo* GetMemoryInfoAtIndex(unsigned int index) const;
|
||||||
|
|
||||||
|
// Print a human-readable representation of the object to stdout.
|
||||||
|
void Print();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class Minidump;
|
||||||
|
|
||||||
|
typedef vector<MinidumpMemoryInfo> MinidumpMemoryInfos;
|
||||||
|
|
||||||
|
static const u_int32_t kStreamType = MD_MEMORY_INFO_LIST_STREAM;
|
||||||
|
|
||||||
|
explicit MinidumpMemoryInfoList(Minidump* minidump);
|
||||||
|
|
||||||
|
bool Read(u_int32_t expected_size);
|
||||||
|
|
||||||
|
// Access to memory info using addresses as the key.
|
||||||
|
RangeMap<u_int64_t, unsigned int> *range_map_;
|
||||||
|
|
||||||
|
MinidumpMemoryInfos* infos_;
|
||||||
|
u_int32_t info_count_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Minidump is the user's interface to a minidump file. It wraps MDRawHeader
|
// Minidump is the user's interface to a minidump file. It wraps MDRawHeader
|
||||||
// and provides access to the minidump's top-level stream directory.
|
// and provides access to the minidump's top-level stream directory.
|
||||||
|
@ -842,6 +912,7 @@ class Minidump {
|
||||||
MinidumpSystemInfo* GetSystemInfo();
|
MinidumpSystemInfo* GetSystemInfo();
|
||||||
MinidumpMiscInfo* GetMiscInfo();
|
MinidumpMiscInfo* GetMiscInfo();
|
||||||
MinidumpBreakpadInfo* GetBreakpadInfo();
|
MinidumpBreakpadInfo* GetBreakpadInfo();
|
||||||
|
MinidumpMemoryInfoList* GetMemoryInfoList();
|
||||||
|
|
||||||
// The next set of methods are provided for users who wish to access
|
// The next set of methods are provided for users who wish to access
|
||||||
// data in minidump files directly, while leveraging the rest of
|
// data in minidump files directly, while leveraging the rest of
|
||||||
|
|
|
@ -3439,6 +3439,264 @@ void MinidumpBreakpadInfo::Print() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// MinidumpMemoryInfo
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
MinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump)
|
||||||
|
: MinidumpObject(minidump),
|
||||||
|
memory_info_() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MinidumpMemoryInfo::IsExecutable() const {
|
||||||
|
u_int32_t protection =
|
||||||
|
memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
|
||||||
|
return protection == MD_MEMORY_PROTECT_EXECUTE ||
|
||||||
|
protection == MD_MEMORY_PROTECT_EXECUTE_READ ||
|
||||||
|
protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MinidumpMemoryInfo::IsWritable() const {
|
||||||
|
u_int32_t protection =
|
||||||
|
memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
|
||||||
|
return protection == MD_MEMORY_PROTECT_READWRITE ||
|
||||||
|
protection == MD_MEMORY_PROTECT_WRITECOPY ||
|
||||||
|
protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE ||
|
||||||
|
protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MinidumpMemoryInfo::Read() {
|
||||||
|
valid_ = false;
|
||||||
|
|
||||||
|
if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfo cannot read memory info";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minidump_->swap()) {
|
||||||
|
Swap(&memory_info_.base_address);
|
||||||
|
Swap(&memory_info_.allocation_base);
|
||||||
|
Swap(&memory_info_.allocation_protection);
|
||||||
|
Swap(&memory_info_.region_size);
|
||||||
|
Swap(&memory_info_.state);
|
||||||
|
Swap(&memory_info_.protection);
|
||||||
|
Swap(&memory_info_.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for base + size overflow or undersize.
|
||||||
|
if (memory_info_.region_size == 0 ||
|
||||||
|
memory_info_.region_size > numeric_limits<u_int64_t>::max() -
|
||||||
|
memory_info_.base_address) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfo has a memory region problem, " <<
|
||||||
|
HexString(memory_info_.base_address) << "+" <<
|
||||||
|
HexString(memory_info_.region_size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_ = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MinidumpMemoryInfo::Print() {
|
||||||
|
if (!valid_) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfo cannot print invalid data";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("MDRawMemoryInfo\n");
|
||||||
|
printf(" base_address = 0x%" PRIx64 "\n",
|
||||||
|
memory_info_.base_address);
|
||||||
|
printf(" allocation_base = 0x%" PRIx64 "\n",
|
||||||
|
memory_info_.allocation_base);
|
||||||
|
printf(" allocation_protection = 0x%x\n",
|
||||||
|
memory_info_.allocation_protection);
|
||||||
|
printf(" region_size = 0x%" PRIx64 "\n", memory_info_.region_size);
|
||||||
|
printf(" state = 0x%x\n", memory_info_.state);
|
||||||
|
printf(" protection = 0x%x\n", memory_info_.protection);
|
||||||
|
printf(" type = 0x%x\n", memory_info_.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// MinidumpMemoryInfoList
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
MinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump)
|
||||||
|
: MinidumpStream(minidump),
|
||||||
|
range_map_(new RangeMap<u_int64_t, unsigned int>()),
|
||||||
|
infos_(NULL),
|
||||||
|
info_count_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MinidumpMemoryInfoList::~MinidumpMemoryInfoList() {
|
||||||
|
delete range_map_;
|
||||||
|
delete infos_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MinidumpMemoryInfoList::Read(u_int32_t expected_size) {
|
||||||
|
// Invalidate cached data.
|
||||||
|
delete infos_;
|
||||||
|
infos_ = NULL;
|
||||||
|
range_map_->Clear();
|
||||||
|
info_count_ = 0;
|
||||||
|
|
||||||
|
valid_ = false;
|
||||||
|
|
||||||
|
MDRawMemoryInfoList header;
|
||||||
|
if (expected_size < sizeof(MDRawMemoryInfoList)) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
|
||||||
|
expected_size << " < " << sizeof(MDRawMemoryInfoList);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!minidump_->ReadBytes(&header, sizeof(header))) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfoList could not read header";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minidump_->swap()) {
|
||||||
|
Swap(&header.size_of_header);
|
||||||
|
Swap(&header.size_of_entry);
|
||||||
|
Swap(&header.number_of_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check that the header is the expected size.
|
||||||
|
//TODO(ted): could possibly handle this more gracefully, assuming
|
||||||
|
// that future versions of the structs would be backwards-compatible.
|
||||||
|
if (header.size_of_header != sizeof(MDRawMemoryInfoList)) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
|
||||||
|
header.size_of_header << " != " <<
|
||||||
|
sizeof(MDRawMemoryInfoList);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check that the entries are the expected size.
|
||||||
|
if (header.size_of_entry != sizeof(MDRawMemoryInfo)) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfoList entry size mismatch, " <<
|
||||||
|
header.size_of_entry << " != " <<
|
||||||
|
sizeof(MDRawMemoryInfo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.number_of_entries >
|
||||||
|
numeric_limits<u_int32_t>::max() / sizeof(MDRawMemoryInfo)) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfoList info count " <<
|
||||||
|
header.number_of_entries <<
|
||||||
|
" would cause multiplication overflow";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expected_size != sizeof(MDRawMemoryInfoList) +
|
||||||
|
header.number_of_entries * sizeof(MDRawMemoryInfo)) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfoList size mismatch, " << expected_size <<
|
||||||
|
" != " << sizeof(MDRawMemoryInfoList) +
|
||||||
|
header.number_of_entries * sizeof(MDRawMemoryInfo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.number_of_entries != 0) {
|
||||||
|
scoped_ptr<MinidumpMemoryInfos> infos(
|
||||||
|
new MinidumpMemoryInfos(header.number_of_entries,
|
||||||
|
MinidumpMemoryInfo(minidump_)));
|
||||||
|
|
||||||
|
for (unsigned int index = 0;
|
||||||
|
index < header.number_of_entries;
|
||||||
|
++index) {
|
||||||
|
MinidumpMemoryInfo* info = &(*infos)[index];
|
||||||
|
|
||||||
|
// Assume that the file offset is correct after the last read.
|
||||||
|
if (!info->Read()) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfoList cannot read info " <<
|
||||||
|
index << "/" << header.number_of_entries;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int64_t base_address = info->GetBase();
|
||||||
|
u_int32_t region_size = info->GetSize();
|
||||||
|
|
||||||
|
if (!range_map_->StoreRange(base_address, region_size, index)) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfoList could not store"
|
||||||
|
" memory region " <<
|
||||||
|
index << "/" << header.number_of_entries << ", " <<
|
||||||
|
HexString(base_address) << "+" <<
|
||||||
|
HexString(region_size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infos_ = infos.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
info_count_ = header.number_of_entries;
|
||||||
|
|
||||||
|
valid_ = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex(
|
||||||
|
unsigned int index) const {
|
||||||
|
if (!valid_) {
|
||||||
|
BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= info_count_) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " <<
|
||||||
|
index << "/" << info_count_;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &(*infos_)[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress(
|
||||||
|
u_int64_t address) const {
|
||||||
|
if (!valid_) {
|
||||||
|
BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for"
|
||||||
|
" GetMemoryInfoForAddress";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int info_index;
|
||||||
|
if (!range_map_->RetrieveRange(address, &info_index, NULL, NULL)) {
|
||||||
|
BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " <<
|
||||||
|
HexString(address);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetMemoryInfoAtIndex(info_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MinidumpMemoryInfoList::Print() {
|
||||||
|
if (!valid_) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMemoryInfoList cannot print invalid data";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("MinidumpMemoryInfoList\n");
|
||||||
|
printf(" info_count = %d\n", info_count_);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
for (unsigned int info_index = 0;
|
||||||
|
info_index < info_count_;
|
||||||
|
++info_index) {
|
||||||
|
printf("info[%d]\n", info_index);
|
||||||
|
(*infos_)[info_index].Print();
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Minidump
|
// Minidump
|
||||||
//
|
//
|
||||||
|
@ -3681,6 +3939,11 @@ MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
|
||||||
return GetStream(&breakpad_info);
|
return GetStream(&breakpad_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() {
|
||||||
|
MinidumpMemoryInfoList* memory_info_list;
|
||||||
|
return GetStream(&memory_info_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Minidump::Print() {
|
void Minidump::Print() {
|
||||||
if (!valid_) {
|
if (!valid_) {
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace {
|
||||||
using google_breakpad::Minidump;
|
using google_breakpad::Minidump;
|
||||||
using google_breakpad::MinidumpThreadList;
|
using google_breakpad::MinidumpThreadList;
|
||||||
using google_breakpad::MinidumpModuleList;
|
using google_breakpad::MinidumpModuleList;
|
||||||
|
using google_breakpad::MinidumpMemoryInfoList;
|
||||||
using google_breakpad::MinidumpMemoryList;
|
using google_breakpad::MinidumpMemoryList;
|
||||||
using google_breakpad::MinidumpException;
|
using google_breakpad::MinidumpException;
|
||||||
using google_breakpad::MinidumpAssertion;
|
using google_breakpad::MinidumpAssertion;
|
||||||
|
@ -160,6 +161,14 @@ static bool PrintMinidumpDump(const char *minidump_file) {
|
||||||
breakpad_info->Print();
|
breakpad_info->Print();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MinidumpMemoryInfoList *memory_info_list = minidump.GetMemoryInfoList();
|
||||||
|
if (!memory_info_list) {
|
||||||
|
++errors;
|
||||||
|
BPLOG(ERROR) << "minidump.GetMemoryInfoList() failed";
|
||||||
|
} else {
|
||||||
|
memory_info_list->Print();
|
||||||
|
}
|
||||||
|
|
||||||
DumpRawStream(&minidump,
|
DumpRawStream(&minidump,
|
||||||
MD_LINUX_CMD_LINE,
|
MD_LINUX_CMD_LINE,
|
||||||
"MD_LINUX_CMD_LINE",
|
"MD_LINUX_CMD_LINE",
|
||||||
|
|
|
@ -46,6 +46,8 @@ namespace {
|
||||||
|
|
||||||
using google_breakpad::Minidump;
|
using google_breakpad::Minidump;
|
||||||
using google_breakpad::MinidumpContext;
|
using google_breakpad::MinidumpContext;
|
||||||
|
using google_breakpad::MinidumpMemoryInfo;
|
||||||
|
using google_breakpad::MinidumpMemoryInfoList;
|
||||||
using google_breakpad::MinidumpMemoryList;
|
using google_breakpad::MinidumpMemoryList;
|
||||||
using google_breakpad::MinidumpMemoryRegion;
|
using google_breakpad::MinidumpMemoryRegion;
|
||||||
using google_breakpad::MinidumpModule;
|
using google_breakpad::MinidumpModule;
|
||||||
|
@ -531,4 +533,59 @@ TEST(Dump, BigDump) {
|
||||||
md_module_list->GetModuleAtIndex(2)->base_address());
|
md_module_list->GetModuleAtIndex(2)->base_address());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Dump, OneMemoryInfo) {
|
||||||
|
Dump dump(0, kBigEndian);
|
||||||
|
Stream stream(dump, MD_MEMORY_INFO_LIST_STREAM);
|
||||||
|
|
||||||
|
// Add the MDRawMemoryInfoList header.
|
||||||
|
const u_int64_t kNumberOfEntries = 1;
|
||||||
|
stream.D32(sizeof(MDRawMemoryInfoList)) // size_of_header
|
||||||
|
.D32(sizeof(MDRawMemoryInfo)) // size_of_entry
|
||||||
|
.D64(kNumberOfEntries); // number_of_entries
|
||||||
|
|
||||||
|
|
||||||
|
// Now add a MDRawMemoryInfo entry.
|
||||||
|
const u_int64_t kBaseAddress = 0x1000;
|
||||||
|
const u_int64_t kRegionSize = 0x2000;
|
||||||
|
stream.D64(kBaseAddress) // base_address
|
||||||
|
.D64(kBaseAddress) // allocation_base
|
||||||
|
.D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // allocation_protection
|
||||||
|
.D32(0) // __alignment1
|
||||||
|
.D64(kRegionSize) // region_size
|
||||||
|
.D32(MD_MEMORY_STATE_COMMIT) // state
|
||||||
|
.D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // protection
|
||||||
|
.D32(MD_MEMORY_TYPE_PRIVATE) // type
|
||||||
|
.D32(0); // __alignment2
|
||||||
|
|
||||||
|
dump.Add(&stream);
|
||||||
|
dump.Finish();
|
||||||
|
|
||||||
|
string contents;
|
||||||
|
ASSERT_TRUE(dump.GetContents(&contents));
|
||||||
|
istringstream minidump_stream(contents);
|
||||||
|
Minidump minidump(minidump_stream);
|
||||||
|
ASSERT_TRUE(minidump.Read());
|
||||||
|
ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
|
||||||
|
|
||||||
|
const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
|
||||||
|
ASSERT_TRUE(dir != NULL);
|
||||||
|
EXPECT_EQ((u_int32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type);
|
||||||
|
|
||||||
|
MinidumpMemoryInfoList *info_list = minidump.GetMemoryInfoList();
|
||||||
|
ASSERT_TRUE(info_list != NULL);
|
||||||
|
ASSERT_EQ(1U, info_list->info_count());
|
||||||
|
|
||||||
|
const MinidumpMemoryInfo *info1 = info_list->GetMemoryInfoAtIndex(0);
|
||||||
|
ASSERT_EQ(kBaseAddress, info1->GetBase());
|
||||||
|
ASSERT_EQ(kRegionSize, info1->GetSize());
|
||||||
|
ASSERT_TRUE(info1->IsExecutable());
|
||||||
|
ASSERT_TRUE(info1->IsWritable());
|
||||||
|
|
||||||
|
// Should get back the same memory region here.
|
||||||
|
const MinidumpMemoryInfo *info2 =
|
||||||
|
info_list->GetMemoryInfoForAddress(kBaseAddress + kRegionSize / 2);
|
||||||
|
ASSERT_EQ(kBaseAddress, info2->GetBase());
|
||||||
|
ASSERT_EQ(kRegionSize, info2->GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in a new issue