• R/O
  • HTTP
  • SSH
  • HTTPS

thirdparty-breakpad: Commit

Breakpad, a crash reporter, from Google.

Original home: https://chromium.googlesource.com/breakpad/breakpad/


Commit MetaInfo

Révision6d0287851fabc21a90838ae068b11f2d777393d5 (tree)
l'heure2017-09-28 06:27:17
AuteurMark Mentovai <mark@chro...>
CommiterMark Mentovai

Message de Log

Dump Crashpad extension structures in minidump_dump

This is currently mostly useful to expose the annotations that Crashpad
stores in minidumps.

Example output:

MDRawCrashpadInfo

version = 1
report_id = 01234567-89ab-cdef-0123-456789abcdef
client_id = fedcba98-7654-3210-fedc-ba9876543210
simple_annotationschannel = canary
simple_annotationsplat = OS X
simple_annotationsprod = Chrome_Mac
simple_annotationsver = 59.0.3069.0
module_list[0].minidump_module_list_index = 0
module_list[0].version = 1
module_list[0].simple_annotationsptype = crashpad-handler
module_list[1].minidump_module_list_index = 28
module_list[1].version = 1
module_list[1].list_annotations[0] = abort() called

Change-Id: I00ba291f93ea3a37fc3754c651b3ccc542e5b8b2
Reviewed-on: https://chromium-review.googlesource.com/688416
Reviewed-by: Robert Sesek <rsesek@chromium.org>

Change Summary

Modification

--- a/src/google_breakpad/common/minidump_format.h
+++ b/src/google_breakpad/common/minidump_format.h
@@ -346,7 +346,11 @@ typedef enum {
346346 MD_LINUX_ENVIRON = 0x47670007, /* /proc/$x/environ */
347347 MD_LINUX_AUXV = 0x47670008, /* /proc/$x/auxv */
348348 MD_LINUX_MAPS = 0x47670009, /* /proc/$x/maps */
349- MD_LINUX_DSO_DEBUG = 0x4767000A /* MDRawDebug{32,64} */
349+ MD_LINUX_DSO_DEBUG = 0x4767000A, /* MDRawDebug{32,64} */
350+
351+ /* Crashpad extension types. 0x4350 = "CP"
352+ * See Crashpad's minidump/minidump_extensions.h. */
353+ MD_CRASHPAD_INFO_STREAM = 0x43500001, /* MDRawCrashpadInfo */
350354 } MDStreamType; /* MINIDUMP_STREAM_TYPE */
351355
352356
@@ -1051,6 +1055,42 @@ typedef struct {
10511055 uint64_t dynamic;
10521056 } MDRawDebug64;
10531057
1058+/* Crashpad extension types. See Crashpad's minidump/minidump_extensions.h. */
1059+
1060+typedef struct {
1061+ MDRVA key;
1062+ MDRVA value;
1063+} MDRawSimpleStringDictionaryEntry;
1064+
1065+typedef struct {
1066+ uint32_t count;
1067+ MDRawSimpleStringDictionaryEntry entries[0];
1068+} MDRawSimpleStringDictionary;
1069+
1070+typedef struct {
1071+ uint32_t version;
1072+ MDLocationDescriptor list_annotations;
1073+ MDLocationDescriptor simple_annotations; /* MDRawSimpleStringDictionary */
1074+} MDRawModuleCrashpadInfo;
1075+
1076+typedef struct {
1077+ uint32_t minidump_module_list_index;
1078+ MDLocationDescriptor location; /* MDRawModuleCrashpadInfo */
1079+} MDRawModuleCrashpadInfoLink;
1080+
1081+typedef struct {
1082+ uint32_t count;
1083+ MDLocationDescriptor modules[0]; /* MDRawModuleCrashpadInfoLink */
1084+} MDRawModuleCrashpadInfoList;
1085+
1086+typedef struct {
1087+ uint32_t version;
1088+ MDGUID report_id;
1089+ MDGUID client_id;
1090+ MDLocationDescriptor simple_annotations; /* MDRawSimpleStringDictionary */
1091+ MDLocationDescriptor module_list; /* MDRawModuleCrashpadInfoList */
1092+} MDRawCrashpadInfo;
1093+
10541094 #if defined(_MSC_VER)
10551095 #pragma warning(pop)
10561096 #endif /* _MSC_VER */
--- a/src/google_breakpad/processor/minidump.h
+++ b/src/google_breakpad/processor/minidump.h
@@ -1103,6 +1103,37 @@ class MinidumpLinuxMapsList : public MinidumpStream {
11031103 DISALLOW_COPY_AND_ASSIGN(MinidumpLinuxMapsList);
11041104 };
11051105
1106+// MinidumpCrashpadInfo wraps MDRawCrashpadInfo, which is an optional stream in
1107+// a minidump that provides additional information about the process state
1108+// at the time the minidump was generated.
1109+class MinidumpCrashpadInfo : public MinidumpStream {
1110+ public:
1111+ const MDRawCrashpadInfo* crashpad_info() const {
1112+ return valid_ ? &crashpad_info_ : NULL;
1113+ }
1114+
1115+ // Print a human-readable representation of the object to stdout.
1116+ void Print();
1117+
1118+ private:
1119+ friend class Minidump;
1120+
1121+ static const uint32_t kStreamType = MD_CRASHPAD_INFO_STREAM;
1122+
1123+ explicit MinidumpCrashpadInfo(Minidump* minidump_);
1124+
1125+ bool Read(uint32_t expected_size);
1126+
1127+ MDRawCrashpadInfo crashpad_info_;
1128+ std::vector<uint32_t> module_crashpad_info_links_;
1129+ std::vector<MDRawModuleCrashpadInfo> module_crashpad_info_;
1130+ std::vector<std::vector<std::string>> module_crashpad_info_list_annotations_;
1131+ std::vector<std::map<std::string, std::string>>
1132+ module_crashpad_info_simple_annotations_;
1133+ std::map<std::string, std::string> simple_annotations_;
1134+};
1135+
1136+
11061137 // Minidump is the user's interface to a minidump file. It wraps MDRawHeader
11071138 // and provides access to the minidump's top-level stream directory.
11081139 class Minidump {
@@ -1164,6 +1195,7 @@ class Minidump {
11641195 virtual MinidumpMiscInfo* GetMiscInfo();
11651196 virtual MinidumpBreakpadInfo* GetBreakpadInfo();
11661197 virtual MinidumpMemoryInfoList* GetMemoryInfoList();
1198+ MinidumpCrashpadInfo* GetCrashpadInfo();
11671199
11681200 // The next method also calls GetStream, but is exclusive for Linux dumps.
11691201 virtual MinidumpLinuxMapsList *GetLinuxMapsList();
@@ -1191,13 +1223,21 @@ class Minidump {
11911223 // Returns the current position of the minidump file.
11921224 off_t Tell();
11931225
1194- // The next 2 methods are medium-level I/O routines.
1226+ // Medium-level I/O routines.
11951227
11961228 // ReadString returns a string which is owned by the caller! offset
11971229 // specifies the offset that a length-encoded string is stored at in the
11981230 // minidump file.
11991231 string* ReadString(off_t offset);
12001232
1233+ bool ReadUTF8String(off_t offset, string* string_utf8);
1234+
1235+ bool ReadStringList(off_t offset, std::vector<std::string>* string_list);
1236+
1237+ bool ReadSimpleStringDictionary(
1238+ off_t offset,
1239+ std::map<std::string, std::string>* simple_string_dictionary);
1240+
12011241 // SeekToStreamType positions the file at the beginning of a stream
12021242 // identified by stream_type, and informs the caller of the stream's
12031243 // length by setting *stream_length. Because stream_map maps each stream
--- a/src/processor/minidump.cc
+++ b/src/processor/minidump.cc
@@ -49,10 +49,8 @@
4949
5050 #include <algorithm>
5151 #include <fstream>
52-#include <iostream>
5352 #include <limits>
54-#include <map>
55-#include <vector>
53+#include <utility>
5654
5755 #include "processor/range_map-inl.h"
5856
@@ -212,6 +210,11 @@ static inline void Swap(MDXStateConfigFeatureMscInfo* xstate_feature_info) {
212210 }
213211 }
214212
213+static inline void Swap(MDRawSimpleStringDictionaryEntry* entry) {
214+ Swap(&entry->key);
215+ Swap(&entry->value);
216+}
217+
215218 static inline void Swap(uint16_t* data, size_t size_in_bytes) {
216219 size_t data_length = size_in_bytes / sizeof(data[0]);
217220 for (size_t i = 0; i < data_length; i++) {
@@ -371,7 +374,7 @@ static void PrintValueOrInvalid(bool valid,
371374 }
372375
373376 // Converts a time_t to a string showing the time in UTC.
374-string TimeTToUTCString(time_t tt) {
377+static string TimeTToUTCString(time_t tt) {
375378 struct tm timestruct;
376379 #ifdef _WIN32
377380 gmtime_s(&timestruct, &tt);
@@ -389,6 +392,24 @@ string TimeTToUTCString(time_t tt) {
389392 }
390393
391394
395+static string MDGUIDToString(const MDGUID& uuid) {
396+ char buf[37];
397+ snprintf(buf, sizeof(buf), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
398+ uuid.data1,
399+ uuid.data2,
400+ uuid.data3,
401+ uuid.data4[0],
402+ uuid.data4[1],
403+ uuid.data4[2],
404+ uuid.data4[3],
405+ uuid.data4[4],
406+ uuid.data4[5],
407+ uuid.data4[6],
408+ uuid.data4[7]);
409+ return std::string(buf);
410+}
411+
412+
392413 //
393414 // MinidumpObject
394415 //
@@ -2481,17 +2502,8 @@ void MinidumpModule::Print() {
24812502
24822503 printf(" (cv_record).cv_signature = 0x%x\n",
24832504 cv_record_70->cv_signature);
2484- printf(" (cv_record).signature = %08x-%04x-%04x-%02x%02x-",
2485- cv_record_70->signature.data1,
2486- cv_record_70->signature.data2,
2487- cv_record_70->signature.data3,
2488- cv_record_70->signature.data4[0],
2489- cv_record_70->signature.data4[1]);
2490- for (unsigned int guidIndex = 2;
2491- guidIndex < 8;
2492- ++guidIndex) {
2493- printf("%02x", cv_record_70->signature.data4[guidIndex]);
2494- }
2505+ printf(" (cv_record).signature = %s\n",
2506+ MDGUIDToString(cv_record_70->signature).c_str());
24952507 printf("\n");
24962508 printf(" (cv_record).age = %d\n",
24972509 cv_record_70->age);
@@ -4746,6 +4758,192 @@ void MinidumpLinuxMapsList::Print() const {
47464758 }
47474759
47484760 //
4761+// MinidumpCrashpadInfo
4762+//
4763+
4764+
4765+MinidumpCrashpadInfo::MinidumpCrashpadInfo(Minidump* minidump)
4766+ : MinidumpStream(minidump),
4767+ crashpad_info_(),
4768+ module_crashpad_info_links_(),
4769+ module_crashpad_info_(),
4770+ module_crashpad_info_list_annotations_(),
4771+ module_crashpad_info_simple_annotations_(),
4772+ simple_annotations_() {
4773+}
4774+
4775+
4776+bool MinidumpCrashpadInfo::Read(uint32_t expected_size) {
4777+ valid_ = false;
4778+
4779+ if (expected_size != sizeof(crashpad_info_)) {
4780+ BPLOG(ERROR) << "MinidumpCrashpadInfo size mismatch, " << expected_size <<
4781+ " != " << sizeof(crashpad_info_);
4782+ return false;
4783+ }
4784+
4785+ if (!minidump_->ReadBytes(&crashpad_info_, sizeof(crashpad_info_))) {
4786+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad info";
4787+ return false;
4788+ }
4789+
4790+ if (minidump_->swap()) {
4791+ Swap(&crashpad_info_.version);
4792+ Swap(&crashpad_info_.report_id);
4793+ Swap(&crashpad_info_.client_id);
4794+ Swap(&crashpad_info_.simple_annotations);
4795+ Swap(&crashpad_info_.module_list);
4796+ }
4797+
4798+ if (crashpad_info_.simple_annotations.data_size) {
4799+ if (!minidump_->ReadSimpleStringDictionary(
4800+ crashpad_info_.simple_annotations.rva,
4801+ &simple_annotations_)) {
4802+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read simple_annotations";
4803+ return false;
4804+ }
4805+ }
4806+
4807+ if (crashpad_info_.module_list.data_size) {
4808+ if (!minidump_->SeekSet(crashpad_info_.module_list.rva)) {
4809+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot seek to module_list";
4810+ return false;
4811+ }
4812+
4813+ uint32_t count;
4814+ if (!minidump_->ReadBytes(&count, sizeof(count))) {
4815+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read module_list count";
4816+ return false;
4817+ }
4818+
4819+ if (minidump_->swap()) {
4820+ Swap(&count);
4821+ }
4822+
4823+ scoped_array<MDRawModuleCrashpadInfoLink> module_crashpad_info_links(
4824+ new MDRawModuleCrashpadInfoLink[count]);
4825+
4826+ // Read the entire array in one fell swoop, instead of reading one entry
4827+ // at a time in the loop.
4828+ if (!minidump_->ReadBytes(
4829+ &module_crashpad_info_links[0],
4830+ sizeof(MDRawModuleCrashpadInfoLink) * count)) {
4831+ BPLOG(ERROR)
4832+ << "MinidumpCrashpadInfo could not read Crashpad module links";
4833+ return false;
4834+ }
4835+
4836+ for (uint32_t index = 0; index < count; ++index) {
4837+ if (minidump_->swap()) {
4838+ Swap(&module_crashpad_info_links[index].minidump_module_list_index);
4839+ Swap(&module_crashpad_info_links[index].location);
4840+ }
4841+
4842+ if (!minidump_->SeekSet(module_crashpad_info_links[index].location.rva)) {
4843+ BPLOG(ERROR)
4844+ << "MinidumpCrashpadInfo cannot seek to Crashpad module info";
4845+ return false;
4846+ }
4847+
4848+ MDRawModuleCrashpadInfo module_crashpad_info;
4849+ if (!minidump_->ReadBytes(&module_crashpad_info,
4850+ sizeof(module_crashpad_info))) {
4851+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module info";
4852+ return false;
4853+ }
4854+
4855+ if (minidump_->swap()) {
4856+ Swap(&module_crashpad_info.version);
4857+ Swap(&module_crashpad_info.list_annotations);
4858+ Swap(&module_crashpad_info.simple_annotations);
4859+ }
4860+
4861+ std::vector<std::string> list_annotations;
4862+ if (module_crashpad_info.list_annotations.data_size) {
4863+ if (!minidump_->ReadStringList(
4864+ module_crashpad_info.list_annotations.rva,
4865+ &list_annotations)) {
4866+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module "
4867+ "info list annotations";
4868+ return false;
4869+ }
4870+ }
4871+
4872+ std::map<std::string, std::string> simple_annotations;
4873+ if (module_crashpad_info.simple_annotations.data_size) {
4874+ if (!minidump_->ReadSimpleStringDictionary(
4875+ module_crashpad_info.simple_annotations.rva,
4876+ &simple_annotations)) {
4877+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module "
4878+ "info simple annotations";
4879+ return false;
4880+ }
4881+ }
4882+
4883+ module_crashpad_info_links_.push_back(
4884+ module_crashpad_info_links[index].minidump_module_list_index);
4885+ module_crashpad_info_.push_back(module_crashpad_info);
4886+ module_crashpad_info_list_annotations_.push_back(list_annotations);
4887+ module_crashpad_info_simple_annotations_.push_back(simple_annotations);
4888+ }
4889+ }
4890+
4891+ valid_ = true;
4892+ return true;
4893+}
4894+
4895+
4896+void MinidumpCrashpadInfo::Print() {
4897+ if (!valid_) {
4898+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot print invalid data";
4899+ return;
4900+ }
4901+
4902+ printf("MDRawCrashpadInfo\n");
4903+ printf(" version = %d\n", crashpad_info_.version);
4904+ printf(" report_id = %s\n",
4905+ MDGUIDToString(crashpad_info_.report_id).c_str());
4906+ printf(" client_id = %s\n",
4907+ MDGUIDToString(crashpad_info_.client_id).c_str());
4908+ for (std::map<string, string>::const_iterator iterator =
4909+ simple_annotations_.begin();
4910+ iterator != simple_annotations_.end();
4911+ ++iterator) {
4912+ printf(" simple_annotations[\"%s\"] = %s\n",
4913+ iterator->first.c_str(), iterator->second.c_str());
4914+ }
4915+ for (uint32_t module_index = 0;
4916+ module_index < module_crashpad_info_links_.size();
4917+ ++module_index) {
4918+ printf(" module_list[%d].minidump_module_list_index = %d\n",
4919+ module_index, module_crashpad_info_links_[module_index]);
4920+ printf(" module_list[%d].version = %d\n",
4921+ module_index, module_crashpad_info_[module_index].version);
4922+ for (uint32_t annotation_index = 0;
4923+ annotation_index <
4924+ module_crashpad_info_list_annotations_[module_index].size();
4925+ ++annotation_index) {
4926+ printf(" module_list[%d].list_annotations[%d] = %s\n",
4927+ module_index,
4928+ annotation_index,
4929+ module_crashpad_info_list_annotations_
4930+ [module_index][annotation_index].c_str());
4931+ }
4932+ for (std::map<string, string>::const_iterator iterator =
4933+ module_crashpad_info_simple_annotations_[module_index].begin();
4934+ iterator !=
4935+ module_crashpad_info_simple_annotations_[module_index].end();
4936+ ++iterator) {
4937+ printf(" module_list[%d].simple_annotations[\"%s\"] = %s\n",
4938+ module_index, iterator->first.c_str(), iterator->second.c_str());
4939+ }
4940+ }
4941+
4942+ printf("\n");
4943+}
4944+
4945+
4946+//
47494947 // Minidump
47504948 //
47514949
@@ -4993,7 +5191,8 @@ bool Minidump::Read() {
49935191 case MD_EXCEPTION_STREAM:
49945192 case MD_SYSTEM_INFO_STREAM:
49955193 case MD_MISC_INFO_STREAM:
4996- case MD_BREAKPAD_INFO_STREAM: {
5194+ case MD_BREAKPAD_INFO_STREAM:
5195+ case MD_CRASHPAD_INFO_STREAM: {
49975196 if (stream_map_->find(stream_type) != stream_map_->end()) {
49985197 // Another stream with this type was already found. A minidump
49995198 // file should contain at most one of each of these stream types.
@@ -5100,6 +5299,11 @@ bool Minidump::IsAndroid() {
51005299 return system_info && system_info->platform_id == MD_OS_ANDROID;
51015300 }
51025301
5302+MinidumpCrashpadInfo* Minidump::GetCrashpadInfo() {
5303+ MinidumpCrashpadInfo* crashpad_info;
5304+ return GetStream(&crashpad_info);
5305+}
5306+
51035307 static const char* get_stream_name(uint32_t stream_type) {
51045308 switch (stream_type) {
51055309 case MD_UNUSED_STREAM:
@@ -5170,6 +5374,8 @@ static const char* get_stream_name(uint32_t stream_type) {
51705374 return "MD_LINUX_MAPS";
51715375 case MD_LINUX_DSO_DEBUG:
51725376 return "MD_LINUX_DSO_DEBUG";
5377+ case MD_CRASHPAD_INFO_STREAM:
5378+ return "MD_CRASHPAD_INFO_STREAM";
51735379 default:
51745380 return "unknown";
51755381 }
@@ -5351,6 +5557,158 @@ string* Minidump::ReadString(off_t offset) {
53515557 }
53525558
53535559
5560+bool Minidump::ReadUTF8String(off_t offset, string* string_utf8) {
5561+ if (!valid_) {
5562+ BPLOG(ERROR) << "Invalid Minidump for ReadString";
5563+ return false;
5564+ }
5565+ if (!SeekSet(offset)) {
5566+ BPLOG(ERROR) << "ReadUTF8String could not seek to string at offset "
5567+ << offset;
5568+ return false;
5569+ }
5570+
5571+ uint32_t bytes;
5572+ if (!ReadBytes(&bytes, sizeof(bytes))) {
5573+ BPLOG(ERROR) << "ReadUTF8String could not read string size at offset " <<
5574+ offset;
5575+ return false;
5576+ }
5577+
5578+ if (swap_) {
5579+ Swap(&bytes);
5580+ }
5581+
5582+ if (bytes > max_string_length_) {
5583+ BPLOG(ERROR) << "ReadUTF8String string length " << bytes <<
5584+ " exceeds maximum " << max_string_length_ <<
5585+ " at offset " << offset;
5586+ return false;
5587+ }
5588+
5589+ string_utf8->resize(bytes);
5590+
5591+ if (!ReadBytes(&(*string_utf8)[0], bytes)) {
5592+ BPLOG(ERROR) << "ReadUTF8String could not read " << bytes <<
5593+ "-byte string at offset " << offset;
5594+ return false;
5595+ }
5596+
5597+ return true;
5598+}
5599+
5600+
5601+bool Minidump::ReadStringList(
5602+ off_t offset,
5603+ std::vector<std::string>* string_list) {
5604+ string_list->clear();
5605+
5606+ if (!SeekSet(offset)) {
5607+ BPLOG(ERROR) << "Minidump cannot seek to string_list";
5608+ return false;
5609+ }
5610+
5611+ uint32_t count;
5612+ if (!ReadBytes(&count, sizeof(count))) {
5613+ BPLOG(ERROR) << "Minidump cannot read string_list count";
5614+ return false;
5615+ }
5616+
5617+ if (swap_) {
5618+ Swap(&count);
5619+ }
5620+
5621+ scoped_array<MDRVA> rvas(new MDRVA[count]);
5622+
5623+ // Read the entire array in one fell swoop, instead of reading one entry
5624+ // at a time in the loop.
5625+ if (!ReadBytes(&rvas[0], sizeof(MDRVA) * count)) {
5626+ BPLOG(ERROR) << "Minidump could not read string_list";
5627+ return false;
5628+ }
5629+
5630+ for (uint32_t index = 0; index < count; ++index) {
5631+ if (swap()) {
5632+ Swap(&rvas[index]);
5633+ }
5634+
5635+ string entry;
5636+ if (!ReadUTF8String(rvas[index], &entry)) {
5637+ BPLOG(ERROR) << "Minidump could not read string_list entry";
5638+ return false;
5639+ }
5640+
5641+ string_list->push_back(entry);
5642+ }
5643+
5644+ return true;
5645+}
5646+
5647+
5648+bool Minidump::ReadSimpleStringDictionary(
5649+ off_t offset,
5650+ std::map<std::string, std::string>* simple_string_dictionary) {
5651+ simple_string_dictionary->clear();
5652+
5653+ if (!SeekSet(offset)) {
5654+ BPLOG(ERROR) << "Minidump cannot seek to simple_string_dictionary";
5655+ return false;
5656+ }
5657+
5658+ uint32_t count;
5659+ if (!ReadBytes(&count, sizeof(count))) {
5660+ BPLOG(ERROR)
5661+ << "Minidump cannot read simple_string_dictionary count";
5662+ return false;
5663+ }
5664+
5665+ if (swap()) {
5666+ Swap(&count);
5667+ }
5668+
5669+ scoped_array<MDRawSimpleStringDictionaryEntry> entries(
5670+ new MDRawSimpleStringDictionaryEntry[count]);
5671+
5672+ // Read the entire array in one fell swoop, instead of reading one entry
5673+ // at a time in the loop.
5674+ if (!ReadBytes(
5675+ &entries[0],
5676+ sizeof(MDRawSimpleStringDictionaryEntry) * count)) {
5677+ BPLOG(ERROR) << "Minidump could not read simple_string_dictionary";
5678+ return false;
5679+ }
5680+
5681+ for (uint32_t index = 0; index < count; ++index) {
5682+ if (swap()) {
5683+ Swap(&entries[index]);
5684+ }
5685+
5686+ string key;
5687+ if (!ReadUTF8String(entries[index].key, &key)) {
5688+ BPLOG(ERROR) << "Minidump could not read simple_string_dictionary key";
5689+ return false;
5690+ }
5691+
5692+ string value;
5693+ if (!ReadUTF8String(entries[index].value, &value)) {
5694+ BPLOG(ERROR) << "Minidump could not read simple_string_dictionary value";
5695+ return false;
5696+ }
5697+
5698+ if (simple_string_dictionary->find(key) !=
5699+ simple_string_dictionary->end()) {
5700+ BPLOG(ERROR)
5701+ << "Minidump: discarding duplicate simple_string_dictionary value "
5702+ << value << " for key " << key;
5703+ } else {
5704+ simple_string_dictionary->insert(std::make_pair(key, value));
5705+ }
5706+ }
5707+
5708+ return true;
5709+}
5710+
5711+
53545712 bool Minidump::SeekToStreamType(uint32_t stream_type,
53555713 uint32_t* stream_length) {
53565714 BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires "
--- a/src/processor/minidump_dump.cc
+++ b/src/processor/minidump_dump.cc
@@ -52,6 +52,7 @@ using google_breakpad::MinidumpAssertion;
5252 using google_breakpad::MinidumpSystemInfo;
5353 using google_breakpad::MinidumpMiscInfo;
5454 using google_breakpad::MinidumpBreakpadInfo;
55+using google_breakpad::MinidumpCrashpadInfo;
5556
5657 struct Options {
5758 Options()
@@ -182,6 +183,12 @@ static bool PrintMinidumpDump(const Options& options) {
182183 memory_info_list->Print();
183184 }
184185
186+ MinidumpCrashpadInfo *crashpad_info = minidump.GetCrashpadInfo();
187+ if (crashpad_info) {
188+ // Crashpad info is optional, so don't treat absence as an error.
189+ crashpad_info->Print();
190+ }
191+
185192 DumpRawStream(&minidump,
186193 MD_LINUX_CMD_LINE,
187194 "MD_LINUX_CMD_LINE",
Afficher sur ancien navigateur de dépôt.