diff options
author | Petr Hosek <phosek@chromium.org> | 2017-09-06 16:19:48 +0000 |
---|---|---|
committer | Petr Hosek <phosek@chromium.org> | 2017-09-06 16:19:48 +0000 |
commit | bdc3e61d21eaaf1c4f5203e47d39fd8d120251ee (patch) | |
tree | 3d9e5fd5508d81d989f5cf127efedb8a47910563 /llvm/tools/llvm-objcopy/Object.cpp | |
parent | f43f714213d431806a292bf3888a99eefc09ea5f (diff) | |
download | bcm5719-llvm-bdc3e61d21eaaf1c4f5203e47d39fd8d120251ee.tar.gz bcm5719-llvm-bdc3e61d21eaaf1c4f5203e47d39fd8d120251ee.zip |
[llvm-objcopy] Add support for relocations
This change adds support for SHT_REL and SHT_RELA sections in
llvm-objcopy.
Patch by Jake Ehrlich
Differential Revision: https://reviews.llvm.org/D36554
llvm-svn: 312643
Diffstat (limited to 'llvm/tools/llvm-objcopy/Object.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/Object.cpp | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/llvm/tools/llvm-objcopy/Object.cpp b/llvm/tools/llvm-objcopy/Object.cpp index 7738171d4e8..ada62aa713b 100644 --- a/llvm/tools/llvm-objcopy/Object.cpp +++ b/llvm/tools/llvm-objcopy/Object.cpp @@ -154,6 +154,39 @@ void SymbolTableSectionImpl<ELFT>::writeSection( } } +template <class ELFT> void RelocationSection<ELFT>::finalize() { + this->Link = Symbols->Index; + this->Info = SecToApplyRel->Index; +} + +template <class ELFT> +void setAddend(Elf_Rel_Impl<ELFT, false> &Rel, uint64_t Addend) {} + +template <class ELFT> +void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) { + Rela.r_addend = Addend; +} + +template <class ELFT> +template <class T> +void RelocationSection<ELFT>::writeRel(T *Buf) const { + for (const auto &Reloc : Relocations) { + Buf->r_offset = Reloc.Offset; + setAddend(*Buf, Reloc.Addend); + Buf->setSymbolAndType(Reloc.Symbol->Index, Reloc.Type, false); + ++Buf; + } +} + +template <class ELFT> +void RelocationSection<ELFT>::writeSection(llvm::FileOutputBuffer &Out) const { + uint8_t *Buf = Out.getBufferStart() + Offset; + if (Type == SHT_REL) + writeRel(reinterpret_cast<Elf_Rel *>(Buf)); + else + writeRel(reinterpret_cast<Elf_Rela *>(Buf)); +} + // Returns true IFF a section is wholly inside the range of a segment static bool sectionWithinSegment(const SectionBase &Section, const Segment &Segment) { @@ -231,11 +264,35 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile, } template <class ELFT> +static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, false> &Rel) {} + +template <class ELFT> +static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) { + ToSet = Rela.r_addend; +} + +template <class ELFT, class T> +void initRelocations(RelocationSection<ELFT> *Relocs, + SymbolTableSection *SymbolTable, T RelRange) { + for (const auto &Rel : RelRange) { + Relocation ToAdd; + ToAdd.Offset = Rel.r_offset; + getAddend(ToAdd.Addend, Rel); + ToAdd.Type = Rel.getType(false); + ToAdd.Symbol = SymbolTable->getSymbolByIndex(Rel.getSymbol(false)); + Relocs->addRelocation(ToAdd); + } +} + +template <class ELFT> std::unique_ptr<SectionBase> Object<ELFT>::makeSection(const llvm::object::ELFFile<ELFT> &ElfFile, const Elf_Shdr &Shdr) { ArrayRef<uint8_t> Data; switch (Shdr.sh_type) { + case SHT_REL: + case SHT_RELA: + return llvm::make_unique<RelocationSection<ELFT>>(); case SHT_STRTAB: return llvm::make_unique<StringTableSection>(); case SHT_SYMTAB: { @@ -279,6 +336,35 @@ void Object<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) { // details about symbol tables. if (SymbolTable) initSymbolTable(ElfFile, SymbolTable); + + // 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 (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"); + } + RelSec->setSymTab(SymTab); + RelSec->setSection(Sections[RelSec->Info - 1].get()); + 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))); + } + } } template <class ELFT> Object<ELFT>::Object(const ELFObjectFile<ELFT> &Obj) { |