aboutsummaryrefslogtreecommitdiff
path: root/src/processor/minidump.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/processor/minidump.cc')
-rw-r--r--src/processor/minidump.cc106
1 files changed, 88 insertions, 18 deletions
diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
index 753c6df7..a9b56a50 100644
--- a/src/processor/minidump.cc
+++ b/src/processor/minidump.cc
@@ -1853,11 +1853,30 @@ string MinidumpModule::code_identifier() const {
break;
}
+ case MD_OS_ANDROID:
+ case MD_OS_LINUX: {
+ // If ELF CodeView data is present, return the debug id.
+ if (cv_record_ && cv_record_signature_ == MD_CVINFOELF_SIGNATURE) {
+ const MDCVInfoELF* cv_record_elf =
+ reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]);
+ assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE);
+
+ for (unsigned int build_id_index = 0;
+ build_id_index < (cv_record_->size() - MDCVInfoELF_minsize);
+ ++build_id_index) {
+ char hexbyte[3];
+ snprintf(hexbyte, sizeof(hexbyte), "%02x",
+ cv_record_elf->build_id[build_id_index]);
+ identifier += hexbyte;
+ }
+ break;
+ }
+ // Otherwise fall through to the case below.
+ }
+
case MD_OS_MAC_OS_X:
case MD_OS_IOS:
case MD_OS_SOLARIS:
- case MD_OS_ANDROID:
- case MD_OS_LINUX:
case MD_OS_NACL:
case MD_OS_PS3: {
// TODO(mmentovai): support uuid extension if present, otherwise fall
@@ -1908,6 +1927,14 @@ string MinidumpModule::debug_file() const {
// GetCVRecord guarantees pdb_file_name is null-terminated.
file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
+ } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) {
+ // It's actually an MDCVInfoELF structure.
+ const MDCVInfoELF* cv_record_elf =
+ reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]);
+ assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE);
+
+ // For MDCVInfoELF, the debug file is the code file.
+ file = *name_;
}
// If there's a CodeView record but it doesn't match a known signature,
@@ -1959,6 +1986,25 @@ string MinidumpModule::debug_file() const {
return file;
}
+static string guid_and_age_to_debug_id(const MDGUID& guid,
+ uint32_t age) {
+ char identifier_string[41];
+ snprintf(identifier_string, sizeof(identifier_string),
+ "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
+ guid.data1,
+ guid.data2,
+ guid.data3,
+ guid.data4[0],
+ guid.data4[1],
+ guid.data4[2],
+ guid.data4[3],
+ guid.data4[4],
+ guid.data4[5],
+ guid.data4[6],
+ guid.data4[7],
+ age);
+ return identifier_string;
+}
string MinidumpModule::debug_identifier() const {
if (!valid_) {
@@ -1981,22 +2027,8 @@ string MinidumpModule::debug_identifier() const {
// Use the same format that the MS symbol server uses in filesystem
// hierarchies.
- char identifier_string[41];
- snprintf(identifier_string, sizeof(identifier_string),
- "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
- 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],
- cv_record_70->signature.data4[2],
- cv_record_70->signature.data4[3],
- cv_record_70->signature.data4[4],
- cv_record_70->signature.data4[5],
- cv_record_70->signature.data4[6],
- cv_record_70->signature.data4[7],
- cv_record_70->age);
- identifier = identifier_string;
+ identifier = guid_and_age_to_debug_id(cv_record_70->signature,
+ cv_record_70->age);
} else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
// It's actually an MDCVInfoPDB20 structure.
const MDCVInfoPDB20* cv_record_20 =
@@ -2009,6 +2041,21 @@ string MinidumpModule::debug_identifier() const {
snprintf(identifier_string, sizeof(identifier_string),
"%08X%x", cv_record_20->signature, cv_record_20->age);
identifier = identifier_string;
+ } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) {
+ // It's actually an MDCVInfoELF structure.
+ const MDCVInfoELF* cv_record_elf =
+ reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]);
+ assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE);
+
+ // For backwards-compatibility, stuff as many bytes as will fit into
+ // a MDGUID and use the MS symbol server format as MDCVInfoPDB70 does
+ // with age = 0. Historically Breakpad would do this during dump
+ // writing to fit the build id data into a MDCVInfoPDB70 struct.
+ // The full build id is available by calling code_identifier.
+ MDGUID guid = {0};
+ memcpy(&guid, &cv_record_elf->build_id,
+ cv_record_->size() - MDCVInfoELF_minsize);
+ identifier = guid_and_age_to_debug_id(guid, 0);
}
}
@@ -2167,6 +2214,15 @@ const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) {
"0-terminated";
return NULL;
}
+ } else if (signature == MD_CVINFOELF_SIGNATURE) {
+ // Now that the structure type is known, recheck the size.
+ if (MDCVInfoELF_minsize > module_.cv_record.data_size) {
+ BPLOG(ERROR) << "MinidumpModule CodeViewELF record size mismatch, " <<
+ MDCVInfoELF_minsize << " > " <<
+ module_.cv_record.data_size;
+ return NULL;
+ }
+ // There's nothing to swap in CVInfoELF, it's just raw bytes.
}
// If the signature doesn't match something above, it's not something
@@ -2367,6 +2423,20 @@ void MinidumpModule::Print() {
cv_record_20->age);
printf(" (cv_record).pdb_file_name = \"%s\"\n",
cv_record_20->pdb_file_name);
+ } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) {
+ const MDCVInfoELF* cv_record_elf =
+ reinterpret_cast<const MDCVInfoELF*>(cv_record);
+ assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE);
+
+ printf(" (cv_record).cv_signature = 0x%x\n",
+ cv_record_elf->cv_signature);
+ printf(" (cv_record).build_id = ");
+ for (unsigned int build_id_index = 0;
+ build_id_index < (cv_record_size - MDCVInfoELF_minsize);
+ ++build_id_index) {
+ printf("%02x", cv_record_elf->build_id[build_id_index]);
+ }
+ printf("\n");
} else {
printf(" (cv_record) = ");
for (unsigned int cv_byte_index = 0;