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(); }
/// 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();
/// 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;
#include "llvm/Support/Error.h"
#include <map>
#include <set>
+#include <unordered_map>
namespace llvm {
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);
/// \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);
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();
/// 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;
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)
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() {
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();
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(
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.
if (DynamicRelSectionOrErr->getSize() != DynamicRelocationsSize)
report_error("section size mismatch for DT_RELASZ",
errc::executable_format_error);
- readDynamicRelocations(DynamicRelSectionOrErr->getSectionRef());
+ readDynamicRelocations(DynamicRelSectionOrErr->getSectionRef(),
+ /*IsJmpRel*/ false);
}
}
}
}
-void RewriteInstance::readDynamicRelocations(const SectionRef &Section) {
+void RewriteInstance::readDynamicRelocations(const SectionRef &Section,
+ bool IsJmpRel) {
assert(BinarySection(*BC, Section).isAllocatable() && "allocatable expected");
LLVM_DEBUG({
});
for (const RelocationRef &Rel : Section.relocations()) {
- uint64_t RType = Rel.getType();
+ const uint64_t RType = Rel.getType();
if (Relocation::isNone(RType))
continue;
<< " : + 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);
}
}
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>
}
}
if (!GOTSection.getObject()) {
- errs() << "BOLT-INFO: no .got section found\n";
+ if (!BC->IsStaticExecutable)
+ errs() << "BOLT-INFO: no .got section found\n";
return;
}
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) {
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();
}
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,
// 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();
--- /dev/null
+--- !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
--- /dev/null
+--- !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
--- /dev/null
+// 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