Revert "Rebase: [Facebook] Revert "[BOLT] Update dynamic relocations from section...
authorspupyrev <spupyrev@fb.com>
Mon, 11 Jul 2022 16:49:41 +0000 (09:49 -0700)
committerspupyrev <spupyrev@fb.com>
Mon, 11 Jul 2022 16:50:47 +0000 (09:50 -0700)
This reverts commit 76029cc53e838e6d86b13b0c39152f474fb09263.

bolt/include/bolt/Core/BinarySection.h
bolt/include/bolt/Core/Relocation.h
bolt/include/bolt/Rewrite/RewriteInstance.h
bolt/lib/Core/Relocation.cpp
bolt/lib/Rewrite/RewriteInstance.cpp
bolt/test/AArch64/Inputs/rels-exe.yaml [new file with mode: 0644]
bolt/test/AArch64/Inputs/rels-so.yaml [new file with mode: 0644]
bolt/test/AArch64/runtime-relocs.test [new file with mode: 0644]

index bef74cc..c91d3d7 100644 (file)
@@ -296,6 +296,16 @@ public:
     return make_range(Relocations.begin(), Relocations.end());
   }
 
+  /// Iterate over all dynamic relocations for this section.
+  iterator_range<RelocationSetType::iterator> dynamicRelocations() {
+    return make_range(DynamicRelocations.begin(), DynamicRelocations.end());
+  }
+
+  /// Iterate over all dynamic relocations for this section.
+  iterator_range<RelocationSetType::const_iterator> dynamicRelocations() const {
+    return make_range(DynamicRelocations.begin(), DynamicRelocations.end());
+  }
+
   /// Does this section have any non-pending relocations?
   bool hasRelocations() const { return !Relocations.empty(); }
 
index 99bf53a..08bb02c 100644 (file)
@@ -95,6 +95,9 @@ struct Relocation {
   /// Return true if relocation type is for thread local storage.
   static bool isTLS(uint64_t Type);
 
+  /// Return code for a NONE relocation
+  static uint64_t getNone();
+
   /// Return code for a PC-relative 4-byte relocation
   static uint64_t getPC32();
 
@@ -104,6 +107,10 @@ struct Relocation {
   /// Return true if this relocation is PC-relative. Return false otherwise.
   bool isPCRelative() const { return isPCRelative(Type); }
 
+  /// Return true if this relocation is R_*_RELATIVE type. Return false
+  /// otherwise.
+  bool isRelative() const { return isRelative(Type); }
+
   /// Emit relocation at a current \p Streamer' position. The caller is
   /// responsible for setting the position correctly.
   size_t emit(MCStreamer *Streamer) const;
index f1ae053..7f39b70 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/Support/Error.h"
 #include <map>
 #include <set>
+#include <unordered_map>
 
 namespace llvm {
 
@@ -131,7 +132,7 @@ private:
   void processLKSMPLocks();
 
   /// Read relocations from a given section.
-  void readDynamicRelocations(const object::SectionRef &Section);
+  void readDynamicRelocations(const object::SectionRef &Section, bool IsJmpRel);
 
   /// Read relocations from a given section.
   void readRelocations(const object::SectionRef &Section);
@@ -208,6 +209,10 @@ private:
   /// \p OldAddress address in the original binary.
   uint64_t getNewFunctionAddress(uint64_t OldAddress);
 
+  /// Return address of a function or moved data in the new binary
+  /// corresponding to \p OldAddress address in the original binary.
+  uint64_t getNewFunctionOrDataAddress(uint64_t OldAddress);
+
   /// Return value for the symbol \p Name in the output.
   uint64_t getNewValueForSymbol(const StringRef Name);
 
@@ -319,6 +324,14 @@ private:
       const std::vector<uint32_t> &NewSectionIndex, WriteFuncTy Write,
       StrTabFuncTy AddToStrTab);
 
+  /// Get output index in dynamic symbol table.
+  uint32_t getOutputDynamicSymbolIndex(const MCSymbol *Symbol) {
+    auto It = SymbolIndex.find(Symbol);
+    if (It != SymbolIndex.end())
+      return It->second;
+    return 0;
+  }
+
   /// Add a notes section containing the BOLT revision and command line options.
   void addBoltInfoSection();
 
@@ -446,11 +459,19 @@ private:
   /// Location and size of dynamic relocations.
   Optional<uint64_t> DynamicRelocationsAddress;
   uint64_t DynamicRelocationsSize{0};
+  uint64_t DynamicRelativeRelocationsCount{0};
 
   /// PLT relocations are special kind of dynamic relocations stored separately.
   Optional<uint64_t> PLTRelocationsAddress;
   uint64_t PLTRelocationsSize{0};
 
+  /// True if relocation of specified type came from .rela.plt
+  DenseMap<uint64_t, bool> IsJmpRelocation;
+
+  /// Index of specified symbol in the dynamic symbol table. NOTE Currently it
+  /// is filled and used only with the relocations-related symbols.
+  std::unordered_map<const MCSymbol *, uint32_t> SymbolIndex;
+
   /// Store all non-zero symbols in this map for a quick address lookup.
   std::map<uint64_t, llvm::object::SymbolRef> FileSymRefs;
 
index ef76430..f989ab1 100644 (file)
@@ -580,11 +580,7 @@ bool Relocation::isX86GOTPCRELX(uint64_t Type) {
   return Type == ELF::R_X86_64_GOTPCRELX || Type == ELF::R_X86_64_REX_GOTPCRELX;
 }
 
-bool Relocation::isNone(uint64_t Type) {
-  if (Arch == Triple::aarch64)
-    return Type == ELF::R_AARCH64_NONE;
-  return Type == ELF::R_X86_64_NONE;
-}
+bool Relocation::isNone(uint64_t Type) { return Type == getNone(); }
 
 bool Relocation::isRelative(uint64_t Type) {
   if (Arch == Triple::aarch64)
@@ -604,10 +600,10 @@ bool Relocation::isTLS(uint64_t Type) {
   return isTLSX86(Type);
 }
 
-bool Relocation::isPCRelative(uint64_t Type) {
+uint64_t Relocation::getNone() {
   if (Arch == Triple::aarch64)
-    return isPCRelativeAArch64(Type);
-  return isPCRelativeX86(Type);
+    return ELF::R_AARCH64_NONE;
+  return ELF::R_X86_64_NONE;
 }
 
 uint64_t Relocation::getPC32() {
@@ -622,6 +618,12 @@ uint64_t Relocation::getPC64() {
   return ELF::R_X86_64_PC64;
 }
 
+bool Relocation::isPCRelative(uint64_t Type) {
+  if (Arch == Triple::aarch64)
+    return isPCRelativeAArch64(Type);
+  return isPCRelativeX86(Type);
+}
+
 size_t Relocation::emit(MCStreamer *Streamer) const {
   const size_t Size = getSizeForType(Type);
   MCContext &Ctx = Streamer->getContext();
index 899e9e7..1047c2c 100644 (file)
@@ -1803,6 +1803,40 @@ int64_t getRelocationAddend(const ELFObjectFileBase *Obj,
   auto *ELF64BE = cast<ELF64BEObjectFile>(Obj);
   return getRelocationAddend(ELF64BE, Rel);
 }
+
+template <typename ELFT>
+uint32_t getRelocationSymbol(const ELFObjectFile<ELFT> *Obj,
+                             const RelocationRef &RelRef) {
+  using ELFShdrTy = typename ELFT::Shdr;
+  uint32_t Symbol = 0;
+  const ELFFile<ELFT> &EF = Obj->getELFFile();
+  DataRefImpl Rel = RelRef.getRawDataRefImpl();
+  const ELFShdrTy *RelocationSection = cantFail(EF.getSection(Rel.d.a));
+  switch (RelocationSection->sh_type) {
+  default:
+    llvm_unreachable("unexpected relocation section type");
+  case ELF::SHT_REL:
+    Symbol = Obj->getRel(Rel)->getSymbol(EF.isMips64EL());
+    break;
+  case ELF::SHT_RELA:
+    Symbol = Obj->getRela(Rel)->getSymbol(EF.isMips64EL());
+    break;
+  }
+
+  return Symbol;
+}
+
+uint32_t getRelocationSymbol(const ELFObjectFileBase *Obj,
+                             const RelocationRef &Rel) {
+  if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj))
+    return getRelocationSymbol(ELF32LE, Rel);
+  if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj))
+    return getRelocationSymbol(ELF64LE, Rel);
+  if (auto *ELF32BE = dyn_cast<ELF32BEObjectFile>(Obj))
+    return getRelocationSymbol(ELF32BE, Rel);
+  auto *ELF64BE = cast<ELF64BEObjectFile>(Obj);
+  return getRelocationSymbol(ELF64BE, Rel);
+}
 } // anonymous namespace
 
 bool RewriteInstance::analyzeRelocation(
@@ -1937,7 +1971,8 @@ void RewriteInstance::processDynamicRelocations() {
     if (PLTRelSectionOrErr->getSize() != PLTRelocationsSize)
       report_error("section size mismatch for DT_PLTRELSZ",
                    errc::executable_format_error);
-    readDynamicRelocations(PLTRelSectionOrErr->getSectionRef());
+    readDynamicRelocations(PLTRelSectionOrErr->getSectionRef(),
+                           /*IsJmpRel*/ true);
   }
 
   // The rest of dynamic relocations - DT_RELA.
@@ -1950,7 +1985,8 @@ void RewriteInstance::processDynamicRelocations() {
     if (DynamicRelSectionOrErr->getSize() != DynamicRelocationsSize)
       report_error("section size mismatch for DT_RELASZ",
                    errc::executable_format_error);
-    readDynamicRelocations(DynamicRelSectionOrErr->getSectionRef());
+    readDynamicRelocations(DynamicRelSectionOrErr->getSectionRef(),
+                           /*IsJmpRel*/ false);
   }
 }
 
@@ -2174,7 +2210,8 @@ void RewriteInstance::processLKSMPLocks() {
   }
 }
 
-void RewriteInstance::readDynamicRelocations(const SectionRef &Section) {
+void RewriteInstance::readDynamicRelocations(const SectionRef &Section,
+                                             bool IsJmpRel) {
   assert(BinarySection(*BC, Section).isAllocatable() && "allocatable expected");
 
   LLVM_DEBUG({
@@ -2184,7 +2221,7 @@ void RewriteInstance::readDynamicRelocations(const SectionRef &Section) {
   });
 
   for (const RelocationRef &Rel : Section.relocations()) {
-    uint64_t RType = Rel.getType();
+    const uint64_t RType = Rel.getType();
     if (Relocation::isNone(RType))
       continue;
 
@@ -2212,7 +2249,13 @@ void RewriteInstance::readDynamicRelocations(const SectionRef &Section) {
              << " : + 0x" << Twine::utohexstr(Addend) << '\n'
     );
 
-    BC->addDynamicRelocation(Rel.getOffset(), Symbol, Rel.getType(), Addend);
+    if (IsJmpRel)
+      IsJmpRelocation[RType] = true;
+
+    if (Symbol)
+      SymbolIndex[Symbol] = getRelocationSymbol(InputFile, Rel);
+
+    BC->addDynamicRelocation(Rel.getOffset(), Symbol, RType, Addend);
   }
 }
 
@@ -4842,28 +4885,108 @@ void
 RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
   using Elf_Rela = typename ELFT::Rela;
   raw_fd_ostream &OS = Out->os();
+  const ELFFile<ELFT> &EF = File->getELFFile();
 
-  for (BinarySection &RelaSection : BC->allocatableRelaSections()) {
-    for (const RelocationRef &Rel : RelaSection.getSectionRef().relocations()) {
-      uint64_t RType = Rel.getType();
-      if (!Relocation::isRelative(RType) && !Relocation::isIRelative(RType))
-        continue;
-      DataRefImpl DRI = Rel.getRawDataRefImpl();
-      const Elf_Rela *RelA = File->getRela(DRI);
-      auto Address = RelA->r_addend;
-      uint64_t NewAddress = getNewFunctionAddress(Address);
-      if (!NewAddress)
-        continue;
-      LLVM_DEBUG(dbgs() << "BOLT-DEBUG: patching (I)RELATIVE "
-                        << RelaSection.getName() << " entry 0x"
-                        << Twine::utohexstr(Address) << " with 0x"
-                        << Twine::utohexstr(NewAddress) << '\n');
-      Elf_Rela NewRelA = *RelA;
-      NewRelA.r_addend = NewAddress;
-      OS.pwrite(reinterpret_cast<const char *>(&NewRelA), sizeof(NewRelA),
-                reinterpret_cast<const char *>(RelA) - File->getData().data());
+  uint64_t RelDynOffset = 0, RelDynEndOffset = 0;
+  uint64_t RelPltOffset = 0, RelPltEndOffset = 0;
+
+  auto setSectionFileOffsets = [&](uint64_t Address, uint64_t &Start,
+                                   uint64_t &End) {
+    ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);
+    Start = Section->getInputFileOffset();
+    End = Start + Section->getSize();
+  };
+
+  if (!DynamicRelocationsAddress && !PLTRelocationsAddress)
+    return;
+
+  if (DynamicRelocationsAddress)
+    setSectionFileOffsets(*DynamicRelocationsAddress, RelDynOffset,
+                          RelDynEndOffset);
+
+  if (PLTRelocationsAddress)
+    setSectionFileOffsets(*PLTRelocationsAddress, RelPltOffset,
+                          RelPltEndOffset);
+
+  DynamicRelativeRelocationsCount = 0;
+
+  auto writeRela = [&OS](const Elf_Rela *RelA, uint64_t &Offset) {
+    OS.pwrite(reinterpret_cast<const char *>(RelA), sizeof(*RelA), Offset);
+    Offset += sizeof(*RelA);
+  };
+
+  auto writeRelocations = [&](bool PatchRelative) {
+    for (BinarySection &Section : BC->allocatableSections()) {
+      for (const Relocation &Rel : Section.dynamicRelocations()) {
+        const bool IsRelative = Rel.isRelative();
+        if (PatchRelative != IsRelative)
+          continue;
+
+        if (IsRelative)
+          ++DynamicRelativeRelocationsCount;
+
+        Elf_Rela NewRelA;
+        uint64_t SectionAddress = Section.getOutputAddress();
+        SectionAddress =
+            SectionAddress == 0 ? Section.getAddress() : SectionAddress;
+        MCSymbol *Symbol = Rel.Symbol;
+        uint32_t SymbolIdx = 0;
+        uint64_t Addend = Rel.Addend;
+
+        if (Rel.Symbol) {
+          SymbolIdx = getOutputDynamicSymbolIndex(Symbol);
+        } else {
+          // Usually this case is used for R_*_(I)RELATIVE relocations
+          const uint64_t Address = getNewFunctionOrDataAddress(Addend);
+          if (Address)
+            Addend = Address;
+        }
+
+        NewRelA.setSymbolAndType(SymbolIdx, Rel.Type, EF.isMips64EL());
+        NewRelA.r_offset = SectionAddress + Rel.Offset;
+        NewRelA.r_addend = Addend;
+
+        const bool IsJmpRel =
+            !!(IsJmpRelocation.find(Rel.Type) != IsJmpRelocation.end());
+        uint64_t &Offset = IsJmpRel ? RelPltOffset : RelDynOffset;
+        const uint64_t &EndOffset =
+            IsJmpRel ? RelPltEndOffset : RelDynEndOffset;
+        if (!Offset || !EndOffset) {
+          errs() << "BOLT-ERROR: Invalid offsets for dynamic relocation\n";
+          exit(1);
+        }
+
+        if (Offset + sizeof(NewRelA) > EndOffset) {
+          errs() << "BOLT-ERROR: Offset overflow for dynamic relocation\n";
+          exit(1);
+        }
+
+        writeRela(&NewRelA, Offset);
+      }
     }
-  }
+  };
+
+  // The dynamic linker expects R_*_RELATIVE relocations to be emitted first
+  writeRelocations(/* PatchRelative */ true);
+  writeRelocations(/* PatchRelative */ false);
+
+  auto fillNone = [&](uint64_t &Offset, uint64_t EndOffset) {
+    if (!Offset)
+      return;
+
+    typename ELFObjectFile<ELFT>::Elf_Rela RelA;
+    RelA.setSymbolAndType(0, Relocation::getNone(), EF.isMips64EL());
+    RelA.r_offset = 0;
+    RelA.r_addend = 0;
+    while (Offset < EndOffset)
+      writeRela(&RelA, Offset);
+
+    assert(Offset == EndOffset && "Unexpected section overflow");
+  };
+
+  // Fill the rest of the sections with R_*_NONE relocations
+  fillNone(RelDynOffset, RelDynEndOffset);
+  fillNone(RelPltOffset, RelPltEndOffset);
 }
 
 template <typename ELFT>
@@ -4879,7 +5002,8 @@ void RewriteInstance::patchELFGOT(ELFObjectFile<ELFT> *File) {
     }
   }
   if (!GOTSection.getObject()) {
-    errs() << "BOLT-INFO: no .got section found\n";
+    if (!BC->IsStaticExecutable)
+      errs() << "BOLT-INFO: no .got section found\n";
     return;
   }
 
@@ -4938,6 +5062,9 @@ void RewriteInstance::patchELFDynamic(ELFObjectFile<ELFT> *File) {
     default:
       ShouldPatch = false;
       break;
+    case ELF::DT_RELACOUNT:
+      NewDE.d_un.d_val = DynamicRelativeRelocationsCount;
+      break;
     case ELF::DT_INIT:
     case ELF::DT_FINI: {
       if (BC->HasRelocations) {
@@ -5043,15 +5170,21 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile<ELFT> *File) {
     case ELF::DT_PLTRELSZ:
       PLTRelocationsSize = Dyn.getVal();
       break;
+    case ELF::DT_RELACOUNT:
+      DynamicRelativeRelocationsCount = Dyn.getVal();
+      break;
     }
   }
 
-  if (!DynamicRelocationsAddress)
+  if (!DynamicRelocationsAddress || !DynamicRelocationsSize) {
+    DynamicRelocationsAddress.reset();
     DynamicRelocationsSize = 0;
+  }
 
-  if (!PLTRelocationsAddress)
+  if (!PLTRelocationsAddress || !PLTRelocationsSize) {
+    PLTRelocationsAddress.reset();
     PLTRelocationsSize = 0;
-
+  }
   return Error::success();
 }
 
@@ -5063,6 +5196,17 @@ uint64_t RewriteInstance::getNewFunctionAddress(uint64_t OldAddress) {
   return Function->getOutputAddress();
 }
 
+uint64_t RewriteInstance::getNewFunctionOrDataAddress(uint64_t OldAddress) {
+  if (uint64_t Function = getNewFunctionAddress(OldAddress))
+    return Function;
+
+  const BinaryData *BD = BC->getBinaryDataAtAddress(OldAddress);
+  if (BD && BD->isMoved())
+    return BD->getOutputAddress();
+
+  return 0;
+}
+
 void RewriteInstance::rewriteFile() {
   std::error_code EC;
   Out = std::make_unique<ToolOutputFile>(opts::OutputFilename, EC,
@@ -5235,14 +5379,14 @@ void RewriteInstance::rewriteFile() {
   // Copy non-allocatable sections once allocatable part is finished.
   rewriteNoteSections();
 
-  // Patch dynamic section/segment.
-  patchELFDynamic();
-
   if (BC->HasRelocations) {
     patchELFAllocatableRelaSections();
     patchELFGOT();
   }
 
+  // Patch dynamic section/segment.
+  patchELFDynamic();
+
   // Update ELF book-keeping info.
   patchELFSectionHeaderTable();
 
diff --git a/bolt/test/AArch64/Inputs/rels-exe.yaml b/bolt/test/AArch64/Inputs/rels-exe.yaml
new file mode 100644 (file)
index 0000000..58f538d
--- /dev/null
@@ -0,0 +1,351 @@
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_AARCH64
+  Entry:           0x210710
+ProgramHeaders:
+  - Type:            PT_PHDR
+    Flags:           [ PF_R ]
+    VAddr:           0x200040
+    Align:           0x8
+  - Type:            PT_INTERP
+    Flags:           [ PF_R ]
+    FirstSec:        .interp
+    LastSec:         .interp
+    VAddr:           0x2002A8
+  - Type:            PT_LOAD
+    Flags:           [ PF_R ]
+    FirstSec:        .interp
+    LastSec:         .rodata
+    VAddr:           0x200000
+    Align:           0x10000
+  - Type:            PT_LOAD
+    Flags:           [ PF_X, PF_R ]
+    FirstSec:        .text
+    LastSec:         .iplt
+    VAddr:           0x210710
+    Align:           0x10000
+  - Type:            PT_LOAD
+    Flags:           [ PF_W, PF_R ]
+    FirstSec:        .iplt
+    LastSec:         .got
+    VAddr:           0x220990
+    Align:           0x10000
+  - Type:            PT_LOAD
+    Flags:           [ PF_W, PF_R ]
+    FirstSec:        .data
+    LastSec:         .bss
+    VAddr:           0x230B40
+    Align:           0x10000
+  - Type:            PT_DYNAMIC
+    Flags:           [ PF_W, PF_R ]
+    FirstSec:        .dynamic
+    LastSec:         .dynamic
+    VAddr:           0x2209A0
+    Align:           0x8
+Sections:
+  - Name:            .interp
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x2002A8
+    AddressAlign:    0x1
+    Content:         2F6C69622F6C642D6C696E75782D616172636836342E736F2E3100
+  - Name:            .dynsym
+    Type:            SHT_DYNSYM
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x2002E8
+    Link:            .dynstr
+    AddressAlign:    0x8
+  - Name:            .dynstr
+    Type:            SHT_STRTAB
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x200418
+    AddressAlign:    0x1
+  - Name:            .rela.dyn
+    Type:            SHT_RELA
+    Flags:           [ SHF_ALLOC, SHF_INFO_LINK ]
+    Address:         0x2004A0
+    Link:            .dynsym
+    AddressAlign:    0x8
+    Info:            .got.plt
+    Relocations:
+      - Offset:          0x220B38
+        Symbol:          t1
+        Type:            R_AARCH64_TLS_TPREL64
+      - Offset:          0x230B98
+        Symbol:          a
+        Type:            R_AARCH64_COPY
+      - Offset:          0x230B88
+        Type:            R_AARCH64_IRELATIVE
+        Addend:          2164764
+  - Name:            .rela.plt
+    Type:            SHT_RELA
+    Flags:           [ SHF_ALLOC, SHF_INFO_LINK ]
+    Address:         0x200500
+    Link:            .dynsym
+    AddressAlign:    0x8
+    Info:            .got.plt
+    Relocations:
+      - Offset:          0x230B68
+        Symbol:          abort
+        Type:            R_AARCH64_JUMP_SLOT
+      - Offset:          0x230B70
+        Symbol:          __libc_start_main
+        Type:            R_AARCH64_JUMP_SLOT
+      - Offset:          0x230B80
+        Symbol:          inc
+        Type:            R_AARCH64_JUMP_SLOT
+  - Name:            .rodata
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_MERGE ]
+    Address:         0x200560
+    AddressAlign:    0x8
+    Content:         '010002000000000000000000000000000000000000000000'
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x210710
+    AddressAlign:    0x8
+    Content:         1D0080D21E0080D2E50300AAE10340F9E2230091E60300910000009000201D911F2003D5230A00101F2003D5E40D0010840000947F0000943800001480000090009845F9400000B482000014C0035FD61F2003D5601F10101F2003D5211F10103F0000EBC000005481FFFF9021B442F9610000B4F00301AA00021FD6C0035FD61F2003D5E01D10101F2003D5A11D1010210000CB22FC7FD3410C818BFF0781EB21FC4193C000005482FFFF9042B842F9620000B4F00302AA00021FD6C0035FD6FD7BBEA9FD030091F30B00F91301009060426E3980000035DEFFFF972000805260422E39F30B40F9FD7BC2A8C0035FD6E4FFFF17FF4300D1E00F00B9E80F40B900050071FF430091C0035FD61F2003D520FFFF10C0035FD6FF8300D1FD7B01A9FD4300918A0000904A9D45F949D03BD528696AB80805001128692AB808010090E80700F900994BB94A000094E80740F900994BB943000094E0031F2AFD7B41A9FF830091C0035FD6FD7BBCA9FD030091F35301A91F2003D5D4080810F55B02A91F2003D535080810940215CBF603002AF76303A9F70301AAF80302AA14000094FF0F94EB6001005494FE4393130080D2A37A73F8E20318AA73060091E10317AAE003162A60003FD69F0213EB21FFFF54F35341A9F55B42A9F76343A9FD7BC4A8C0035FD61F2003D5C0035FD6
+  - Name:            .plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x210920
+    AddressAlign:    0x10
+    Content:         F07BBFA91001009011B245F910822D9120021FD61F2003D51F2003D51F2003D51001009011B645F910A22D9120021FD61001009011BA45F910C22D9120021FD61001009011BE45F910E22D9120021FD61001009011C245F910022E9120021FD6
+  - Name:            .iplt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x210980
+    AddressAlign:    0x10
+    Content:         1001009011C645F910222E9120021FD6
+  - Name:            .dynamic
+    Type:            SHT_DYNAMIC
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x2209A0
+    Link:            .dynstr
+    AddressAlign:    0x8
+    Entries:
+      - Tag:             DT_NEEDED
+        Value:           0x7C
+      - Tag:             DT_NEEDED
+        Value:           0x67
+      - Tag:             DT_DEBUG
+        Value:           0x0
+      - Tag:             DT_RELA
+        Value:           0x2004A0
+      - Tag:             DT_RELASZ
+        Value:           0x48
+      - Tag:             DT_RELAENT
+        Value:           0x18
+      - Tag:             DT_JMPREL
+        Value:           0x200500
+      - Tag:             DT_PLTRELSZ
+        Value:           0x48
+      - Tag:             DT_PLTGOT
+        Value:           0x230B50
+      - Tag:             DT_PLTREL
+        Value:           0x7
+      - Tag:             DT_SYMTAB
+        Value:           0x2002E8
+      - Tag:             DT_SYMENT
+        Value:           0x18
+      - Tag:             DT_STRTAB
+        Value:           0x200418
+      - Tag:             DT_STRSZ
+        Value:           0x83
+      - Tag:             DT_NULL
+        Value:           0x0
+  - Name:            .got
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x220B30
+    AddressAlign:    0x8
+    Content:         '00000000000000000000000000000000'
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x230B40
+    AddressAlign:    0x8
+    Content:         '00000000000000000000000000000000'
+  - Name:            .got.plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x230B50
+    AddressAlign:    0x8
+    Content:         '00000000000000000000000000000000000000000000000020092100000000002009210000000000200921000000000020092100000000000000000000000000'
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x230B90
+    AddressAlign:    0x8
+    Size:            0xC
+  - Name:            .rela.text
+    Type:            SHT_RELA
+    Flags:           [ SHF_INFO_LINK ]
+    Link:            .symtab
+    AddressAlign:    0x8
+    Info:            .text
+    Relocations:
+      - Offset:          0x210728
+        Symbol:          .text
+        Type:            R_AARCH64_ADR_PREL_PG_HI21
+        Addend:          56
+      - Offset:          0x21072C
+        Symbol:          .text
+        Type:            R_AARCH64_ADD_ABS_LO12_NC
+        Addend:          56
+      - Offset:          0x210740
+        Symbol:          __libc_start_main
+        Type:            R_AARCH64_CALL26
+      - Offset:          0x210744
+        Symbol:          abort
+        Type:            R_AARCH64_CALL26
+      - Offset:          0x210748
+        Symbol:          main
+        Type:            R_AARCH64_JUMP26
+      - Offset:          0x210778
+        Symbol:          .rodata
+        Type:            R_AARCH64_ADR_PREL_PG_HI21
+        Addend:          8
+      - Offset:          0x21077C
+        Symbol:          .rodata
+        Type:            R_AARCH64_LDST64_ABS_LO12_NC
+        Addend:          8
+      - Offset:          0x2107B8
+        Symbol:          .rodata
+        Type:            R_AARCH64_ADR_PREL_PG_HI21
+        Addend:          16
+      - Offset:          0x2107BC
+        Symbol:          .rodata
+        Type:            R_AARCH64_LDST64_ABS_LO12_NC
+        Addend:          16
+      - Offset:          0x2107DC
+        Symbol:          .bss
+        Type:            R_AARCH64_ADR_PREL_PG_HI21
+      - Offset:          0x2107E0
+        Symbol:          .bss
+        Type:            R_AARCH64_LDST8_ABS_LO12_NC
+      - Offset:          0x2107F0
+        Symbol:          .bss
+        Type:            R_AARCH64_LDST8_ABS_LO12_NC
+      - Offset:          0x21081C
+        Symbol:          dec
+        Type:            R_AARCH64_ADR_PREL_PG_HI21
+      - Offset:          0x210820
+        Symbol:          dec
+        Type:            R_AARCH64_ADD_ABS_LO12_NC
+      - Offset:          0x210834
+        Symbol:          t1
+        Type:            R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
+      - Offset:          0x210838
+        Symbol:          t1
+        Type:            R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
+      - Offset:          0x21084C
+        Symbol:          a
+        Type:            R_AARCH64_ADR_PREL_PG_HI21
+      - Offset:          0x210854
+        Symbol:          a
+        Type:            R_AARCH64_LDST32_ABS_LO12_NC
+      - Offset:          0x210858
+        Symbol:          ifuncDec
+        Type:            R_AARCH64_CALL26
+      - Offset:          0x210860
+        Symbol:          a
+        Type:            R_AARCH64_LDST32_ABS_LO12_NC
+      - Offset:          0x210864
+        Symbol:          inc
+        Type:            R_AARCH64_CALL26
+Symbols:
+  - Name:            .text
+    Type:            STT_SECTION
+    Section:         .text
+    Value:           0x210710
+  - Name:            .data
+    Type:            STT_SECTION
+    Section:         .data
+    Value:           0x230B40
+  - Name:            .bss
+    Type:            STT_SECTION
+    Section:         .bss
+    Value:           0x230B90
+  - Name:            .rodata
+    Type:            STT_SECTION
+    Section:         .rodata
+    Value:           0x200560
+  - Name:            .interp
+    Type:            STT_SECTION
+    Section:         .interp
+    Value:           0x2002A8
+  - Name:            _DYNAMIC
+    Section:         .dynamic
+    Value:           0x2209A0
+    Other:           [ STV_HIDDEN ]
+  - Name:            abort
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+  - Name:            _start
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x210710
+  - Name:            main
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x210828
+    Size:            0x50
+  - Name:            __libc_start_main
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+  - Name:            dec
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x210804
+    Size:            0x18
+  - Name:            resolver
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x21081C
+    Size:            0xC
+  - Name:            t1
+    Type:            STT_TLS
+    Binding:         STB_GLOBAL
+  - Name:            a
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0x230B98
+    Size:            0x4
+  - Name:            ifuncDec
+    Type:            STT_GNU_IFUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x21081C
+    Size:            0xC
+  - Name:            inc
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+DynamicSymbols:
+  - Name:            abort
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+  - Name:            __libc_start_main
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+  - Name:            t1
+    Type:            STT_TLS
+    Binding:         STB_GLOBAL
+  - Name:            inc
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+  - Name:            a
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0x230B98
+    Size:            0x4
diff --git a/bolt/test/AArch64/Inputs/rels-so.yaml b/bolt/test/AArch64/Inputs/rels-so.yaml
new file mode 100644 (file)
index 0000000..9ff4295
--- /dev/null
@@ -0,0 +1,306 @@
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_DYN
+  Machine:         EM_AARCH64
+ProgramHeaders:
+  - Type:            PT_PHDR
+    Flags:           [ PF_R ]
+    VAddr:           0x40
+    Align:           0x8
+  - Type:            PT_LOAD
+    Flags:           [ PF_R ]
+    FirstSec:        .dynsym
+    LastSec:         .dynamic
+    Align:           0x10000
+  - Type:            PT_LOAD
+    Flags:           [ PF_X, PF_R ]
+    FirstSec:        .text
+    LastSec:         .tbss
+    VAddr:           0x10658
+    Align:           0x10000
+  - Type:            PT_LOAD
+    Flags:           [ PF_W, PF_R ]
+    FirstSec:        .tbss
+    LastSec:         .got
+    VAddr:           0x207F0
+    Align:           0x10000
+  - Type:            PT_LOAD
+    Flags:           [ PF_W, PF_R ]
+    FirstSec:        .data
+    LastSec:         .bss
+    VAddr:           0x309C8
+    Align:           0x10000
+  - Type:            PT_TLS
+    Flags:           [ PF_R ]
+    FirstSec:        .tbss
+    LastSec:         .tbss
+    VAddr:           0x107F0
+    Align:           0x4
+  - Type:            PT_DYNAMIC
+    Flags:           [ PF_W, PF_R ]
+    FirstSec:        .dynamic
+    LastSec:         .dynamic
+    VAddr:           0x20800
+    Align:           0x8
+  - Type:            PT_GNU_RELRO
+    Flags:           [ PF_R ]
+    FirstSec:        .tbss
+    LastSec:         .got
+    VAddr:           0x207F0
+Sections:
+  - Name:            .dynsym
+    Type:            SHT_DYNSYM
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x270
+    Link:            .dynstr
+    AddressAlign:    0x8
+  - Name:            .dynstr
+    Type:            SHT_STRTAB
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x3AC
+    AddressAlign:    0x1
+  - Name:            .rela.dyn
+    Type:            SHT_RELA
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x428
+    Link:            .dynsym
+    AddressAlign:    0x8
+    Relocations:
+      - Offset:          0x209B0
+        Symbol:          a
+        Type:            R_AARCH64_GLOB_DAT
+      - Offset:          0x309D8
+        Symbol:          a
+        Type:            R_AARCH64_ABS64
+      - Offset:          0x209B8
+        Symbol:          t1
+        Type:            R_AARCH64_TLSDESC
+  - Name:            .rela.plt
+    Type:            SHT_RELA
+    Flags:           [ SHF_ALLOC, SHF_INFO_LINK ]
+    Address:         0x530
+    Link:            .dynsym
+    AddressAlign:    0x8
+    Info:            .got.plt
+    Relocations:
+      - Offset:          0x30A00
+        Symbol:          __gmon_start__
+        Type:            R_AARCH64_JUMP_SLOT
+      - Offset:          0x30A08
+        Symbol:          __cxa_finalize
+        Type:            R_AARCH64_JUMP_SLOT
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x10658
+    AddressAlign:    0x8
+    Content:         8000009000C844F9400000B45B000014C0035FD6000000001F2003D5A01B10101F2003D5611B10103F0000EBC00000548100009021CC44F9610000B4F00301AA00021FD6C0035FD61F2003D5201A10101F2003D5E1191010210000CB22FC7FD3410C818BFF0781EB21FC4193C00000548200009042D044F9620000B4F00302AA00021FD6C0035FD6FD7BBEA9FD030091F30B00F91301009060426839400100358000009000D444F9800000B40001009000E444F935000094D8FFFF972000805260422839F30B40F9FD7BC2A8C0035FD6DEFFFF17FF8300D1FD7B01A9FD430091A0C31FB88900009029D944F9280140B908050011280100B98000009001DC44F900E0269120003FD649D03BD5286960B808050011286920B8A8C35FB800050011FD7B41A9FF830091C0035FD6
+  - Name:            .plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x107B0
+    AddressAlign:    0x10
+    Content:         F07BBFA91001009011FE44F910E2279120021FD61F2003D51F2003D51F2003D510010090110245F91002289120021FD610010090110645F91022289120021FD6
+  - Name:            .tbss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
+    Address:         0x107F0
+    AddressAlign:    0x4
+    Size:            0x4
+  - Name:            .dynamic
+    Type:            SHT_DYNAMIC
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x20800
+    Link:            .dynstr
+    AddressAlign:    0x8
+    Entries:
+      - Tag:             DT_NEEDED
+        Value:           0x60
+      - Tag:             DT_SONAME
+        Value:           0x75
+      - Tag:             DT_RELA
+        Value:           0x428
+      - Tag:             DT_RELASZ
+        Value:           0x48
+      - Tag:             DT_RELAENT
+        Value:           0x18
+      - Tag:             DT_RELACOUNT
+        Value:           0x4
+      - Tag:             DT_JMPREL
+        Value:           0x530
+      - Tag:             DT_PLTRELSZ
+        Value:           0x30
+      - Tag:             DT_PLTGOT
+        Value:           0x309E8
+      - Tag:             DT_PLTREL
+        Value:           0x7
+      - Tag:             DT_SYMTAB
+        Value:           0x270
+      - Tag:             DT_SYMENT
+        Value:           0x18
+      - Tag:             DT_STRTAB
+        Value:           0x3AC
+      - Tag:             DT_STRSZ
+        Value:           0x7C
+      - Tag:             DT_GNU_HASH
+        Value:           0x380
+      - Tag:             DT_NULL
+        Value:           0x0
+  - Name:            .got
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x20990
+    AddressAlign:    0x8
+    Content:         '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x309C8
+    AddressAlign:    0x8
+    Content:         '0000000000000000010000000000000000000000000000000000000000000000'
+  - Name:            .got.plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x309E8
+    AddressAlign:    0x8
+    Content:         000000000000000000000000000000000000000000000000B007010000000000B007010000000000
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x30A10
+    AddressAlign:    0x4
+    Size:            0x8
+  - Name:            .rela.text
+    Type:            SHT_RELA
+    Flags:           [ SHF_INFO_LINK ]
+    Link:            .symtab
+    AddressAlign:    0x8
+    Info:            .text
+    Relocations:
+      - Offset:          0x1073C
+        Symbol:          a
+        Type:            R_AARCH64_ADR_GOT_PAGE
+      - Offset:          0x10740
+        Symbol:          a
+        Type:            R_AARCH64_LD64_GOT_LO12_NC
+      - Offset:          0x10750
+        Symbol:          t1
+        Type:            R_AARCH64_TLSDESC_ADR_PAGE21
+      - Offset:          0x10754
+        Symbol:          t1
+        Type:            R_AARCH64_TLSDESC_LD64_LO12
+      - Offset:          0x10758
+        Symbol:          t1
+        Type:            R_AARCH64_TLSDESC_ADD_LO12
+      - Offset:          0x1075C
+        Symbol:          t1
+        Type:            R_AARCH64_TLSDESC_CALL
+  - Name:            .rela.data
+    Type:            SHT_RELA
+    Flags:           [ SHF_INFO_LINK ]
+    Link:            .symtab
+    AddressAlign:    0x8
+    Info:            .data
+    Relocations:
+      - Offset:          0x309C8
+        Symbol:          __dso_handle
+        Type:            R_AARCH64_ABS64
+      - Offset:          0x309D8
+        Symbol:          a
+        Type:            R_AARCH64_ABS64
+      - Offset:          0x309E0
+        Symbol:          .bss
+        Type:            R_AARCH64_ABS64
+        Addend:          4
+Symbols:
+  - Name:            '$x'
+    Section:         .text
+    Value:           0x10658
+  - Name:            call_weak_fn
+    Type:            STT_FUNC
+    Section:         .text
+    Value:           0x10658
+    Size:            0x14
+  - Name:            .text
+    Type:            STT_SECTION
+    Section:         .text
+    Value:           0x10658
+  - Name:            .data
+    Type:            STT_SECTION
+    Section:         .data
+    Value:           0x309C8
+  - Name:            .bss
+    Type:            STT_SECTION
+    Section:         .bss
+    Value:           0x30A10
+  - Name:            frame_dummy
+    Type:            STT_FUNC
+    Section:         .text
+    Value:           0x10728
+  - Name:            __dso_handle
+    Type:            STT_OBJECT
+    Section:         .data
+    Value:           0x309C8
+    Other:           [ STV_HIDDEN ]
+  - Name:            .tbss
+    Type:            STT_SECTION
+    Section:         .tbss
+    Value:           0x107F0
+  - Name:            _DYNAMIC
+    Section:         .dynamic
+    Value:           0x20800
+    Other:           [ STV_HIDDEN ]
+  - Name:            inc
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x1072C
+    Size:            0x58
+  - Name:            a
+    Type:            STT_OBJECT
+    Section:         .data
+    Binding:         STB_GLOBAL
+    Value:           0x309D0
+    Size:            0x4
+  - Name:            t1
+    Type:            STT_TLS
+    Section:         .tbss
+    Binding:         STB_GLOBAL
+    Size:            0x4
+  - Name:            b
+    Type:            STT_OBJECT
+    Section:         .data
+    Binding:         STB_GLOBAL
+    Value:           0x309D8
+    Size:            0x8
+DynamicSymbols:
+  - Name:            __gmon_start__
+    Binding:         STB_WEAK
+  - Name:            __cxa_finalize
+    Type:            STT_FUNC
+    Binding:         STB_WEAK
+  - Name:            inc
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x1072C
+    Size:            0x58
+  - Name:            a
+    Type:            STT_OBJECT
+    Section:         .data
+    Binding:         STB_GLOBAL
+    Value:           0x309D0
+    Size:            0x4
+  - Name:            t1
+    Type:            STT_TLS
+    Section:         .tbss
+    Binding:         STB_GLOBAL
+    Size:            0x4
+  - Name:            b
+    Type:            STT_OBJECT
+    Section:         .data
+    Binding:         STB_GLOBAL
+    Value:           0x309D8
+    Size:            0x8
diff --git a/bolt/test/AArch64/runtime-relocs.test b/bolt/test/AArch64/runtime-relocs.test
new file mode 100644 (file)
index 0000000..a8347b5
--- /dev/null
@@ -0,0 +1,43 @@
+// This test checks dynamic relocations support for aarch64.
+
+RUN: yaml2obj %p/Inputs/rels-so.yaml &> %t.so
+RUN: yaml2obj %p/Inputs/rels-exe.yaml &> %t.exe
+RUN: llvm-bolt %t.so -o %t.bolt.so --use-old-text=0 --lite=0
+RUN: llvm-bolt %t.exe -o %t.bolt.exe --use-old-text=0 --lite=0
+
+// Check relocations in library:
+
+RUN: llvm-readelf -rW %t.bolt.so | FileCheck %s -check-prefix=CHECKLIB
+
+CHECKLIB: {{.*}} R_AARCH64_GLOB_DAT     {{.*}} a + 0
+CHECKLIB: {{.*}} R_AARCH64_TLSDESC      {{.*}} t1 + 0
+CHECKLIB: {{.*}} R_AARCH64_ABS64        {{.*}} a + 0
+
+// Check relocations in executable:
+
+RUN: llvm-readelf -rW %t.bolt.exe | FileCheck %s -check-prefix=CHECKEXE
+
+CHECKEXE: {{.*}} R_AARCH64_TLS_TPREL64  {{.*}} t1 + 0
+CHECKEXE: {{.*}} R_AARCH64_COPY         {{.*}} a + 0
+CHECKEXE: {{.*}} R_AARCH64_JUMP_SLOT    {{.*}} inc + 0
+
+// Check traditional TLS relocations R_AARCH64_TLS_DTPMOD64 and
+// R_AARCH64_TLS_DTPREL64 emitted correctly after bolt. Since these
+// relocations are obsolete and clang and lld does not support them,
+// the initial binary was built with gcc and ld with -mtls-dialect=trad flag.
+
+RUN: yaml2obj %p/Inputs/tls-trad.yaml &> %t.trad.so
+RUN: llvm-bolt %t.trad.so -o %t.trad.bolt.so --use-old-text=0 --lite=0
+RUN: llvm-readelf -rW %t.trad.so | FileCheck %s -check-prefix=CHECKTRAD
+
+CHECKTRAD: {{.*}} R_AARCH64_TLS_DTPMOD64 {{.*}} t1 + 0
+CHECKTRAD: {{.*}} R_AARCH64_TLS_DTPREL64 {{.*}} t1 + 0
+
+// The ld linker emits R_AARCH64_TLSDESC to .rela.plt section, check that
+// it is emitted correctly.
+
+RUN: yaml2obj %p/Inputs/tls-ld.yaml &> %t.ld.so
+RUN: llvm-bolt %t.ld.so -o %t.ld.bolt.so --use-old-text=0 --lite=0
+RUN: llvm-readelf -rW %t.ld.bolt.so | FileCheck %s -check-prefix=CHECKLD
+
+CHECKLD: {{.*}} R_AARCH64_TLSDESC        {{.*}} t1 + 0