Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -114,6 +114,8 @@ CallGraphProfile; bool AllowMultipleDefinition; bool AndroidPackDynRelocs = false; + bool RelrPackDynRelocs = false; + bool AndroidRelrPackDynRelocs = false; bool ARMHasBlx = false; bool ARMHasMovtMovw = false; bool ARMJ1J2BranchEncoding = false; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -854,6 +854,12 @@ StringRef S = Arg->getValue(); if (S == "android") Config->AndroidPackDynRelocs = true; + else if (S == "relr") + Config->RelrPackDynRelocs = true; + else if (S == "android-relr") { + Config->RelrPackDynRelocs = true; + Config->AndroidRelrPackDynRelocs = true; + } else if (S != "none") error("unknown -pack-dyn-relocs format: " + S); } Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -412,7 +412,8 @@ void LinkerScript::discard(ArrayRef V) { for (InputSection *S : V) { if (S == InX::ShStrTab || S == InX::Dynamic || S == InX::DynSymTab || - S == InX::DynStrTab || S == InX::RelaPlt || S == InX::RelaDyn) + S == InX::DynStrTab || S == InX::RelaPlt || S == InX::RelaDyn || + S == InX::RelrDyn) error("discarding " + S->Name + " section is not allowed"); // You can discard .hash and .gnu.hash sections by linker scripts. Since Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -233,7 +233,7 @@ defm pack_dyn_relocs: Eq<"pack-dyn-relocs", "Pack dynamic relocations in the given format">, - MetaVarName<"[none,android]">; + MetaVarName<"[none,android,relr,android-relr]">; defm pie: B<"pie", "Create a position independent executable", Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -438,6 +438,7 @@ typedef typename ELFT::Dyn Elf_Dyn; typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; + typedef typename ELFT::Relr Elf_Relr; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; @@ -473,7 +474,7 @@ void addReloc(RelType DynType, InputSectionBase *InputSec, uint64_t OffsetInSec, Symbol *Sym, int64_t Addend, RelExpr Expr, RelType Type); - void addReloc(const DynamicReloc &Reloc); + virtual void addReloc(const DynamicReloc &Reloc); bool empty() const override { return Relocs.empty(); } size_t getSize() const override { return Relocs.size() * this->Entsize; } size_t getRelativeRelocCount() const { return NumRelativeRelocs; } @@ -517,6 +518,28 @@ SmallVector RelocData; }; +template +class RelrPackedRelocationSection final : public RelocationBaseSection { + typedef typename ELFT::Relr Elf_Relr; + +public: + RelrPackedRelocationSection(StringRef Name); + + void addReloc(const DynamicReloc &Reloc) override { + Relocs.push_back(Reloc); + } + bool updateAllocSize() override; + size_t getSize() const override { + return RelrRelocs.size() * this->Entsize; + } + void writeTo(uint8_t *Buf) override { + memcpy(Buf, RelrRelocs.data(), getSize()); + } + +private: + std::vector RelrRelocs; +}; + struct SymbolTableEntry { Symbol *Sym; size_t StrTabOffset; @@ -958,6 +981,7 @@ static PltSection *Plt; static PltSection *Iplt; static RelocationBaseSection *RelaDyn; + static RelocationBaseSection *RelrDyn; static RelocationBaseSection *RelaPlt; static RelocationBaseSection *RelaIplt; static StringTableSection *ShStrTab; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1288,6 +1288,12 @@ addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels); } } + if (InX::RelrDyn && !InX::RelrDyn->empty()) { + addInSec(InX::RelrDyn->DynamicTag, InX::RelrDyn); + addSize(InX::RelrDyn->SizeDynamicTag, InX::RelrDyn->getParent()); + addInt(Config->AndroidRelrPackDynRelocs ? DT_ANDROID_RELRENT : DT_RELRENT, + sizeof(Elf_Relr)); + } // .rel[a].plt section usually consists of two parts, containing plt and // iplt relocations. It is possible to have only iplt relocations in the // output. In that case RelaPlt is empty and have zero offset, the same offset @@ -1437,17 +1443,28 @@ uint64_t OffsetInSec, Symbol *Sym, int64_t Addend, RelExpr Expr, RelType Type) { - // Write the addends to the relocated address if required. We skip - // it if the written value would be zero. - if (Config->WriteAddends && (Expr != R_ADDEND || Addend != 0)) + // Write the addends to the relocated address if required. + bool WriteAddend = Config->WriteAddends; + // When using RELR relocations, we need to write the addend since RELR + // relocations decode to offsets only. + if (Config->RelrPackDynRelocs && DynType == Target->RelativeRel) + WriteAddend = true; + // Skip it if the written value would be zero. + if (Expr == R_ADDEND && Addend == 0) + WriteAddend = false; + if (WriteAddend) InputSec->Relocations.push_back({Expr, Type, OffsetInSec, Addend, Sym}); addReloc({DynType, InputSec, OffsetInSec, Expr != R_ADDEND, Sym, Addend}); } void RelocationBaseSection::addReloc(const DynamicReloc &Reloc) { - if (Reloc.Type == Target->RelativeRel) - ++NumRelativeRelocs; - Relocs.push_back(Reloc); + if (InX::RelrDyn && Reloc.Type == Target->RelativeRel) + InX::RelrDyn->addReloc(Reloc); + else { + if (Reloc.Type == Target->RelativeRel) + ++NumRelativeRelocs; + Relocs.push_back(Reloc); + } } void RelocationBaseSection::finalizeContents() { @@ -1688,6 +1705,89 @@ return RelocData.size() != OldSize; } +template +RelrPackedRelocationSection::RelrPackedRelocationSection(StringRef Name) + : RelocationBaseSection( + Name, Config->AndroidRelrPackDynRelocs ? SHT_ANDROID_RELR : SHT_RELR, + Config->AndroidRelrPackDynRelocs ? DT_ANDROID_RELR : DT_RELR, + Config->AndroidRelrPackDynRelocs ? DT_ANDROID_RELRSZ : DT_RELRSZ) { + this->Entsize = sizeof(Elf_Relr); +} + +template +bool RelrPackedRelocationSection::updateAllocSize() { + size_t OldSize = RelrRelocs.size(); + RelrRelocs.clear(); + + // Word type: uint32_t for Elf32, and uint64_t for Elf64. + typedef typename ELFT::uint Word; + + // Word size in number of bytes. + const size_t WordSize = sizeof(Word); + + // Number of bits to use for the relocation offsets bitmap. + // These many relative relocations can be encoded in a single entry. + const size_t NBits = 8*WordSize - 1; + + // Get offsets for all relative relocations and sort them. + std::vector Offsets; + for (const DynamicReloc &Rel : Relocs) { + Offsets.push_back(Rel.getOffset()); + } + std::sort(Offsets.begin(), Offsets.end()); + + // Encode relocations in SHT_RELR section. + // Details of the encoding are described in this post: + // https://groups.google.com/d/msg/generic-abi/bX460iggiKg/Pi9aSwwABgAJ + Word Base = 0; + typename std::vector::iterator Curr = Offsets.begin(); + while (Curr != Offsets.end()) { + Word Current = *Curr; + if (Current%2 != 0) { + error("odd offset for RELR relocation (" + Twine(Current) + "), " + + "pass --pack-dyn-relocs=none to disable RELR relocations"); + ++Curr; + continue; + } + + Word Bits = 0; + typename std::vector::iterator Next = Curr; + if ((Base > 0) && (Base <= Current)) { + while (Next != Offsets.end()) { + Word Delta = *Next - Base; + // If Next is too far out, it cannot be folded into Curr. + if (Delta >= (NBits * WordSize)) + break; + // If Next is not a multiple of WordSize away, it cannot + // be folded into Curr. + if ((Delta % WordSize) != 0) + break; + // Next can be folded into Curr, add it to the bitmap. + Bits |= 1ULL << (Delta / WordSize); + ++Next; + } + } + + Elf_Relr R; + if (Bits == 0) { + R.r_data = Current; + // This is not a continuation entry, only one offset was + // consumed. Set base offset for subsequent bitmap entries. + Base = Current + WordSize; + ++Curr; + } else { + R.r_data = (Bits<<1) | 1; + // This is a continuation entry encoding multiple offsets + // in a bitmap. Advance base offset by NBits words. + Base += NBits * WordSize; + Curr = Next; + } + RelrRelocs.push_back(R); + } + + return RelrRelocs.size() != OldSize; +} + SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &StrTabSec) : SyntheticSection(StrTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0, StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB, @@ -2887,6 +2987,7 @@ PltSection *InX::Plt; PltSection *InX::Iplt; RelocationBaseSection *InX::RelaDyn; +RelocationBaseSection *InX::RelrDyn; RelocationBaseSection *InX::RelaPlt; RelocationBaseSection *InX::RelaIplt; StringTableSection *InX::ShStrTab; @@ -2948,6 +3049,11 @@ template class elf::AndroidPackedRelocationSection; template class elf::AndroidPackedRelocationSection; +template class elf::RelrPackedRelocationSection; +template class elf::RelrPackedRelocationSection; +template class elf::RelrPackedRelocationSection; +template class elf::RelrPackedRelocationSection; + template class elf::SymbolTableSection; template class elf::SymbolTableSection; template class elf::SymbolTableSection; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -349,6 +349,11 @@ Add(InX::RelaDyn); } + if (Config->RelrPackDynRelocs) { + InX::RelrDyn = make>(".relr.dyn"); + Add(InX::RelrDyn); + } + // Add .got. MIPS' .got is so different from the other archs, // it has its own class. if (Config->EMachine == EM_MIPS) { @@ -1657,12 +1662,12 @@ // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. applySynthetic( - {InX::DynSymTab, InX::Bss, InX::BssRelRo, InX::GnuHashTab, - InX::HashTab, InX::SymTab, InX::ShStrTab, InX::StrTab, - In::VerDef, InX::DynStrTab, InX::Got, InX::MipsGot, - InX::IgotPlt, InX::GotPlt, InX::RelaDyn, InX::RelaIplt, - InX::RelaPlt, InX::Plt, InX::Iplt, InX::EhFrameHdr, - In::VerSym, In::VerNeed, InX::Dynamic}, + {InX::DynSymTab, InX::Bss, InX::BssRelRo, InX::GnuHashTab, + InX::HashTab, InX::SymTab, InX::ShStrTab, InX::StrTab, + In::VerDef, InX::DynStrTab, InX::Got, InX::MipsGot, + InX::IgotPlt, InX::GotPlt, InX::RelaDyn, InX::RelrDyn, + InX::RelaIplt, InX::RelaPlt, InX::Plt, InX::Iplt, + InX::EhFrameHdr, In::VerSym, In::VerNeed, InX::Dynamic}, [](SyntheticSection *SS) { SS->finalizeContents(); }); if (!Script->HasSectionsCommand && !Config->Relocatable) @@ -1677,7 +1682,8 @@ // for jump instructions that is the linker's responsibility for creating // range extension thunks for. As the generation of the content may also // alter InputSection addresses we must converge to a fixed point. - if (Target->NeedsThunks || Config->AndroidPackDynRelocs) { + if (Target->NeedsThunks || Config->AndroidPackDynRelocs || + Config->RelrPackDynRelocs) { ThunkCreator TC; AArch64Err843419Patcher A64P; bool Changed; @@ -1694,6 +1700,8 @@ if (InX::MipsGot) InX::MipsGot->updateAllocSize(); Changed |= InX::RelaDyn->updateAllocSize(); + if (InX::RelrDyn) + Changed |= InX::RelrDyn->updateAllocSize(); } while (Changed); } Index: test/ELF/pack-dyn-relocs.s =================================================================== --- test/ELF/pack-dyn-relocs.s +++ test/ELF/pack-dyn-relocs.s @@ -5,9 +5,6 @@ // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.a32 // RUN: ld.lld -pie --pack-dyn-relocs=none %t.a32 %t.a32.so -o %t2.a32 // RUN: llvm-readobj -relocations %t2.a32 | FileCheck --check-prefix=UNPACKED32 %s -// RUN: ld.lld -pie --pack-dyn-relocs android %t.a32 %t.a32.so -o %t3.a32 -// RUN: llvm-readobj -s -dynamic-table %t3.a32 | FileCheck --check-prefix=PACKED32-HEADERS %s -// RUN: llvm-readobj -relocations %t3.a32 | FileCheck --check-prefix=PACKED32 %s // Unpacked should have the relative relocations in their natural order. // UNPACKED32: 0x1000 R_ARM_RELATIVE - 0x0 @@ -40,65 +37,125 @@ // UNPACKED32-NEXT: 0x1020 R_ARM_ABS32 bar2 0x0 // UNPACKED32-NEXT: 0x1040 R_ARM_ABS32 zed2 0x0 -// PACKED32-HEADERS: Index: 1 -// PACKED32-HEADERS-NEXT: Name: .dynsym +// RUN: ld.lld -pie --pack-dyn-relocs=android %t.a32 %t.a32.so -o %t3.a32 +// RUN: llvm-readobj -s -dynamic-table %t3.a32 | FileCheck --check-prefix=ANDROID32-HEADERS %s +// RUN: llvm-readobj -relocations %t3.a32 | FileCheck --check-prefix=ANDROID32 %s -// PACKED32-HEADERS: Name: .rel.dyn -// PACKED32-HEADERS-NEXT: Type: SHT_ANDROID_REL -// PACKED32-HEADERS-NEXT: Flags [ (0x2) -// PACKED32-HEADERS-NEXT: SHF_ALLOC (0x2) -// PACKED32-HEADERS-NEXT: ] -// PACKED32-HEADERS-NEXT: Address: [[ADDR:.*]] -// PACKED32-HEADERS-NEXT: Offset: [[ADDR]] -// PACKED32-HEADERS-NEXT: Size: [[SIZE:.*]] -// PACKED32-HEADERS-NEXT: Link: 1 -// PACKED32-HEADERS-NEXT: Info: 0 -// PACKED32-HEADERS-NEXT: AddressAlignment: 4 -// PACKED32-HEADERS-NEXT: EntrySize: 1 +// ANDROID32-HEADERS: Index: 1 +// ANDROID32-HEADERS-NEXT: Name: .dynsym -// PACKED32-HEADERS: 0x6000000F ANDROID_REL [[ADDR]] -// PACKED32-HEADERS: 0x60000010 ANDROID_RELSZ [[SIZE]] +// ANDROID32-HEADERS: Name: .rel.dyn +// ANDROID32-HEADERS-NEXT: Type: SHT_ANDROID_REL +// ANDROID32-HEADERS-NEXT: Flags [ (0x2) +// ANDROID32-HEADERS-NEXT: SHF_ALLOC (0x2) +// ANDROID32-HEADERS-NEXT: ] +// ANDROID32-HEADERS-NEXT: Address: [[ADDR:.*]] +// ANDROID32-HEADERS-NEXT: Offset: [[ADDR]] +// ANDROID32-HEADERS-NEXT: Size: [[SIZE:.*]] +// ANDROID32-HEADERS-NEXT: Link: 1 +// ANDROID32-HEADERS-NEXT: Info: 0 +// ANDROID32-HEADERS-NEXT: AddressAlignment: 4 +// ANDROID32-HEADERS-NEXT: EntrySize: 1 + +// ANDROID32-HEADERS: 0x6000000F ANDROID_REL [[ADDR]] +// ANDROID32-HEADERS: 0x60000010 ANDROID_RELSZ [[SIZE]] // Packed should have the larger groups of relative relocations first, // i.e. the 8 and 9 followed by the 7. -// PACKED32: 0x1000 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1004 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1008 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x100C R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1010 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1014 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1018 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x101C R_ARM_RELATIVE - 0x0 - -// PACKED32-NEXT: 0x1044 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1048 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x104C R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1050 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1054 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1058 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x105C R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1060 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1064 R_ARM_RELATIVE - 0x0 - -// PACKED32-NEXT: 0x1024 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1028 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x102C R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1030 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1034 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x1038 R_ARM_RELATIVE - 0x0 -// PACKED32-NEXT: 0x103C R_ARM_RELATIVE - 0x0 - -// PACKED32-NEXT: 0x1020 R_ARM_ABS32 bar2 0x0 -// PACKED32-NEXT: 0x1040 R_ARM_ABS32 zed2 0x0 +// ANDROID32: 0x1000 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1004 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1008 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x100C R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1010 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1014 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1018 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x101C R_ARM_RELATIVE - 0x0 + +// ANDROID32-NEXT: 0x1044 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1048 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x104C R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1050 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1054 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1058 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x105C R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1060 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1064 R_ARM_RELATIVE - 0x0 + +// ANDROID32-NEXT: 0x1024 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1028 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x102C R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1030 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1034 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x1038 R_ARM_RELATIVE - 0x0 +// ANDROID32-NEXT: 0x103C R_ARM_RELATIVE - 0x0 + +// ANDROID32-NEXT: 0x1020 R_ARM_ABS32 bar2 0x0 +// ANDROID32-NEXT: 0x1040 R_ARM_ABS32 zed2 0x0 + +// RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a32 %t.a32.so -o %t4.a32 +// RUN: llvm-readobj -s -dynamic-table %t4.a32 | FileCheck --check-prefix=RELR32-HEADERS %s +// RUN: llvm-readobj -relocations %t4.a32 | FileCheck --check-prefix=RELR32 %s +// RUN: llvm-readobj -relocations -decode-relr %t4.a32 | FileCheck --check-prefix=RELRD32 %s + +// RELR32-HEADERS: Index: 1 +// RELR32-HEADERS-NEXT: Name: .dynsym + +// RELR32-HEADERS: Name: .relr.dyn +// RELR32-HEADERS-NEXT: Type: SHT_RELR +// RELR32-HEADERS-NEXT: Flags [ (0x2) +// RELR32-HEADERS-NEXT: SHF_ALLOC (0x2) +// RELR32-HEADERS-NEXT: ] +// RELR32-HEADERS-NEXT: Address: [[ADDR:.*]] +// RELR32-HEADERS-NEXT: Offset: [[ADDR]] +// RELR32-HEADERS-NEXT: Size: 8 +// RELR32-HEADERS-NEXT: Link: 1 +// RELR32-HEADERS-NEXT: Info: 0 +// RELR32-HEADERS-NEXT: AddressAlignment: 4 +// RELR32-HEADERS-NEXT: EntrySize: 4 + +// RELR32-HEADERS: 0x00000024 RELR [[ADDR]] +// RELR32-HEADERS: 0x00000023 RELRSZ 0x8 +// RELR32-HEADERS: 0x00000025 RELRENT 0x4 + +// SHT_RELR section contains address/bitmap entries +// encoding the offsets for relative relocation. +// RELR32: 0x1000 R_RELR_RELATIVE - 0x0 +// RELR32-NEXT: 0x3FEFEFF R_RELR_RELATIVE - 0x0 + +// Decoded SHT_RELR section is same as UNPACKED, +// but contains only the relative relocations. +// RELRD32: 0x1000 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1004 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1008 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x100C R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1010 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1014 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1018 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x101C R_ARM_RELATIVE - 0x0 + +// RELRD32-NEXT: 0x1024 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1028 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x102C R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1030 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1034 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1038 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x103C R_ARM_RELATIVE - 0x0 + +// RELRD32-NEXT: 0x1044 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1048 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x104C R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1050 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1054 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1058 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x105C R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1060 R_ARM_RELATIVE - 0x0 +// RELRD32-NEXT: 0x1064 R_ARM_RELATIVE - 0x0 // RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/shared2.s -o %t.a64.so.o // RUN: ld.lld -shared %t.a64.so.o -o %t.a64.so // RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.a64 // RUN: ld.lld -pie --pack-dyn-relocs=none %t.a64 %t.a64.so -o %t2.a64 // RUN: llvm-readobj -relocations %t2.a64 | FileCheck --check-prefix=UNPACKED64 %s -// RUN: ld.lld -pie --pack-dyn-relocs=android %t.a64 %t.a64.so -o %t3.a64 -// RUN: llvm-readobj -s -dynamic-table %t3.a64 | FileCheck --check-prefix=PACKED64-HEADERS %s -// RUN: llvm-readobj -relocations %t3.a64 | FileCheck --check-prefix=PACKED64 %s // UNPACKED64: 0x10000 R_AARCH64_RELATIVE - 0x1 // UNPACKED64-NEXT: 0x10008 R_AARCH64_RELATIVE - 0x2 @@ -130,54 +187,117 @@ // UNPACKED64-NEXT: 0x10040 R_AARCH64_ABS64 bar2 0x1 // UNPACKED64-NEXT: 0x10080 R_AARCH64_ABS64 zed2 0x0 -// PACKED64: 0x10000 R_AARCH64_RELATIVE - 0x1 -// PACKED64-NEXT: 0x10008 R_AARCH64_RELATIVE - 0x2 -// PACKED64-NEXT: 0x10010 R_AARCH64_RELATIVE - 0x3 -// PACKED64-NEXT: 0x10018 R_AARCH64_RELATIVE - 0x4 -// PACKED64-NEXT: 0x10020 R_AARCH64_RELATIVE - 0x5 -// PACKED64-NEXT: 0x10028 R_AARCH64_RELATIVE - 0x6 -// PACKED64-NEXT: 0x10030 R_AARCH64_RELATIVE - 0x7 -// PACKED64-NEXT: 0x10038 R_AARCH64_RELATIVE - 0x8 - -// PACKED64-NEXT: 0x10088 R_AARCH64_RELATIVE - 0x1 -// PACKED64-NEXT: 0x10090 R_AARCH64_RELATIVE - 0x2 -// PACKED64-NEXT: 0x10098 R_AARCH64_RELATIVE - 0x3 -// PACKED64-NEXT: 0x100A0 R_AARCH64_RELATIVE - 0x4 -// PACKED64-NEXT: 0x100A8 R_AARCH64_RELATIVE - 0x5 -// PACKED64-NEXT: 0x100B0 R_AARCH64_RELATIVE - 0x6 -// PACKED64-NEXT: 0x100B8 R_AARCH64_RELATIVE - 0x7 -// PACKED64-NEXT: 0x100C0 R_AARCH64_RELATIVE - 0x8 -// PACKED64-NEXT: 0x100C8 R_AARCH64_RELATIVE - 0x9 - -// PACKED64-NEXT: 0x10048 R_AARCH64_RELATIVE - 0x1 -// PACKED64-NEXT: 0x10050 R_AARCH64_RELATIVE - 0x2 -// PACKED64-NEXT: 0x10058 R_AARCH64_RELATIVE - 0x3 -// PACKED64-NEXT: 0x10060 R_AARCH64_RELATIVE - 0x4 -// PACKED64-NEXT: 0x10068 R_AARCH64_RELATIVE - 0x5 -// PACKED64-NEXT: 0x10070 R_AARCH64_RELATIVE - 0x6 -// PACKED64-NEXT: 0x10078 R_AARCH64_RELATIVE - 0x7 - -// PACKED64-NEXT: 0x10040 R_AARCH64_ABS64 bar2 0x1 -// PACKED64-NEXT: 0x10080 R_AARCH64_ABS64 zed2 0x0 - -// PACKED64-HEADERS: Index: 1 -// PACKED64-HEADERS-NEXT: Name: .dynsym - -// PACKED64-HEADERS: Name: .rela.dyn -// PACKED64-HEADERS-NEXT: Type: SHT_ANDROID_RELA -// PACKED64-HEADERS-NEXT: Flags [ (0x2) -// PACKED64-HEADERS-NEXT: SHF_ALLOC (0x2) -// PACKED64-HEADERS-NEXT: ] -// PACKED64-HEADERS-NEXT: Address: [[ADDR:.*]] -// PACKED64-HEADERS-NEXT: Offset: [[ADDR]] -// PACKED64-HEADERS-NEXT: Size: [[SIZE:.*]] -// PACKED64-HEADERS-NEXT: Link: 1 -// PACKED64-HEADERS-NEXT: Info: 0 -// PACKED64-HEADERS-NEXT: AddressAlignment: 8 -// PACKED64-HEADERS-NEXT: EntrySize: 1 - -// PACKED64-HEADERS: 0x0000000060000011 ANDROID_RELA [[ADDR]] -// PACKED64-HEADERS: 0x0000000060000012 ANDROID_RELASZ [[SIZE]] +// RUN: ld.lld -pie --pack-dyn-relocs=android %t.a64 %t.a64.so -o %t3.a64 +// RUN: llvm-readobj -s -dynamic-table %t3.a64 | FileCheck --check-prefix=ANDROID64-HEADERS %s +// RUN: llvm-readobj -relocations %t3.a64 | FileCheck --check-prefix=ANDROID64 %s + +// ANDROID64-HEADERS: Index: 1 +// ANDROID64-HEADERS-NEXT: Name: .dynsym + +// ANDROID64-HEADERS: Name: .rela.dyn +// ANDROID64-HEADERS-NEXT: Type: SHT_ANDROID_RELA +// ANDROID64-HEADERS-NEXT: Flags [ (0x2) +// ANDROID64-HEADERS-NEXT: SHF_ALLOC (0x2) +// ANDROID64-HEADERS-NEXT: ] +// ANDROID64-HEADERS-NEXT: Address: [[ADDR:.*]] +// ANDROID64-HEADERS-NEXT: Offset: [[ADDR]] +// ANDROID64-HEADERS-NEXT: Size: [[SIZE:.*]] +// ANDROID64-HEADERS-NEXT: Link: 1 +// ANDROID64-HEADERS-NEXT: Info: 0 +// ANDROID64-HEADERS-NEXT: AddressAlignment: 8 +// ANDROID64-HEADERS-NEXT: EntrySize: 1 + +// ANDROID64-HEADERS: 0x0000000060000011 ANDROID_RELA [[ADDR]] +// ANDROID64-HEADERS: 0x0000000060000012 ANDROID_RELASZ [[SIZE]] + +// ANDROID64: 0x10000 R_AARCH64_RELATIVE - 0x1 +// ANDROID64-NEXT: 0x10008 R_AARCH64_RELATIVE - 0x2 +// ANDROID64-NEXT: 0x10010 R_AARCH64_RELATIVE - 0x3 +// ANDROID64-NEXT: 0x10018 R_AARCH64_RELATIVE - 0x4 +// ANDROID64-NEXT: 0x10020 R_AARCH64_RELATIVE - 0x5 +// ANDROID64-NEXT: 0x10028 R_AARCH64_RELATIVE - 0x6 +// ANDROID64-NEXT: 0x10030 R_AARCH64_RELATIVE - 0x7 +// ANDROID64-NEXT: 0x10038 R_AARCH64_RELATIVE - 0x8 + +// ANDROID64-NEXT: 0x10088 R_AARCH64_RELATIVE - 0x1 +// ANDROID64-NEXT: 0x10090 R_AARCH64_RELATIVE - 0x2 +// ANDROID64-NEXT: 0x10098 R_AARCH64_RELATIVE - 0x3 +// ANDROID64-NEXT: 0x100A0 R_AARCH64_RELATIVE - 0x4 +// ANDROID64-NEXT: 0x100A8 R_AARCH64_RELATIVE - 0x5 +// ANDROID64-NEXT: 0x100B0 R_AARCH64_RELATIVE - 0x6 +// ANDROID64-NEXT: 0x100B8 R_AARCH64_RELATIVE - 0x7 +// ANDROID64-NEXT: 0x100C0 R_AARCH64_RELATIVE - 0x8 +// ANDROID64-NEXT: 0x100C8 R_AARCH64_RELATIVE - 0x9 + +// ANDROID64-NEXT: 0x10048 R_AARCH64_RELATIVE - 0x1 +// ANDROID64-NEXT: 0x10050 R_AARCH64_RELATIVE - 0x2 +// ANDROID64-NEXT: 0x10058 R_AARCH64_RELATIVE - 0x3 +// ANDROID64-NEXT: 0x10060 R_AARCH64_RELATIVE - 0x4 +// ANDROID64-NEXT: 0x10068 R_AARCH64_RELATIVE - 0x5 +// ANDROID64-NEXT: 0x10070 R_AARCH64_RELATIVE - 0x6 +// ANDROID64-NEXT: 0x10078 R_AARCH64_RELATIVE - 0x7 + +// ANDROID64-NEXT: 0x10040 R_AARCH64_ABS64 bar2 0x1 +// ANDROID64-NEXT: 0x10080 R_AARCH64_ABS64 zed2 0x0 + +// RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a64 %t.a64.so -o %t4.a64 +// RUN: llvm-readobj -s -dynamic-table %t4.a64 | FileCheck --check-prefix=RELR64-HEADERS %s +// RUN: llvm-readobj -relocations %t4.a64 | FileCheck --check-prefix=RELR64 %s +// RUN: llvm-readobj -relocations -decode-relr %t4.a64 | FileCheck --check-prefix=RELRD64 %s + +// RELR64-HEADERS: Index: 1 +// RELR64-HEADERS-NEXT: Name: .dynsym + +// RELR64-HEADERS: Name: .relr.dyn +// RELR64-HEADERS-NEXT: Type: SHT_RELR +// RELR64-HEADERS-NEXT: Flags [ (0x2) +// RELR64-HEADERS-NEXT: SHF_ALLOC (0x2) +// RELR64-HEADERS-NEXT: ] +// RELR64-HEADERS-NEXT: Address: [[ADDR:.*]] +// RELR64-HEADERS-NEXT: Offset: [[ADDR]] +// RELR64-HEADERS-NEXT: Size: 16 +// RELR64-HEADERS-NEXT: Link: 1 +// RELR64-HEADERS-NEXT: Info: 0 +// RELR64-HEADERS-NEXT: AddressAlignment: 8 +// RELR64-HEADERS-NEXT: EntrySize: 8 + +// RELR64-HEADERS: 0x0000000000000024 RELR [[ADDR]] +// RELR64-HEADERS: 0x0000000000000023 RELRSZ 0x10 +// RELR64-HEADERS: 0x0000000000000025 RELRENT 0x8 + +// SHT_RELR section contains address/bitmap entries +// encoding the offsets for relative relocation. +// RELR64: 0x10000 R_RELR_RELATIVE - 0x0 +// RELR64-NEXT: 0x3FEFEFF R_RELR_RELATIVE - 0x0 + +// Decoded SHT_RELR section is same as UNPACKED, +// but contains only the relative relocations. +// RELRD64: 0x10000 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10008 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10010 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10018 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10020 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10028 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10030 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10038 R_AARCH64_RELATIVE - 0x0 + +// RELRD64-NEXT: 0x10048 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10050 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10058 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10060 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10068 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10070 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10078 R_AARCH64_RELATIVE - 0x0 + +// RELRD64-NEXT: 0x10088 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10090 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x10098 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x100A0 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x100A8 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x100B0 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x100B8 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x100C0 R_AARCH64_RELATIVE - 0x0 +// RELRD64-NEXT: 0x100C8 R_AARCH64_RELATIVE - 0x0 .data .dc.a __ehdr_start + 1