Index: src/common/linux/file_id.cc |
diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc |
index 00b37313afd9e3814aa4ab3e567550f41dd41763..bc16fa36424a3f228479f26a6cf1d25fcd98c9f7 100644 |
--- a/src/common/linux/file_id.cc |
+++ b/src/common/linux/file_id.cc |
@@ -48,6 +48,9 @@ |
namespace google_breakpad { |
+// Used in a few places for backwards-compatibility. |
+const size_t kMDGUIDSize = sizeof(MDGUID); |
+ |
FileID::FileID(const char* path) : path_(path) {} |
// ELF note name and desc are 32-bits word padded. |
@@ -58,9 +61,12 @@ FileID::FileID(const char* path) : path_(path) {} |
template<typename ElfClass> |
static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length, |
- uint8_t identifier[kMDGUIDSize]) { |
+ uint8_t identifier[kMaxBuildID], |
+ size_t* identifier_length) { |
typedef typename ElfClass::Nhdr Nhdr; |
+ assert(identifier_length); |
+ |
const void* section_end = reinterpret_cast<const char*>(section) + length; |
const Nhdr* note_header = reinterpret_cast<const Nhdr*>(section); |
while (reinterpret_cast<const void *>(note_header) < section_end) { |
@@ -76,21 +82,26 @@ static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length, |
return false; |
} |
- const char* build_id = reinterpret_cast<const char*>(note_header) + |
+ const uint8_t* build_id = reinterpret_cast<const uint8_t*>(note_header) + |
sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz); |
// Copy as many bits of the build ID as will fit |
- // into the GUID space. |
- my_memset(identifier, 0, kMDGUIDSize); |
- memcpy(identifier, build_id, |
- std::min(kMDGUIDSize, (size_t)note_header->n_descsz)); |
+ // into |identifier|. This should always fit unless someone has |
+ // passed --build-id=0x... to the linker with a longer-than-standard |
+ // hex string. |
+ my_memset(identifier, 0, kMaxBuildID); |
+ *identifier_length = std::min(kMaxBuildID, (size_t)note_header->n_descsz); |
+ memcpy(identifier, build_id, *identifier_length); |
return true; |
} |
// Attempt to locate a .note.gnu.build-id section in an ELF binary |
// and copy as many bytes of it as will fit into |identifier|. |
+// Set |*identifier_length| to the number of bytes copied. |
static bool FindElfBuildIDNote(const void *elf_mapped_base, |
- uint8_t identifier[kMDGUIDSize]) { |
+ uint8_t identifier[kMaxBuildID], |
+ size_t* identifier_length) { |
+ assert(identifier_length); |
void* note_section; |
size_t note_size; |
int elfclass; |
@@ -105,10 +116,12 @@ static bool FindElfBuildIDNote(const void *elf_mapped_base, |
if (elfclass == ELFCLASS32) { |
return ElfClassBuildIDNoteIdentifier<ElfClass32>(note_section, note_size, |
- identifier); |
+ identifier, |
+ identifier_length); |
} else if (elfclass == ELFCLASS64) { |
return ElfClassBuildIDNoteIdentifier<ElfClass64>(note_section, note_size, |
- identifier); |
+ identifier, |
+ identifier_length); |
} |
return false; |
@@ -117,7 +130,9 @@ static bool FindElfBuildIDNote(const void *elf_mapped_base, |
// Attempt to locate the .text section of an ELF binary and generate |
// a simple hash by XORing the first page worth of bytes into |identifier|. |
static bool HashElfTextSection(const void *elf_mapped_base, |
- uint8_t identifier[kMDGUIDSize]) { |
+ uint8_t identifier[kMaxBuildID], |
+ size_t* identifier_length) { |
+ assert(identifier_length); |
void* text_section; |
size_t text_size; |
if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS, |
@@ -126,6 +141,8 @@ static bool HashElfTextSection(const void *elf_mapped_base, |
return false; |
} |
+ // Only provide |kMDGUIDSize| bytes to keep identifiers produced by this |
+ // function backwards-compatible. |
my_memset(identifier, 0, kMDGUIDSize); |
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section); |
const uint8_t* ptr_end = ptr + std::min(text_size, static_cast<size_t>(4096)); |
@@ -134,30 +151,34 @@ static bool HashElfTextSection(const void *elf_mapped_base, |
identifier[i] ^= ptr[i]; |
ptr += kMDGUIDSize; |
} |
+ *identifier_length = kMDGUIDSize; |
return true; |
} |
// static |
bool FileID::ElfFileIdentifierFromMappedFile(const void* base, |
- uint8_t identifier[kMDGUIDSize]) { |
+ uint8_t identifier[kMaxBuildID], |
+ size_t* identifier_length) { |
// Look for a build id note first. |
- if (FindElfBuildIDNote(base, identifier)) |
+ if (FindElfBuildIDNote(base, identifier, identifier_length)) |
return true; |
// Fall back on hashing the first page of the text section. |
- return HashElfTextSection(base, identifier); |
+ return HashElfTextSection(base, identifier, identifier_length); |
} |
-bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) { |
+bool FileID::ElfFileIdentifier(uint8_t identifier[kMaxBuildID], |
+ size_t* identifier_length) { |
MemoryMappedFile mapped_file(path_.c_str(), 0); |
if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)? |
return false; |
- return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier); |
+ return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier, |
+ identifier_length); |
} |
// static |
-void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize], |
+void FileID::ConvertIdentifierToString(const uint8_t identifier[kMaxBuildID], |
char* buffer, int buffer_length) { |
uint8_t identifier_swapped[kMDGUIDSize]; |