Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(609)

Unified Diff: src/processor/minidump.cc

Issue 4744002: Support the CrashpadInfo stream. Also: Decode x86 FPU state. Base URL: http://google-breakpad.googlecode.com/svn/trunk/
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/processor/dump_context.cc ('k') | src/processor/minidump_dump.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/processor/minidump.cc
===================================================================
--- src/processor/minidump.cc (revision 1435)
+++ src/processor/minidump.cc (working copy)
@@ -54,8 +54,8 @@
#include <fstream>
#include <iostream>
#include <limits>
-#include <map>
#include <vector>
+#include <utility>
#include "processor/range_map-inl.h"
@@ -208,6 +208,11 @@
Swap(&system_time->milliseconds);
}
+static inline void Swap(MDRawSimpleStringDictionaryEntry* entry) {
+ Swap(&entry->key);
+ Swap(&entry->value);
+}
+
static inline void Swap(uint16_t* data, size_t size_in_bytes) {
size_t data_length = size_in_bytes / sizeof(data[0]);
for (size_t i = 0; i < data_length; i++) {
@@ -367,7 +372,7 @@
}
// Converts a time_t to a string showing the time in UTC.
-string TimeTToUTCString(time_t tt) {
+static string TimeTToUTCString(time_t tt) {
struct tm timestruct;
#ifdef _WIN32
gmtime_s(&timestruct, &tt);
@@ -385,6 +390,24 @@
}
+static string MDGUIDToString(const MDGUID& uuid) {
+ char buf[37];
+ snprintf(buf, sizeof(buf), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid.data1,
+ uuid.data2,
+ uuid.data3,
+ uuid.data4[0],
+ uuid.data4[1],
+ uuid.data4[2],
+ uuid.data4[3],
+ uuid.data4[4],
+ uuid.data4[5],
+ uuid.data4[6],
+ uuid.data4[7]);
+ return std::string(buf);
+}
+
+
//
// MinidumpObject
//
@@ -1185,7 +1208,7 @@
//
-uint32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024; // 1MB
+uint32_t MinidumpMemoryRegion::max_bytes_ = 8 * 1024 * 1024; // 1MB
MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
@@ -2341,17 +2364,8 @@
printf(" (cv_record).cv_signature = 0x%x\n",
cv_record_70->cv_signature);
- printf(" (cv_record).signature = %08x-%04x-%04x-%02x%02x-",
- cv_record_70->signature.data1,
- cv_record_70->signature.data2,
- cv_record_70->signature.data3,
- cv_record_70->signature.data4[0],
- cv_record_70->signature.data4[1]);
- for (unsigned int guidIndex = 2;
- guidIndex < 8;
- ++guidIndex) {
- printf("%02x", cv_record_70->signature.data4[guidIndex]);
- }
+ printf(" (cv_record).signature = %s\n",
+ MDGUIDToString(cv_record_70->signature).c_str());
printf("\n");
printf(" (cv_record).age = %d\n",
cv_record_70->age);
@@ -3974,6 +3988,192 @@
//
+// MinidumpCrashpadInfo
+//
+
+
+MinidumpCrashpadInfo::MinidumpCrashpadInfo(Minidump* minidump)
+ : MinidumpStream(minidump),
+ crashpad_info_(),
+ module_crashpad_info_links_(),
+ module_crashpad_info_(),
+ module_crashpad_info_list_annotations_(),
+ module_crashpad_info_simple_annotations_(),
+ simple_annotations_() {
+}
+
+
+bool MinidumpCrashpadInfo::Read(uint32_t expected_size) {
+ valid_ = false;
+
+ if (expected_size != sizeof(crashpad_info_)) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo size mismatch, " << expected_size <<
+ " != " << sizeof(crashpad_info_);
+ return false;
+ }
+
+ if (!minidump_->ReadBytes(&crashpad_info_, sizeof(crashpad_info_))) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&crashpad_info_.version);
+ Swap(&crashpad_info_.report_id);
+ Swap(&crashpad_info_.client_id);
+ Swap(&crashpad_info_.simple_annotations);
+ Swap(&crashpad_info_.module_list);
+ }
+
+ if (crashpad_info_.simple_annotations.data_size) {
+ if (!minidump_->ReadSimpleStringDictionary(
+ crashpad_info_.simple_annotations.rva,
+ &simple_annotations_)) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read simple_annotations";
+ return false;
+ }
+ }
+
+ if (crashpad_info_.module_list.data_size) {
+ if (!minidump_->SeekSet(crashpad_info_.module_list.rva)) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot seek to module_list";
+ return false;
+ }
+
+ uint32_t count;
+ if (!minidump_->ReadBytes(&count, sizeof(count))) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read module_list count";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&count);
+ }
+
+ scoped_array<MDRawModuleCrashpadInfoLink> module_crashpad_info_links(
+ new MDRawModuleCrashpadInfoLink[count]);
+
+ // Read the entire array in one fell swoop, instead of reading one entry
+ // at a time in the loop.
+ if (!minidump_->ReadBytes(
+ &module_crashpad_info_links[0],
+ sizeof(MDRawModuleCrashpadInfoLink) * count)) {
+ BPLOG(ERROR)
+ << "MinidumpCrashpadInfo could not read Crashpad module links";
+ return false;
+ }
+
+ for (uint32_t index = 0; index < count; ++index) {
+ if (minidump_->swap()) {
+ Swap(&module_crashpad_info_links[index].minidump_module_list_index);
+ Swap(&module_crashpad_info_links[index].location);
+ }
+
+ if (!minidump_->SeekSet(module_crashpad_info_links[index].location.rva)) {
+ BPLOG(ERROR)
+ << "MinidumpCrashpadInfo cannot seek to Crashpad module info";
+ return false;
+ }
+
+ MDRawModuleCrashpadInfo module_crashpad_info;
+ if (!minidump_->ReadBytes(&module_crashpad_info,
+ sizeof(module_crashpad_info))) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&module_crashpad_info.version);
+ Swap(&module_crashpad_info.list_annotations);
+ Swap(&module_crashpad_info.simple_annotations);
+ }
+
+ std::vector<std::string> list_annotations;
+ if (module_crashpad_info.list_annotations.data_size) {
+ if (!minidump_->ReadStringList(
+ module_crashpad_info.list_annotations.rva,
+ &list_annotations)) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module "
+ "info list annotations";
+ return false;
+ }
+ }
+
+ std::map<std::string, std::string> simple_annotations;
+ if (module_crashpad_info.simple_annotations.data_size) {
+ if (!minidump_->ReadSimpleStringDictionary(
+ module_crashpad_info.simple_annotations.rva,
+ &simple_annotations)) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module "
+ "info simple annotations";
+ return false;
+ }
+ }
+
+ module_crashpad_info_links_.push_back(
+ module_crashpad_info_links[index].minidump_module_list_index);
+ module_crashpad_info_.push_back(module_crashpad_info);
+ module_crashpad_info_list_annotations_.push_back(list_annotations);
+ module_crashpad_info_simple_annotations_.push_back(simple_annotations);
+ }
+ }
+
+ valid_ = true;
+ return true;
+}
+
+
+void MinidumpCrashpadInfo::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawCrashpadInfo\n");
+ printf(" version = %d\n", crashpad_info_.version);
+ printf(" report_id = %s\n",
+ MDGUIDToString(crashpad_info_.report_id).c_str());
+ printf(" client_id = %s\n",
+ MDGUIDToString(crashpad_info_.client_id).c_str());
+ for (std::map<string, string>::const_iterator iterator =
+ simple_annotations_.begin();
+ iterator != simple_annotations_.end();
+ ++iterator) {
+ printf(" simple_annotations[\"%s\"] = %s\n",
+ iterator->first.c_str(), iterator->second.c_str());
+ }
+ for (uint32_t module_index = 0;
+ module_index < module_crashpad_info_links_.size();
+ ++module_index) {
+ printf(" module_list[%d].minidump_module_list_index = %d\n",
+ module_index, module_crashpad_info_links_[module_index]);
+ printf(" module_list[%d].version = %d\n",
+ module_index, module_crashpad_info_[module_index].version);
+ for (uint32_t annotation_index = 0;
+ annotation_index <
+ module_crashpad_info_list_annotations_[module_index].size();
+ ++annotation_index) {
+ printf(" module_list[%d].list_annotations[%d] = %s\n",
+ module_index,
+ annotation_index,
+ module_crashpad_info_list_annotations_
+ [module_index][annotation_index].c_str());
+ }
+ for (std::map<string, string>::const_iterator iterator =
+ module_crashpad_info_simple_annotations_[module_index].begin();
+ iterator !=
+ module_crashpad_info_simple_annotations_[module_index].end();
+ ++iterator) {
+ printf(" module_list[%d].simple_annotations[\"%s\"] = %s\n",
+ module_index, iterator->first.c_str(), iterator->second.c_str());
+ }
+ }
+
+ printf("\n");
+}
+
+
+//
// Minidump
//
@@ -4214,7 +4414,8 @@
case MD_EXCEPTION_STREAM:
case MD_SYSTEM_INFO_STREAM:
case MD_MISC_INFO_STREAM:
- case MD_BREAKPAD_INFO_STREAM: {
+ case MD_BREAKPAD_INFO_STREAM:
+ case MD_CRASHPAD_INFO_STREAM: {
if (stream_map_->find(stream_type) != stream_map_->end()) {
// Another stream with this type was already found. A minidump
// file should contain at most one of each of these stream types.
@@ -4292,6 +4493,11 @@
return GetStream(&memory_info_list);
}
+MinidumpCrashpadInfo* Minidump::GetCrashpadInfo() {
+ MinidumpCrashpadInfo* crashpad_info;
+ return GetStream(&crashpad_info);
+}
+
static const char* get_stream_name(uint32_t stream_type) {
switch (stream_type) {
case MD_UNUSED_STREAM:
@@ -4354,6 +4560,8 @@
return "MD_LINUX_MAPS";
case MD_LINUX_DSO_DEBUG:
return "MD_LINUX_DSO_DEBUG";
+ case MD_CRASHPAD_INFO_STREAM:
+ return "MD_CRASHPAD_INFO_STREAM";
default:
return "unknown";
}
@@ -4535,6 +4743,156 @@
}
+bool Minidump::ReadUTF8String(off_t offset, string* string_utf8) {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid Minidump for ReadString";
+ return false;
+ }
+ if (!SeekSet(offset)) {
+ BPLOG(ERROR) << "ReadUTF8String could not seek to string at offset "
+ << offset;
+ return false;
+ }
+
+ uint32_t bytes;
+ if (!ReadBytes(&bytes, sizeof(bytes))) {
+ BPLOG(ERROR) << "ReadUTF8String could not read string size at offset " <<
+ offset;
+ return false;
+ }
+ if (swap_)
+ Swap(&bytes);
+
+ if (bytes > max_string_length_) {
+ BPLOG(ERROR) << "ReadUTF8String string length " << bytes <<
+ " exceeds maximum " << max_string_length_ <<
+ " at offset " << offset;
+ return false;
+ }
+
+ string_utf8->resize(bytes);
+
+ if (!ReadBytes(&(*string_utf8)[0], bytes)) {
+ BPLOG(ERROR) << "ReadUTF8String could not read " << bytes <<
+ "-byte string at offset " << offset;
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Minidump::ReadStringList(
+ off_t offset,
+ std::vector<std::string>* string_list) {
+ string_list->clear();
+
+ if (!SeekSet(offset)) {
+ BPLOG(ERROR) << "Minidump cannot seek to string_list";
+ return false;
+ }
+
+ uint32_t count;
+ if (!ReadBytes(&count, sizeof(count))) {
+ BPLOG(ERROR) << "Minidump cannot read string_list count";
+ return false;
+ }
+
+ if (swap()) {
+ Swap(&count);
+ }
+
+ scoped_array<MDRVA> rvas(new MDRVA[count]);
+
+ // Read the entire array in one fell swoop, instead of reading one entry
+ // at a time in the loop.
+ if (!ReadBytes(&rvas[0], sizeof(MDRVA) * count)) {
+ BPLOG(ERROR) << "Minidump could not read string_list";
+ return false;
+ }
+
+ for (uint32_t index = 0; index < count; ++index) {
+ if (swap()) {
+ Swap(&rvas[index]);
+ }
+
+ string entry;
+ if (!ReadUTF8String(rvas[index], &entry)) {
+ BPLOG(ERROR) << "Minidump could not read string_list entry";
+ return false;
+ }
+
+ string_list->push_back(entry);
+ }
+
+ return true;
+}
+
+
+bool Minidump::ReadSimpleStringDictionary(
+ off_t offset,
+ std::map<std::string, std::string>* simple_string_dictionary) {
+ simple_string_dictionary->clear();
+
+ if (!SeekSet(offset)) {
+ BPLOG(ERROR) << "Minidump cannot seek to simple_string_dictionary";
+ return false;
+ }
+
+ uint32_t count;
+ if (!ReadBytes(&count, sizeof(count))) {
+ BPLOG(ERROR)
+ << "Minidump cannot read simple_string_dictionary count";
+ return false;
+ }
+
+ if (swap()) {
+ Swap(&count);
+ }
+
+ scoped_array<MDRawSimpleStringDictionaryEntry> entries(
+ new MDRawSimpleStringDictionaryEntry[count]);
+
+ // Read the entire array in one fell swoop, instead of reading one entry
+ // at a time in the loop.
+ if (!ReadBytes(
+ &entries[0],
+ sizeof(MDRawSimpleStringDictionaryEntry) * count)) {
+ BPLOG(ERROR) << "Minidump could not read simple_string_dictionary";
+ return false;
+ }
+
+ for (uint32_t index = 0; index < count; ++index) {
+ if (swap()) {
+ Swap(&entries[index]);
+ }
+
+ string key;
+ if (!ReadUTF8String(entries[index].key, &key)) {
+ BPLOG(ERROR) << "Minidump could not read simple_string_dictionary key";
+ return false;
+ }
+
+ string value;
+ if (!ReadUTF8String(entries[index].value, &value)) {
+ BPLOG(ERROR) << "Minidump could not read simple_string_dictionary value";
+ return false;
+ }
+
+ if (simple_string_dictionary->find(key) !=
+ simple_string_dictionary->end()) {
+ BPLOG(ERROR)
+ << "Minidump: discarding duplicate simple_string_dictionary value "
+ << value << " for key " << key;
+ } else {
+ simple_string_dictionary->insert(std::make_pair(key, value));
+ }
+ }
+
+ return true;
+}
+
+
bool Minidump::SeekToStreamType(uint32_t stream_type,
uint32_t* stream_length) {
BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires "
« no previous file with comments | « src/processor/dump_context.cc ('k') | src/processor/minidump_dump.cc » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld 1004:630ec63f810e-tainted