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:
Scott Graham 2016-02-29 13:28:05 -08:00
parent 70ae71fe51
commit c307f94f19
22 changed files with 468 additions and 2 deletions

View File

@ -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

View File

@ -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_;

View File

@ -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

View File

@ -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(

View File

@ -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',

View File

@ -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 =

View File

@ -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',

View 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

View 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_

View 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

View File

@ -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

View File

@ -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_;

View File

@ -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)

View File

@ -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*

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
};

View File

@ -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',

View File

@ -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

View File

@ -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

View File

@ -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