Index: tools/llvm-objcopy/Object.h =================================================================== --- tools/llvm-objcopy/Object.h +++ tools/llvm-objcopy/Object.h @@ -35,6 +35,7 @@ class RelocationSection; class DynamicRelocationSection; class GnuDebugLinkSection; +class SectionIndexSection; class Segment; class Object; @@ -52,10 +53,10 @@ iterator begin() { return iterator(Sections.data()); } iterator end() { return iterator(Sections.data() + Sections.size()); } - SectionBase *getSection(uint16_t Index, Twine ErrMsg); + SectionBase *getSection(uint32_t Index, Twine ErrMsg); template - T *getSectionOfType(uint16_t Index, Twine IndexErrMsg, Twine TypeErrMsg); + T *getSectionOfType(uint32_t Index, Twine IndexErrMsg, Twine TypeErrMsg); }; enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE }; @@ -71,6 +72,7 @@ virtual void visit(const RelocationSection &Sec) = 0; virtual void visit(const DynamicRelocationSection &Sec) = 0; virtual void visit(const GnuDebugLinkSection &Sec) = 0; + virtual void visit(const SectionIndexSection &Sec) = 0; }; class SectionWriter : public SectionVisitor { @@ -87,6 +89,7 @@ virtual void visit(const SymbolTableSection &Sec) override = 0; virtual void visit(const RelocationSection &Sec) override = 0; virtual void visit(const GnuDebugLinkSection &Sec) override = 0; + virtual void visit(const SectionIndexSection &Sec) override = 0; SectionWriter(FileOutputBuffer &Buf) : Out(Buf) {} }; @@ -102,6 +105,7 @@ void visit(const SymbolTableSection &Sec) override; void visit(const RelocationSection &Sec) override; void visit(const GnuDebugLinkSection &Sec) override; + void visit(const SectionIndexSection &Sec) override; ELFSectionWriter(FileOutputBuffer &Buf) : SectionWriter(Buf) {} }; @@ -117,6 +121,7 @@ void visit(const SymbolTableSection &Sec) override; void visit(const RelocationSection &Sec) override; void visit(const GnuDebugLinkSection &Sec) override; + void visit(const SectionIndexSection &Sec) override; BinarySectionWriter(FileOutputBuffer &Buf) : SectionWriter(Buf) {} }; @@ -322,6 +327,7 @@ SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2, SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4, SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8, + SYMBOL_XINDEX = ELF::SHN_XINDEX, }; struct Symbol { @@ -339,21 +345,42 @@ uint16_t getShndx() const; }; +class SectionIndexSection : public SectionBase { + MAKE_SEC_WRITER_FRIEND + +private: + std::vector Indexes; + SymbolTableSection *Symbols; + +public: + virtual ~SectionIndexSection() {} + void addIndex(uint32_t Index) { + Indexes.push_back(Index); + Size += 4; + } + void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; } + void initialize(SectionTableRef SecTable) override { Size = 0; } + void finalize() override; + void accept(SectionVisitor &Visitor) const override; +}; + class SymbolTableSection : public SectionBase { MAKE_SEC_WRITER_FRIEND protected: std::vector> Symbols; StringTableSection *SymbolNames = nullptr; + SectionIndexSection *SectionIndexes = nullptr; using SymPtr = std::unique_ptr; public: + void setShndx(SectionIndexSection *Shndx) { SectionIndexes = Shndx; } void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; } void addSymbol(StringRef Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn, uint64_t Value, uint8_t Visibility, uint16_t Shndx, uint64_t Sz); - void addSymbolNames(); + void prepareForLayout(); const SectionBase *getStrTab() const { return SymbolNames; } const Symbol *getSymbolByIndex(uint32_t Index) const; void removeSectionReferences(const SectionBase *Sec) override; @@ -512,6 +539,7 @@ template class ELFBuilder { private: using Elf_Shdr = typename ELFT::Shdr; + using Elf_Word = typename ELFT::Word; const ELFFile &ElfFile; Object &Obj; @@ -567,6 +595,7 @@ StringTableSection *SectionNames = nullptr; SymbolTableSection *SymbolTable = nullptr; + SectionIndexSection *SectionIndexes = nullptr; Object(std::shared_ptr Data) : OwnedData(Data) {} virtual ~Object() = default; Index: tools/llvm-objcopy/Object.cpp =================================================================== --- tools/llvm-objcopy/Object.cpp +++ tools/llvm-objcopy/Object.cpp @@ -69,6 +69,10 @@ SectionVisitor::~SectionVisitor() {} +void BinarySectionWriter::visit(const SectionIndexSection &Sec) { + error("Cannot write section index table '" + Sec.Name + "' "); +} + void BinarySectionWriter::visit(const SymbolTableSection &Sec) { error("Cannot write symbol table '" + Sec.Name + "' out to binary"); } @@ -118,6 +122,21 @@ Visitor.visit(*this); } +template +void ELFSectionWriter::visit(const SectionIndexSection &Sec) { + uint8_t *Buf = Out.getBufferStart() + Sec.Offset; + auto *Indexes = reinterpret_cast(Buf); + // Loop though symbols setting each entry of the symbol table. + for (auto &Index : Sec.Indexes) + *Indexes++ = Index; +} + +void SectionIndexSection::finalize() { Link = Symbols->Index; } + +void SectionIndexSection::accept(SectionVisitor &Visitor) const { + Visitor.visit(*this); +} + static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) { switch (Index) { case SHN_ABS: @@ -136,8 +155,12 @@ return false; } +// Large indexes force us to clarify exactly what this function should do. This +// function should return the proper value of st_shndx uint16_t Symbol::getShndx() const { if (DefinedIn != nullptr) { + if (DefinedIn->Index >= SHN_LORESERVE) + return SHN_XINDEX; return DefinedIn->Index; } switch (ShndxType) { @@ -151,6 +174,7 @@ case SYMBOL_HEXAGON_SCOMMON_2: case SYMBOL_HEXAGON_SCOMMON_4: case SYMBOL_HEXAGON_SCOMMON_8: + case SYMBOL_XINDEX: return static_cast(ShndxType); } llvm_unreachable("Symbol with invalid ShndxType encountered"); @@ -165,12 +189,10 @@ Sym.Binding = Bind; Sym.Type = Type; Sym.DefinedIn = DefinedIn; - if (DefinedIn == nullptr) { - if (Shndx >= SHN_LORESERVE) - Sym.ShndxType = static_cast(Shndx); - else - Sym.ShndxType = SYMBOL_SIMPLE_INDEX; - } + if (Shndx >= SHN_LORESERVE) + Sym.ShndxType = static_cast(Shndx); + else + Sym.ShndxType = SYMBOL_SIMPLE_INDEX; Sym.Value = Value; Sym.Visibility = Visibility; Sym.Size = Sz; @@ -236,7 +258,17 @@ Info = MaxLocalIndex + 1; } -void SymbolTableSection::addSymbolNames() { +void SymbolTableSection::prepareForLayout() { + // Add all potential section indexes before file layout so that the section + // index section has the approprite size. + if (SectionIndexes != nullptr) { + for (const auto &Sym : Symbols) { + if (Sym->DefinedIn != nullptr) + SectionIndexes->addIndex(Sym->DefinedIn->Index); + else + SectionIndexes->addIndex(SHN_UNDEF); + } + } // Add all of our strings to SymbolNames so that SymbolNames has the right // size before layout is decided. for (auto &Sym : Symbols) @@ -493,9 +525,8 @@ // inspecting the ParentSegment. if (compareSegmentsByOffset(&Parent, &Child)) if (Child.ParentSegment == nullptr || - compareSegmentsByOffset(&Parent, Child.ParentSegment)) { + compareSegmentsByOffset(&Parent, Child.ParentSegment)) Child.ParentSegment = &Parent; - } } } } @@ -506,11 +537,26 @@ const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index)); StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr)); - for (const auto &Sym : unwrapOrError(ElfFile.symbols(&Shdr))) { + auto Symbols = unwrapOrError(ElfFile.symbols(&Shdr)); + for (const auto &Sym : Symbols) { SectionBase *DefSection = nullptr; StringRef Name = unwrapOrError(Sym.getName(StrTabData)); - if (Sym.st_shndx >= SHN_LORESERVE) { + if (Sym.st_shndx == SHN_XINDEX) { + if (Obj.SectionIndexes == nullptr) + error("Symbol '" + Name + + "' has index SHN_XINDEX but no SHT_SYMTAB_SHNDX section exists."); + + const Elf_Shdr &ShndxSec = + *unwrapOrError(ElfFile.getSection(Obj.SectionIndexes->Index)); + ArrayRef ShndxData = unwrapOrError( + ElfFile.template getSectionContentsAsArray(&ShndxSec)); + auto Index = ShndxData[&Sym - Symbols.begin()]; + DefSection = Obj.sections().getSection( + Index, + "Symbol '" + Name + "' is defined in invalid section with index " + + Twine(Index)); + } else if (Sym.st_shndx >= SHN_LORESERVE) { if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) { error( "Symbol '" + Name + @@ -550,17 +596,18 @@ } } -SectionBase *SectionTableRef::getSection(uint16_t Index, Twine ErrMsg) { +SectionBase *SectionTableRef::getSection(uint32_t Index, Twine ErrMsg) { if (Index == SHN_UNDEF || Index > Sections.size()) error(ErrMsg); return Sections[Index - 1].get(); } template -T *SectionTableRef::getSectionOfType(uint16_t Index, Twine IndexErrMsg, +T *SectionTableRef::getSectionOfType(uint32_t Index, Twine IndexErrMsg, Twine TypeErrMsg) { - if (T *Sec = dyn_cast(getSection(Index, IndexErrMsg))) + if (T *Sec = dyn_cast(getSection(Index, IndexErrMsg))) { return Sec; + } error(TypeErrMsg); } @@ -599,8 +646,21 @@ case SHT_SYMTAB: { auto &SymTab = Obj.addSection(); Obj.SymbolTable = &SymTab; + if (Obj.SectionIndexes != nullptr) { + Obj.SectionIndexes->setSymTab(Obj.SymbolTable); + Obj.SymbolTable->setShndx(Obj.SectionIndexes); + } return SymTab; } + case SHT_SYMTAB_SHNDX: { + auto &Shndx = Obj.addSection(); + Obj.SectionIndexes = &Shndx; + if (Obj.SymbolTable != nullptr) { + Obj.SectionIndexes->setSymTab(Obj.SymbolTable); + Obj.SymbolTable->setShndx(Obj.SectionIndexes); + } + return Shndx; + } case SHT_NOBITS: return Obj.addSection
(Data); default: @@ -747,8 +807,28 @@ Ehdr.e_shentsize = sizeof(Elf_Shdr); if (WriteSectionHeaders) { Ehdr.e_shoff = Obj.SHOffset; - Ehdr.e_shnum = size(Obj.sections()) + 1; - Ehdr.e_shstrndx = Obj.SectionNames->Index; + // """ + // If the number of sections is greater than or equal to + // SHN_LORESERVE (0xff00), this member has the value zero and the actual + // number of section header table entries is contained in the sh_size field + // of the section header at index 0. + // """ + auto Shnum = size(Obj.sections()) + 1; + if (Shnum >= SHN_LORESERVE) + Ehdr.e_shnum = 0; + else + Ehdr.e_shnum = Shnum; + // """ + // If the section name string table section index is greater than or equal + // to + // SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff) and + // the actual index of the section name string table section is contained in + // the sh_link field of the section header at index 0. + // """ + if (Obj.SectionNames->Index >= SHN_LORESERVE) + Ehdr.e_shstrndx = SHN_XINDEX; + else + Ehdr.e_shstrndx = Obj.SectionNames->Index; } else { Ehdr.e_shoff = 0; Ehdr.e_shnum = 0; @@ -771,8 +851,27 @@ Shdr.sh_flags = 0; Shdr.sh_addr = 0; Shdr.sh_offset = 0; - Shdr.sh_size = 0; - Shdr.sh_link = 0; + // """ + // If the number of sections is greater than or equal to + // SHN_LORESERVE (0xff00), this member has the value zero and the actual + // number of section header table entries is contained in the sh_size field + // of the section header at index 0. + // """ + auto Shnum = size(Obj.sections()) + 1; + if (Shnum >= SHN_LORESERVE) + Shdr.sh_size = Shnum; + else + Shdr.sh_size = 0; + // """ + // If the section name string table section index is greater than or equal to + // SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff) and + // the actual index of the section name string table section is contained in + // the sh_link field of the section header at index 0. + // """ + if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE) + Shdr.sh_link = Obj.SectionNames->Index; + else + Shdr.sh_link = 0; Shdr.sh_info = 0; Shdr.sh_addralign = 0; Shdr.sh_entsize = 0; @@ -973,9 +1072,10 @@ for (const auto &Section : Obj.sections()) { Obj.SectionNames->addString(Section.Name); } - // Make sure we add the names of all the symbols. + // Some sections don't yet have their final size due to symbols not keeping + // other sections updated. if (Obj.SymbolTable != nullptr) - Obj.SymbolTable->addSymbolNames(); + Obj.SymbolTable->prepareForLayout(); Obj.sortSections(); assignOffsets();