| 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];
|
|
|
|
|