mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-10 06:36:02 +00:00
Add ExceptionSnapshotMinidump.
Implemented all of the interface except Context(). Bug: crashpad:10 Change-Id: If76e539fd7b995da50f83e02f095f05537f5572a Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/1567489 Commit-Queue: Peter Wen <wnwen@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org> Reviewed-by: Scott Graham <scottmg@chromium.org> Reviewed-by: Casey Dahlin <sadmac@google.com>
This commit is contained in:
parent
c31a86a340
commit
a7859e9bc6
@ -36,6 +36,8 @@ static_library("snapshot") {
|
|||||||
"memory_snapshot.cc",
|
"memory_snapshot.cc",
|
||||||
"memory_snapshot.h",
|
"memory_snapshot.h",
|
||||||
"memory_snapshot_generic.h",
|
"memory_snapshot_generic.h",
|
||||||
|
"minidump/exception_snapshot_minidump.cc",
|
||||||
|
"minidump/exception_snapshot_minidump.h",
|
||||||
"minidump/memory_snapshot_minidump.cc",
|
"minidump/memory_snapshot_minidump.cc",
|
||||||
"minidump/memory_snapshot_minidump.h",
|
"minidump/memory_snapshot_minidump.h",
|
||||||
"minidump/minidump_annotation_reader.cc",
|
"minidump/minidump_annotation_reader.cc",
|
||||||
|
93
snapshot/minidump/exception_snapshot_minidump.cc
Normal file
93
snapshot/minidump/exception_snapshot_minidump.cc
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright 2019 The Crashpad Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "snapshot/minidump/exception_snapshot_minidump.h"
|
||||||
|
|
||||||
|
#include "snapshot/minidump/minidump_string_reader.h"
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
ExceptionSnapshotMinidump::ExceptionSnapshotMinidump()
|
||||||
|
: ExceptionSnapshot(),
|
||||||
|
minidump_exception_stream_(),
|
||||||
|
exception_information_(),
|
||||||
|
initialized_() {}
|
||||||
|
|
||||||
|
ExceptionSnapshotMinidump::~ExceptionSnapshotMinidump() {}
|
||||||
|
|
||||||
|
bool ExceptionSnapshotMinidump::Initialize(FileReaderInterface* file_reader,
|
||||||
|
RVA minidump_exception_stream_rva) {
|
||||||
|
DCHECK(initialized_.is_uninitialized());
|
||||||
|
initialized_.set_invalid();
|
||||||
|
|
||||||
|
if (!file_reader->SeekSet(minidump_exception_stream_rva)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_reader->ReadExactly(&minidump_exception_stream_,
|
||||||
|
sizeof(minidump_exception_stream_))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t num_parameters =
|
||||||
|
minidump_exception_stream_.ExceptionRecord.NumberParameters;
|
||||||
|
for (size_t i = 0; i < num_parameters; ++i) {
|
||||||
|
exception_information_.push_back(
|
||||||
|
minidump_exception_stream_.ExceptionRecord.ExceptionInformation[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialized_.set_valid();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CPUContext* ExceptionSnapshotMinidump::Context() const {
|
||||||
|
DCHECK(initialized_.is_valid());
|
||||||
|
NOTREACHED(); // https://crashpad.chromium.org/bug/10
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ExceptionSnapshotMinidump::ThreadID() const {
|
||||||
|
DCHECK(initialized_.is_valid());
|
||||||
|
return minidump_exception_stream_.ThreadId;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ExceptionSnapshotMinidump::Exception() const {
|
||||||
|
DCHECK(initialized_.is_valid());
|
||||||
|
return minidump_exception_stream_.ExceptionRecord.ExceptionCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ExceptionSnapshotMinidump::ExceptionInfo() const {
|
||||||
|
DCHECK(initialized_.is_valid());
|
||||||
|
return minidump_exception_stream_.ExceptionRecord.ExceptionFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ExceptionSnapshotMinidump::ExceptionAddress() const {
|
||||||
|
DCHECK(initialized_.is_valid());
|
||||||
|
return minidump_exception_stream_.ExceptionRecord.ExceptionAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<uint64_t>& ExceptionSnapshotMinidump::Codes() const {
|
||||||
|
DCHECK(initialized_.is_valid());
|
||||||
|
return exception_information_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const MemorySnapshot*> ExceptionSnapshotMinidump::ExtraMemory()
|
||||||
|
const {
|
||||||
|
DCHECK(initialized_.is_valid());
|
||||||
|
return std::vector<const MemorySnapshot*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace crashpad
|
72
snapshot/minidump/exception_snapshot_minidump.h
Normal file
72
snapshot/minidump/exception_snapshot_minidump.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// Copyright 2019 The Crashpad Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CRASHPAD_SNAPSHOT_MINIDUMP_EXCEPTION_SNAPSHOT_MINIDUMP_H_
|
||||||
|
#define CRASHPAD_SNAPSHOT_MINIDUMP_EXCEPTION_SNAPSHOT_MINIDUMP_H_
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <dbghelp.h>
|
||||||
|
|
||||||
|
#include "build/build_config.h"
|
||||||
|
#include "snapshot/cpu_context.h"
|
||||||
|
#include "snapshot/exception_snapshot.h"
|
||||||
|
#include "util/file/file_reader.h"
|
||||||
|
#include "util/misc/initialization_state.h"
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
//! \brief An ExceptionSnapshot based on a minidump file.
|
||||||
|
class ExceptionSnapshotMinidump final : public ExceptionSnapshot {
|
||||||
|
public:
|
||||||
|
ExceptionSnapshotMinidump();
|
||||||
|
~ExceptionSnapshotMinidump() override;
|
||||||
|
|
||||||
|
//! \brief Initializes the object.
|
||||||
|
//!
|
||||||
|
//! \param[in] file_reader A file reader corresponding to a minidump file.
|
||||||
|
//! The file reader must support seeking.
|
||||||
|
//! \param[in] minidump_exception_stream_rva The file offset in \a file_reader
|
||||||
|
//! at which the MINIDUMP_EXCEPTION_STREAM structure is located.
|
||||||
|
//!
|
||||||
|
//! \return `true` if the snapshot could be created, `false` otherwise with
|
||||||
|
//! an appropriate message logged.
|
||||||
|
bool Initialize(FileReaderInterface* file_reader,
|
||||||
|
RVA minidump_exception_stream_rva);
|
||||||
|
|
||||||
|
// ExceptionSnapshot:
|
||||||
|
const CPUContext* Context() const override;
|
||||||
|
uint64_t ThreadID() const override;
|
||||||
|
uint32_t Exception() const override;
|
||||||
|
uint32_t ExceptionInfo() const override;
|
||||||
|
uint64_t ExceptionAddress() const override;
|
||||||
|
const std::vector<uint64_t>& Codes() const override;
|
||||||
|
std::vector<const MemorySnapshot*> ExtraMemory() const override;
|
||||||
|
|
||||||
|
// Allow callers to explicitly check whether this exception snapshot has been
|
||||||
|
// initialized.
|
||||||
|
bool IsValid() const { return initialized_.is_valid(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
MINIDUMP_EXCEPTION_STREAM minidump_exception_stream_;
|
||||||
|
std::vector<uint64_t> exception_information_;
|
||||||
|
InitializationState initialized_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ExceptionSnapshotMinidump);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace crashpad
|
||||||
|
|
||||||
|
#endif // CRASHPAD_SNAPSHOT_MINIDUMP_EXCEPTION_SNAPSHOT_MINIDUMP_H_
|
@ -53,12 +53,12 @@ ProcessSnapshotMinidump::ProcessSnapshotMinidump()
|
|||||||
custom_streams_(),
|
custom_streams_(),
|
||||||
crashpad_info_(),
|
crashpad_info_(),
|
||||||
system_snapshot_(),
|
system_snapshot_(),
|
||||||
|
exception_snapshot_(),
|
||||||
arch_(CPUArchitecture::kCPUArchitectureUnknown),
|
arch_(CPUArchitecture::kCPUArchitectureUnknown),
|
||||||
annotations_simple_map_(),
|
annotations_simple_map_(),
|
||||||
file_reader_(nullptr),
|
file_reader_(nullptr),
|
||||||
process_id_(static_cast<pid_t>(-1)),
|
process_id_(static_cast<pid_t>(-1)),
|
||||||
initialized_() {
|
initialized_() {}
|
||||||
}
|
|
||||||
|
|
||||||
ProcessSnapshotMinidump::~ProcessSnapshotMinidump() {
|
ProcessSnapshotMinidump::~ProcessSnapshotMinidump() {
|
||||||
}
|
}
|
||||||
@ -109,13 +109,10 @@ bool ProcessSnapshotMinidump::Initialize(FileReaderInterface* file_reader) {
|
|||||||
stream_map_[stream_type] = &directory.Location;
|
stream_map_[stream_type] = &directory.Location;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InitializeCrashpadInfo() ||
|
if (!InitializeCrashpadInfo() || !InitializeMiscInfo() ||
|
||||||
!InitializeMiscInfo() ||
|
!InitializeModules() || !InitializeSystemSnapshot() ||
|
||||||
!InitializeModules() ||
|
!InitializeMemoryInfo() || !InitializeThreads() ||
|
||||||
!InitializeSystemSnapshot() ||
|
!InitializeCustomMinidumpStreams() || !InitializeExceptionSnapshot()) {
|
||||||
!InitializeMemoryInfo() ||
|
|
||||||
!InitializeThreads() ||
|
|
||||||
!InitializeCustomMinidumpStreams()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +209,10 @@ std::vector<UnloadedModuleSnapshot> ProcessSnapshotMinidump::UnloadedModules()
|
|||||||
|
|
||||||
const ExceptionSnapshot* ProcessSnapshotMinidump::Exception() const {
|
const ExceptionSnapshot* ProcessSnapshotMinidump::Exception() const {
|
||||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||||
NOTREACHED(); // https://crashpad.chromium.org/bug/10
|
if (exception_snapshot_.IsValid()) {
|
||||||
|
return &exception_snapshot_;
|
||||||
|
}
|
||||||
|
// Allow caller to know whether the minidump contained an exception stream.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,4 +576,22 @@ bool ProcessSnapshotMinidump::InitializeCustomMinidumpStreams() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProcessSnapshotMinidump::InitializeExceptionSnapshot() {
|
||||||
|
const auto& stream_it = stream_map_.find(kMinidumpStreamTypeException);
|
||||||
|
if (stream_it == stream_map_.end()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream_it->second->DataSize < sizeof(MINIDUMP_EXCEPTION_STREAM)) {
|
||||||
|
LOG(ERROR) << "system info size mismatch";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exception_snapshot_.Initialize(file_reader_, stream_it->second->Rva)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "minidump/minidump_extensions.h"
|
#include "minidump/minidump_extensions.h"
|
||||||
#include "snapshot/exception_snapshot.h"
|
#include "snapshot/exception_snapshot.h"
|
||||||
#include "snapshot/memory_snapshot.h"
|
#include "snapshot/memory_snapshot.h"
|
||||||
|
#include "snapshot/minidump/exception_snapshot_minidump.h"
|
||||||
#include "snapshot/minidump/minidump_stream.h"
|
#include "snapshot/minidump/minidump_stream.h"
|
||||||
#include "snapshot/minidump/module_snapshot_minidump.h"
|
#include "snapshot/minidump/module_snapshot_minidump.h"
|
||||||
#include "snapshot/minidump/system_snapshot_minidump.h"
|
#include "snapshot/minidump/system_snapshot_minidump.h"
|
||||||
@ -129,6 +130,10 @@ class ProcessSnapshotMinidump final : public ProcessSnapshot {
|
|||||||
// Initializes custom minidump streams.
|
// Initializes custom minidump streams.
|
||||||
bool InitializeCustomMinidumpStreams();
|
bool InitializeCustomMinidumpStreams();
|
||||||
|
|
||||||
|
// Initializes data carried in a MINIDUMP_EXCEPTION_STREAM stream on behalf of
|
||||||
|
// Initialize().
|
||||||
|
bool InitializeExceptionSnapshot();
|
||||||
|
|
||||||
MINIDUMP_HEADER header_;
|
MINIDUMP_HEADER header_;
|
||||||
std::vector<MINIDUMP_DIRECTORY> stream_directory_;
|
std::vector<MINIDUMP_DIRECTORY> stream_directory_;
|
||||||
std::map<MinidumpStreamType, const MINIDUMP_LOCATION_DESCRIPTOR*> stream_map_;
|
std::map<MinidumpStreamType, const MINIDUMP_LOCATION_DESCRIPTOR*> stream_map_;
|
||||||
@ -141,6 +146,7 @@ class ProcessSnapshotMinidump final : public ProcessSnapshot {
|
|||||||
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_;
|
||||||
|
internal::ExceptionSnapshotMinidump exception_snapshot_;
|
||||||
CPUArchitecture arch_;
|
CPUArchitecture arch_;
|
||||||
std::map<std::string, std::string> annotations_simple_map_;
|
std::map<std::string, std::string> annotations_simple_map_;
|
||||||
FileReaderInterface* file_reader_; // weak
|
FileReaderInterface* file_reader_; // weak
|
||||||
|
@ -1170,6 +1170,83 @@ TEST(ProcessSnapshotMinidump, CustomMinidumpStreams) {
|
|||||||
EXPECT_STREQ((char*)&stream_data.front(), kStreamUnreservedData);
|
EXPECT_STREQ((char*)&stream_data.front(), kStreamUnreservedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ProcessSnapshotMinidump, Exception) {
|
||||||
|
StringFile string_file;
|
||||||
|
|
||||||
|
MINIDUMP_HEADER header = {};
|
||||||
|
EXPECT_TRUE(string_file.Write(&header, sizeof(header)));
|
||||||
|
|
||||||
|
uint32_t exception_signo =
|
||||||
|
static_cast<uint32_t>(-1); // crashpad::Signals::kSimulatedSigno
|
||||||
|
|
||||||
|
MINIDUMP_EXCEPTION minidump_exception = {};
|
||||||
|
minidump_exception.ExceptionCode = exception_signo;
|
||||||
|
minidump_exception.ExceptionFlags = 2;
|
||||||
|
minidump_exception.ExceptionRecord = 4;
|
||||||
|
minidump_exception.ExceptionAddress = 0xdeedb00f;
|
||||||
|
minidump_exception.NumberParameters = 2;
|
||||||
|
minidump_exception.ExceptionInformation[0] = 51;
|
||||||
|
minidump_exception.ExceptionInformation[1] = 62;
|
||||||
|
|
||||||
|
MINIDUMP_EXCEPTION_STREAM minidump_exception_stream = {};
|
||||||
|
minidump_exception_stream.ThreadId = 5;
|
||||||
|
minidump_exception_stream.ExceptionRecord = minidump_exception;
|
||||||
|
|
||||||
|
MINIDUMP_DIRECTORY minidump_exception_directory = {};
|
||||||
|
minidump_exception_directory.StreamType = kMinidumpStreamTypeException;
|
||||||
|
minidump_exception_directory.Location.DataSize =
|
||||||
|
sizeof(MINIDUMP_EXCEPTION_STREAM);
|
||||||
|
minidump_exception_directory.Location.Rva =
|
||||||
|
static_cast<RVA>(string_file.SeekGet());
|
||||||
|
|
||||||
|
ASSERT_TRUE(string_file.Write(&minidump_exception_stream,
|
||||||
|
sizeof(minidump_exception_stream)));
|
||||||
|
|
||||||
|
header.StreamDirectoryRva = static_cast<RVA>(string_file.SeekGet());
|
||||||
|
ASSERT_TRUE(string_file.Write(&minidump_exception_directory,
|
||||||
|
sizeof(minidump_exception_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));
|
||||||
|
|
||||||
|
const ExceptionSnapshot* s = process_snapshot.Exception();
|
||||||
|
|
||||||
|
EXPECT_EQ(s->ThreadID(), 5UL);
|
||||||
|
EXPECT_EQ(s->Exception(), exception_signo);
|
||||||
|
EXPECT_EQ(s->ExceptionInfo(), 2U);
|
||||||
|
EXPECT_EQ(s->ExceptionAddress(), 0xdeedb00f);
|
||||||
|
|
||||||
|
const std::vector<uint64_t> codes = s->Codes();
|
||||||
|
EXPECT_EQ(codes.size(), 2UL);
|
||||||
|
EXPECT_EQ(codes[0], 51UL);
|
||||||
|
EXPECT_EQ(codes[1], 62UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ProcessSnapshotMinidump, NoExceptionInMinidump) {
|
||||||
|
StringFile string_file;
|
||||||
|
|
||||||
|
MINIDUMP_HEADER header = {};
|
||||||
|
EXPECT_TRUE(string_file.Write(&header, sizeof(header)));
|
||||||
|
|
||||||
|
header.Signature = MINIDUMP_SIGNATURE;
|
||||||
|
header.Version = MINIDUMP_VERSION;
|
||||||
|
header.NumberOfStreams = 0;
|
||||||
|
EXPECT_TRUE(string_file.SeekSet(0));
|
||||||
|
EXPECT_TRUE(string_file.Write(&header, sizeof(header)));
|
||||||
|
|
||||||
|
ProcessSnapshotMinidump process_snapshot;
|
||||||
|
EXPECT_TRUE(process_snapshot.Initialize(&string_file));
|
||||||
|
|
||||||
|
const ExceptionSnapshot* s = process_snapshot.Exception();
|
||||||
|
EXPECT_EQ(s, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -116,6 +116,8 @@
|
|||||||
'minidump/minidump_string_list_reader.h',
|
'minidump/minidump_string_list_reader.h',
|
||||||
'minidump/minidump_string_reader.cc',
|
'minidump/minidump_string_reader.cc',
|
||||||
'minidump/minidump_string_reader.h',
|
'minidump/minidump_string_reader.h',
|
||||||
|
'minidump/exception_snapshot_minidump.cc',
|
||||||
|
'minidump/exception_snapshot_minidump.h',
|
||||||
'minidump/memory_snapshot_minidump.cc',
|
'minidump/memory_snapshot_minidump.cc',
|
||||||
'minidump/memory_snapshot_minidump.h',
|
'minidump/memory_snapshot_minidump.h',
|
||||||
'minidump/module_snapshot_minidump.cc',
|
'minidump/module_snapshot_minidump.cc',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user