Implement MemoryMap for ProcessSnapshotMinidump

Bug: crashpad:10
Change-Id: Icca05321b729fd869a371707940fab40e12e8e22
Reviewed-on: https://chromium-review.googlesource.com/c/1294254
Commit-Queue: Casey Dahlin <sadmac@google.com>
Reviewed-by: Scott Graham <scottmg@chromium.org>
This commit is contained in:
Casey Dahlin 2018-10-22 11:14:09 -07:00 committed by Commit Bot
parent bf327d8ceb
commit 411f0ae41d
3 changed files with 152 additions and 2 deletions

View File

@ -16,11 +16,29 @@
#include <utility>
#include "snapshot/memory_map_region_snapshot.h"
#include "snapshot/minidump/minidump_simple_string_dictionary_reader.h"
#include "util/file/file_io.h"
namespace crashpad {
namespace internal {
class MemoryMapRegionSnapshotMinidump : public MemoryMapRegionSnapshot {
public:
MemoryMapRegionSnapshotMinidump(MINIDUMP_MEMORY_INFO info) : info_(info) {}
~MemoryMapRegionSnapshotMinidump() override = default;
const MINIDUMP_MEMORY_INFO& AsMinidumpMemoryInfo() const override {
return info_;
}
private:
MINIDUMP_MEMORY_INFO info_;
};
} // namespace internal
ProcessSnapshotMinidump::ProcessSnapshotMinidump()
: ProcessSnapshot(),
header_(),
@ -90,6 +108,7 @@ bool ProcessSnapshotMinidump::Initialize(FileReaderInterface* file_reader) {
!InitializeMiscInfo() ||
!InitializeModules() ||
!InitializeSystemSnapshot() ||
!InitializeMemoryInfo() ||
!InitializeThreads()) {
return false;
}
@ -194,8 +213,7 @@ const ExceptionSnapshot* ProcessSnapshotMinidump::Exception() const {
std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotMinidump::MemoryMap()
const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
NOTREACHED(); // https://crashpad.chromium.org/bug/10
return std::vector<const MemoryMapRegionSnapshot*>();
return mem_regions_exposed_;
}
std::vector<HandleSnapshot> ProcessSnapshotMinidump::Handles() const {
@ -396,6 +414,56 @@ bool ProcessSnapshotMinidump::InitializeModulesCrashpadInfo(
return true;
}
bool ProcessSnapshotMinidump::InitializeMemoryInfo() {
const auto& stream_it = stream_map_.find(kMinidumpStreamTypeMemoryInfoList);
if (stream_it == stream_map_.end()) {
return true;
}
if (stream_it->second->DataSize < sizeof(MINIDUMP_MEMORY_INFO_LIST)) {
LOG(ERROR) << "memory_info_list size mismatch";
return false;
}
if (!file_reader_->SeekSet(stream_it->second->Rva)) {
return false;
}
MINIDUMP_MEMORY_INFO_LIST list;
if (!file_reader_->ReadExactly(&list, sizeof(list))) {
return false;
}
if (list.SizeOfHeader != sizeof(list)) {
return false;
}
if (list.SizeOfEntry != sizeof(MINIDUMP_MEMORY_INFO)) {
return false;
}
if (sizeof(MINIDUMP_MEMORY_INFO_LIST) +
list.NumberOfEntries * list.SizeOfEntry != stream_it->second->DataSize) {
LOG(ERROR) << "memory_info_list size mismatch";
return false;
}
for (uint32_t i = 0; i < list.NumberOfEntries; i++) {
MINIDUMP_MEMORY_INFO info;
if (!file_reader_->ReadExactly(&info, sizeof(info))) {
return false;
}
mem_regions_.emplace_back(
std::make_unique<internal::MemoryMapRegionSnapshotMinidump>(info));
mem_regions_exposed_.emplace_back(mem_regions_.back().get());
}
return true;
}
bool ProcessSnapshotMinidump::InitializeThreads() {
const auto& stream_it = stream_map_.find(kMinidumpStreamTypeThreadList);
if (stream_it == stream_map_.end()) {

View File

@ -43,6 +43,10 @@
namespace crashpad {
namespace internal {
class MemoryMapRegionSnapshotMinidump;
} // namespace internal
//! \brief A ProcessSnapshot based on a minidump file.
class ProcessSnapshotMinidump final : public ProcessSnapshot {
public:
@ -91,6 +95,10 @@ class ProcessSnapshotMinidump final : public ProcessSnapshot {
// Initialize().
bool InitializeThreads();
// Initializes data carried in a MINIDUMP_MEMORY_INFO_LIST stream on behalf of
// Initialize().
bool InitializeMemoryInfo();
// Initializes data carried in a MINIDUMP_SYSTEM_INFO stream on behalf of
// Initialize().
bool InitializeSystemSnapshot();
@ -112,6 +120,9 @@ class ProcessSnapshotMinidump final : public ProcessSnapshot {
std::vector<std::unique_ptr<internal::ModuleSnapshotMinidump>> modules_;
std::vector<std::unique_ptr<internal::ThreadSnapshotMinidump>> threads_;
std::vector<UnloadedModuleSnapshot> unloaded_modules_;
std::vector<std::unique_ptr<internal::MemoryMapRegionSnapshotMinidump>>
mem_regions_;
std::vector<const MemoryMapRegionSnapshot*> mem_regions_exposed_;
MinidumpCrashpadInfo crashpad_info_;
internal::SystemSnapshotMinidump system_snapshot_;
CPUArchitecture arch_;

View File

@ -24,6 +24,7 @@
#include "gtest/gtest.h"
#include "minidump/minidump_context.h"
#include "snapshot/minidump/minidump_annotation_reader.h"
#include "snapshot/memory_map_region_snapshot.h"
#include "snapshot/module_snapshot.h"
#include "util/file/string_file.h"
#include "util/misc/pdb_structures.h"
@ -968,6 +969,76 @@ TEST(ProcessSnapshotMinidump, ThreadContextX86_64) {
}
}
TEST(ProcessSnapshotMinidump, MemoryMap) {
StringFile string_file;
MINIDUMP_HEADER header = {};
EXPECT_TRUE(string_file.Write(&header, sizeof(header)));
MINIDUMP_MEMORY_INFO minidump_memory_info_1 = {};
MINIDUMP_MEMORY_INFO minidump_memory_info_2 = {};
uint32_t minidump_memory_info_count = 2;
minidump_memory_info_1.BaseAddress = 1;
minidump_memory_info_1.AllocationBase = 2;
minidump_memory_info_1.AllocationProtect = 3;
minidump_memory_info_1.RegionSize = 4;
minidump_memory_info_1.State = 5;
minidump_memory_info_1.Protect = 6;
minidump_memory_info_1.Type = 6;
minidump_memory_info_2.BaseAddress = 7;
minidump_memory_info_2.AllocationBase = 8;
minidump_memory_info_2.AllocationProtect = 9;
minidump_memory_info_2.RegionSize = 10;
minidump_memory_info_2.State = 11;
minidump_memory_info_2.Protect = 12;
minidump_memory_info_2.Type = 13;
MINIDUMP_MEMORY_INFO_LIST minidump_memory_info_list = {};
minidump_memory_info_list.SizeOfHeader = sizeof(minidump_memory_info_list);
minidump_memory_info_list.SizeOfEntry = sizeof(MINIDUMP_MEMORY_INFO);
minidump_memory_info_list.NumberOfEntries = minidump_memory_info_count;
MINIDUMP_DIRECTORY minidump_memory_info_list_directory = {};
minidump_memory_info_list_directory.StreamType =
kMinidumpStreamTypeMemoryInfoList;
minidump_memory_info_list_directory.Location.DataSize =
sizeof(minidump_memory_info_list) +
minidump_memory_info_count * sizeof(MINIDUMP_MEMORY_INFO);
minidump_memory_info_list_directory.Location.Rva =
static_cast<RVA>(string_file.SeekGet());
EXPECT_TRUE(string_file.Write(&minidump_memory_info_list,
sizeof(minidump_memory_info_list)));
EXPECT_TRUE(string_file.Write(&minidump_memory_info_1,
sizeof(minidump_memory_info_1)));
EXPECT_TRUE(string_file.Write(&minidump_memory_info_2,
sizeof(minidump_memory_info_2)));
header.StreamDirectoryRva = static_cast<RVA>(string_file.SeekGet());
EXPECT_TRUE(string_file.Write(&minidump_memory_info_list_directory,
sizeof(minidump_memory_info_list_directory)));
header.Signature = MINIDUMP_SIGNATURE;
header.Version = MINIDUMP_VERSION;
header.NumberOfStreams = 1;
EXPECT_TRUE(string_file.SeekSet(0));
EXPECT_TRUE(string_file.Write(&header, sizeof(header)));
ProcessSnapshotMinidump process_snapshot;
EXPECT_TRUE(process_snapshot.Initialize(&string_file));
std::vector<const MemoryMapRegionSnapshot*> map =
process_snapshot.MemoryMap();
ASSERT_EQ(map.size(), minidump_memory_info_count);
EXPECT_EQ(memcmp(&map[0]->AsMinidumpMemoryInfo(), &minidump_memory_info_1,
sizeof(minidump_memory_info_1)), 0);
EXPECT_EQ(memcmp(&map[1]->AsMinidumpMemoryInfo(), &minidump_memory_info_2,
sizeof(minidump_memory_info_2)), 0);
}
} // namespace
} // namespace test
} // namespace crashpad