From 500cfcf363dc708834ddcc88d032c6efa7f62636 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Thu, 4 Apr 2024 16:41:04 +0300 Subject: [PATCH 1/4] [lld][AArch64][ELF][PAC] Support `.relr.auth.dyn` section Support `R_AARCH64_AUTH_RELATIVE` relocation compression as described in https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#relocation-compression --- lld/ELF/Arch/AArch64.cpp | 13 +++ lld/ELF/Relocations.cpp | 10 +- lld/ELF/SyntheticSections.cpp | 21 +++- lld/ELF/SyntheticSections.h | 15 ++- lld/ELF/Writer.cpp | 39 +++++++ lld/test/ELF/aarch64-reloc-pauth.s | 182 +++++++++++++++++++++++------ 6 files changed, 233 insertions(+), 47 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 017c17c2b03d8..a60f595f10aee 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -400,6 +400,19 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, case R_AARCH64_PREL64: write64(loc, val); break; + case R_AARCH64_AUTH_ABS64: + // If val is wider than 32 bits, the relocation must have been moved from + // .relr.auth.dyn to .rela.dyn, and the addend write is not needed. + // + // If val fits in 32 bits, we have two potential scenarios: + // * True RELR: Write the 32-bit `val` + // * RELA: Even if the value now fits in 32 bits, it might have been + // converted from RELR during an iteration in + // finalizeAddressDependentContent(). Writing the value is harmless + // because dynamic linking ignores it. + if (isInt<32>(val)) + write32(loc, val); + break; case R_AARCH64_ADD_ABS_LO12_NC: or32AArch64Imm(loc, val); break; diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 55274344f8811..5f66b98fac687 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -898,9 +898,9 @@ static void addRelativeReloc(InputSectionBase &isec, uint64_t offsetInSec, isec.addReloc({expr, type, offsetInSec, addend, &sym}); if (shard) part.relrDyn->relocsVec[parallel::getThreadIndex()].push_back( - {&isec, offsetInSec}); + {&isec, isec.relocs().size() - 1}); else - part.relrDyn->relocs.push_back({&isec, offsetInSec}); + part.relrDyn->relocs.push_back({&isec, isec.relocs().size() - 1}); return; } part.relaDyn->addRelativeReloc(target->relativeRel, isec, offsetInSec, @@ -1154,6 +1154,12 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, // relative relocation. Use a symbolic relocation instead. if (sym.isPreemptible) { part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type); + } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0) { + // When symbol values are determined in + // finalizeAddressDependentContent, some .relr.auth.dyn relocations + // may be moved to .rela.dyn. + sec->addReloc({expr, type, offset, addend, &sym}); + part.relrAuthDyn->relocs.push_back({sec, sec->relocs().size() - 1}); } else { part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, DynamicReloc::AddendOnlyWithTargetVA, sym, diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 4427a12008680..b34496473d56d 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1416,6 +1416,12 @@ DynamicSection::computeContents() { addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT, sizeof(Elf_Relr)); } + if (part.relrAuthDyn && part.relrAuthDyn->getParent() && + !part.relrAuthDyn->relocs.empty()) { + addInSec(DT_AARCH64_AUTH_RELR, *part.relrAuthDyn); + addInt(DT_AARCH64_AUTH_RELRSZ, part.relrAuthDyn->getParent()->size); + addInt(DT_AARCH64_AUTH_RELRENT, sizeof(Elf_Relr)); + } if (isMain && in.relaPlt->isNeeded()) { addInSec(DT_JMPREL, *in.relaPlt); entries.emplace_back(DT_PLTRELSZ, addPltRelSz()); @@ -1727,10 +1733,13 @@ template void RelocationSection::writeTo(uint8_t *buf) { } } -RelrBaseSection::RelrBaseSection(unsigned concurrency) - : SyntheticSection(SHF_ALLOC, - config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR, - config->wordsize, ".relr.dyn"), +RelrBaseSection::RelrBaseSection(unsigned concurrency, bool isAArch64Auth) + : SyntheticSection( + SHF_ALLOC, + isAArch64Auth + ? SHT_AARCH64_AUTH_RELR + : (config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR), + config->wordsize, isAArch64Auth ? ".relr.auth.dyn" : ".relr.dyn"), relocsVec(concurrency) {} void RelrBaseSection::mergeRels() { @@ -1998,8 +2007,8 @@ bool AndroidPackedRelocationSection::updateAllocSize() { } template -RelrSection::RelrSection(unsigned concurrency) - : RelrBaseSection(concurrency) { +RelrSection::RelrSection(unsigned concurrency, bool isAArch64Auth) + : RelrBaseSection(concurrency, isAArch64Auth) { this->entsize = config->wordsize; } diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 02a669b01d152..04e8d1992ecf7 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -543,7 +543,9 @@ class RelocationBaseSection : public SyntheticSection { static bool classof(const SectionBase *d) { return SyntheticSection::classof(d) && (d->type == llvm::ELF::SHT_RELA || d->type == llvm::ELF::SHT_REL || - d->type == llvm::ELF::SHT_RELR); + d->type == llvm::ELF::SHT_RELR || + (config->emachine == llvm::ELF::EM_AARCH64 && + d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR)); } int32_t dynamicTag, sizeDynamicTag; SmallVector relocs; @@ -591,15 +593,17 @@ class AndroidPackedRelocationSection final : public RelocationBaseSection { }; struct RelativeReloc { - uint64_t getOffset() const { return inputSec->getVA(offsetInSec); } + uint64_t getOffset() const { + return inputSec->getVA(inputSec->relocs()[relocIdx].offset); + } const InputSectionBase *inputSec; - uint64_t offsetInSec; + size_t relocIdx; }; class RelrBaseSection : public SyntheticSection { public: - RelrBaseSection(unsigned concurrency); + RelrBaseSection(unsigned concurrency, bool isAArch64Auth = false); void mergeRels(); bool isNeeded() const override { return !relocs.empty() || @@ -617,7 +621,7 @@ template class RelrSection final : public RelrBaseSection { using Elf_Relr = typename ELFT::Relr; public: - RelrSection(unsigned concurrency); + RelrSection(unsigned concurrency, bool isAArch64Auth = false); bool updateAllocSize() override; size_t getSize() const override { return relrRelocs.size() * this->entsize; } @@ -1319,6 +1323,7 @@ struct Partition { std::unique_ptr packageMetadataNote; std::unique_ptr relaDyn; std::unique_ptr relrDyn; + std::unique_ptr relrAuthDyn; std::unique_ptr verDef; std::unique_ptr verNeed; std::unique_ptr verSym; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index fc9084f40044d..9ea5ff5ba716a 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -456,6 +456,9 @@ template void elf::createSyntheticSections() { if (config->relrPackDynRelocs) { part.relrDyn = std::make_unique>(threadCount); add(*part.relrDyn); + part.relrAuthDyn = std::make_unique>( + threadCount, /*isAArch64Auth=*/true); + add(*part.relrAuthDyn); } if (!config->relocatable) { @@ -1730,9 +1733,33 @@ template void Writer::finalizeAddressDependentContent() { in.mipsGot->updateAllocSize(); for (Partition &part : partitions) { + // The R_AARCH64_AUTH_RELATIVE has a smaller addend field as bits [63:32] + // encode the signing schema. We've put relocations in .relr.auth.dyn + // during RelocationScanner::processAux, but the target VA for some of + // them might be wider than 32 bits. We can only know the final VA at this + // point, so move relocations with large values from .relr.auth.dyn to + // .rela.dyn. + if (part.relrAuthDyn) { + auto it = llvm::remove_if( + part.relrAuthDyn->relocs, [&part](const RelativeReloc &elem) { + const Relocation &reloc = elem.inputSec->relocs()[elem.relocIdx]; + if (isInt<32>(reloc.sym->getVA(reloc.addend))) + return false; + part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, elem.inputSec, + reloc.offset, + DynamicReloc::AddendOnlyWithTargetVA, + *reloc.sym, reloc.addend, R_ABS}); + // See also AArch64::relocate + return true; + }); + changed |= (it != part.relrAuthDyn->relocs.end()); + part.relrAuthDyn->relocs.erase(it, part.relrAuthDyn->relocs.end()); + } changed |= part.relaDyn->updateAllocSize(); if (part.relrDyn) changed |= part.relrDyn->updateAllocSize(); + if (part.relrAuthDyn) + changed |= part.relrAuthDyn->updateAllocSize(); if (part.memtagGlobalDescriptors) changed |= part.memtagGlobalDescriptors->updateAllocSize(); } @@ -1883,6 +1910,14 @@ static void removeUnusedSyntheticSections() { auto *sec = cast(s); if (sec->getParent() && sec->isNeeded()) return false; + // .relr.auth.dyn relocations may be moved to .rela.dyn in + // finalizeAddressDependentContent, making .rela.dyn no longer empty. + // Conservatively keep .rela.dyn. .relr.auth.dyn can be made empty, but + // we would fail to remove it here. + if (config->emachine == EM_AARCH64 && config->relrPackDynRelocs) + if (auto *relSec = dyn_cast(sec)) + if (relSec == mainPart->relaDyn.get()) + return false; unused.insert(sec); return true; }); @@ -2195,6 +2230,10 @@ template void Writer::finalizeSections() { part.relrDyn->mergeRels(); finalizeSynthetic(part.relrDyn.get()); } + if (part.relrAuthDyn) { + part.relrAuthDyn->mergeRels(); + finalizeSynthetic(part.relrAuthDyn.get()); + } finalizeSynthetic(part.dynSymTab.get()); finalizeSynthetic(part.gnuHashTab.get()); diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index b603d8ffdcabd..55e8803f3d571 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -1,11 +1,13 @@ # REQUIRES: aarch64 -# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.a.o -# RUN: ld.lld -shared %t.a.o -soname=so -o %t.a.so -# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +# RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: ld.lld -pie %t.o %t.a.so -o %t -# RUN: llvm-readobj -r %t | FileCheck --check-prefix=UNPACKED %s +# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o a.o +# RUN: ld.lld -shared a.o -soname=so -o a.so +# RUN: llvm-mc -filetype=obj -triple=aarch64 main.s -o main.o + +# RUN: ld.lld -pie main.o a.so -o main +# RUN: llvm-readobj -r main | FileCheck --check-prefix=UNPACKED %s # UNPACKED: Section ({{.+}}) .rela.dyn { # UNPACKED-NEXT: 0x30470 R_AARCH64_AUTH_RELATIVE - 0x1 @@ -21,8 +23,8 @@ # UNPACKED-NEXT: 0x304B0 R_AARCH64_AUTH_ABS64 bar2 0x0 # UNPACKED-NEXT: } -# RUN: ld.lld %t.o %t.a.so -o %t.nopie -# RUN: llvm-readobj -r %t.nopie | FileCheck --check-prefix=NOPIE %s +# RUN: ld.lld main.o a.so -o main.nopie +# RUN: llvm-readobj -r main.nopie | FileCheck --check-prefix=NOPIE %s # NOPIE: Section ({{.+}}) .rela.dyn { # NOPIE: 0x230460 R_AARCH64_AUTH_RELATIVE - 0x200001 @@ -38,67 +40,111 @@ # NOPIE-NEXT: 0x2304A0 R_AARCH64_AUTH_ABS64 bar2 0x0 # NOPIE-NEXT: } -# RUN: ld.lld -pie %t.o %t.a.so -o %t.pie -# RUN: llvm-readelf -S -d -r -x .test %t.pie | FileCheck --check-prefixes=PIE,HEX %s - -# PIE: Section Headers: -# PIE-NEXT: Name Type Address Off Size ES Flg Lk Inf Al -# PIE: .rela.dyn RELA {{0*}}[[#%x,ADDR1:]] -# PIE-SAME: {{0*}}[[#ADDR1]] 000108 18 A 1 0 8 - -# PIE: Relocation section '.rela.dyn' at offset 0x[[#ADDR1]] contains 11 entries: -# PIE-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend -# PIE-NEXT: 0000000000030470 0000000000000411 R_AARCH64_AUTH_RELATIVE 1 -# PIE-NEXT: 0000000000030478 0000000000000411 R_AARCH64_AUTH_RELATIVE 30472 -# PIE-NEXT: 0000000000030480 0000000000000411 R_AARCH64_AUTH_RELATIVE fffffffffffffffd -# PIE-NEXT: 0000000000030488 0000000000000411 R_AARCH64_AUTH_RELATIVE 12345678 -# PIE-NEXT: 0000000000030490 0000000000000411 R_AARCH64_AUTH_RELATIVE 123456789a -# PIE-NEXT: 0000000000030498 0000000000000411 R_AARCH64_AUTH_RELATIVE ffffffedcba98766 -# PIE-NEXT: 00000000000304a0 0000000000000411 R_AARCH64_AUTH_RELATIVE 8003046f -# PIE-NEXT: 00000000000304b9 0000000000000411 R_AARCH64_AUTH_RELATIVE 4 -# PIE-NEXT: 00000000000304c2 0000000000000411 R_AARCH64_AUTH_RELATIVE 30475 -# PIE-NEXT: 00000000000304a8 0000000100000244 R_AARCH64_AUTH_ABS64 0000000000000000 zed2 + 1111 -# PIE-NEXT: 00000000000304b0 0000000200000244 R_AARCH64_AUTH_ABS64 0000000000000000 bar2 + 0 +# RUN: ld.lld -pie -z pack-relative-relocs main.o a.so -o main.pie +# RUN: llvm-readelf -S -d -r -x .test main.pie | FileCheck --check-prefixes=RELR,HEX %s + +# RELR: Section Headers: +# RELR-NEXT: Name Type Address Off Size ES Flg Lk Inf Al +# RELR: .rela.dyn RELA {{0*}}[[ADDR1:.*]] {{0*}}[[ADDR1]] 000090 18 A 1 0 8 +# RELR: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.*]] {{0*}}[[ADDR2]] 000018 08 A 0 0 8 + +# RELR: Dynamic section at offset {{.*}} contains 16 entries +# RELR: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR2]] +# RELR-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes) +# RELR-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes) + +## Decoded SHT_RELR section is same as UNPACKED, +## but contains only the relative relocations. +## Any relative relocations with odd offset or value wider than 32 bits stay in SHT_RELA. + +# RELR: Relocation section '.rela.dyn' at offset 0x[[ADDR1]] contains 6 entries: +# RELR-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +# RELR-NEXT: 0000000000030460 0000000000000411 R_AARCH64_AUTH_RELATIVE 123456789a +# RELR-NEXT: 0000000000030468 0000000000000411 R_AARCH64_AUTH_RELATIVE ffffffedcba98766 +# RELR-NEXT: 0000000000030470 0000000000000411 R_AARCH64_AUTH_RELATIVE 8003043f +# RELR-NEXT: 0000000000030489 0000000000000411 R_AARCH64_AUTH_RELATIVE 4 +# RELR-NEXT: 0000000000030478 0000000100000244 R_AARCH64_AUTH_ABS64 0000000000000000 zed2 + 1111 +# RELR-NEXT: 0000000000030480 0000000200000244 R_AARCH64_AUTH_ABS64 0000000000000000 bar2 + 0 +# RELR-EMPTY: +# RELR-NEXT: Relocation section '.relr.auth.dyn' at offset 0x[[ADDR2]] contains 5 entries: +# RELR-NEXT: Offset Info Type Symbol's Value Symbol's Name +# RELR-NEXT: 0000000000030440 0000000000000403 R_AARCH64_RELATIVE +# RELR-NEXT: 0000000000030448 0000000000000403 R_AARCH64_RELATIVE +# RELR-NEXT: 0000000000030450 0000000000000403 R_AARCH64_RELATIVE +# RELR-NEXT: 0000000000030458 0000000000000403 R_AARCH64_RELATIVE +# RELR-NEXT: 0000000000030492 0000000000000403 R_AARCH64_RELATIVE + +# RUN: llvm-readobj -r --raw-relr main.pie | \ +# RUN: FileCheck --match-full-lines --check-prefix=RAW-RELR %s + +## SHT_RELR section contains address/bitmap entries +## encoding the offsets for relative relocation. + +# RAW-RELR: Section ({{.+}}) .relr.auth.dyn { +# RAW-RELR-NEXT: 0x30440 +# RAW-RELR-NEXT: 0xF +## 0xF = 0b111100..00 +## lsb hsb +## Bits 1..3 are set, we have relocs at 0x30440 and the next 3 places: 0x30448, 0x3450, 0x30458 +# RAW-RELR-NEXT: 0x30492 +## A single reloc at ^^^^^^^ +# RAW-RELR-NEXT: } # HEX: Hex dump of section '.test': -# HEX-NEXT: 0x00030470 00000000 2a000020 00000000 2b000000 +# HEX-NEXT: 0x00030440 01000000 2a000020 42040300 2b000000 +## ^^^^^^^^ Implicit val = 1 = __ehdr_start + 1 ## ^^^^ Discr = 42 ## ^^ Key (bits 5..6) = DA +## ^^^^^^^^ Implicit val = 0x30442 = 0x30440 + 2 = .test + 2 ## ^^^^ Discr = 43 ## ^^ Key (bits 5..6) = IA -# HEX-NEXT: 0x00030480 00000000 2c000080 00000000 2d000020 +# HEX-NEXT: 0x00030450 fdffffff 2c000080 78563412 2d000020 +## ^^^^^^^^ Implicit val = -3 = __ehdr_start - 3 ## ^^^^ Discr = 44 ## ^^ Key (bits 5..6) = IA ## ^^ Addr diversity (bit 7) = true +## ^^^^^^^^ Implicit val = 0x12345678 = __ehdr_start + 0x12345678 ## ^^^^ Discr = 45 ## ^^ Key (bits 5..6) = DA -# HEX-NEXT: 0x00030490 00000000 2e000020 00000000 2f000020 +# HEX-NEXT: 0x00030460 00000000 2e000020 00000000 2f000020 +## ^^^^^^^^ No implicit val (rela reloc due val wider than 32 bits) ## ^^^^ Discr = 46 ## ^^ Key (bits 5..6) = DA +## ^^^^^^^^ No implicit val (rela reloc due to val wider than 32 bits) ## ^^^^ Discr = 47 ## ^^ Key (bits 5..6) = DA -# HEX-NEXT: 0x000304a0 00000000 30000020 00000000 31000020 +# HEX-NEXT: 0x00030470 00000000 30000020 00000000 31000020 +## ^^^^^^^^ No implicit val (rela reloc due val wider than 32 bits) ## ^^^^ Discr = 48 ## ^^ Key (bits 5..6) = DA +## ^^^^^^^^ No implicit val (rela reloc due to a preemptible symbol) ## ^^^^ Discr = 49 ## ^^ Key (bits 5..6) = DA -# HEX-NEXT: 0x000304b0 00000000 32000000 77000000 00330000 +# HEX-NEXT: 0x00030480 00000000 32000000 77000000 00330000 +## ^^^^^^^^ No implicit val (rela reloc due to a preemptible symbol) ## ^^^^ Discr = 50 ## ^^ Key (bits 5..6) = IA +## ^^^^^^ ^^ No implicit val (rela reloc due to odd offset) ## ^^^^ Discr = 51 -# HEX-NEXT: 0x000304c0 20770000 00003400 0020{{\ }} +# HEX-NEXT: 0x00030490 20774504 03003400 0020{{\ }} ## ^^ Key (bits 5..6) = DA +## ^^^^ ^^^^ Implicit val = 0x30445 = 0x30440 + 5 = .test + 5 ## ^^^^ Discr = 52 ## ^^ Key (bits 5..6) = DA +#--- main.s + .section .test, "aw" .p2align 3 .quad (__ehdr_start + 1)@AUTH(da,42) .quad (.test + 2)@AUTH(ia,43) .quad (__ehdr_start - 3)@AUTH(ia,44,addr) .quad (__ehdr_start + 0x12345678)@AUTH(da,45) +## Addend wider than 32 bits, not enough room for storing implicitly, would go to rela .quad (__ehdr_start + 0x123456789A)@AUTH(da,46) +## Negative addend wider than 32 bits, not enough room for storing implicitly, would go to rela .quad (__ehdr_start - 0x123456789A)@AUTH(da,47) +## INT32_MAX plus non-zero .test is wider than 32 bits, not enough room for storing implicitly, would go to rela .quad (.test + 0x7FFFFFFF)@AUTH(da,48) .quad (zed2 + 0x1111)@AUTH(da,49) .quad bar2@AUTH(ia,50) @@ -106,3 +152,71 @@ .quad (__ehdr_start + 4)@AUTH(da,51) .byte 0x77 .quad (.test + 5)@AUTH(da,52) + +#--- empty-relr.s + +## .relr.auth.dyn relocations that do not fit 32 bits are moved to .rela.dyn. +## In this case .relr.auth.dyn will be made empty, but +## removeUnusedSyntheticSections fails to remove the section. + +# RUN: llvm-mc -filetype=obj -triple=aarch64 empty-relr.s -o empty-relr.o +# RUN: ld.lld -pie -z pack-relative-relocs empty-relr.o -o empty-relr +# RUN: llvm-readelf -S -d -r empty-relr | FileCheck --check-prefixes=EMPTY-RELR %s + +# EMPTY-RELR: Section Headers: +# EMPTY-RELR-NEXT: Name Type Address Off Size ES Flg Lk Inf Al +# EMPTY-RELR: .rela.dyn RELA {{0*}}[[ADDR1:.*]] {{0*}}[[ADDR1]] 000018 18 A 0 0 8 +# EMPTY-RELR: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.*]] {{0*}}[[ADDR2]] 000000 08 A 0 0 8 + +# EMPTY-RELR: Dynamic section at offset {{.*}} contains 12 entries +# EMPTY-RELR-NOT: (AARCH64_AUTH_RELR) +# EMPTY-RELR-NOT: (AARCH64_AUTH_RELRSZ) +# EMPTY-RELR-NOT: (AARCH64_AUTH_RELRENT) +# EMPTY-RELR: 0x0000000000000007 (RELA) 0x[[ADDR1]] +# EMPTY-RELR-NEXT: 0x0000000000000008 (RELASZ) 24 (bytes) +# EMPTY-RELR-NEXT: 0x0000000000000009 (RELAENT) 24 (bytes) + +# EMPTY-RELR: Relocation section '.rela.dyn' at offset {{.*}} contains 1 entries: +# EMPTY-RELR-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +# EMPTY-RELR-NEXT: 0000000000030320 0000000000000411 R_AARCH64_AUTH_RELATIVE 8003031f +# EMPTY-RELR-EMPTY: +# EMPTY-RELR-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 0 entries: +# EMPTY-RELR-NEXT: Offset Info Type Symbol's Value Symbol's Name + +.section .test, "aw" +.p2align 3 +.quad (.test + 0x7FFFFFFF)@AUTH(da,42) + +#--- empty-rela.s + +## .relr.auth.dyn relocations that do not fit 32 bits are moved to .rela.dyn. +## If this scenario does not happen, .rela.dyn will remain empty, +## but removeUnusedSyntheticSections fails to remove the section. + +# RUN: llvm-mc -filetype=obj -triple=aarch64 empty-rela.s -o empty-rela.o +# RUN: ld.lld -pie -z pack-relative-relocs empty-rela.o -o empty-rela +# RUN: llvm-readelf -S -d -r empty-rela | FileCheck --check-prefixes=EMPTY-RELA %s + +# EMPTY-RELA: Section Headers: +# EMPTY-RELA-NEXT: Name Type Address Off Size ES Flg Lk Inf Al +# EMPTY-RELA: .rela.dyn RELA {{0*}}[[ADDR1:.*]] {{0*}}[[ADDR1]] 000000 18 A 0 0 8 +# EMPTY-RELA: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.*]] {{0*}}[[ADDR2]] 000008 08 A 0 0 8 + +# EMPTY-RELA: Dynamic section at offset {{.*}} contains 12 entries +# EMPTY-RELA-NOT: (RELR) +# EMPTY-RELA-NOT: (RELRSZ) +# EMPTY-RELA-NOT: (RELRENT) +# EMPTY-RELA: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR2]] +# EMPTY-RELA-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 8 (bytes) +# EMPTY-RELA-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes) + +# EMPTY-RELA: Relocation section '.rela.dyn' at offset {{.*}} contains 0 entries: +# EMPTY-RELA-NEXT: Offset Info Type Symbol's Value Symbol's Name +# EMPTY-RELA-EMPTY: +# EMPTY-RELA-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 1 entries: +# EMPTY-RELA-NEXT: Offset Info Type Symbol's Value Symbol's Name +# EMPTY-RELA-NEXT: 0000000000030310 0000000000000403 R_AARCH64_RELATIVE + +.section .test, "aw" +.p2align 3 +.quad (.test + 0x12345678)@AUTH(da,42) From 411d04c98ac7a18b8a1056e0d25a00ac8a5b1a42 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 14 May 2024 22:36:58 +0300 Subject: [PATCH 2/4] Fix readelf output of relr See d86079f93c9f59d31f2cebb55dce24783070bd77 and 89c95effe82c09b9a42408f4823409331f8fa266. --- lld/test/ELF/aarch64-reloc-pauth.s | 34 ++++++++---------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index 55e8803f3d571..d8591659ce336 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -67,28 +67,12 @@ # RELR-NEXT: 0000000000030480 0000000200000244 R_AARCH64_AUTH_ABS64 0000000000000000 bar2 + 0 # RELR-EMPTY: # RELR-NEXT: Relocation section '.relr.auth.dyn' at offset 0x[[ADDR2]] contains 5 entries: -# RELR-NEXT: Offset Info Type Symbol's Value Symbol's Name -# RELR-NEXT: 0000000000030440 0000000000000403 R_AARCH64_RELATIVE -# RELR-NEXT: 0000000000030448 0000000000000403 R_AARCH64_RELATIVE -# RELR-NEXT: 0000000000030450 0000000000000403 R_AARCH64_RELATIVE -# RELR-NEXT: 0000000000030458 0000000000000403 R_AARCH64_RELATIVE -# RELR-NEXT: 0000000000030492 0000000000000403 R_AARCH64_RELATIVE - -# RUN: llvm-readobj -r --raw-relr main.pie | \ -# RUN: FileCheck --match-full-lines --check-prefix=RAW-RELR %s - -## SHT_RELR section contains address/bitmap entries -## encoding the offsets for relative relocation. - -# RAW-RELR: Section ({{.+}}) .relr.auth.dyn { -# RAW-RELR-NEXT: 0x30440 -# RAW-RELR-NEXT: 0xF -## 0xF = 0b111100..00 -## lsb hsb -## Bits 1..3 are set, we have relocs at 0x30440 and the next 3 places: 0x30448, 0x3450, 0x30458 -# RAW-RELR-NEXT: 0x30492 -## A single reloc at ^^^^^^^ -# RAW-RELR-NEXT: } +# RELR-NEXT: Index: Entry Address Symbolic Address +# RELR-NEXT: 0000: 0000000000030440 0000000000030440 $d.0 +# RELR-NEXT: 0001: 000000000000000f 0000000000030448 $d.0 + 0x8 +# RELR-NEXT: 0000000000030450 $d.0 + 0x10 +# RELR-NEXT: 0000000000030458 $d.0 + 0x18 +# RELR-NEXT: 0002: 0000000000030492 0000000000030492 $d.0 + 0x52 # HEX: Hex dump of section '.test': # HEX-NEXT: 0x00030440 01000000 2a000020 42040300 2b000000 @@ -181,7 +165,7 @@ # EMPTY-RELR-NEXT: 0000000000030320 0000000000000411 R_AARCH64_AUTH_RELATIVE 8003031f # EMPTY-RELR-EMPTY: # EMPTY-RELR-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 0 entries: -# EMPTY-RELR-NEXT: Offset Info Type Symbol's Value Symbol's Name +# EMPTY-RELR-NEXT: Index: Entry Address Symbolic Address .section .test, "aw" .p2align 3 @@ -214,8 +198,8 @@ # EMPTY-RELA-NEXT: Offset Info Type Symbol's Value Symbol's Name # EMPTY-RELA-EMPTY: # EMPTY-RELA-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 1 entries: -# EMPTY-RELA-NEXT: Offset Info Type Symbol's Value Symbol's Name -# EMPTY-RELA-NEXT: 0000000000030310 0000000000000403 R_AARCH64_RELATIVE +# EMPTY-RELA-NEXT: Index: Entry Address Symbolic Address +# EMPTY-RELA-NEXT: 0000: 0000000000030310 0000000000030310 $d.0 .section .test, "aw" .p2align 3 From e68efcf46ebf0abdeec9f1fd5ed6a14e51e07e42 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 14 May 2024 22:40:35 +0300 Subject: [PATCH 3/4] Address review comments --- lld/ELF/Arch/AArch64.cpp | 2 +- lld/ELF/SyntheticSections.h | 4 ++-- lld/ELF/Writer.cpp | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index afa59df04fed2..b0aa0b9b8e9da 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -433,7 +433,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, // .relr.auth.dyn to .rela.dyn, and the addend write is not needed. // // If val fits in 32 bits, we have two potential scenarios: - // * True RELR: Write the 32-bit `val` + // * True RELR: Write the 32-bit `val`. // * RELA: Even if the value now fits in 32 bits, it might have been // converted from RELR during an iteration in // finalizeAddressDependentContent(). Writing the value is harmless diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index b361a95b5a24f..eaa09ea7194fb 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -549,8 +549,8 @@ class RelocationBaseSection : public SyntheticSection { return SyntheticSection::classof(d) && (d->type == llvm::ELF::SHT_RELA || d->type == llvm::ELF::SHT_REL || d->type == llvm::ELF::SHT_RELR || - (config->emachine == llvm::ELF::EM_AARCH64 && - d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR)); + (d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR && + config->emachine == llvm::ELF::EM_AARCH64)); } int32_t dynamicTag, sizeDynamicTag; SmallVector relocs; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 16509de2476c3..fe2e1900520a4 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1459,7 +1459,7 @@ template void Writer::finalizeAddressDependentContent() { // during RelocationScanner::processAux, but the target VA for some of // them might be wider than 32 bits. We can only know the final VA at this // point, so move relocations with large values from .relr.auth.dyn to - // .rela.dyn. + // .rela.dyn. See also AArch64::relocate. if (part.relrAuthDyn) { auto it = llvm::remove_if( part.relrAuthDyn->relocs, [&part](const RelativeReloc &elem) { @@ -1470,7 +1470,6 @@ template void Writer::finalizeAddressDependentContent() { reloc.offset, DynamicReloc::AddendOnlyWithTargetVA, *reloc.sym, reloc.addend, R_ABS}); - // See also AArch64::relocate return true; }); changed |= (it != part.relrAuthDyn->relocs.end()); From 8a83e0574e3ef011b0b0bd66ce166f55887226d2 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 15 May 2024 21:52:29 +0300 Subject: [PATCH 4/4] Change `.*` to `.+` in test --- lld/test/ELF/aarch64-reloc-pauth.s | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index d8591659ce336..f1ce29eaae467 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -45,10 +45,10 @@ # RELR: Section Headers: # RELR-NEXT: Name Type Address Off Size ES Flg Lk Inf Al -# RELR: .rela.dyn RELA {{0*}}[[ADDR1:.*]] {{0*}}[[ADDR1]] 000090 18 A 1 0 8 -# RELR: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.*]] {{0*}}[[ADDR2]] 000018 08 A 0 0 8 +# RELR: .rela.dyn RELA {{0*}}[[ADDR1:.+]] {{0*}}[[ADDR1]] 000090 18 A 1 0 8 +# RELR: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.+]] {{0*}}[[ADDR2]] 000018 08 A 0 0 8 -# RELR: Dynamic section at offset {{.*}} contains 16 entries +# RELR: Dynamic section at offset {{.+}} contains 16 entries # RELR: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR2]] # RELR-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes) # RELR-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes) @@ -149,10 +149,10 @@ # EMPTY-RELR: Section Headers: # EMPTY-RELR-NEXT: Name Type Address Off Size ES Flg Lk Inf Al -# EMPTY-RELR: .rela.dyn RELA {{0*}}[[ADDR1:.*]] {{0*}}[[ADDR1]] 000018 18 A 0 0 8 -# EMPTY-RELR: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.*]] {{0*}}[[ADDR2]] 000000 08 A 0 0 8 +# EMPTY-RELR: .rela.dyn RELA {{0*}}[[ADDR1:.+]] {{0*}}[[ADDR1]] 000018 18 A 0 0 8 +# EMPTY-RELR: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.+]] {{0*}}[[ADDR2]] 000000 08 A 0 0 8 -# EMPTY-RELR: Dynamic section at offset {{.*}} contains 12 entries +# EMPTY-RELR: Dynamic section at offset {{.+}} contains 12 entries # EMPTY-RELR-NOT: (AARCH64_AUTH_RELR) # EMPTY-RELR-NOT: (AARCH64_AUTH_RELRSZ) # EMPTY-RELR-NOT: (AARCH64_AUTH_RELRENT) @@ -160,11 +160,11 @@ # EMPTY-RELR-NEXT: 0x0000000000000008 (RELASZ) 24 (bytes) # EMPTY-RELR-NEXT: 0x0000000000000009 (RELAENT) 24 (bytes) -# EMPTY-RELR: Relocation section '.rela.dyn' at offset {{.*}} contains 1 entries: +# EMPTY-RELR: Relocation section '.rela.dyn' at offset {{.+}} contains 1 entries: # EMPTY-RELR-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend # EMPTY-RELR-NEXT: 0000000000030320 0000000000000411 R_AARCH64_AUTH_RELATIVE 8003031f # EMPTY-RELR-EMPTY: -# EMPTY-RELR-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 0 entries: +# EMPTY-RELR-NEXT: Relocation section '.relr.auth.dyn' at offset {{.+}} contains 0 entries: # EMPTY-RELR-NEXT: Index: Entry Address Symbolic Address .section .test, "aw" @@ -183,10 +183,10 @@ # EMPTY-RELA: Section Headers: # EMPTY-RELA-NEXT: Name Type Address Off Size ES Flg Lk Inf Al -# EMPTY-RELA: .rela.dyn RELA {{0*}}[[ADDR1:.*]] {{0*}}[[ADDR1]] 000000 18 A 0 0 8 -# EMPTY-RELA: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.*]] {{0*}}[[ADDR2]] 000008 08 A 0 0 8 +# EMPTY-RELA: .rela.dyn RELA {{0*}}[[ADDR1:.+]] {{0*}}[[ADDR1]] 000000 18 A 0 0 8 +# EMPTY-RELA: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.+]] {{0*}}[[ADDR2]] 000008 08 A 0 0 8 -# EMPTY-RELA: Dynamic section at offset {{.*}} contains 12 entries +# EMPTY-RELA: Dynamic section at offset {{.+}} contains 12 entries # EMPTY-RELA-NOT: (RELR) # EMPTY-RELA-NOT: (RELRSZ) # EMPTY-RELA-NOT: (RELRENT) @@ -194,10 +194,10 @@ # EMPTY-RELA-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 8 (bytes) # EMPTY-RELA-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes) -# EMPTY-RELA: Relocation section '.rela.dyn' at offset {{.*}} contains 0 entries: +# EMPTY-RELA: Relocation section '.rela.dyn' at offset {{.+}} contains 0 entries: # EMPTY-RELA-NEXT: Offset Info Type Symbol's Value Symbol's Name # EMPTY-RELA-EMPTY: -# EMPTY-RELA-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 1 entries: +# EMPTY-RELA-NEXT: Relocation section '.relr.auth.dyn' at offset {{.+}} contains 1 entries: # EMPTY-RELA-NEXT: Index: Entry Address Symbolic Address # EMPTY-RELA-NEXT: 0000: 0000000000030310 0000000000030310 $d.0