Linux: Add a test for "extra memory" / code-around-pc

And implement ExtraMemory() for ProcessSnapshotMinidump for this purpose.

Bug: crashpad:10,crashpad:30
Change-Id: I889c42c7e91358336671ae8d00154af820725e7b
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3279301
Reviewed-by: Joshua Peraza <jperaza@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
This commit is contained in:
Jakob Kummerow 2021-11-12 23:22:38 +01:00 committed by Crashpad LUCI CQ
parent bede7bb29e
commit 08978c7b75
3 changed files with 79 additions and 4 deletions

View File

@ -147,6 +147,26 @@ void ValidateAttachment(const CrashReportDatabase::UploadReport* report) {
0); 0);
} }
void ValidateExtraMemory(const ProcessSnapshotMinidump& minidump) {
// Verify that if we have an exception, then the code around the instruction
// pointer is included in the extra memory.
const ExceptionSnapshot* exception = minidump.Exception();
if (exception == nullptr)
return;
uint64_t pc = exception->Context()->InstructionPointer();
std::vector<const MemorySnapshot*> snippets = minidump.ExtraMemory();
bool pc_found = false;
for (const MemorySnapshot* snippet : snippets) {
uint64_t start = snippet->Address();
uint64_t end = start + snippet->Size();
if (pc >= start && pc < end) {
pc_found = true;
break;
}
}
EXPECT_TRUE(pc_found);
}
void ValidateDump(const CrashReportDatabase::UploadReport* report) { void ValidateDump(const CrashReportDatabase::UploadReport* report) {
ProcessSnapshotMinidump minidump_snapshot; ProcessSnapshotMinidump minidump_snapshot;
ASSERT_TRUE(minidump_snapshot.Initialize(report->Reader())); ASSERT_TRUE(minidump_snapshot.Initialize(report->Reader()));
@ -164,6 +184,8 @@ void ValidateDump(const CrashReportDatabase::UploadReport* report) {
#endif #endif
ValidateAttachment(report); ValidateAttachment(report);
ValidateExtraMemory(minidump_snapshot);
for (const ModuleSnapshot* module : minidump_snapshot.Modules()) { for (const ModuleSnapshot* module : minidump_snapshot.Modules()) {
for (const AnnotationSnapshot& annotation : module->AnnotationObjects()) { for (const AnnotationSnapshot& annotation : module->AnnotationObjects()) {
if (static_cast<Annotation::Type>(annotation.type) != if (static_cast<Annotation::Type>(annotation.type) !=

View File

@ -117,8 +117,9 @@ bool ProcessSnapshotMinidump::Initialize(FileReaderInterface* file_reader) {
if (!InitializeCrashpadInfo() || !InitializeMiscInfo() || if (!InitializeCrashpadInfo() || !InitializeMiscInfo() ||
!InitializeModules() || !InitializeSystemSnapshot() || !InitializeModules() || !InitializeSystemSnapshot() ||
!InitializeMemoryInfo() || !InitializeThreads() || !InitializeMemoryInfo() || !InitializeExtraMemory() ||
!InitializeCustomMinidumpStreams() || !InitializeExceptionSnapshot()) { !InitializeThreads() || !InitializeCustomMinidumpStreams() ||
!InitializeExceptionSnapshot()) {
return false; return false;
} }
@ -234,8 +235,11 @@ std::vector<HandleSnapshot> ProcessSnapshotMinidump::Handles() const {
std::vector<const MemorySnapshot*> ProcessSnapshotMinidump::ExtraMemory() std::vector<const MemorySnapshot*> ProcessSnapshotMinidump::ExtraMemory()
const { const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_); INITIALIZATION_STATE_DCHECK_VALID(initialized_);
NOTREACHED(); // https://crashpad.chromium.org/bug/10 std::vector<const MemorySnapshot*> chunks;
return std::vector<const MemorySnapshot*>(); for (const auto& chunk : extra_memory_) {
chunks.push_back(chunk.get());
}
return chunks;
} }
const ProcessMemory* ProcessSnapshotMinidump::Memory() const { const ProcessMemory* ProcessSnapshotMinidump::Memory() const {
@ -502,6 +506,50 @@ bool ProcessSnapshotMinidump::InitializeMemoryInfo() {
return true; return true;
} }
bool ProcessSnapshotMinidump::InitializeExtraMemory() {
const auto& stream_it = stream_map_.find(kMinidumpStreamTypeMemoryList);
if (stream_it == stream_map_.end()) {
return true;
}
if (stream_it->second->DataSize < sizeof(MINIDUMP_MEMORY_LIST)) {
LOG(ERROR) << "memory_list size mismatch";
return false;
}
if (!file_reader_->SeekSet(stream_it->second->Rva)) {
return false;
}
// MSVC won't let us stack-allocate a MINIDUMP_MEMORY_LIST because of its
// trailing zero-element array. Luckily we're only interested in its other
// field anyway: a uint32_t indicating the number of memory descriptors that
// follow.
static_assert(
sizeof(MINIDUMP_MEMORY_LIST) == 4,
"MINIDUMP_MEMORY_LIST's only actual field should be an uint32_t");
uint32_t num_ranges;
if (!file_reader_->ReadExactly(&num_ranges, sizeof(num_ranges))) {
return false;
}
// We have to manually keep track of the locations of the entries in the
// contiguous list of MINIDUMP_MEMORY_DESCRIPTORs, because the Initialize()
// function jumps around the file to find the contents of each snapshot.
FileOffset location = file_reader_->SeekGet();
for (uint32_t i = 0; i < num_ranges; i++) {
extra_memory_.emplace_back(
std::make_unique<internal::MemorySnapshotMinidump>());
if (!extra_memory_.back()->Initialize(file_reader_,
static_cast<RVA>(location))) {
return false;
}
location += sizeof(MINIDUMP_MEMORY_DESCRIPTOR);
}
return true;
}
bool ProcessSnapshotMinidump::InitializeThreads() { bool ProcessSnapshotMinidump::InitializeThreads() {
const auto& stream_it = stream_map_.find(kMinidumpStreamTypeThreadList); const auto& stream_it = stream_map_.find(kMinidumpStreamTypeThreadList);
if (stream_it == stream_map_.end()) { if (stream_it == stream_map_.end()) {

View File

@ -116,6 +116,10 @@ class ProcessSnapshotMinidump final : public ProcessSnapshot {
// Initialize(). // Initialize().
bool InitializeMemoryInfo(); bool InitializeMemoryInfo();
// Initializes data carried in a MINIDUMP_MEMORY_LIST stream on behalf of
// Initialize().
bool InitializeExtraMemory();
// Initializes data carried in a MINIDUMP_SYSTEM_INFO stream on behalf of // Initializes data carried in a MINIDUMP_SYSTEM_INFO stream on behalf of
// Initialize(). // Initialize().
bool InitializeSystemSnapshot(); bool InitializeSystemSnapshot();
@ -147,6 +151,7 @@ class ProcessSnapshotMinidump final : public ProcessSnapshot {
std::vector<std::unique_ptr<internal::MemoryMapRegionSnapshotMinidump>> std::vector<std::unique_ptr<internal::MemoryMapRegionSnapshotMinidump>>
mem_regions_; mem_regions_;
std::vector<const MemoryMapRegionSnapshot*> mem_regions_exposed_; std::vector<const MemoryMapRegionSnapshot*> mem_regions_exposed_;
std::vector<std::unique_ptr<internal::MemorySnapshotMinidump>> extra_memory_;
std::vector<std::unique_ptr<MinidumpStream>> custom_streams_; std::vector<std::unique_ptr<MinidumpStream>> custom_streams_;
MinidumpCrashpadInfo crashpad_info_; MinidumpCrashpadInfo crashpad_info_;
internal::SystemSnapshotMinidump system_snapshot_; internal::SystemSnapshotMinidump system_snapshot_;