Index: tools/llvm-objcopy/Object.h =================================================================== --- tools/llvm-objcopy/Object.h +++ tools/llvm-objcopy/Object.h @@ -18,6 +18,23 @@ #include class Segment; +class SectionBase; + +class SectionTable { +private: + llvm::ArrayRef> Sections; + +public: + SectionTable(llvm::ArrayRef> Secs) + : Sections(Secs) {} + SectionTable(const SectionTable &) = default; + + SectionBase *getSection(uint16_t Index, llvm::Twine ErrMsg); + + template + T *getSectionOfType(uint16_t Index, llvm::Twine ErrMsg, + llvm::Twine CastErrMsg); +}; class SectionBase { public: @@ -39,6 +56,7 @@ uint64_t Type = llvm::ELF::SHT_NULL; virtual ~SectionBase() {} + virtual void initialize(SectionTable Obj); virtual void finalize(); template void writeHeader(llvm::FileOutputBuffer &Out) const; virtual void writeSection(llvm::FileOutputBuffer &Out) const = 0; @@ -154,6 +172,7 @@ uint64_t Sz); void addSymbolNames(); const Symbol *getSymbolByIndex(uint32_t Index) const; + void initialize(SectionTable Obj) override; void finalize() override; static bool classof(const SectionBase *S) { return S->Type == llvm::ELF::SHT_SYMTAB; @@ -187,6 +206,7 @@ void setSymTab(SymbolTableSection *StrTab) { Symbols = StrTab; } void setSection(SectionBase *Sec) { SecToApplyRel = Sec; } void addRelocation(Relocation Rel) { Relocations.push_back(Rel); } + void initialize(SectionTable Obj) override; void finalize() override; void writeSection(llvm::FileOutputBuffer &Out) const override; static bool classof(const SectionBase *S) { @@ -201,6 +221,7 @@ public: SectionWithStrTab(llvm::ArrayRef Data) : Section(Data) {} void setStrTab(StringTableSection *StringTable) { StrTab = StringTable; } + void initialize(SectionTable Obj) override; void finalize() override; static bool classof(const SectionBase *S); }; @@ -232,17 +253,11 @@ typedef typename ELFT::Phdr Elf_Phdr; void initSymbolTable(const llvm::object::ELFFile &ElfFile, - SymbolTableSection *SymTab); + SymbolTableSection *SymTab, SectionTable SecTable); SecPtr makeSection(const llvm::object::ELFFile &ElfFile, const Elf_Shdr &Shdr); void readProgramHeaders(const llvm::object::ELFFile &ElfFile); - void readSectionHeaders(const llvm::object::ELFFile &ElfFile); - - SectionBase *getSection(uint16_t Index, llvm::Twine ErrMsg); - - template - T *getSectionOfType(uint16_t Index, llvm::Twine ErrMsg, - llvm::Twine CastErrMsg); + SectionTable readSectionHeaders(const llvm::object::ELFFile &ElfFile); protected: StringTableSection *SectionNames; Index: tools/llvm-objcopy/Object.cpp =================================================================== --- tools/llvm-objcopy/Object.cpp +++ tools/llvm-objcopy/Object.cpp @@ -49,6 +49,7 @@ std::copy(std::begin(Contents), std::end(Contents), Buf); } +void SectionBase::initialize(SectionTable SecTable) {} void SectionBase::finalize() {} template @@ -149,6 +150,16 @@ Size += this->EntrySize; } +void SymbolTableSection::initialize(SectionTable SecTable) { + Size = 0; + setStrTab(SecTable.getSectionOfType( + Link, + "Symbol table has link index of " + Twine(Link) + + " which is not a valid index", + "Symbol table has link index of " + Twine(Link) + + " which is not a string table")); +} + void SymbolTableSection::finalize() { // Make sure SymbolNames is finalized before getting name indexes. SymbolNames->finalize(); @@ -195,6 +206,19 @@ } } +template +void RelocationSection::initialize(SectionTable SecTable) { + setSymTab(SecTable.getSectionOfType( + Link, + "Link field value " + Twine(Link) + " in section " + Name + " is invalid", + "Link field value " + Twine(Link) + " in section " + Name + + " is not a symbol table")); + + setSection(SecTable.getSection(Info, + "Info field value " + Twine(Info) + + " in section " + Name + " is invalid")); +} + template void RelocationSection::finalize() { this->Link = Symbols->Index; this->Info = SecToApplyRel->Index; @@ -232,6 +256,13 @@ return isa(S) || isa(S); } +void SectionWithStrTab::initialize(SectionTable SecTable) { + setStrTab(SecTable.getSectionOfType( + Link, + "Link field value " + Twine(Link) + " in section " + Name + " is invalid", + "Link field value " + Twine(Link) + " in section " + Name + + " is not a string table")); +} void SectionWithStrTab::finalize() { this->Link = StrTab->Index; } // Returns true IFF a section is wholly inside the range of a segment @@ -311,15 +342,8 @@ template void Object::initSymbolTable(const llvm::object::ELFFile &ElfFile, - SymbolTableSection *SymTab) { - - SymTab->Size = 0; - SymTab->setStrTab(getSectionOfType( - SymbolTable->Link, - "Symbol table has link index of " + Twine(SymTab->Link) + - " which is not a valid index", - "Symbol table has link index of " + Twine(SymTab->Link) + - " which is not a string table")); + SymbolTableSection *SymTab, + SectionTable SecTable) { const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index)); StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr)); @@ -336,7 +360,7 @@ Twine(Sym.st_shndx)); } } else if (Sym.st_shndx != SHN_UNDEF) { - DefSection = getSection( + DefSection = SecTable.getSection( Sym.st_shndx, "Symbol '" + Name + "' is defined in invalid section with index " + Twine(Sym.st_shndx)); @@ -368,16 +392,14 @@ } } -template -SectionBase *Object::getSection(uint16_t Index, Twine ErrMsg) { +SectionBase *SectionTable::getSection(uint16_t Index, Twine ErrMsg) { if (Index == SHN_UNDEF || Index > Sections.size()) error(ErrMsg); return Sections[Index - 1].get(); } -template template -T *Object::getSectionOfType(uint16_t Index, Twine ErrMsg, +T *SectionTable::getSectionOfType(uint16_t Index, Twine ErrMsg, Twine CastErrMsg) { if (T *TSec = llvm::dyn_cast(getSection(Index, ErrMsg))) return TSec; @@ -428,7 +450,7 @@ } template -void Object::readSectionHeaders(const ELFFile &ElfFile) { +SectionTable Object::readSectionHeaders(const ELFFile &ElfFile) { uint32_t Index = 0; for (const auto &Shdr : unwrapOrError(ElfFile.sections())) { if (Index == 0) { @@ -451,46 +473,35 @@ Sections.push_back(std::move(Sec)); } + SectionTable SecTable(Sections); + // Now that all of the sections have been added we can fill out some extra - // details about symbol tables. - if (SymbolTable) - initSymbolTable(ElfFile, SymbolTable); + // details about symbol tables. We need the symbol table filled out before + // any relocations. + if (SymbolTable) { + SymbolTable->initialize(SecTable); + initSymbolTable(ElfFile, SymbolTable, SecTable); + } // Now that all sections and symbols have been added we can add // relocations that reference symbols and set the link and info fields for // relocation sections. for (auto &Section : Sections) { + if (Section.get() == SymbolTable) + continue; + Section->initialize(SecTable); if (auto RelSec = dyn_cast>(Section.get())) { - auto SymTab = getSectionOfType( - RelSec->Link, - "Link field value " + Twine(RelSec->Link) + " in section " + - RelSec->Name + " is invalid", - "Link field value " + Twine(RelSec->Link) + " in section " + - RelSec->Name + " is not a symbol table"); - RelSec->setSymTab(SymTab); - - RelSec->setSection(getSection(RelSec->Info, - "Info field value " + Twine(RelSec->Link) + - " in section " + RelSec->Name + - " is invalid")); - auto Shdr = unwrapOrError(ElfFile.sections()).begin() + RelSec->Index; if (RelSec->Type == SHT_REL) - initRelocations(RelSec, SymTab, unwrapOrError(ElfFile.rels(Shdr))); + initRelocations(RelSec, SymbolTable, unwrapOrError(ElfFile.rels(Shdr))); else - initRelocations(RelSec, SymTab, unwrapOrError(ElfFile.relas(Shdr))); - } - - if (auto Sec = dyn_cast(Section.get())) { - Sec->setStrTab(getSectionOfType( - Sec->Link, - "Link field value " + Twine(Sec->Link) + " in section " + Sec->Name + - " is invalid", - "Link field value " + Twine(Sec->Link) + " in section " + Sec->Name + - " is not a string table")); + initRelocations(RelSec, SymbolTable, + unwrapOrError(ElfFile.relas(Shdr))); } } + + return SecTable; } template Object::Object(const ELFObjectFile &Obj) { @@ -504,10 +515,10 @@ Entry = Ehdr.e_entry; Flags = Ehdr.e_flags; - readSectionHeaders(ElfFile); + SectionTable SecTable = readSectionHeaders(ElfFile); readProgramHeaders(ElfFile); - SectionNames = getSectionOfType( + SectionNames = SecTable.getSectionOfType( Ehdr.e_shstrndx, "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf header " + " is invalid",