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