diff options
author | Jake Ehrlich <jakehehrlich@google.com> | 2017-09-20 17:11:58 +0000 |
---|---|---|
committer | Jake Ehrlich <jakehehrlich@google.com> | 2017-09-20 17:11:58 +0000 |
commit | 3028b9dc74cd3e1134ad72127d963032d1a511f9 (patch) | |
tree | 182fb777708a8b5804c7281f3232322d69c0fb33 /tools/llvm-objcopy | |
parent | f5c82586b2b214349bd7e593b3111aa912248db0 (diff) |
Reland "[llvm-objcopy] Add support for .dynamic, .dynsym, and .dynstr"
I overzealously landed this before I was sure that another change
wouldn't break the build that this change depends on.
This change adds support for sections involved in dynamic loading such
as SHT_DYNAMIC, SHT_DYNSYM, and allocated string tables.
The two added binaries used for tests can be downloaded here and here
Differential Revision: https://reviews.llvm.org/D36560
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313767 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-objcopy')
-rw-r--r-- | tools/llvm-objcopy/Object.cpp | 111 | ||||
-rw-r--r-- | tools/llvm-objcopy/Object.h | 34 |
2 files changed, 114 insertions, 31 deletions
diff --git a/tools/llvm-objcopy/Object.cpp b/tools/llvm-objcopy/Object.cpp index 16bfdfd140c..28323f47500 100644 --- a/tools/llvm-objcopy/Object.cpp +++ b/tools/llvm-objcopy/Object.cpp @@ -228,6 +228,12 @@ void RelocationSection<ELFT>::writeSection(llvm::FileOutputBuffer &Out) const { writeRel(reinterpret_cast<Elf_Rela *>(Buf)); } +bool SectionWithStrTab::classof(const SectionBase *S) { + return isa<DynamicSymbolTableSection>(S) || isa<DynamicSection>(S); +} + +void SectionWithStrTab::finalize() { this->Link = StrTab->Index; } + // Returns true IFF a section is wholly inside the range of a segment static bool sectionWithinSegment(const SectionBase &Section, const Segment &Segment) { @@ -308,16 +314,12 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile, SymbolTableSection *SymTab) { SymTab->Size = 0; - if (SymbolTable->Link - 1 >= Sections.size()) - error("Symbol table has link index of " + Twine(SymbolTable->Link) + - " which is not a valid index"); - - if (auto StrTab = - dyn_cast<StringTableSection>(Sections[SymbolTable->Link - 1].get())) - SymTab->setStrTab(StrTab); - else - error("Symbol table has link index of " + Twine(SymbolTable->Link) + - "which is not a string table"); + SymTab->setStrTab(getSectionOfType<StringTableSection>( + 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")); const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index)); StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr)); @@ -325,6 +327,7 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile, for (const auto &Sym : unwrapOrError(ElfFile.symbols(&Shdr))) { SectionBase *DefSection = nullptr; StringRef Name = unwrapOrError(Sym.getName(StrTabData)); + if (Sym.st_shndx >= SHN_LORESERVE) { if (!isValidReservedSectionIndex(Sym.st_shndx, Machine)) { error( @@ -333,12 +336,12 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile, Twine(Sym.st_shndx)); } } else if (Sym.st_shndx != SHN_UNDEF) { - if (Sym.st_shndx >= Sections.size()) - error("Symbol '" + Name + - "' is defined in invalid section with index " + + DefSection = getSection( + Sym.st_shndx, + "Symbol '" + Name + "' is defined in invalid section with index " + Twine(Sym.st_shndx)); - DefSection = Sections[Sym.st_shndx - 1].get(); } + SymTab->addSymbol(Name, Sym.getBinding(), Sym.getType(), DefSection, Sym.getValue(), Sym.st_shndx, Sym.st_size); } @@ -366,6 +369,22 @@ void initRelocations(RelocationSection<ELFT> *Relocs, } template <class ELFT> +SectionBase *Object<ELFT>::getSection(uint16_t Index, Twine ErrMsg) { + if (Index == SHN_UNDEF || Index > Sections.size()) + error(ErrMsg); + return Sections[Index - 1].get(); +} + +template <class ELFT> +template <class T> +T *Object<ELFT>::getSectionOfType(uint16_t Index, Twine IndexErrMsg, + Twine TypeErrMsg) { + if (T *TSec = llvm::dyn_cast<T>(getSection(Index, IndexErrMsg))) + return TSec; + error(TypeErrMsg); +} + +template <class ELFT> std::unique_ptr<SectionBase> Object<ELFT>::makeSection(const llvm::object::ELFFile<ELFT> &ElfFile, const Elf_Shdr &Shdr) { @@ -375,7 +394,26 @@ Object<ELFT>::makeSection(const llvm::object::ELFFile<ELFT> &ElfFile, case SHT_RELA: return llvm::make_unique<RelocationSection<ELFT>>(); case SHT_STRTAB: + // If a string table is allocated we don't want to mess with it. That would + // mean altering the memory image. There are no special link types or + // anything so we can just use a Section. + if (Shdr.sh_flags & SHF_ALLOC) { + Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); + return llvm::make_unique<Section>(Data); + } return llvm::make_unique<StringTableSection>(); + case SHT_HASH: + case SHT_GNU_HASH: + // Hash tables should refer to SHT_DYNSYM which we're not going to change. + // Because of this we don't need to mess with the hash tables either. + Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); + return llvm::make_unique<Section>(Data); + case SHT_DYNSYM: + Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); + return llvm::make_unique<DynamicSymbolTableSection>(Data); + case SHT_DYNAMIC: + Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); + return llvm::make_unique<DynamicSection>(Data); case SHT_SYMTAB: { auto SymTab = llvm::make_unique<SymbolTableSectionImpl<ELFT>>(); SymbolTable = SymTab.get(); @@ -423,28 +461,35 @@ void Object<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) { // relocation sections. for (auto &Section : Sections) { if (auto RelSec = dyn_cast<RelocationSection<ELFT>>(Section.get())) { - if (RelSec->Link - 1 >= Sections.size() || RelSec->Link == 0) { - error("Link field value " + Twine(RelSec->Link) + " in section " + - RelSec->Name + " is invalid"); - } - if (RelSec->Info - 1 >= Sections.size() || RelSec->Info == 0) { - error("Info field value " + Twine(RelSec->Link) + " in section " + - RelSec->Name + " is invalid"); - } - auto SymTab = - dyn_cast<SymbolTableSection>(Sections[RelSec->Link - 1].get()); - if (SymTab == nullptr) { - error("Link field of relocation section " + RelSec->Name + - " is not a symbol table"); - } + + auto SymTab = getSectionOfType<SymbolTableSection>( + 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(Sections[RelSec->Info - 1].get()); + + 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))); else initRelocations(RelSec, SymTab, unwrapOrError(ElfFile.relas(Shdr))); } + + if (auto Sec = dyn_cast<SectionWithStrTab>(Section.get())) { + Sec->setStrTab(getSectionOfType<StringTableSection>( + 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")); + } } } @@ -462,8 +507,12 @@ template <class ELFT> Object<ELFT>::Object(const ELFObjectFile<ELFT> &Obj) { readSectionHeaders(ElfFile); readProgramHeaders(ElfFile); - SectionNames = - dyn_cast<StringTableSection>(Sections[Ehdr.e_shstrndx - 1].get()); + SectionNames = getSectionOfType<StringTableSection>( + Ehdr.e_shstrndx, + "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf header " + + " is invalid", + "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf header " + + " is not a string table"); } template <class ELFT> diff --git a/tools/llvm-objcopy/Object.h b/tools/llvm-objcopy/Object.h index ca17d183076..9ee8b7377a0 100644 --- a/tools/llvm-objcopy/Object.h +++ b/tools/llvm-objcopy/Object.h @@ -194,6 +194,34 @@ public: } }; +class SectionWithStrTab : public Section { +private: + StringTableSection *StrTab; + +public: + SectionWithStrTab(llvm::ArrayRef<uint8_t> Data) : Section(Data) {} + void setStrTab(StringTableSection *StringTable) { StrTab = StringTable; } + void finalize() override; + static bool classof(const SectionBase *S); +}; + +class DynamicSymbolTableSection : public SectionWithStrTab { +public: + DynamicSymbolTableSection(llvm::ArrayRef<uint8_t> Data) + : SectionWithStrTab(Data) {} + static bool classof(const SectionBase *S) { + return S->Type == llvm::ELF::SHT_DYNSYM; + } +}; + +class DynamicSection : public SectionWithStrTab { +public: + DynamicSection(llvm::ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {} + static bool classof(const SectionBase *S) { + return S->Type == llvm::ELF::SHT_DYNAMIC; + } +}; + template <class ELFT> class Object { private: typedef std::unique_ptr<SectionBase> SecPtr; @@ -210,6 +238,12 @@ private: void readProgramHeaders(const llvm::object::ELFFile<ELFT> &ElfFile); void readSectionHeaders(const llvm::object::ELFFile<ELFT> &ElfFile); + SectionBase *getSection(uint16_t Index, llvm::Twine ErrMsg); + + template <class T> + T *getSectionOfType(uint16_t Index, llvm::Twine IndexErrMsg, + llvm::Twine TypeErrMsg); + protected: StringTableSection *SectionNames; SymbolTableSection *SymbolTable; |