| Index: third_party/crashpad/crashpad/minidump/minidump_file_writer.cc
|
| diff --git a/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc
|
| index 6a91ca6b2067cbc00f99723b513a3c69f8832327..3e99d2a3932ea08c27c152f991a7db186af92371 100644
|
| --- a/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc
|
| +++ b/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc
|
| @@ -29,6 +29,7 @@
|
| #include "minidump/minidump_thread_id_map.h"
|
| #include "minidump/minidump_thread_writer.h"
|
| #include "minidump/minidump_unloaded_module_writer.h"
|
| +#include "minidump/minidump_user_extension_stream_data_source.h"
|
| #include "minidump/minidump_user_stream_writer.h"
|
| #include "minidump/minidump_writer_util.h"
|
| #include "snapshot/exception_snapshot.h"
|
| @@ -74,11 +75,13 @@ void MinidumpFileWriter::InitializeFromSnapshot(
|
| const SystemSnapshot* system_snapshot = process_snapshot->System();
|
| auto system_info = base::WrapUnique(new MinidumpSystemInfoWriter());
|
| system_info->InitializeFromSnapshot(system_snapshot);
|
| - AddStream(std::move(system_info));
|
| + bool add_stream_result = AddStream(std::move(system_info));
|
| + DCHECK(add_stream_result);
|
|
|
| auto misc_info = base::WrapUnique(new MinidumpMiscInfoWriter());
|
| misc_info->InitializeFromSnapshot(process_snapshot);
|
| - AddStream(std::move(misc_info));
|
| + add_stream_result = AddStream(std::move(misc_info));
|
| + DCHECK(add_stream_result);
|
|
|
| auto memory_list = base::WrapUnique(new MinidumpMemoryListWriter());
|
| auto thread_list = base::WrapUnique(new MinidumpThreadListWriter());
|
| @@ -86,33 +89,29 @@ void MinidumpFileWriter::InitializeFromSnapshot(
|
| MinidumpThreadIDMap thread_id_map;
|
| thread_list->InitializeFromSnapshot(process_snapshot->Threads(),
|
| &thread_id_map);
|
| - AddStream(std::move(thread_list));
|
| + add_stream_result = AddStream(std::move(thread_list));
|
| + DCHECK(add_stream_result);
|
|
|
| const ExceptionSnapshot* exception_snapshot = process_snapshot->Exception();
|
| if (exception_snapshot) {
|
| auto exception = base::WrapUnique(new MinidumpExceptionWriter());
|
| exception->InitializeFromSnapshot(exception_snapshot, thread_id_map);
|
| - AddStream(std::move(exception));
|
| + add_stream_result = AddStream(std::move(exception));
|
| + DCHECK(add_stream_result);
|
| }
|
|
|
| auto module_list = base::WrapUnique(new MinidumpModuleListWriter());
|
| 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 = base::WrapUnique(new MinidumpUserStreamWriter());
|
| - user_stream->InitializeFromSnapshot(stream);
|
| - AddStream(std::move(user_stream));
|
| - }
|
| - }
|
| + add_stream_result = AddStream(std::move(module_list));
|
| + DCHECK(add_stream_result);
|
|
|
| auto unloaded_modules = process_snapshot->UnloadedModules();
|
| if (!unloaded_modules.empty()) {
|
| auto unloaded_module_list =
|
| base::WrapUnique(new MinidumpUnloadedModuleListWriter());
|
| unloaded_module_list->InitializeFromSnapshot(unloaded_modules);
|
| - AddStream(std::move(unloaded_module_list));
|
| + add_stream_result = AddStream(std::move(unloaded_module_list));
|
| + DCHECK(add_stream_result);
|
| }
|
|
|
| auto crashpad_info = base::WrapUnique(new MinidumpCrashpadInfoWriter());
|
| @@ -121,7 +120,8 @@ void MinidumpFileWriter::InitializeFromSnapshot(
|
| // Since the MinidumpCrashpadInfo stream is an extension, it’s safe to not add
|
| // it to the minidump file if it wouldn’t carry any useful information.
|
| if (crashpad_info->IsUseful()) {
|
| - AddStream(std::move(crashpad_info));
|
| + add_stream_result = AddStream(std::move(crashpad_info));
|
| + DCHECK(add_stream_result);
|
| }
|
|
|
| std::vector<const MemoryMapRegionSnapshot*> memory_map_snapshot =
|
| @@ -130,21 +130,50 @@ void MinidumpFileWriter::InitializeFromSnapshot(
|
| auto memory_info_list =
|
| base::WrapUnique(new MinidumpMemoryInfoListWriter());
|
| memory_info_list->InitializeFromSnapshot(memory_map_snapshot);
|
| - AddStream(std::move(memory_info_list));
|
| + add_stream_result = AddStream(std::move(memory_info_list));
|
| + DCHECK(add_stream_result);
|
| }
|
|
|
| std::vector<HandleSnapshot> handles_snapshot = process_snapshot->Handles();
|
| if (!handles_snapshot.empty()) {
|
| auto handle_data_writer = base::WrapUnique(new MinidumpHandleDataWriter());
|
| handle_data_writer->InitializeFromSnapshot(handles_snapshot);
|
| - AddStream(std::move(handle_data_writer));
|
| + add_stream_result = AddStream(std::move(handle_data_writer));
|
| + DCHECK(add_stream_result);
|
| }
|
|
|
| memory_list->AddFromSnapshot(process_snapshot->ExtraMemory());
|
| - if (exception_snapshot)
|
| + if (exception_snapshot) {
|
| memory_list->AddFromSnapshot(exception_snapshot->ExtraMemory());
|
| + }
|
| +
|
| + // These user streams must be added last. Otherwise, a user stream with the
|
| + // same type as a well-known stream could preempt the well-known stream. As it
|
| + // stands now, earlier-discovered user streams can still preempt
|
| + // later-discovered ones. The well-known memory list stream is added after
|
| + // these user streams, but only with a check here to avoid adding a user
|
| + // stream that would preempt the memory list stream.
|
| + for (const auto& module : process_snapshot->Modules()) {
|
| + for (const UserMinidumpStream* stream : module->CustomMinidumpStreams()) {
|
| + if (stream->stream_type() == kMinidumpStreamTypeMemoryList) {
|
| + LOG(WARNING) << "discarding duplicate stream of type "
|
| + << stream->stream_type();
|
| + continue;
|
| + }
|
| + auto user_stream = base::WrapUnique(new MinidumpUserStreamWriter());
|
| + user_stream->InitializeFromSnapshot(stream);
|
| + AddStream(std::move(user_stream));
|
| + }
|
| + }
|
|
|
| - AddStream(std::move(memory_list));
|
| + // The memory list stream should be added last. This keeps the “extra memory”
|
| + // at the end so that if the minidump file is truncated, other, more critical
|
| + // data is more likely to be preserved. Note that non-“extra” memory regions
|
| + // will not have to ride at the end of the file. Thread stack memory, for
|
| + // example, exists as a children of threads, and appears alongside them in the
|
| + // file, despite also being mentioned by the memory list stream.
|
| + add_stream_result = AddStream(std::move(memory_list));
|
| + DCHECK(add_stream_result);
|
| }
|
|
|
| void MinidumpFileWriter::SetTimestamp(time_t timestamp) {
|
| @@ -153,18 +182,35 @@ void MinidumpFileWriter::SetTimestamp(time_t timestamp) {
|
| internal::MinidumpWriterUtil::AssignTimeT(&header_.TimeDateStamp, timestamp);
|
| }
|
|
|
| -void MinidumpFileWriter::AddStream(
|
| +bool MinidumpFileWriter::AddStream(
|
| std::unique_ptr<internal::MinidumpStreamWriter> stream) {
|
| DCHECK_EQ(state(), kStateMutable);
|
|
|
| MinidumpStreamType stream_type = stream->StreamType();
|
|
|
| auto rv = stream_types_.insert(stream_type);
|
| - CHECK(rv.second) << "stream_type " << stream_type << " already present";
|
| + if (!rv.second) {
|
| + LOG(WARNING) << "discarding duplicate stream of type " << stream_type;
|
| + return false;
|
| + }
|
|
|
| streams_.push_back(stream.release());
|
|
|
| DCHECK_EQ(streams_.size(), stream_types_.size());
|
| + return true;
|
| +}
|
| +
|
| +bool MinidumpFileWriter::AddUserExtensionStream(
|
| + std::unique_ptr<MinidumpUserExtensionStreamDataSource>
|
| + user_extension_stream_data) {
|
| + DCHECK_EQ(state(), kStateMutable);
|
| +
|
| + auto user_stream = base::WrapUnique(new MinidumpUserStreamWriter());
|
| + user_stream->InitializeFromBuffer(user_extension_stream_data->stream_type(),
|
| + user_extension_stream_data->buffer(),
|
| + user_extension_stream_data->buffer_size());
|
| +
|
| + return AddStream(std::move(user_stream));
|
| }
|
|
|
| bool MinidumpFileWriter::WriteEverything(FileWriterInterface* file_writer) {
|
|
|