Index: tools/llvm-objcopy/Object.h =================================================================== --- tools/llvm-objcopy/Object.h +++ tools/llvm-objcopy/Object.h @@ -18,6 +18,24 @@ #include class Segment; +class SectionBase; + +class SectionTableRef { +private: + llvm::ArrayRef> Sections; + +public: + SectionTableRef(llvm::ArrayRef> Secs) + : Sections(Secs) {} + SectionTableRef(const SectionTableRef &) = default; + + SectionBase *getSection(uint16_t Index, llvm::Twine ErrMsg); + + template + + T *getSectionOfType(uint16_t Index, llvm::Twine IndexErrMsg, + llvm::Twine TypeErrMsg); +}; class SectionBase { public: @@ -39,6 +57,7 @@ uint64_t Type = llvm::ELF::SHT_NULL; virtual ~SectionBase() {} + virtual void initialize(SectionTableRef Obj); virtual void finalize(); template void writeHeader(llvm::FileOutputBuffer &Out) const; virtual void writeSection(llvm::FileOutputBuffer &Out) const = 0; @@ -154,6 +173,7 @@ uint64_t Sz); void addSymbolNames(); const Symbol *getSymbolByIndex(uint32_t Index) const; + void initialize(SectionTableRef Obj) override; void finalize() override; static bool classof(const SectionBase *S) { return S->Type == llvm::ELF::SHT_SYMTAB; @@ -187,6 +207,7 @@ void setSymTab(SymbolTableSection *StrTab) { Symbols = StrTab; } void setSection(SectionBase *Sec) { SecToApplyRel = Sec; } void addRelocation(Relocation Rel) { Relocations.push_back(Rel); } + void initialize(SectionTableRef Obj) override; void finalize() override; void writeSection(llvm::FileOutputBuffer &Out) const override; static bool classof(const SectionBase *S) { @@ -201,6 +222,7 @@ public: SectionWithStrTab(llvm::ArrayRef Data) : Section(Data) {} void setStrTab(StringTableSection *StringTable) { StrTab = StringTable; } + void initialize(SectionTableRef Obj) override; void finalize() override; static bool classof(const SectionBase *S); }; @@ -232,11 +254,11 @@ typedef typename ELFT::Phdr Elf_Phdr; void initSymbolTable(const llvm::object::ELFFile &ElfFile, - SymbolTableSection *SymTab); + SymbolTableSection *SymTab, SectionTableRef 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); + SectionTableRef readSectionHeaders(const llvm::object::ELFFile &ElfFile); SectionBase *getSection(uint16_t Index, llvm::Twine ErrMsg); 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(SectionTableRef SecTable) {} void SectionBase::finalize() {} template @@ -149,6 +150,16 @@ Size += this->EntrySize; } +void SymbolTableSection::initialize(SectionTableRef 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(SectionTableRef 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,14 @@ return isa(S) || isa(S); } +void SectionWithStrTab::initialize(SectionTableRef 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 +343,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, + SectionTableRef SecTable) { const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index)); StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr)); @@ -336,7 +361,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,6 +393,20 @@ } } +SectionBase *SectionTableRef::getSection(uint16_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, + Twine TypeErrMsg) { + if (T *TSec = llvm::dyn_cast(getSection(Index, IndexErrMsg))) + return TSec; + error(TypeErrMsg); +} + template SectionBase *Object::getSection(uint16_t Index, Twine ErrMsg) { if (Index == SHN_UNDEF || Index > Sections.size()) @@ -428,7 +467,7 @@ } template -void Object::readSectionHeaders(const ELFFile &ElfFile) { +SectionTableRef Object::readSectionHeaders(const ELFFile &ElfFile) { uint32_t Index = 0; for (const auto &Shdr : unwrapOrError(ElfFile.sections())) { if (Index == 0) { @@ -451,35 +490,30 @@ Sections.push_back(std::move(Sec)); } + SectionTableRef 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))); + initRelocations(RelSec, SymbolTable, + unwrapOrError(ElfFile.relas(Shdr))); } if (auto Sec = dyn_cast(Section.get())) { @@ -491,6 +525,8 @@ " is not a string table")); } } + + return SecTable; } template Object::Object(const ELFObjectFile &Obj) { @@ -504,10 +540,10 @@ Entry = Ehdr.e_entry; Flags = Ehdr.e_flags; - readSectionHeaders(ElfFile); + SectionTableRef 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",