mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
Support custom streams in the minidump
BUG=crashpad:95 Change-Id: Iee956906651dfd56e0ae3d2bcec82daabdc97067 Reviewed-on: https://chromium-review.googlesource.com/329733 Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
parent
70ae71fe51
commit
c307f94f19
@ -101,7 +101,8 @@ CrashpadInfo::CrashpadInfo()
|
||||
gather_indirectly_referenced_memory_(TriState::kUnset),
|
||||
padding_0_(0),
|
||||
extra_memory_ranges_(nullptr),
|
||||
simple_annotations_(nullptr)
|
||||
simple_annotations_(nullptr),
|
||||
user_data_minidump_stream_head_(nullptr)
|
||||
#if !defined(NDEBUG) && defined(OS_WIN)
|
||||
,
|
||||
invalid_read_detection_(0xbadc0de)
|
||||
@ -109,4 +110,17 @@ CrashpadInfo::CrashpadInfo()
|
||||
{
|
||||
}
|
||||
|
||||
void CrashpadInfo::AddUserDataMinidumpStream(uint32_t stream_type,
|
||||
const void* data,
|
||||
size_t size) {
|
||||
auto to_be_added = new internal::UserDataMinidumpStreamListEntry();
|
||||
to_be_added->next = base::checked_cast<uint64_t>(
|
||||
reinterpret_cast<uintptr_t>(user_data_minidump_stream_head_));
|
||||
to_be_added->stream_type = stream_type;
|
||||
to_be_added->base_address =
|
||||
base::checked_cast<uint64_t>(reinterpret_cast<uintptr_t>(data));
|
||||
to_be_added->size = base::checked_cast<uint64_t>(size);
|
||||
user_data_minidump_stream_head_ = to_be_added;
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
||||
|
@ -29,6 +29,29 @@
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
namespace internal {
|
||||
|
||||
//! \brief A linked list of blocks representing custom streams in the minidump,
|
||||
//! with addresses (and size) stored as uint64_t to simplify reading from
|
||||
//! the handler process.
|
||||
struct UserDataMinidumpStreamListEntry {
|
||||
//! \brief The address of the next entry in the linked list.
|
||||
uint64_t next;
|
||||
|
||||
//! \brief The base address of the memory block in the target process' address
|
||||
//! space that represents the user data stream.
|
||||
uint64_t base_address;
|
||||
|
||||
//! \brief The size of memory block in the target process' address space that
|
||||
//! represents the user data stream.
|
||||
uint64_t size;
|
||||
|
||||
//! \brief The stream type identifier.
|
||||
uint32_t stream_type;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
//! \brief A structure that can be used by a Crashpad-enabled program to
|
||||
//! provide information to the Crashpad crash handler.
|
||||
//!
|
||||
@ -89,7 +112,7 @@ struct CrashpadInfo {
|
||||
//! that it has been disabled.
|
||||
//!
|
||||
//! The Crashpad handler should not normally be disabled. More commonly, it
|
||||
//! is appropraite to disable crash report upload by calling
|
||||
//! is appropriate to disable crash report upload by calling
|
||||
//! Settings::SetUploadsEnabled().
|
||||
void set_crashpad_handler_behavior(TriState crashpad_handler_behavior) {
|
||||
crashpad_handler_behavior_ = crashpad_handler_behavior;
|
||||
@ -130,6 +153,27 @@ struct CrashpadInfo {
|
||||
gather_indirectly_referenced_memory_ = gather_indirectly_referenced_memory;
|
||||
}
|
||||
|
||||
//! \brief Adds a custom stream to the minidump.
|
||||
//!
|
||||
//! The memory block referenced by \a data and \a size will added to the
|
||||
//! minidump as separate stream with type \stream_type. The memory referred to
|
||||
//! by \a data and \a size is owned by the caller and must remain valid while
|
||||
//! it is in effect for the CrashpadInfo object.
|
||||
//!
|
||||
//! Note that streams will appear in the minidump in the reverse order to
|
||||
//! which they are added.
|
||||
//!
|
||||
//! TODO(scottmg) This is currently only supported on Windows.
|
||||
//!
|
||||
//! \param[in] stream_type The stream type identifier to use. This should be
|
||||
//! normally be larger than `MINIDUMP_STREAM_TYPE::LastReservedStream`
|
||||
//! which is `0xffff`.
|
||||
//! \param[in] data The base pointer of the stream data.
|
||||
//! \param[in] size The size of the stream data.
|
||||
void AddUserDataMinidumpStream(uint32_t stream_type,
|
||||
const void* data,
|
||||
size_t size);
|
||||
|
||||
enum : uint32_t {
|
||||
kSignature = 'CPad',
|
||||
};
|
||||
@ -154,6 +198,7 @@ struct CrashpadInfo {
|
||||
uint8_t padding_0_;
|
||||
SimpleAddressRangeBag* extra_memory_ranges_; // weak
|
||||
SimpleStringDictionary* simple_annotations_; // weak
|
||||
internal::UserDataMinidumpStreamListEntry* user_data_minidump_stream_head_;
|
||||
|
||||
#if !defined(NDEBUG) && defined(OS_WIN)
|
||||
uint32_t invalid_read_detection_;
|
||||
|
@ -176,6 +176,10 @@ enum MINIDUMP_STREAM_TYPE {
|
||||
|
||||
//! \brief The stream type for MINIDUMP_MEMORY_INFO_LIST.
|
||||
MemoryInfoListStream = 16,
|
||||
|
||||
//! \brief Values greater than this value will not be used by the system
|
||||
//! and can be used for custom user data streams.
|
||||
LastReservedStream = 0xffff,
|
||||
};
|
||||
|
||||
//! \brief Information about the CPU (or CPUs) that ran the process that the
|
||||
|
@ -225,6 +225,18 @@ int CrashyMain(int argc, wchar_t* argv[]) {
|
||||
crashpad::CrashpadInfo::GetCrashpadInfo()
|
||||
->set_gather_indirectly_referenced_memory(TriState::kEnabled);
|
||||
|
||||
std::vector<uint8_t> data_stream1(128, 'x');
|
||||
crashpad::CrashpadInfo::GetCrashpadInfo()->AddUserDataMinidumpStream(
|
||||
222222,
|
||||
reinterpret_cast<const void*>(data_stream1.data()),
|
||||
data_stream1.size());
|
||||
|
||||
std::vector<uint8_t> data_stream2(4096, 'z');
|
||||
crashpad::CrashpadInfo::GetCrashpadInfo()->AddUserDataMinidumpStream(
|
||||
333333,
|
||||
reinterpret_cast<const void*>(data_stream2.data()),
|
||||
data_stream2.size());
|
||||
|
||||
AllocateMemoryOfVariousProtections();
|
||||
|
||||
if (InitializeCriticalSectionWithDebugInfoIfPossible(
|
||||
|
@ -72,6 +72,8 @@
|
||||
'minidump_thread_writer.h',
|
||||
'minidump_unloaded_module_writer.cc',
|
||||
'minidump_unloaded_module_writer.h',
|
||||
'minidump_user_stream_writer.cc',
|
||||
'minidump_user_stream_writer.h',
|
||||
'minidump_writable.cc',
|
||||
'minidump_writable.h',
|
||||
'minidump_writer_util.cc',
|
||||
|
@ -28,8 +28,10 @@
|
||||
#include "minidump/minidump_thread_id_map.h"
|
||||
#include "minidump/minidump_thread_writer.h"
|
||||
#include "minidump/minidump_unloaded_module_writer.h"
|
||||
#include "minidump/minidump_user_stream_writer.h"
|
||||
#include "minidump/minidump_writer_util.h"
|
||||
#include "snapshot/exception_snapshot.h"
|
||||
#include "snapshot/module_snapshot.h"
|
||||
#include "snapshot/process_snapshot.h"
|
||||
#include "util/file/file_writer.h"
|
||||
#include "util/numeric/safe_assignment.h"
|
||||
@ -96,6 +98,14 @@ void MinidumpFileWriter::InitializeFromSnapshot(
|
||||
module_list->InitializeFromSnapshot(process_snapshot->Modules());
|
||||
AddStream(std::move(module_list));
|
||||
|
||||
for (const auto& module : process_snapshot->Modules()) {
|
||||
for (const UserMinidumpStream* stream : module->CustomMinidumpStreams()) {
|
||||
auto user_stream = make_scoped_ptr(new MinidumpUserStreamWriter());
|
||||
user_stream->InitializeFromSnapshot(stream);
|
||||
AddStream(std::move(user_stream));
|
||||
}
|
||||
}
|
||||
|
||||
auto unloaded_modules = process_snapshot->UnloadedModules();
|
||||
if (!unloaded_modules.empty()) {
|
||||
auto unloaded_module_list =
|
||||
|
@ -50,6 +50,7 @@
|
||||
'minidump_thread_id_map_test.cc',
|
||||
'minidump_thread_writer_test.cc',
|
||||
'minidump_unloaded_module_writer_test.cc',
|
||||
'minidump_user_stream_writer_test.cc',
|
||||
'minidump_writable_test.cc',
|
||||
'test/minidump_context_test_util.cc',
|
||||
'test/minidump_context_test_util.h',
|
||||
|
73
minidump/minidump_user_stream_writer.cc
Normal file
73
minidump/minidump_user_stream_writer.cc
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2016 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 "minidump/minidump_user_stream_writer.h"
|
||||
|
||||
#include "util/file/file_writer.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
MinidumpUserStreamWriter::MinidumpUserStreamWriter()
|
||||
: stream_type_(0), reader_() {
|
||||
}
|
||||
|
||||
MinidumpUserStreamWriter::~MinidumpUserStreamWriter() {
|
||||
}
|
||||
|
||||
void MinidumpUserStreamWriter::InitializeFromSnapshot(
|
||||
const UserMinidumpStream* stream) {
|
||||
DCHECK_EQ(state(), kStateMutable);
|
||||
|
||||
stream_type_ = stream->stream_type();
|
||||
if (stream->memory())
|
||||
stream->memory()->Read(&reader_);
|
||||
}
|
||||
|
||||
bool MinidumpUserStreamWriter::Freeze() {
|
||||
DCHECK_EQ(state(), kStateMutable);
|
||||
DCHECK_NE(stream_type_, 0u);
|
||||
return MinidumpStreamWriter::Freeze();
|
||||
}
|
||||
|
||||
size_t MinidumpUserStreamWriter::SizeOfObject() {
|
||||
DCHECK_GE(state(), kStateFrozen);
|
||||
return reader_.size();
|
||||
}
|
||||
|
||||
std::vector<internal::MinidumpWritable*>
|
||||
MinidumpUserStreamWriter::Children() {
|
||||
DCHECK_GE(state(), kStateFrozen);
|
||||
return std::vector<internal::MinidumpWritable*>();
|
||||
}
|
||||
|
||||
bool MinidumpUserStreamWriter::WriteObject(FileWriterInterface* file_writer) {
|
||||
DCHECK_EQ(state(), kStateWritable);
|
||||
return file_writer->Write(reader_.data(), reader_.size());
|
||||
}
|
||||
|
||||
MinidumpStreamType MinidumpUserStreamWriter::StreamType() const {
|
||||
return static_cast<MinidumpStreamType>(stream_type_);
|
||||
}
|
||||
|
||||
MinidumpUserStreamWriter::MemoryReader::~MemoryReader() {}
|
||||
|
||||
bool MinidumpUserStreamWriter::MemoryReader::MemorySnapshotDelegateRead(
|
||||
void* data,
|
||||
size_t size) {
|
||||
data_.resize(size);
|
||||
memcpy(&data_[0], data, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
77
minidump/minidump_user_stream_writer.h
Normal file
77
minidump/minidump_user_stream_writer.h
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2016 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_MINIDUMP_MINIDUMP_USER_STREAM_WRITER_H_
|
||||
#define CRASHPAD_MINIDUMP_MINIDUMP_USER_STREAM_WRITER_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "minidump/minidump_stream_writer.h"
|
||||
#include "minidump/minidump_writable.h"
|
||||
#include "snapshot/module_snapshot.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
//! \brief The writer for a MINIDUMP_USER_STREAM in a minidump file.
|
||||
class MinidumpUserStreamWriter final : public internal::MinidumpStreamWriter {
|
||||
public:
|
||||
MinidumpUserStreamWriter();
|
||||
~MinidumpUserStreamWriter() override;
|
||||
|
||||
//! \brief Initializes a MINIDUMP_USER_STREAM based on \a stream.
|
||||
//!
|
||||
//! \param[in] stream The memory and stream type to use as source data.
|
||||
//!
|
||||
//! \note Valid in #kStateMutable.
|
||||
void InitializeFromSnapshot(const UserMinidumpStream* stream);
|
||||
|
||||
protected:
|
||||
// MinidumpWritable:
|
||||
bool Freeze() override;
|
||||
size_t SizeOfObject() override;
|
||||
std::vector<internal::MinidumpWritable*> Children() override;
|
||||
bool WriteObject(FileWriterInterface* file_writer) override;
|
||||
|
||||
// MinidumpStreamWriter:
|
||||
MinidumpStreamType StreamType() const override;
|
||||
|
||||
private:
|
||||
class MemoryReader : public MemorySnapshot::Delegate {
|
||||
public:
|
||||
~MemoryReader() override;
|
||||
bool MemorySnapshotDelegateRead(void* data, size_t size) override;
|
||||
|
||||
const void* data() const {
|
||||
return reinterpret_cast<const void*>(data_.data());
|
||||
}
|
||||
size_t size() const { return data_.size(); }
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> data_;
|
||||
};
|
||||
|
||||
uint32_t stream_type_;
|
||||
MemoryReader reader_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MinidumpUserStreamWriter);
|
||||
};
|
||||
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_MINIDUMP_MINIDUMP_USER_STREAM_WRITER_H_
|
104
minidump/minidump_user_stream_writer_test.cc
Normal file
104
minidump/minidump_user_stream_writer_test.cc
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2016 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 "minidump/minidump_user_stream_writer.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "minidump/minidump_file_writer.h"
|
||||
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||
#include "minidump/test/minidump_writable_test_util.h"
|
||||
#include "snapshot/test/test_memory_snapshot.h"
|
||||
#include "util/file/string_file.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
// The user stream is expected to be the only stream.
|
||||
void GetUserStream(const std::string& file_contents,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR* user_stream_location,
|
||||
uint32_t stream_type) {
|
||||
const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER);
|
||||
const size_t kUserStreamOffset =
|
||||
kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY);
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
MinidumpHeaderAtStart(file_contents, &directory);
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
const size_t kDirectoryIndex = 0;
|
||||
|
||||
ASSERT_EQ(stream_type, directory[kDirectoryIndex].StreamType);
|
||||
EXPECT_EQ(kUserStreamOffset, directory[kDirectoryIndex].Location.Rva);
|
||||
*user_stream_location = directory[kDirectoryIndex].Location;
|
||||
}
|
||||
|
||||
TEST(MinidumpUserStreamWriter, NoData) {
|
||||
MinidumpFileWriter minidump_file_writer;
|
||||
auto user_stream_writer = make_scoped_ptr(new MinidumpUserStreamWriter());
|
||||
const uint32_t kTestStreamId = 0x123456;
|
||||
auto stream = make_scoped_ptr(new UserMinidumpStream(kTestStreamId, nullptr));
|
||||
user_stream_writer->InitializeFromSnapshot(stream.get());
|
||||
minidump_file_writer.AddStream(std::move(user_stream_writer));
|
||||
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY),
|
||||
string_file.string().size());
|
||||
|
||||
MINIDUMP_LOCATION_DESCRIPTOR user_stream_location;
|
||||
ASSERT_NO_FATAL_FAILURE(GetUserStream(
|
||||
string_file.string(), &user_stream_location, kTestStreamId));
|
||||
EXPECT_EQ(0u, user_stream_location.DataSize);
|
||||
}
|
||||
|
||||
TEST(MinidumpUserStreamWriter, OneStream) {
|
||||
MinidumpFileWriter minidump_file_writer;
|
||||
auto user_stream_writer = make_scoped_ptr(new MinidumpUserStreamWriter());
|
||||
const uint32_t kTestStreamId = 0x123456;
|
||||
|
||||
TestMemorySnapshot* test_data = new TestMemorySnapshot();
|
||||
test_data->SetAddress(97865);
|
||||
const size_t kStreamSize = 128;
|
||||
test_data->SetSize(kStreamSize);
|
||||
test_data->SetValue('c');
|
||||
auto stream =
|
||||
make_scoped_ptr(new UserMinidumpStream(kTestStreamId, test_data));
|
||||
user_stream_writer->InitializeFromSnapshot(stream.get());
|
||||
minidump_file_writer.AddStream(std::move(user_stream_writer));
|
||||
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + kStreamSize,
|
||||
string_file.string().size());
|
||||
|
||||
MINIDUMP_LOCATION_DESCRIPTOR user_stream_location;
|
||||
ASSERT_NO_FATAL_FAILURE(GetUserStream(
|
||||
string_file.string(), &user_stream_location, kTestStreamId));
|
||||
EXPECT_EQ(kStreamSize, user_stream_location.DataSize);
|
||||
const std::string stream_data = string_file.string().substr(
|
||||
user_stream_location.Rva, user_stream_location.DataSize);
|
||||
EXPECT_EQ(std::string(kStreamSize, 'c'), stream_data);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
@ -187,5 +187,10 @@ std::set<CheckedRange<uint64_t>> ModuleSnapshotMac::ExtraMemoryRanges() const {
|
||||
return std::set<CheckedRange<uint64_t>>();
|
||||
}
|
||||
|
||||
std::vector<const UserMinidumpStream*>
|
||||
ModuleSnapshotMac::CustomMinidumpStreams() const {
|
||||
return std::vector<const UserMinidumpStream*>();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
||||
|
@ -80,6 +80,7 @@ class ModuleSnapshotMac final : public ModuleSnapshot {
|
||||
std::vector<std::string> AnnotationsVector() const override;
|
||||
std::map<std::string, std::string> AnnotationsSimpleMap() const override;
|
||||
std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const override;
|
||||
std::vector<const UserMinidumpStream*> CustomMinidumpStreams() const override;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
|
@ -42,4 +42,7 @@ PROCESS_TYPE_STRUCT_BEGIN(CrashpadInfo)
|
||||
|
||||
// SimpleStringDictionary*
|
||||
PROCESS_TYPE_STRUCT_MEMBER(Pointer, simple_annotations)
|
||||
|
||||
// UserDataStreamListEntry*
|
||||
PROCESS_TYPE_STRUCT_MEMBER(Pointer, user_data_minidump_stream_head)
|
||||
PROCESS_TYPE_STRUCT_END(CrashpadInfo)
|
||||
|
@ -138,9 +138,17 @@ ModuleSnapshotMinidump::AnnotationsSimpleMap() const {
|
||||
std::set<CheckedRange<uint64_t>> ModuleSnapshotMinidump::ExtraMemoryRanges()
|
||||
const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED(); // https://crashpad.chromium.org/bug/10
|
||||
return std::set<CheckedRange<uint64_t>>();
|
||||
}
|
||||
|
||||
std::vector<const UserMinidumpStream*>
|
||||
ModuleSnapshotMinidump::CustomMinidumpStreams() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED(); // https://crashpad.chromium.org/bug/10
|
||||
return std::vector<const UserMinidumpStream*>();
|
||||
}
|
||||
|
||||
bool ModuleSnapshotMinidump::InitializeModuleCrashpadInfo(
|
||||
FileReaderInterface* file_reader,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR*
|
||||
|
@ -77,6 +77,7 @@ class ModuleSnapshotMinidump final : public ModuleSnapshot {
|
||||
std::vector<std::string> AnnotationsVector() const override;
|
||||
std::map<std::string, std::string> AnnotationsSimpleMap() const override;
|
||||
std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const override;
|
||||
std::vector<const UserMinidumpStream*> CustomMinidumpStreams() const override;
|
||||
|
||||
private:
|
||||
// Initializes data carried in a MinidumpModuleCrashpadInfo structure on
|
||||
|
@ -23,11 +23,35 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "util/misc/uuid.h"
|
||||
#include "util/numeric/checked_range.h"
|
||||
#include "snapshot/memory_snapshot.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
class MemorySnapshot;
|
||||
|
||||
//! \brief Information describing a custom user data stream in a minidump.
|
||||
class UserMinidumpStream {
|
||||
public:
|
||||
//! \brief Constructs a UserMinidumpStream, takes ownership of \a memory.
|
||||
UserMinidumpStream(uint32_t stream_type, MemorySnapshot* memory)
|
||||
: memory_(memory), stream_type_(stream_type) {}
|
||||
|
||||
const MemorySnapshot* memory() const { return memory_.get(); }
|
||||
uint32_t stream_type() const { return stream_type_; }
|
||||
|
||||
private:
|
||||
//! \brief The memory representing the custom minidump stream.
|
||||
scoped_ptr<MemorySnapshot> memory_;
|
||||
|
||||
//! \brief The stream type that the minidump stream will be tagged with.
|
||||
uint32_t stream_type_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(UserMinidumpStream);
|
||||
};
|
||||
|
||||
//! \brief An abstract interface to a snapshot representing a code module
|
||||
//! (binary image) loaded into a snapshot process.
|
||||
class ModuleSnapshot {
|
||||
@ -174,6 +198,15 @@ class ModuleSnapshot {
|
||||
//! \brief Returns a set of extra memory ranges specified in the module as
|
||||
//! being desirable to include in the crash dump.
|
||||
virtual std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const = 0;
|
||||
|
||||
//! \brief Returns a list of custom minidump stream specified in the module to
|
||||
//! be included in the crash dump.
|
||||
//!
|
||||
//! \return The caller does not take ownership of the returned objects, they
|
||||
//! are scoped to the lifetime of the ModuleSnapshot object that they were
|
||||
//! obtained from.
|
||||
virtual std::vector<const UserMinidumpStream*> CustomMinidumpStreams()
|
||||
const = 0;
|
||||
};
|
||||
|
||||
} // namespace crashpad
|
||||
|
@ -98,5 +98,10 @@ std::set<CheckedRange<uint64_t>> TestModuleSnapshot::ExtraMemoryRanges() const {
|
||||
return extra_memory_ranges_;
|
||||
}
|
||||
|
||||
std::vector<const UserMinidumpStream*>
|
||||
TestModuleSnapshot::CustomMinidumpStreams() const {
|
||||
return custom_minidump_streams_;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "snapshot/module_snapshot.h"
|
||||
#include "util/stdlib/pointer_container.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
@ -79,6 +80,9 @@ class TestModuleSnapshot final : public ModuleSnapshot {
|
||||
const std::set<CheckedRange<uint64_t>>& extra_memory_ranges) {
|
||||
extra_memory_ranges_ = extra_memory_ranges;
|
||||
}
|
||||
void AddCustomMinidumpStream(const UserMinidumpStream* stream) {
|
||||
custom_minidump_streams_.push_back(stream);
|
||||
}
|
||||
|
||||
// ModuleSnapshot:
|
||||
|
||||
@ -100,6 +104,7 @@ class TestModuleSnapshot final : public ModuleSnapshot {
|
||||
std::vector<std::string> AnnotationsVector() const override;
|
||||
std::map<std::string, std::string> AnnotationsSimpleMap() const override;
|
||||
std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const override;
|
||||
std::vector<const UserMinidumpStream*> CustomMinidumpStreams() const override;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
@ -115,6 +120,7 @@ class TestModuleSnapshot final : public ModuleSnapshot {
|
||||
std::vector<std::string> annotations_vector_;
|
||||
std::map<std::string, std::string> annotations_simple_map_;
|
||||
std::set<CheckedRange<uint64_t>> extra_memory_ranges_;
|
||||
PointerVector<const UserMinidumpStream> custom_minidump_streams_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TestModuleSnapshot);
|
||||
};
|
||||
|
@ -290,6 +290,12 @@ def RunTests(cdb_path,
|
||||
r'\?\?\?\?\?\?\?\? \?\?\?\?\?\?\?\?',
|
||||
'extra memory removal')
|
||||
|
||||
out = CdbRun(cdb_path, dump_path, '.dumpdebug')
|
||||
out.Check(r'type \?\?\? \(333333\), size 00001000',
|
||||
'first user stream')
|
||||
out.Check(r'type \?\?\? \(222222\), size 00000080',
|
||||
'second user stream')
|
||||
|
||||
if z7_dump_path:
|
||||
out = CdbRun(cdb_path, z7_dump_path, '.ecxr;lm')
|
||||
out.Check('This dump file has an exception of interest stored in it',
|
||||
|
@ -15,7 +15,9 @@
|
||||
#include "snapshot/win/module_snapshot_win.h"
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "client/crashpad_info.h"
|
||||
#include "client/simple_address_range_bag.h"
|
||||
#include "snapshot/win/memory_snapshot_win.h"
|
||||
#include "snapshot/win/pe_image_annotations_reader.h"
|
||||
#include "snapshot/win/pe_image_reader.h"
|
||||
#include "util/misc/tri_state.h"
|
||||
@ -196,6 +198,24 @@ std::set<CheckedRange<uint64_t>> ModuleSnapshotWin::ExtraMemoryRanges() const {
|
||||
return ranges;
|
||||
}
|
||||
|
||||
std::vector<const UserMinidumpStream*>
|
||||
ModuleSnapshotWin::CustomMinidumpStreams() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
streams_.clear();
|
||||
if (process_reader_->Is64Bit()) {
|
||||
GetCrashpadUserMinidumpStreams<process_types::internal::Traits64>(
|
||||
&streams_);
|
||||
} else {
|
||||
GetCrashpadUserMinidumpStreams<process_types::internal::Traits32>(
|
||||
&streams_);
|
||||
}
|
||||
|
||||
std::vector<const UserMinidumpStream*> result;
|
||||
for (const auto* stream : streams_)
|
||||
result.push_back(stream);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Traits>
|
||||
void ModuleSnapshotWin::GetCrashpadOptionsInternal(
|
||||
CrashpadInfoClientOptions* options) {
|
||||
@ -262,5 +282,32 @@ void ModuleSnapshotWin::GetCrashpadExtraMemoryRanges(
|
||||
}
|
||||
}
|
||||
|
||||
template <class Traits>
|
||||
void ModuleSnapshotWin::GetCrashpadUserMinidumpStreams(
|
||||
PointerVector<const UserMinidumpStream>* streams) const {
|
||||
process_types::CrashpadInfo<Traits> crashpad_info;
|
||||
if (!pe_image_reader_->GetCrashpadInfo(&crashpad_info))
|
||||
return;
|
||||
|
||||
for (uint64_t cur = crashpad_info.user_data_minidump_stream_head; cur;) {
|
||||
internal::UserDataMinidumpStreamListEntry list_entry;
|
||||
if (!process_reader_->ReadMemory(
|
||||
cur, sizeof(list_entry), &list_entry)) {
|
||||
LOG(WARNING) << "could not read user data stream entry from "
|
||||
<< base::UTF16ToUTF8(name_);
|
||||
return;
|
||||
}
|
||||
|
||||
scoped_ptr<internal::MemorySnapshotWin> memory(
|
||||
new internal::MemorySnapshotWin());
|
||||
memory->Initialize(
|
||||
process_reader_, list_entry.base_address, list_entry.size);
|
||||
streams->push_back(
|
||||
new UserMinidumpStream(list_entry.stream_type, memory.release()));
|
||||
|
||||
cur = list_entry.next;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "snapshot/win/process_reader_win.h"
|
||||
#include "util/misc/initialization_state.h"
|
||||
#include "util/misc/initialization_state_dcheck.h"
|
||||
#include "util/stdlib/pointer_container.h"
|
||||
#include "util/win/process_info.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -86,6 +87,7 @@ class ModuleSnapshotWin final : public ModuleSnapshot {
|
||||
std::vector<std::string> AnnotationsVector() const override;
|
||||
std::map<std::string, std::string> AnnotationsSimpleMap() const override;
|
||||
std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const override;
|
||||
std::vector<const UserMinidumpStream*> CustomMinidumpStreams() const override;
|
||||
|
||||
private:
|
||||
template <class Traits>
|
||||
@ -95,6 +97,10 @@ class ModuleSnapshotWin final : public ModuleSnapshot {
|
||||
void GetCrashpadExtraMemoryRanges(
|
||||
std::set<CheckedRange<uint64_t>>* ranges) const;
|
||||
|
||||
template <class Traits>
|
||||
void GetCrashpadUserMinidumpStreams(
|
||||
PointerVector<const UserMinidumpStream>* streams) const;
|
||||
|
||||
// Initializes vs_fixed_file_info_ if it has not yet been initialized, and
|
||||
// returns a pointer to it. Returns nullptr on failure, with a message logged
|
||||
// on the first call.
|
||||
@ -107,6 +113,8 @@ class ModuleSnapshotWin final : public ModuleSnapshot {
|
||||
ProcessReaderWin* process_reader_; // weak
|
||||
time_t timestamp_;
|
||||
uint32_t age_;
|
||||
// Too const-y: https://crashpad.chromium.org/bug/9.
|
||||
mutable PointerVector<const UserMinidumpStream> streams_;
|
||||
InitializationStateDcheck initialized_;
|
||||
|
||||
// VSFixedFileInfo() is logically const, but updates these members on the
|
||||
|
@ -45,6 +45,7 @@ struct CrashpadInfo {
|
||||
uint8_t padding_0;
|
||||
typename Traits::Pointer extra_address_ranges;
|
||||
typename Traits::Pointer simple_annotations;
|
||||
typename Traits::Pointer user_data_minidump_stream_head;
|
||||
};
|
||||
|
||||
} // namespace process_types
|
||||
|
Loading…
x
Reference in New Issue
Block a user