Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -55,6 +55,15 @@ // For --target2 enum class Target2Policy { Abs, Rel, GotRel }; +// For --pack-dyn-relocs +enum class PackDynRelocsPolicy { + None, + Android, + Relr, + AndroidRelr, + AndroidPlusRelr +}; + struct SymbolVersion { llvm::StringRef Name; bool IsExternCpp; @@ -113,7 +122,9 @@ uint64_t> CallGraphProfile; bool AllowMultipleDefinition; - bool AndroidPackDynRelocs = false; + bool AndroidPackDynRelocs; + bool RelrPackDynRelocs; + bool AndroidRelrPackDynRelocs; bool ARMHasBlx = false; bool ARMHasMovtMovw = false; bool ARMJ1J2BranchEncoding = false; @@ -189,6 +200,7 @@ StripPolicy Strip; UnresolvedPolicy UnresolvedSymbols; Target2Policy Target2; + PackDynRelocsPolicy PackDynRelocs; BuildIdKind BuildId = BuildIdKind::None; ELFKind EKind = ELFNoneKind; uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -465,6 +465,21 @@ return Target2Policy::GotRel; } +static PackDynRelocsPolicy getPackDynRelocs(opt::InputArgList &Args) { + StringRef S = Args.getLastArgValue(OPT_pack_dyn_relocs, "none"); + if (S == "android") + return PackDynRelocsPolicy::Android; + if (S == "relr") + return PackDynRelocsPolicy::Relr; + if (S == "android-relr") + return PackDynRelocsPolicy::AndroidRelr; + if (S == "android+relr") + return PackDynRelocsPolicy::AndroidPlusRelr; + if (S != "none") + error("unknown -pack-dyn-relocs mode: " + S); + return PackDynRelocsPolicy::None; +} + static bool isOutputFormatBinary(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_oformat)) { StringRef S = Arg->getValue(); @@ -755,6 +770,7 @@ Config->Sysroot = Args.getLastArgValue(OPT_sysroot); Config->Target1Rel = Args.hasFlag(OPT_target1_rel, OPT_target1_abs, false); Config->Target2 = getTarget2(Args); + Config->PackDynRelocs = getPackDynRelocs(Args); Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir); Config->ThinLTOCachePolicy = CHECK( parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), @@ -851,14 +867,6 @@ std::tie(Config->BuildId, Config->BuildIdVector) = getBuildId(Args); - if (auto *Arg = Args.getLastArg(OPT_pack_dyn_relocs)) { - StringRef S = Arg->getValue(); - if (S == "android") - Config->AndroidPackDynRelocs = true; - else if (S != "none") - error("unknown -pack-dyn-relocs format: " + S); - } - if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)) if (Optional Buffer = readFile(Arg->getValue())) Config->SymbolOrderingFile = getSymbolOrderingFile(*Buffer); @@ -946,6 +954,18 @@ Config->WriteAddends = Args.hasFlag(OPT_apply_dynamic_relocs, OPT_no_apply_dynamic_relocs, false) || !Config->IsRela; + + Config->AndroidPackDynRelocs = + Config->PackDynRelocs == PackDynRelocsPolicy::Android || + Config->PackDynRelocs == PackDynRelocsPolicy::AndroidPlusRelr; + + Config->AndroidRelrPackDynRelocs = + Config->PackDynRelocs == PackDynRelocsPolicy::AndroidRelr || + Config->PackDynRelocs == PackDynRelocsPolicy::AndroidPlusRelr; + + Config->RelrPackDynRelocs = + Config->PackDynRelocs == PackDynRelocsPolicy::Relr || + Config->AndroidRelrPackDynRelocs; } // Returns a value of "-format" option. 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,android+relr]">; defm pie: B<"pie", "Create a position independent executable", Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -732,8 +732,14 @@ Type = Target->RelativeRel; else Type = Target->GotRel; - InX::RelaDyn->addReloc(Type, InX::Got, Off, &Sym, 0, - Sym.IsPreemptible ? R_ADDEND : R_ABS, Target->GotRel); + + RelocationBaseSection *RelSec = InX::RelaDyn; + if (InX::RelrDyn && Type == Target->RelativeRel && InX::Got->Alignment >= 2 && + Off % 2 == 0) + RelSec = InX::RelrDyn; + + RelSec->addReloc(Type, InX::Got, Off, &Sym, 0, + Sym.IsPreemptible ? R_ADDEND : R_ABS, Target->GotRel); } // Return true if we can define a symbol in the executable that @@ -783,8 +789,11 @@ bool IsPreemptibleValue = Sym.IsPreemptible && Expr != R_GOT; if (!IsPreemptibleValue) { - InX::RelaDyn->addReloc(Target->RelativeRel, &Sec, Offset, &Sym, Addend, - Expr, Type); + RelocationBaseSection *RelSec = InX::RelaDyn; + if (InX::RelrDyn && Sec.Alignment >= 2 && Offset % 2 == 0) + RelSec = InX::RelrDyn; + RelSec->addReloc(Target->RelativeRel, &Sec, Offset, &Sym, Addend, Expr, + Type); return; } else if (RelType Rel = Target->getDynRel(Type)) { InX::RelaDyn->addReloc(Rel, &Sec, Offset, &Sym, Addend, R_ADDEND, Type); 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; @@ -517,6 +518,23 @@ SmallVector RelocData; }; +template +class RelrPackedRelocationSection final : public RelocationBaseSection { + typedef typename ELFT::Relr Elf_Relr; + +public: + RelrPackedRelocationSection(StringRef Name); + + 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 +976,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 @@ -1295,6 +1295,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 @@ -1444,9 +1450,18 @@ 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)) + // Add a dynamic relocation that might need an addend. This takes care of + // writing the addend to the output section if needed. We need to write + // the addend if either: + // - Config->WriteAddends is true, or + // - We're writing a RELR relocation. + // We can skip writing the addend if the written value would be zero. + bool WriteAddend = Config->WriteAddends; + if (Config->RelrPackDynRelocs && DynType == Target->RelativeRel) + WriteAddend = true; + 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}); } @@ -1695,6 +1710,105 @@ 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() { + // This function computes the contents of an SHT_RELR packed relocation + // section. + // + // Proposal for adding SHT_RELR sections to generic-abi is here: + // https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg + // + // The encoded sequence of Elf64_Relr entries in a SHT_RELR section looks + // like [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ] + // + // i.e. start with an address, followed by any number of bitmaps. The address + // entry encodes 1 relocation. The subsequent bitmap entries encode up to 63 + // relocations each, at subsequent offsets following the last address entry. + // + // The bitmap entries must have 1 in the least significant bit. The assumption + // here is that an address cannot have 1 in lsb. Odd addresses are not + // supported. + // + // Excluding the least significant bit in the bitmap, each non-zero bit in + // the bitmap represents a relocation to be applied to a corresponding machine + // word that follows the base address word. The second least significant bit + // represents the machine word immediately following the initial address, and + // each bit that follows represents the next word, in linear order. As such, + // a single bitmap can encode up to 31 relocations in a 32-bit object, and + // 63 relocations in a 64-bit object. + // + // This encoding has a couple of interesting properties: + // 1. Looking at any entry, it is clear whether it's an address or a bitmap: + // even means address, odd means bitmap. + // 2. Just a simple list of addresses is a valid encoding. + + size_t OldSize = RelrRelocs.size(); + RelrRelocs.clear(); + + // 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 * Config->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()); + + uint64_t Base = 0; + typename std::vector::iterator Curr = Offsets.begin(); + while (Curr != Offsets.end()) { + uint64_t Current = *Curr; + assert(Current % 2 == 0); + + uint64_t Bits = 0; + typename std::vector::iterator Next = Curr; + if (Base > 0 && Base <= Current) { + while (Next != Offsets.end()) { + uint64_t Delta = *Next - Base; + // If Next is too far out, it cannot be folded into Curr. + if (Delta >= NBits * Config->Wordsize) + break; + // If Next is not a multiple of wordsize away, it cannot + // be folded into Curr. + if (Delta % Config->Wordsize != 0) + break; + // Next can be folded into Curr, add it to the bitmap. + Bits |= 1ULL << (Delta / Config->Wordsize); + ++Next; + } + } + + Elf_Relr R; + if (Bits == 0) { + R = Current; + // This is not a continuation entry, only one offset was + // consumed. Set base offset for subsequent bitmap entries. + Base = Current + Config->Wordsize; + ++Curr; + } else { + R = (Bits << 1) | 1; + // This is a continuation entry encoding multiple offsets + // in a bitmap. Advance base offset by NBits words. + Base += NBits * Config->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, @@ -2894,6 +3008,7 @@ PltSection *InX::Plt; PltSection *InX::Iplt; RelocationBaseSection *InX::RelaDyn; +RelocationBaseSection *InX::RelrDyn; RelocationBaseSection *InX::RelaPlt; RelocationBaseSection *InX::RelaIplt; StringTableSection *InX::ShStrTab; @@ -2955,6 +3070,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 -raw-relr %t4.a32 | FileCheck --check-prefix=RAW-RELR32 %s +// RUN: llvm-readobj -relocations %t4.a32 | FileCheck --check-prefix=RELR32 %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. +// RAW-RELR32: 0x1000 +// RAW-RELR32-NEXT: 0x3FEFEFF + +// Decoded SHT_RELR section is same as UNPACKED, +// but contains only the relative relocations. +// RELR32: 0x1000 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1004 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1008 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x100C R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1010 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1014 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1018 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x101C R_ARM_RELATIVE - 0x0 + +// RELR32-NEXT: 0x1024 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1028 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x102C R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1030 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1034 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1038 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x103C R_ARM_RELATIVE - 0x0 + +// RELR32-NEXT: 0x1044 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1048 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x104C R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1050 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1054 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1058 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x105C R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x1060 R_ARM_RELATIVE - 0x0 +// RELR32-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,56 +187,120 @@ // 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 -raw-relr %t4.a64 | FileCheck --check-prefix=RAW-RELR64 %s +// RUN: llvm-readobj -relocations %t4.a64 | FileCheck --check-prefix=RELR64 %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. +// RAW-RELR64: 0x10000 +// RAW-RELR64-NEXT: 0x3FEFEFF + +// Decoded SHT_RELR section is same as UNPACKED, +// but contains only the relative relocations. +// RELR64: 0x10000 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10008 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10010 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10018 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10020 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10028 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10030 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10038 R_AARCH64_RELATIVE - 0x0 + +// RELR64-NEXT: 0x10048 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10050 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10058 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10060 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10068 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10070 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10078 R_AARCH64_RELATIVE - 0x0 + +// RELR64-NEXT: 0x10088 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10090 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x10098 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x100A0 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x100A8 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x100B0 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x100B8 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x100C0 R_AARCH64_RELATIVE - 0x0 +// RELR64-NEXT: 0x100C8 R_AARCH64_RELATIVE - 0x0 .data +.align 2 .dc.a __ehdr_start + 1 .dc.a __ehdr_start + 2 .dc.a __ehdr_start + 3