Index: src/processor/minidump.cc |
diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc |
index 753c6df72e66a72662cf5b2edbc4c10b0d91a805..fb583c17be12a3ec23905893111f9a8a60c2e72f 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 byte[3]; |
Mark Mentovai
2016/02/09 19:27:05
build_id[build_id_index] is the byte, this is a st
|
+ snprintf(byte, sizeof(byte), "%02x", |
+ cv_record_elf->build_id[build_id_index]); |
+ identifier += byte; |
+ } |
+ 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; |