[llvm] r312643 - [llvm-objcopy] Add support for relocations

Petr Hosek via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 6 09:19:48 PDT 2017


Author: phosek
Date: Wed Sep  6 09:19:48 2017
New Revision: 312643

URL: http://llvm.org/viewvc/llvm-project?rev=312643&view=rev
Log:
[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

Added:
    llvm/trunk/test/tools/llvm-objcopy/basic-relocations.test
    llvm/trunk/test/tools/llvm-objcopy/no-symbol-relocation.test
Modified:
    llvm/trunk/tools/llvm-objcopy/Object.cpp
    llvm/trunk/tools/llvm-objcopy/Object.h

Added: llvm/trunk/test/tools/llvm-objcopy/basic-relocations.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/basic-relocations.test?rev=312643&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/basic-relocations.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/basic-relocations.test Wed Sep  6 09:19:48 2017
@@ -0,0 +1,91 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy %t %t2
+# RUN: llvm-readobj -relocations %t2 | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1000
+    AddressAlign:    0x0000000000000010
+    Content:         "0000000000000000"
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    Info:            .text
+    Relocations:
+      - Offset: 0x1000
+        Symbol: foo
+        Type:   R_X86_64_PC32
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x2000
+    AddressAlign:    0x0000000000000010
+    Content:         "0000000000000000"
+  - Name:            .rel.data
+    Type:            SHT_REL
+    Link:            .symtab
+    Info:            .data
+    Relocations:
+      - Offset: 0x2000
+        Symbol: bar
+        Type:   R_X86_64_PC32
+  - Name:            .rela.data
+    Type:            SHT_RELA
+    Link:            .symtab
+    Info:            .data
+    Relocations:
+      - Offset: 0x2000
+        Symbol: barA
+        Type:   R_X86_64_PC32
+        Addend: 0x17
+  - Name:            .rela.text
+    Type:            SHT_RELA
+    Link:            .symtab
+    Info:            .text
+    Relocations:
+      - Offset: 0x1000
+        Symbol: fooA
+        Type:   R_X86_64_PC32
+        Addend: 0x13
+Symbols:
+  Global:
+    - Name:     _start
+      Type:     STT_FUNC
+      Section:  .text
+      Value:    0x1000
+      Size:     4
+    - Name:     foo
+      Type:     STT_FUNC
+      Size:     4
+    - Name:     fooA
+      Type:     STT_FUNC
+      Size:     4
+    - Name:     bar
+      Type:     STT_OBJECT
+      Size:     4
+    - Name:     barA
+      Type:     STT_OBJECT
+      Size:     4
+
+# CHECK:     Relocations [
+# CHECK-NEXT:  Section (2) .rel.text {
+# CHECK-NEXT:    0x1000 R_X86_64_PC32 foo 0x0
+# CHECK-NEXT:  }
+# CHECK-NEXT:  Section (4) .rel.data {
+# CHECK-NEXT:    0x2000 R_X86_64_PC32 bar 0x0
+# CHECK-NEXT:  }
+# CHECK-NEXT:  Section (5) .rela.data {
+# CHECK-NEXT:    0x2000 R_X86_64_PC32 barA 0x17
+# CHECK-NEXT:  }
+# CHECK-NEXT:  Section (6) .rela.text {
+# CHECK-NEXT:    0x1000 R_X86_64_PC32 fooA 0x13
+# CHECK-NEXT:  }
+# CHECK-NEXT:]

Added: llvm/trunk/test/tools/llvm-objcopy/no-symbol-relocation.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/no-symbol-relocation.test?rev=312643&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/no-symbol-relocation.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/no-symbol-relocation.test Wed Sep  6 09:19:48 2017
@@ -0,0 +1,30 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy %t %t2
+# RUN: llvm-readobj -relocations %t2 | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1000
+    AddressAlign:    0x0000000000000010
+    Content:         "0000000000000000"
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    Info:            .text
+    Relocations:
+      - Offset: 0x1000
+        Type:   R_X86_64_RELATIVE
+
+# CHECK:     Relocations [
+# CHECK-NEXT:  Section (2) .rel.text {
+# CHECK-NEXT:    0x1000 R_X86_64_RELATIVE - 0x0
+# CHECK-NEXT:  }
+# CHECK-NEXT:]

Modified: llvm/trunk/tools/llvm-objcopy/Object.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/Object.cpp?rev=312643&r1=312642&r2=312643&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/Object.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/Object.cpp Wed Sep  6 09:19:48 2017
@@ -154,6 +154,39 @@ void SymbolTableSectionImpl<ELFT>::write
   }
 }
 
+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
 }
 
 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(co
   // 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) {

Modified: llvm/trunk/tools/llvm-objcopy/Object.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/Object.h?rev=312643&r1=312642&r2=312643&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/Object.h (original)
+++ llvm/trunk/tools/llvm-objcopy/Object.h Wed Sep  6 09:19:48 2017
@@ -146,6 +146,35 @@ template <class ELFT> class SymbolTableS
   void writeSection(llvm::FileOutputBuffer &Out) const override;
 };
 
+struct Relocation {
+  const Symbol *Symbol;
+  uint64_t Offset;
+  uint64_t Addend;
+  uint32_t Type;
+};
+
+template <class ELFT> class RelocationSection : public SectionBase {
+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 finalize() override;
+  void writeSection(llvm::FileOutputBuffer &Out) const override;
+  static bool classof(const SectionBase *S) {
+    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;




More information about the llvm-commits mailing list