Index: source/Plugins/ObjectFile/ELF/ELFHeader.h =================================================================== --- source/Plugins/ObjectFile/ELF/ELFHeader.h +++ source/Plugins/ObjectFile/ELF/ELFHeader.h @@ -68,10 +68,17 @@ elf_half e_machine; ///< Target architecture. elf_half e_ehsize; ///< Byte size of the ELF header. elf_half e_phentsize; ///< Size of a program header table entry. - elf_half e_phnum; ///< Number of program header entries. + elf_half e_phnum_hdr; ///< Number of program header entries. elf_half e_shentsize; ///< Size of a section header table entry. - elf_half e_shnum; ///< Number of section header entries. - elf_half e_shstrndx; ///< String table section index. + elf_half e_shnum_hdr; ///< Number of section header entries. + elf_half e_shstrndx_hdr; ///< String table section index. + + // In some cases these numbers do not fit in 16 bits and they are + // stored outside of the header in section #0. Here are the actual + // values. + elf_word e_phnum; ///< Number of program header entries. + elf_word e_shnum; ///< Number of section header entries. + elf_word e_shstrndx; ///< String table section index. ELFHeader(); @@ -107,6 +114,11 @@ GetRelocationJumpSlotType() const; //-------------------------------------------------------------------------- + /// Check if there should be header extension in section header #0 + bool + HasHeaderExtension() const; + + //-------------------------------------------------------------------------- /// Parse an ELFHeader entry starting at position \p offset and /// update the data extractor with the address size and byte order /// attributes as defined by the header. @@ -145,6 +157,17 @@ /// 8), else zero if the address size could not be determined. static unsigned AddressSizeInBytes(const uint8_t *magic); + +private: + + //-------------------------------------------------------------------------- + /// Parse an ELFHeader header extension entry. This method is called + /// by Parse(). + /// + /// @param[in] data + /// The DataExtractor to read from. + void + ParseHeaderExtension(lldb_private::DataExtractor &data); }; //------------------------------------------------------------------------------ Index: source/Plugins/ObjectFile/ELF/ELFHeader.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ELFHeader.cpp +++ source/Plugins/ObjectFile/ELF/ELFHeader.cpp @@ -105,6 +105,44 @@ } bool +ELFHeader::HasHeaderExtension() const +{ + bool result = false; + + // Check if any of these values looks like sentinel. + result |= e_phnum_hdr == 0xFFFF; + result |= e_shnum_hdr == 0; + result |= e_shstrndx_hdr == 0xFFFF; + + // If header extension is present, the section offset cannot be null. + result &= e_shoff != 0; + + // Done. + return result; +} + +void +ELFHeader::ParseHeaderExtension(lldb_private::DataExtractor &data) +{ + // Extract section #0 header. + ELFSectionHeader section_zero; + lldb::offset_t offset = 0; + lldb_private::DataExtractor sh_data(data, e_shoff, e_shentsize); + bool ok = section_zero.Parse(sh_data, &offset); + + // If we succeeded, fix the header. + if (ok) + { + if (e_phnum_hdr == 0xFFFF) + e_phnum = section_zero.sh_info; + if (e_shnum_hdr == 0) + e_shnum = section_zero.sh_size; + if (e_shstrndx_hdr == 0xFFFF) + e_shstrndx = section_zero.sh_link; + } +} + +bool ELFHeader::Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset) { // Read e_ident. This provides byte order and address size info. @@ -131,11 +169,23 @@ if (data.GetU32(offset, &e_flags, 1) == NULL) return false; - // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and - // e_shstrndx. + // Read e_ehsize, e_phentsize, e_phnum_hdr, e_shentsize, + // e_shnum_hdr and e_shstrndx_hdr. if (data.GetU16(offset, &e_ehsize, 6) == NULL) return false; + // Initialize e_phnum, e_shnum, and e_shstrndx with the values + // read from the header. + e_phnum = e_phnum_hdr; + e_shnum = e_shnum_hdr; + e_shstrndx = e_shstrndx_hdr; + + // See if we have extended header in section #0. + if (HasHeaderExtension()) + { + ParseHeaderExtension(data); + } + return true; } Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -682,7 +682,8 @@ DataExtractor data; data.SetData(data_sp); elf::ELFHeader header; - if (header.Parse(data, &data_offset)) + lldb::offset_t header_offset = data_offset; + if (header.Parse(data, &header_offset)) { if (data_sp) { @@ -717,9 +718,22 @@ log->Printf ("ObjectFileELF::%s file '%s' set ELF module OS type from ELF header OSABI.", __FUNCTION__, file.GetPath ().c_str ()); } + // In case there is header extension in the section #0, the header + // we parsed above could have sentinel values for e_phnum, e_shnum, + // and e_shstrndx. In this case we need to reparse the header + // with a bigger data source to get the actual values. + size_t section_header_end = header.e_shoff + header.e_shentsize; + if (header.HasHeaderExtension() && section_header_end > data_sp->GetByteSize()) + { + data_sp = file.MemoryMapFileContentsIfLocal (file_offset, section_header_end); + data.SetData(data_sp); + lldb::offset_t header_offset = data_offset; + header.Parse(data, &header_offset); + } + // Try to get the UUID from the section list. Usually that's at the end, so // map the file in if we don't have it already. - size_t section_header_end = header.e_shoff + header.e_shnum * header.e_shentsize; + section_header_end = header.e_shoff + header.e_shnum * header.e_shentsize; if (section_header_end > data_sp->GetByteSize()) { data_sp = file.MemoryMapFileContentsIfLocal (file_offset, section_header_end); @@ -3199,10 +3213,10 @@ s->Printf("e_flags = 0x%8.8x\n", header.e_flags); s->Printf("e_ehsize = 0x%4.4x\n", header.e_ehsize); s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize); - s->Printf("e_phnum = 0x%4.4x\n", header.e_phnum); + s->Printf("e_phnum = 0x%8.8x\n", header.e_phnum); s->Printf("e_shentsize = 0x%4.4x\n", header.e_shentsize); - s->Printf("e_shnum = 0x%4.4x\n", header.e_shnum); - s->Printf("e_shstrndx = 0x%4.4x\n", header.e_shstrndx); + s->Printf("e_shnum = 0x%8.8x\n", header.e_shnum); + s->Printf("e_shstrndx = 0x%8.8x\n", header.e_shstrndx); } //---------------------------------------------------------------------- Index: source/Plugins/Process/elf-core/ProcessElfCore.cpp =================================================================== --- source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -64,6 +64,8 @@ if (crash_file) { // Read enough data for a ELF32 header or ELF64 header + // Note: Here we care about e_type field only, so it is safe + // to ignore possible presence of the header extension. const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr); lldb::DataBufferSP data_sp (crash_file->ReadFileContents(0, header_size));