diff options
Diffstat (limited to 'src/processor/minidump.cc')
-rw-r--r-- | src/processor/minidump.cc | 106 |
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; |