diff options
author | Jake Ehrlich <jakehehrlich@google.com> | 2017-09-26 18:02:25 +0000 |
---|---|---|
committer | Jake Ehrlich <jakehehrlich@google.com> | 2017-09-26 18:02:25 +0000 |
commit | 9f1a390f72ea5ee64f3e7859133983e878835c0a (patch) | |
tree | f68df258ececeb26efed3e0db6227150b86f8df2 /llvm | |
parent | 448e8ad94326713b2ef3d19b7fdc397e81114750 (diff) | |
download | bcm5719-llvm-9f1a390f72ea5ee64f3e7859133983e878835c0a.tar.gz bcm5719-llvm-9f1a390f72ea5ee64f3e7859133983e878835c0a.zip |
[llvm-objcopy] Add support for dynamic relocations
This change adds support for dynamic relocations (allocated
SHT_REL/SHT_RELA sections with a dynamic symbol table as their link).
The binary I added for the test is here:
https://drive.google.com/file/d/0B3gtIAmiMwZXSjJUZE9pUjd4M0k/view?usp=sharing
Unless support for dynamic symbol tables in yaml2obj is added this is
needed.
Differential Revision: https://reviews.llvm.org/D37915
llvm-svn: 314227
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/test/tools/llvm-objcopy/Inputs/dynrel.elf | bin | 0 -> 13560 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-objcopy/dynamic-relocations.test | 19 | ||||
-rw-r--r-- | llvm/tools/llvm-objcopy/Object.cpp | 47 | ||||
-rw-r--r-- | llvm/tools/llvm-objcopy/Object.h | 46 |
4 files changed, 72 insertions, 40 deletions
diff --git a/llvm/test/tools/llvm-objcopy/Inputs/dynrel.elf b/llvm/test/tools/llvm-objcopy/Inputs/dynrel.elf Binary files differnew file mode 100644 index 00000000000..fe9d6835421 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/Inputs/dynrel.elf diff --git a/llvm/test/tools/llvm-objcopy/dynamic-relocations.test b/llvm/test/tools/llvm-objcopy/dynamic-relocations.test new file mode 100644 index 00000000000..e544e2dd8ef --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/dynamic-relocations.test @@ -0,0 +1,19 @@ +# RUN: llvm-objcopy %p/Inputs/dynrel.elf %t +# RUN: llvm-readobj -sections -section-data %t | FileCheck %s + +#CHECK: Name: .rela.plt +#CHECK-NEXT: Type: SHT_RELA +#CHECK-NEXT: Flags [ +#CHECK-NEXT: SHF_ALLOC +#CHECK-NEXT: ] +#CHECK-NEXT: Address: +#CHECK-NEXT: Offset: +#CHECK-NEXT: Size: 24 +#CHECK-NEXT: Link: +#CHECK-NEXT: Info: +#CHECK-NEXT: AddressAlignment: 8 +#CHECK-NEXT: EntrySize: 24 +#CHECK-NEXT: SectionData ( +#CHECK-NEXT: 0000: 18202000 00000000 07000000 01000000 |. .............| +#CHECK-NEXT: 0010: 00000000 00000000 |........| +#CHECK-NEXT: ) diff --git a/llvm/tools/llvm-objcopy/Object.cpp b/llvm/tools/llvm-objcopy/Object.cpp index a8cd321086b..cb7fddeee77 100644 --- a/llvm/tools/llvm-objcopy/Object.cpp +++ b/llvm/tools/llvm-objcopy/Object.cpp @@ -206,22 +206,24 @@ void SymbolTableSectionImpl<ELFT>::writeSection( } } -template <class ELFT> -void RelocationSection<ELFT>::initialize(SectionTableRef SecTable) { - setSymTab(SecTable.getSectionOfType<SymbolTableSection>( +template <class SymTabType> +void RelocationSectionBase<SymTabType>::initialize(SectionTableRef SecTable) { + setSymTab(SecTable.getSectionOfType<SymTabType>( 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")); + if (Info != SHN_UNDEF) + setSection(SecTable.getSection(Info, + "Info field value " + Twine(Info) + + " in section " + Name + " is invalid")); } -template <class ELFT> void RelocationSection<ELFT>::finalize() { +template <class SymTabType> void RelocationSectionBase<SymTabType>::finalize() { this->Link = Symbols->Index; - this->Info = SecToApplyRel->Index; + if (SecToApplyRel != nullptr) + this->Info = SecToApplyRel->Index; } template <class ELFT> @@ -252,6 +254,11 @@ void RelocationSection<ELFT>::writeSection(llvm::FileOutputBuffer &Out) const { writeRel(reinterpret_cast<Elf_Rela *>(Buf)); } +void DynamicRelocationSection::writeSection(llvm::FileOutputBuffer &Out) const { + std::copy(std::begin(Contents), std::end(Contents), + Out.getBufferStart() + Offset); +} + bool SectionWithStrTab::classof(const SectionBase *S) { return isa<DynamicSymbolTableSection>(S) || isa<DynamicSection>(S); } @@ -401,29 +408,13 @@ SectionBase *SectionTableRef::getSection(uint16_t Index, Twine ErrMsg) { template <class T> T *SectionTableRef::getSectionOfType(uint16_t Index, Twine IndexErrMsg, - Twine TypeErrMsg) { + Twine TypeErrMsg) { if (T *Sec = llvm::dyn_cast<T>(getSection(Index, IndexErrMsg))) return Sec; error(TypeErrMsg); } 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) { @@ -431,6 +422,10 @@ Object<ELFT>::makeSection(const llvm::object::ELFFile<ELFT> &ElfFile, switch (Shdr.sh_type) { case SHT_REL: case SHT_RELA: + if (Shdr.sh_flags & SHF_ALLOC) { + Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); + return llvm::make_unique<DynamicRelocationSection>(Data); + } 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 @@ -517,7 +512,7 @@ SectionTableRef Object<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) { } if (auto Sec = dyn_cast<SectionWithStrTab>(Section.get())) { - Sec->setStrTab(getSectionOfType<StringTableSection>( + Sec->setStrTab(SecTable.getSectionOfType<StringTableSection>( Sec->Link, "Link field value " + Twine(Sec->Link) + " in section " + Sec->Name + " is invalid", diff --git a/llvm/tools/llvm-objcopy/Object.h b/llvm/tools/llvm-objcopy/Object.h index 6e849e47006..41c9d7b4a3b 100644 --- a/llvm/tools/llvm-objcopy/Object.h +++ b/llvm/tools/llvm-objcopy/Object.h @@ -32,7 +32,6 @@ public: SectionBase *getSection(uint16_t Index, llvm::Twine ErrMsg); template <class T> - T *getSectionOfType(uint16_t Index, llvm::Twine IndexErrMsg, llvm::Twine TypeErrMsg); }; @@ -192,25 +191,35 @@ struct Relocation { uint32_t Type; }; -template <class ELFT> class RelocationSection : public SectionBase { +template <class SymTabType> class RelocationSectionBase : public SectionBase { +private: + SymTabType *Symbols; + SectionBase *SecToApplyRel; + +public: + void setSymTab(SymTabType *StrTab) { Symbols = StrTab; } + void setSection(SectionBase *Sec) { SecToApplyRel = Sec; } + void initialize(SectionTableRef SecTable) override; + void finalize() override; +}; + +template <class ELFT> +class RelocationSection : public RelocationSectionBase<SymbolTableSection> { private: typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; std::vector<Relocation> Relocations; - SymbolTableSection *Symbols; - SectionBase *SecToApplyRel; template <class T> void writeRel(T *Buf) const; public: - void setSymTab(SymbolTableSection *StrTab) { Symbols = StrTab; } - void setSection(SectionBase *Sec) { SecToApplyRel = Sec; } void addRelocation(Relocation Rel) { Relocations.push_back(Rel); } - void initialize(SectionTableRef SecTable) override; - void finalize() override; void writeSection(llvm::FileOutputBuffer &Out) const override; + static bool classof(const SectionBase *S) { + if (S->Flags & llvm::ELF::SHF_ALLOC) + return false; return S->Type == llvm::ELF::SHT_REL || S->Type == llvm::ELF::SHT_RELA; } }; @@ -244,6 +253,21 @@ public: } }; +class DynamicRelocationSection + : public RelocationSectionBase<DynamicSymbolTableSection> { +private: + llvm::ArrayRef<uint8_t> Contents; + +public: + DynamicRelocationSection(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {} + void writeSection(llvm::FileOutputBuffer &Out) const override; + static bool classof(const SectionBase *S) { + if (!(S->Flags & llvm::ELF::SHF_ALLOC)) + return false; + return S->Type == llvm::ELF::SHT_REL || S->Type == llvm::ELF::SHT_RELA; + } +}; + template <class ELFT> class Object { private: typedef std::unique_ptr<SectionBase> SecPtr; @@ -260,12 +284,6 @@ private: void readProgramHeaders(const llvm::object::ELFFile<ELFT> &ElfFile); SectionTableRef 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; |