From c493d78e6c482bb530189de05b79e7082a224fab Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Thu, 28 Sep 2023 03:14:35 +0300 Subject: [PATCH 01/34] [lld][AArch64][ELF][PAC] Support AUTH relocations and AUTH ELF marking This patch adds lld support for: - Dynamic R_AARCH64_AUTH_* relocations (including RELR compressed AUTH relocations) as described here: https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#auth-variant-dynamic-relocations - .note.AARCH64-PAUTH-ABI-tag section as defined here https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking Co-authored-by: Peter Collingbourne --- lld/ELF/Arch/AArch64.cpp | 5 + lld/ELF/Config.h | 4 + lld/ELF/Driver.cpp | 57 +++++++++- lld/ELF/InputFiles.cpp | 44 ++++++++ lld/ELF/InputFiles.h | 1 + lld/ELF/Relocations.cpp | 26 +++++ lld/ELF/SyntheticSections.cpp | 44 ++++++-- lld/ELF/SyntheticSections.h | 19 +++- lld/ELF/Writer.cpp | 17 +++ lld/test/ELF/aarch64-feature-pauth.s | 83 ++++++++++++++ lld/test/ELF/aarch64-ptrauth.s | 156 +++++++++++++++++++++++++++ 11 files changed, 445 insertions(+), 11 deletions(-) create mode 100644 lld/test/ELF/aarch64-feature-pauth.s create mode 100644 lld/test/ELF/aarch64-ptrauth.s diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 048f0ec30ebd2..6828d3f57c10e 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -112,6 +112,7 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, case R_AARCH64_MOVW_UABS_G2: case R_AARCH64_MOVW_UABS_G2_NC: case R_AARCH64_MOVW_UABS_G3: + case R_AARCH64_AUTH_ABS64: return R_ABS; case R_AARCH64_TLSDESC_ADR_PAGE21: return R_AARCH64_TLSDESC_PAGE; @@ -395,6 +396,10 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, case R_AARCH64_PREL64: write64(loc, val); break; + case R_AARCH64_AUTH_ABS64: + checkIntUInt(loc, val, 32, rel); + write32(loc, val); + break; case R_AARCH64_ADD_ABS_LO12_NC: or32AArch64Imm(loc, val); break; diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 56229334f9a44..1b633a7984276 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -187,6 +187,7 @@ struct Config { llvm::StringRef cmseOutputLib; StringRef zBtiReport = "none"; StringRef zCetReport = "none"; + StringRef zPauthReport = "none"; llvm::StringRef ltoBasicBlockSections; std::pair thinLTOObjectSuffixReplace; llvm::StringRef thinLTOPrefixReplaceOld; @@ -275,6 +276,7 @@ struct Config { bool relocatable; bool relrGlibc = false; bool relrPackDynRelocs = false; + bool relrPackAuthDynRelocs = false; llvm::DenseSet saveTempsArgs; llvm::SmallVector, 0> shuffleSections; bool singleRoRx; @@ -492,6 +494,8 @@ struct Ctx { void reset(); llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &); + + SmallVector aarch64PauthAbiTag; }; LLVM_LIBRARY_VISIBILITY extern Ctx ctx; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 6bef09eeca015..4e8e9eb86ecf7 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -65,6 +65,7 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" +#include #include #include #include @@ -459,6 +460,8 @@ static void checkOptions() { error("-z force-bti only supported on AArch64"); if (config->zBtiReport != "none") error("-z bti-report only supported on AArch64"); + if (config->zPauthReport != "none") + error("-z pauth-report only supported on AArch64"); } if (config->emachine != EM_386 && config->emachine != EM_X86_64 && @@ -558,6 +561,7 @@ constexpr const char *knownZFlags[] = { "nognustack", "nokeep-text-section-prefix", "nopack-relative-relocs", + "nopack-relative-auth-relocs", "norelro", "noseparate-code", "nostart-stop-gc", @@ -566,6 +570,7 @@ constexpr const char *knownZFlags[] = { "origin", "pac-plt", "pack-relative-relocs", + "pack-relative-auth-relocs", "rel", "rela", "relro", @@ -583,7 +588,7 @@ constexpr const char *knownZFlags[] = { static bool isKnownZFlag(StringRef s) { return llvm::is_contained(knownZFlags, s) || s.starts_with("common-page-size=") || s.starts_with("bti-report=") || - s.starts_with("cet-report=") || + s.starts_with("cet-report=") || s.starts_with("pauth-report=") || s.starts_with("dead-reloc-in-nonalloc=") || s.starts_with("max-page-size=") || s.starts_with("stack-size=") || s.starts_with("start-stop-visibility="); @@ -1514,7 +1519,8 @@ static void readConfigs(opt::InputArgList &args) { } auto reports = {std::make_pair("bti-report", &config->zBtiReport), - std::make_pair("cet-report", &config->zCetReport)}; + std::make_pair("cet-report", &config->zCetReport), + std::make_pair("pauth-report", &config->zPauthReport)}; for (opt::Arg *arg : args.filtered(OPT_z)) { std::pair option = StringRef(arg->getValue()).split('='); @@ -1671,6 +1677,9 @@ static void readConfigs(opt::InputArgList &args) { getPackDynRelocs(args); } + config->relrPackAuthDynRelocs = getZFlag( + args, "pack-relative-auth-relocs", "nopack-relative-auth-relocs", false); + if (auto *arg = args.getLastArg(OPT_symbol_ordering_file)){ if (args.hasArg(OPT_call_graph_ordering_file)) error("--symbol-ordering-file and --call-graph-order-file " @@ -2639,6 +2648,47 @@ static uint32_t getAndFeatures() { return ret; } +static void getAarch64PauthInfo() { + if (ctx.objectFiles.empty()) + return; + + auto NonEmptyIt = std::find_if( + ctx.objectFiles.begin(), ctx.objectFiles.end(), + [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); }); + if (NonEmptyIt == ctx.objectFiles.end()) + return; + + ctx.aarch64PauthAbiTag = (*NonEmptyIt)->aarch64PauthAbiTag; + StringRef F1 = (*NonEmptyIt)->getName(); + for (ELFFileBase *F : ArrayRef(ctx.objectFiles)) { + StringRef F2 = F->getName(); + const SmallVector &D1 = ctx.aarch64PauthAbiTag; + const SmallVector &D2 = F->aarch64PauthAbiTag; + if (D1.empty() != D2.empty()) { + auto Helper = [](StringRef Report, const Twine &Msg) { + if (Report == "warning") + warn(Msg); + else if (Report == "error") + error(Msg); + }; + + Helper(config->zPauthReport, + (D1.empty() ? F1.str() : F2.str()) + + " has no AArch64 PAuth compatibility info while " + + (D1.empty() ? F2.str() : F1.str()) + + " has one; either all or no input files must have it"); + } + + if (!D1.empty() && !D2.empty() && + !std::equal(D1.begin(), D1.end(), D2.begin(), D2.end())) + errorOrWarn( + "incompatible values of AArch64 PAuth compatibility info found" + "\n" + + F1 + ": 0x" + toHex(ArrayRef(D1.data(), D1.size())) + "\n" + F2 + + ": 0x" + toHex(ArrayRef(D2.data(), D2.size()))); + } +} + static void initSectionsAndLocalSyms(ELFFileBase *file, bool ignoreComdats) { switch (file->ekind) { case ELF32LEKind: @@ -2976,6 +3026,9 @@ void LinkerDriver::link(opt::InputArgList &args) { // contain a hint to tweak linker's and loader's behaviors. config->andFeatures = getAndFeatures(); + if (config->emachine == EM_AARCH64) + getAarch64PauthInfo(); + // The Target instance handles target-specific stuff, such as applying // relocations or writing a PLT section. It also contains target-dependent // values such as a default image base address. diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index cc2c5916e05c2..44c8050f2c967 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -962,6 +962,44 @@ template static uint32_t readAndFeatures(const InputSection &sec) { return featuresSet; } +// Extract compatibility info for aarch64 pointer authentication from the +// .note.AARCH64-PAUTH-ABI-tag section and write it to the corresponding ObjFile +// field. See the following ABI documentation: +// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking +template +static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile &f) { + using Elf_Nhdr = typename ELFT::Nhdr; + using Elf_Note = typename ELFT::Note; + ArrayRef data = sec.content(); + auto reportError = [&](const Twine &msg) { + errorOrWarn(toString(sec.file) + ":(" + sec.name + "): " + msg); + }; + + auto *nhdr = reinterpret_cast(data.data()); + if (data.size() < sizeof(Elf_Nhdr) || + data.size() < nhdr->getSize(sec.addralign)) { + reportError("section is too short"); + return; + } + + Elf_Note note(*nhdr); + if (nhdr->n_type != NT_ARM_TYPE_PAUTH_ABI_TAG) + reportError("invalid type field value " + Twine(nhdr->n_type) + " (" + + Twine(NT_ARM_TYPE_PAUTH_ABI_TAG) + " expected)"); + if (note.getName() != "ARM") + reportError("invalid name field value " + note.getName() + + " (ARM expected)"); + + ArrayRef desc = note.getDesc(sec.addralign); + if (desc.size() < 16) { + reportError("too short AArch64 PAuth compatibility info " + "(at least 16 bytes expected)"); + return; + } + + f.aarch64PauthAbiTag = SmallVector(iterator_range(desc)); +} + template InputSectionBase *ObjFile::getRelocTarget(uint32_t idx, const Elf_Shdr &sec, @@ -1020,6 +1058,12 @@ InputSectionBase *ObjFile::createInputSection(uint32_t idx, return &InputSection::discarded; } + if (config->emachine == EM_AARCH64 && + name == ".note.AARCH64-PAUTH-ABI-tag") { + readAArch64PauthAbiTag(InputSection(*this, sec, name), *this); + return &InputSection::discarded; + } + // Split stacks is a feature to support a discontiguous stack, // commonly used in the programming language Go. For the details, // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index ab98d78fcf145..6a74ba7fb2099 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -218,6 +218,7 @@ class ELFFileBase : public InputFile { public: uint32_t andFeatures = 0; bool hasCommonSyms = false; + SmallVector aarch64PauthAbiTag; }; // .o file. diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index fe3d7f419e84a..5b5e6b154d52f 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1444,6 +1444,32 @@ template void RelocationScanner::scanOne(RelTy *&i) { } } + if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { + // Assume relocations from relocatable objects are RELA. + assert(RelTy::IsRela); + std::lock_guard lock(relocMutex); + // For a preemptible symbol, we can't use a relative relocation. For an + // undefined symbol, we can't compute offset at link-time and use a relative + // relocation. Use a symbolic relocation instead. + Partition &part = sec->getPartition(); + if (sym.isPreemptible || sym.isUndefined()) { + part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type); + } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 && + isInt<32>(sym.getVA(addend))) { + // Implicit addend is below 32-bits so we can use the compressed + // relative relocation section. The R_AARCH64_AUTH_RELATIVE + // has a smaller addend fielf as bits [63:32] encode the signing-schema. + sec->addReloc({expr, type, offset, addend, &sym}); + part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back( + {sec, offset}); + } else { + part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, + DynamicReloc::AddendOnlyWithTargetVA, sym, addend, + R_ABS}); + } + return; + } + // If the relocation does not emit a GOT or GOTPLT entry but its computation // uses their addresses, we need GOT or GOTPLT to be created. // diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 2b32eb3a0fe35..fa7589806a7b5 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -331,6 +331,29 @@ void GnuPropertySection::writeTo(uint8_t *buf) { size_t GnuPropertySection::getSize() const { return config->is64 ? 32 : 28; } +AArch64PauthAbiTag::AArch64PauthAbiTag() + : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE, + config->wordsize, ".note.AARCH64-PAUTH-ABI-tag") {} + +bool AArch64PauthAbiTag::isNeeded() const { + return !ctx.aarch64PauthAbiTag.empty(); +} + +void AArch64PauthAbiTag::writeTo(uint8_t *buf) { + const SmallVector &data = ctx.aarch64PauthAbiTag; + write32(buf, 4); // Name size + write32(buf + 4, data.size()); // Content size + write32(buf + 8, NT_ARM_TYPE_PAUTH_ABI_TAG); // Type + memcpy(buf + 12, "ARM", 4); // Name string + memcpy(buf + 16, data.data(), data.size()); + memset(buf + 16 + data.size(), 0, getSize() - 16 - data.size()); // Padding +} + +size_t AArch64PauthAbiTag::getSize() const { + return alignToPowerOf2(16 + ctx.aarch64PauthAbiTag.size(), + config->is64 ? 8 : 4); +} + BuildIdSection::BuildIdSection() : SyntheticSection(SHF_ALLOC, SHT_NOTE, 4, ".note.gnu.build-id"), hashSize(getHashSize()) {} @@ -1406,6 +1429,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)); + } // .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 @@ -1717,10 +1746,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() { @@ -1988,8 +2020,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 3a9f4ba886f6b..d183a547c6820 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -144,6 +144,16 @@ class GnuPropertySection final : public SyntheticSection { size_t getSize() const override; }; +// .note.AARCH64-PAUTH-ABI-tag section. See +// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking +class AArch64PauthAbiTag final : public SyntheticSection { +public: + AArch64PauthAbiTag(); + void writeTo(uint8_t *buf) override; + size_t getSize() const override; + bool isNeeded() const override; +}; + // .note.gnu.build-id section. class BuildIdSection : public SyntheticSection { // First 16 bytes are a header. @@ -543,7 +553,8 @@ 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 || + d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR); } int32_t dynamicTag, sizeDynamicTag; SmallVector relocs; @@ -599,7 +610,7 @@ struct RelativeReloc { 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 +628,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 +1330,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; @@ -1363,6 +1375,7 @@ struct InStruct { std::unique_ptr strTab; std::unique_ptr symTab; std::unique_ptr symTabShndx; + std::unique_ptr aarch64PauthAbiTag; void reset(); }; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index a84e4864ab0e5..f1b569daada66 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -445,6 +445,12 @@ template void elf::createSyntheticSections() { add(*part.relrDyn); } + if (config->relrPackAuthDynRelocs) { + part.relrAuthDyn = std::make_unique>( + threadCount, /*isAArch64Auth=*/true); + add(*part.relrAuthDyn); + } + if (!config->relocatable) { if (config->ehFrameHdr) { part.ehFrameHdr = std::make_unique(); @@ -566,6 +572,11 @@ template void elf::createSyntheticSections() { if (config->andFeatures) add(*make()); + if (!ctx.aarch64PauthAbiTag.empty()) { + in.aarch64PauthAbiTag = std::make_unique(); + add(*in.aarch64PauthAbiTag); + } + // .note.GNU-stack is always added when we are creating a re-linkable // object file. Other linkers are using the presence of this marker // section to control the executable-ness of the stack area, but that @@ -1725,6 +1736,8 @@ template void Writer::finalizeAddressDependentContent() { changed |= part.relaDyn->updateAllocSize(); if (part.relrDyn) changed |= part.relrDyn->updateAllocSize(); + if (part.relrAuthDyn) + changed |= part.relrAuthDyn->updateAllocSize(); if (part.memtagDescriptors) changed |= part.memtagDescriptors->updateAllocSize(); } @@ -2179,6 +2192,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-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s new file mode 100644 index 0000000000000..0520b2f28631e --- /dev/null +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -0,0 +1,83 @@ +# REQUIRES: aarch64 + +# RUN: rm -rf %t && split-file %s %t && cd %t + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag1.s -o tag11.o +# RUN: cp tag11.o tag12.o +# RUN: ld.lld -shared tag11.o tag12.o -o tagok.so +# RUN: llvm-readelf -n tagok.so | FileCheck --check-prefix OK %s + +# OK: AArch64 PAuth ABI tag: platform 0x2a, version 0x1 + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o +# RUN: not ld.lld tag11.o tag12.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s + +# ERR1: error: incompatible values of AArch64 PAuth compatibility info found +# ERR1: {{.*}}: 0x2A000000000000000{{1|2}}00000000000000 +# ERR1: {{.*}}: 0x2A000000000000000{{1|2}}00000000000000 + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o +# RUN: not ld.lld errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s + +# ERR2: error: {{.*}}: invalid type field value 42 (1 expected) +# ERR2-NEXT: error: {{.*}}: invalid name field value XXX (ARM expected) +# ERR2-NEXT: error: {{.*}}: too short AArch64 PAuth compatibility info (at least 16 bytes expected) + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o short.o +# RUN: not ld.lld short.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR3 %s + +# ERR3: error: {{.*}}: section is too short + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu no-info.s -o noinfo1.o +# RUN: cp noinfo1.o noinfo2.o +# RUN: not ld.lld -z pauth-report=error tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s +# RUN: ld.lld -z pauth-report=warning tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s +# RUN: ld.lld -z pauth-report=none tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix NONE %s + +# ERR4: error: {{.*}}noinfo1.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it +# ERR4-NEXT: error: {{.*}}noinfo2.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it +# WARN: warning: {{.*}}noinfo1.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it +# WARN-NEXT: warning: {{.*}}noinfo2.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it +# NONE-NOT: {{.*}} has no AArch64 PAuth compatibility info while {{.*}} has one; either all or no input files must have it + +#--- abi-tag-short.s + +.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.long 4 +.long 8 + +#--- abi-tag-errs.s + +.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.long 4 +.long 8 +.long 42 +.asciz "XXX" + +.quad 42 + +#--- abi-tag1.s + +.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.long 4 +.long 16 +.long 1 +.asciz "ARM" + +.quad 42 // platform +.quad 1 // version + +#--- abi-tag2.s + +.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.long 4 +.long 16 +.long 1 +.asciz "ARM" + +.quad 42 // platform +.quad 2 // version + +#--- no-info.s + +.section ".test", "a" diff --git a/lld/test/ELF/aarch64-ptrauth.s b/lld/test/ELF/aarch64-ptrauth.s new file mode 100644 index 0000000000000..db946fc4c3e55 --- /dev/null +++ b/lld/test/ELF/aarch64-ptrauth.s @@ -0,0 +1,156 @@ +// REQUIRES: aarch64 + +// RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o +// RUN: ld.lld -shared %t.so.o -soname=so -o %t.so +// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +// RUN: ld.lld -pie -z nopack-relative-auth-relocs %t.o %t.so -o %t2 +// RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s + +// UNPACKED: Section ({{.+}}) .rela.dyn { +// UNPACKED-NEXT: 0x30680 R_AARCH64_AUTH_RELATIVE - 0x1 +// UNPACKED-NEXT: 0x30688 R_AARCH64_AUTH_RELATIVE - 0x2 +// UNPACKED-NEXT: 0x30690 R_AARCH64_AUTH_RELATIVE - 0x3 +// UNPACKED-NEXT: 0x30698 R_AARCH64_AUTH_RELATIVE - 0x4 +// UNPACKED-NEXT: 0x306A0 R_AARCH64_AUTH_RELATIVE - 0x5 +// UNPACKED-NEXT: 0x306A8 R_AARCH64_AUTH_RELATIVE - 0x6 +// UNPACKED-NEXT: 0x306B0 R_AARCH64_AUTH_RELATIVE - 0x7 +// UNPACKED-NEXT: 0x306B8 R_AARCH64_AUTH_RELATIVE - 0x8 +// UNPACKED-NEXT: 0x306C8 R_AARCH64_AUTH_RELATIVE - 0x1 +// UNPACKED-NEXT: 0x306D0 R_AARCH64_AUTH_RELATIVE - 0x2 +// UNPACKED-NEXT: 0x306D8 R_AARCH64_AUTH_RELATIVE - 0x3 +// UNPACKED-NEXT: 0x306E0 R_AARCH64_AUTH_RELATIVE - 0x4 +// UNPACKED-NEXT: 0x306E8 R_AARCH64_AUTH_RELATIVE - 0x5 +// UNPACKED-NEXT: 0x306F0 R_AARCH64_AUTH_RELATIVE - 0x6 +// UNPACKED-NEXT: 0x306F8 R_AARCH64_AUTH_RELATIVE - 0x7 +// UNPACKED-NEXT: 0x30710 R_AARCH64_AUTH_RELATIVE - 0x1 +// UNPACKED-NEXT: 0x30718 R_AARCH64_AUTH_RELATIVE - 0x2 +// UNPACKED-NEXT: 0x30720 R_AARCH64_AUTH_RELATIVE - 0x3 +// UNPACKED-NEXT: 0x30728 R_AARCH64_AUTH_RELATIVE - 0x4 +// UNPACKED-NEXT: 0x30730 R_AARCH64_AUTH_RELATIVE - 0x5 +// UNPACKED-NEXT: 0x30738 R_AARCH64_AUTH_RELATIVE - 0x6 +// UNPACKED-NEXT: 0x30740 R_AARCH64_AUTH_RELATIVE - 0x7 +// UNPACKED-NEXT: 0x30748 R_AARCH64_AUTH_RELATIVE - 0x8 +// UNPACKED-NEXT: 0x30750 R_AARCH64_AUTH_RELATIVE - 0x9 +// UNPACKED-NEXT: 0x30759 R_AARCH64_AUTH_RELATIVE - 0xA +// UNPACKED-NEXT: 0x306C0 R_AARCH64_AUTH_ABS64 bar2 0x1 +// UNPACKED-NEXT: 0x30708 R_AARCH64_AUTH_ABS64 bar2 0x0 +// UNPACKED-NEXT: 0x30761 R_AARCH64_AUTH_ABS64 bar2 0x0 +// UNPACKED-NEXT: 0x30769 R_AARCH64_AUTH_ABS64 bar2 0x0 +// UNPACKED-NEXT: 0x30771 R_AARCH64_AUTH_ABS64 bar2 0x1 +// UNPACKED-NEXT: 0x30779 R_AARCH64_AUTH_ABS64 bar2 0x1 +// UNPACKED-NEXT: 0x30781 R_AARCH64_AUTH_ABS64 bar2 0x0 +// UNPACKED-NEXT: 0x30700 R_AARCH64_AUTH_ABS64 zed2 0x0 +// UNPACKED-NEXT: } + +// RUN: ld.lld -pie -z pack-relative-auth-relocs %t.o %t.so -o %t2 +// RUN: llvm-readobj -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s +// RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s +// RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s + +// RELR-HEADERS: Index: 1 +// RELR-HEADERS-NEXT: Name: .dynsym + +// RELR-HEADERS: Name: .relr.auth.dyn +// RELR-HEADERS-NEXT: Type: SHT_AARCH64_AUTH_RELR +// RELR-HEADERS-NEXT: Flags [ (0x2) +// RELR-HEADERS-NEXT: SHF_ALLOC (0x2) +// RELR-HEADERS-NEXT: ] +// RELR-HEADERS-NEXT: Address: [[ADDR:.*]] +// RELR-HEADERS-NEXT: Offset: [[ADDR]] +// RELR-HEADERS-NEXT: Size: 16 +// RELR-HEADERS-NEXT: Link: 0 +// RELR-HEADERS-NEXT: Info: 0 +// RELR-HEADERS-NEXT: AddressAlignment: 8 +// RELR-HEADERS-NEXT: EntrySize: 8 + +// RELR-HEADERS: 0x0000000070000012 AARCH64_AUTH_RELR [[ADDR]] +// RELR-HEADERS: 0x0000000070000011 AARCH64_AUTH_RELRSZ 16 (bytes) +// RELR-HEADERS: 0x0000000070000013 AARCH64_AUTH_RELRENT 8 (bytes) + +/// SHT_RELR section contains address/bitmap entries +/// encoding the offsets for relative relocation. +// RAW-RELR: Section ({{.+}}) .relr.auth.dyn { +// RAW-RELR-NEXT: 0x30480 +// RAW-RELR-NEXT: 0x7FCFEFF +// RAW-RELR-NEXT: } + +/// Decoded SHT_RELR section is same as UNPACKED, +/// but contains only the relative relocations. +/// Any relative relocations with odd offset stay in SHT_RELA. + +// RELR: Section ({{.+}}) .rela.dyn { +// RELR-NEXT: 0x30559 R_AARCH64_AUTH_RELATIVE - 0xA +// RELR-NEXT: 0x304C0 R_AARCH64_AUTH_ABS64 bar2 0x1 +// RELR-NEXT: 0x30508 R_AARCH64_AUTH_ABS64 bar2 0x0 +// RELR-NEXT: 0x30561 R_AARCH64_AUTH_ABS64 bar2 0x0 +// RELR-NEXT: 0x30569 R_AARCH64_AUTH_ABS64 bar2 0x0 +// RELR-NEXT: 0x30571 R_AARCH64_AUTH_ABS64 bar2 0x1 +// RELR-NEXT: 0x30579 R_AARCH64_AUTH_ABS64 bar2 0x1 +// RELR-NEXT: 0x30581 R_AARCH64_AUTH_ABS64 bar2 0x0 +// RELR-NEXT: 0x30500 R_AARCH64_AUTH_ABS64 zed2 0x0 +// RELR-NEXT: } +// RELR-NEXT: Section ({{.+}}) .relr.auth.dyn { +// RELR-NEXT: 0x30480 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30488 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30490 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30498 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304A0 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304A8 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304B0 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304B8 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304C8 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304D0 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304D8 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304E0 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304E8 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304F0 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x304F8 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30510 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30518 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30520 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30528 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30530 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30538 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30540 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30548 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x30550 R_AARCH64_RELATIVE - +// RELR-NEXT: } + +.section .test, "aw" +.p2align 3 +.quad (__ehdr_start + 1)@AUTH(da,42) +.quad (__ehdr_start + 2)@AUTH(da,42) +.quad (__ehdr_start + 3)@AUTH(da,42) +.quad (__ehdr_start + 4)@AUTH(da,42) +.quad (__ehdr_start + 5)@AUTH(da,42) +.quad (__ehdr_start + 6)@AUTH(da,42) +.quad (__ehdr_start + 7)@AUTH(da,42) +.quad (__ehdr_start + 8)@AUTH(da,42) +.quad (bar2 + 1)@AUTH(ia,42) + +.quad (__ehdr_start + 1)@AUTH(da,65535) +.quad (__ehdr_start + 2)@AUTH(da,65535) +.quad (__ehdr_start + 3)@AUTH(da,65535) +.quad (__ehdr_start + 4)@AUTH(da,65535) +.quad (__ehdr_start + 5)@AUTH(da,65535) +.quad (__ehdr_start + 6)@AUTH(da,65535) +.quad (__ehdr_start + 7)@AUTH(da,65535) +.quad zed2@AUTH(da,42) +.quad bar2@AUTH(ia,42) + +.quad (__ehdr_start + 1)@AUTH(da,0) +.quad (__ehdr_start + 2)@AUTH(da,0) +.quad (__ehdr_start + 3)@AUTH(da,0) +.quad (__ehdr_start + 4)@AUTH(da,0) +.quad (__ehdr_start + 5)@AUTH(da,0) +.quad (__ehdr_start + 6)@AUTH(da,0) +.quad (__ehdr_start + 7)@AUTH(da,0) +.quad (__ehdr_start + 8)@AUTH(da,0) +.quad (__ehdr_start + 9)@AUTH(da,0) +.byte 00 +.quad (__ehdr_start + 10)@AUTH(da,0) +.quad bar2@AUTH(ia,42) +.quad bar2@AUTH(ia,42) +.quad (bar2 + 1)@AUTH(ia,42) +.quad (bar2 + 1)@AUTH(ia,42) +.quad bar2@AUTH(ia,42) From 589c6455a929f41ed3a79fc7d91119586eb1ee7b Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 12 Dec 2023 09:05:38 +0300 Subject: [PATCH 02/34] Address trivial review comments --- lld/ELF/Driver.cpp | 46 ++++++++++++------------ lld/ELF/InputFiles.cpp | 2 +- lld/test/ELF/aarch64-bti-pac-cli-error.s | 15 +++++--- lld/test/ELF/aarch64-feature-pauth.s | 2 +- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 4e8e9eb86ecf7..ca5a8b8d994a4 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2648,44 +2648,44 @@ static uint32_t getAndFeatures() { return ret; } -static void getAarch64PauthInfo() { +static void getAArch64PauthInfo() { if (ctx.objectFiles.empty()) return; - auto NonEmptyIt = std::find_if( + auto it = std::find_if( ctx.objectFiles.begin(), ctx.objectFiles.end(), [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); }); - if (NonEmptyIt == ctx.objectFiles.end()) + if (it == ctx.objectFiles.end()) return; - ctx.aarch64PauthAbiTag = (*NonEmptyIt)->aarch64PauthAbiTag; - StringRef F1 = (*NonEmptyIt)->getName(); - for (ELFFileBase *F : ArrayRef(ctx.objectFiles)) { - StringRef F2 = F->getName(); - const SmallVector &D1 = ctx.aarch64PauthAbiTag; - const SmallVector &D2 = F->aarch64PauthAbiTag; - if (D1.empty() != D2.empty()) { - auto Helper = [](StringRef Report, const Twine &Msg) { - if (Report == "warning") - warn(Msg); - else if (Report == "error") - error(Msg); + ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag; + StringRef f1 = (*it)->getName(); + for (ELFFileBase *f : ArrayRef(ctx.objectFiles)) { + StringRef f2 = f->getName(); + const SmallVector &d1 = ctx.aarch64PauthAbiTag; + const SmallVector &d2 = f->aarch64PauthAbiTag; + if (d1.empty() != d2.empty()) { + auto helper = [](StringRef report, const Twine &msg) { + if (report == "warning") + warn(msg); + else if (report == "error") + error(msg); }; - Helper(config->zPauthReport, - (D1.empty() ? F1.str() : F2.str()) + + helper(config->zPauthReport, + (d1.empty() ? f1.str() : f2.str()) + " has no AArch64 PAuth compatibility info while " + - (D1.empty() ? F2.str() : F1.str()) + + (d1.empty() ? f2.str() : f1.str()) + " has one; either all or no input files must have it"); } - if (!D1.empty() && !D2.empty() && - !std::equal(D1.begin(), D1.end(), D2.begin(), D2.end())) + if (!d1.empty() && !d2.empty() && + !std::equal(d1.begin(), d1.end(), d2.begin(), d2.end())) errorOrWarn( "incompatible values of AArch64 PAuth compatibility info found" "\n" + - F1 + ": 0x" + toHex(ArrayRef(D1.data(), D1.size())) + "\n" + F2 + - ": 0x" + toHex(ArrayRef(D2.data(), D2.size()))); + f1 + ": 0x" + toHex(ArrayRef(d1.data(), d1.size())) + "\n" + f2 + + ": 0x" + toHex(ArrayRef(d2.data(), d2.size()))); } } @@ -3027,7 +3027,7 @@ void LinkerDriver::link(opt::InputArgList &args) { config->andFeatures = getAndFeatures(); if (config->emachine == EM_AARCH64) - getAarch64PauthInfo(); + getAArch64PauthInfo(); // The Target instance handles target-specific stuff, such as applying // relocations or writing a PLT section. It also contains target-dependent diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 44c8050f2c967..d7ceaf476cf9b 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -992,7 +992,7 @@ static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile &f) { ArrayRef desc = note.getDesc(sec.addralign); if (desc.size() < 16) { - reportError("too short AArch64 PAuth compatibility info " + reportError("AArch64 PAuth compatibility info is too short " "(at least 16 bytes expected)"); return; } diff --git a/lld/test/ELF/aarch64-bti-pac-cli-error.s b/lld/test/ELF/aarch64-bti-pac-cli-error.s index b8ab1a28fa5a8..703c0aac6ea5a 100644 --- a/lld/test/ELF/aarch64-bti-pac-cli-error.s +++ b/lld/test/ELF/aarch64-bti-pac-cli-error.s @@ -1,17 +1,22 @@ # REQUIRES: x86 # RUN: llvm-mc --triple=x86_64-pc-linux --filetype=obj -o %t.o %s -# RUN: not ld.lld -z pac-plt -z force-bti -z bti-report=error %t.o -o /dev/null 2>&1 | FileCheck %s +# RUN: not ld.lld -z pac-plt -z force-bti -z bti-report=error \ +# RUN: -z pauth-report=error %t.o -o /dev/null 2>&1 | FileCheck %s +# RUN: not ld.lld -z pac-plt -z force-bti -z bti-report=warning \ +# RUN: -z pauth-report=warning %t.o -o /dev/null 2>&1 | FileCheck %s # -## Check that we error if -z pac-plt, -z force-bti and -z bti-report=error are used when target is not -## aarch64 +## Check that we error if -z pac-plt, -z force-bti are present and +## -z bti-report and -z pauth-report are not none when target is not aarch64 # CHECK: error: -z pac-plt only supported on AArch64 # CHECK-NEXT: error: -z force-bti only supported on AArch64 # CHECK-NEXT: error: -z bti-report only supported on AArch64 +# CHECK-NEXT: error: -z pauth-report only supported on AArch64 -# RUN: not ld.lld -z bti-report=something %t.o -o /dev/null 2>&1 | \ -# RUN: FileCheck --check-prefix=REPORT_INVALID %s +# RUN: not ld.lld -z bti-report=something -z pauth-report=something \ +# RUN: %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=REPORT_INVALID %s # REPORT_INVALID: error: -z bti-report= parameter something is not recognized +# REPORT_INVALID: error: -z pauth-report= parameter something is not recognized # REPORT_INVALID-EMPTY: .globl start diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 0520b2f28631e..9060eb71f8175 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -21,7 +21,7 @@ # ERR2: error: {{.*}}: invalid type field value 42 (1 expected) # ERR2-NEXT: error: {{.*}}: invalid name field value XXX (ARM expected) -# ERR2-NEXT: error: {{.*}}: too short AArch64 PAuth compatibility info (at least 16 bytes expected) +# ERR2-NEXT: error: {{.*}}: AArch64 PAuth compatibility info is too short (at least 16 bytes expected) # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o short.o # RUN: not ld.lld short.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR3 %s From d3411595fbbe37a14b0187ff0d134bd105892931 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 9 Jan 2024 21:53:00 +0300 Subject: [PATCH 03/34] Use `pack-relative-relocs` for both regular and auth relr relocs --- lld/ELF/Config.h | 1 - lld/ELF/Driver.cpp | 3 --- lld/ELF/Writer.cpp | 3 --- lld/test/ELF/aarch64-ptrauth.s | 4 ++-- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 1b633a7984276..e2a3cb2a61e93 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -276,7 +276,6 @@ struct Config { bool relocatable; bool relrGlibc = false; bool relrPackDynRelocs = false; - bool relrPackAuthDynRelocs = false; llvm::DenseSet saveTempsArgs; llvm::SmallVector, 0> shuffleSections; bool singleRoRx; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index ca5a8b8d994a4..6ab93c74bc645 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1677,9 +1677,6 @@ static void readConfigs(opt::InputArgList &args) { getPackDynRelocs(args); } - config->relrPackAuthDynRelocs = getZFlag( - args, "pack-relative-auth-relocs", "nopack-relative-auth-relocs", false); - if (auto *arg = args.getLastArg(OPT_symbol_ordering_file)){ if (args.hasArg(OPT_call_graph_ordering_file)) error("--symbol-ordering-file and --call-graph-order-file " diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index af2544c3fa0f7..81e743d67dabd 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -450,9 +450,6 @@ template void elf::createSyntheticSections() { if (config->relrPackDynRelocs) { part.relrDyn = std::make_unique>(threadCount); add(*part.relrDyn); - } - - if (config->relrPackAuthDynRelocs) { part.relrAuthDyn = std::make_unique>( threadCount, /*isAArch64Auth=*/true); add(*part.relrAuthDyn); diff --git a/lld/test/ELF/aarch64-ptrauth.s b/lld/test/ELF/aarch64-ptrauth.s index db946fc4c3e55..26cc2d779e748 100644 --- a/lld/test/ELF/aarch64-ptrauth.s +++ b/lld/test/ELF/aarch64-ptrauth.s @@ -3,7 +3,7 @@ // RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o // RUN: ld.lld -shared %t.so.o -soname=so -o %t.so // RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o -// RUN: ld.lld -pie -z nopack-relative-auth-relocs %t.o %t.so -o %t2 +// RUN: ld.lld -pie -z nopack-relative-relocs %t.o %t.so -o %t2 // RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s // UNPACKED: Section ({{.+}}) .rela.dyn { @@ -42,7 +42,7 @@ // UNPACKED-NEXT: 0x30700 R_AARCH64_AUTH_ABS64 zed2 0x0 // UNPACKED-NEXT: } -// RUN: ld.lld -pie -z pack-relative-auth-relocs %t.o %t.so -o %t2 +// RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2 // RUN: llvm-readobj -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s // RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s // RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s From b791da9dd02f8b3bf59d2d235181f945844d3039 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 9 Jan 2024 21:59:35 +0300 Subject: [PATCH 04/34] Rename aarch64-ptrauth.s to aarch64-reloc-pauth.s --- lld/test/ELF/{aarch64-ptrauth.s => aarch64-reloc-pauth.s} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lld/test/ELF/{aarch64-ptrauth.s => aarch64-reloc-pauth.s} (100%) diff --git a/lld/test/ELF/aarch64-ptrauth.s b/lld/test/ELF/aarch64-reloc-pauth.s similarity index 100% rename from lld/test/ELF/aarch64-ptrauth.s rename to lld/test/ELF/aarch64-reloc-pauth.s From b95dcf8e7cd9c3c162a25c93a9c2b09ba8bb124c Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 9 Jan 2024 22:23:16 +0300 Subject: [PATCH 05/34] Remove unneeded test directives --- lld/test/ELF/aarch64-reloc-pauth.s | 114 +++-------------------------- 1 file changed, 12 insertions(+), 102 deletions(-) diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index 26cc2d779e748..79e6e4246cc45 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -7,39 +7,10 @@ // RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s // UNPACKED: Section ({{.+}}) .rela.dyn { -// UNPACKED-NEXT: 0x30680 R_AARCH64_AUTH_RELATIVE - 0x1 -// UNPACKED-NEXT: 0x30688 R_AARCH64_AUTH_RELATIVE - 0x2 -// UNPACKED-NEXT: 0x30690 R_AARCH64_AUTH_RELATIVE - 0x3 -// UNPACKED-NEXT: 0x30698 R_AARCH64_AUTH_RELATIVE - 0x4 -// UNPACKED-NEXT: 0x306A0 R_AARCH64_AUTH_RELATIVE - 0x5 -// UNPACKED-NEXT: 0x306A8 R_AARCH64_AUTH_RELATIVE - 0x6 -// UNPACKED-NEXT: 0x306B0 R_AARCH64_AUTH_RELATIVE - 0x7 -// UNPACKED-NEXT: 0x306B8 R_AARCH64_AUTH_RELATIVE - 0x8 -// UNPACKED-NEXT: 0x306C8 R_AARCH64_AUTH_RELATIVE - 0x1 -// UNPACKED-NEXT: 0x306D0 R_AARCH64_AUTH_RELATIVE - 0x2 -// UNPACKED-NEXT: 0x306D8 R_AARCH64_AUTH_RELATIVE - 0x3 -// UNPACKED-NEXT: 0x306E0 R_AARCH64_AUTH_RELATIVE - 0x4 -// UNPACKED-NEXT: 0x306E8 R_AARCH64_AUTH_RELATIVE - 0x5 -// UNPACKED-NEXT: 0x306F0 R_AARCH64_AUTH_RELATIVE - 0x6 -// UNPACKED-NEXT: 0x306F8 R_AARCH64_AUTH_RELATIVE - 0x7 -// UNPACKED-NEXT: 0x30710 R_AARCH64_AUTH_RELATIVE - 0x1 -// UNPACKED-NEXT: 0x30718 R_AARCH64_AUTH_RELATIVE - 0x2 -// UNPACKED-NEXT: 0x30720 R_AARCH64_AUTH_RELATIVE - 0x3 -// UNPACKED-NEXT: 0x30728 R_AARCH64_AUTH_RELATIVE - 0x4 -// UNPACKED-NEXT: 0x30730 R_AARCH64_AUTH_RELATIVE - 0x5 -// UNPACKED-NEXT: 0x30738 R_AARCH64_AUTH_RELATIVE - 0x6 -// UNPACKED-NEXT: 0x30740 R_AARCH64_AUTH_RELATIVE - 0x7 -// UNPACKED-NEXT: 0x30748 R_AARCH64_AUTH_RELATIVE - 0x8 -// UNPACKED-NEXT: 0x30750 R_AARCH64_AUTH_RELATIVE - 0x9 -// UNPACKED-NEXT: 0x30759 R_AARCH64_AUTH_RELATIVE - 0xA -// UNPACKED-NEXT: 0x306C0 R_AARCH64_AUTH_ABS64 bar2 0x1 -// UNPACKED-NEXT: 0x30708 R_AARCH64_AUTH_ABS64 bar2 0x0 -// UNPACKED-NEXT: 0x30761 R_AARCH64_AUTH_ABS64 bar2 0x0 -// UNPACKED-NEXT: 0x30769 R_AARCH64_AUTH_ABS64 bar2 0x0 -// UNPACKED-NEXT: 0x30771 R_AARCH64_AUTH_ABS64 bar2 0x1 -// UNPACKED-NEXT: 0x30779 R_AARCH64_AUTH_ABS64 bar2 0x1 -// UNPACKED-NEXT: 0x30781 R_AARCH64_AUTH_ABS64 bar2 0x0 -// UNPACKED-NEXT: 0x30700 R_AARCH64_AUTH_ABS64 zed2 0x0 +// UNPACKED-NEXT: 0x303C8 R_AARCH64_AUTH_RELATIVE - 0x1 +// UNPACKED-NEXT: 0x303E1 R_AARCH64_AUTH_RELATIVE - 0x2 +// UNPACKED-NEXT: 0x303D0 R_AARCH64_AUTH_ABS64 zed2 0x0 +// UNPACKED-NEXT: 0x303D8 R_AARCH64_AUTH_ABS64 bar2 0x0 // UNPACKED-NEXT: } // RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2 @@ -57,21 +28,20 @@ // RELR-HEADERS-NEXT: ] // RELR-HEADERS-NEXT: Address: [[ADDR:.*]] // RELR-HEADERS-NEXT: Offset: [[ADDR]] -// RELR-HEADERS-NEXT: Size: 16 +// RELR-HEADERS-NEXT: Size: 8 // RELR-HEADERS-NEXT: Link: 0 // RELR-HEADERS-NEXT: Info: 0 // RELR-HEADERS-NEXT: AddressAlignment: 8 // RELR-HEADERS-NEXT: EntrySize: 8 // RELR-HEADERS: 0x0000000070000012 AARCH64_AUTH_RELR [[ADDR]] -// RELR-HEADERS: 0x0000000070000011 AARCH64_AUTH_RELRSZ 16 (bytes) +// RELR-HEADERS: 0x0000000070000011 AARCH64_AUTH_RELRSZ 8 (bytes) // RELR-HEADERS: 0x0000000070000013 AARCH64_AUTH_RELRENT 8 (bytes) /// SHT_RELR section contains address/bitmap entries /// encoding the offsets for relative relocation. // RAW-RELR: Section ({{.+}}) .relr.auth.dyn { -// RAW-RELR-NEXT: 0x30480 -// RAW-RELR-NEXT: 0x7FCFEFF +// RAW-RELR-NEXT: 0x303E8 // RAW-RELR-NEXT: } /// Decoded SHT_RELR section is same as UNPACKED, @@ -79,78 +49,18 @@ /// Any relative relocations with odd offset stay in SHT_RELA. // RELR: Section ({{.+}}) .rela.dyn { -// RELR-NEXT: 0x30559 R_AARCH64_AUTH_RELATIVE - 0xA -// RELR-NEXT: 0x304C0 R_AARCH64_AUTH_ABS64 bar2 0x1 -// RELR-NEXT: 0x30508 R_AARCH64_AUTH_ABS64 bar2 0x0 -// RELR-NEXT: 0x30561 R_AARCH64_AUTH_ABS64 bar2 0x0 -// RELR-NEXT: 0x30569 R_AARCH64_AUTH_ABS64 bar2 0x0 -// RELR-NEXT: 0x30571 R_AARCH64_AUTH_ABS64 bar2 0x1 -// RELR-NEXT: 0x30579 R_AARCH64_AUTH_ABS64 bar2 0x1 -// RELR-NEXT: 0x30581 R_AARCH64_AUTH_ABS64 bar2 0x0 -// RELR-NEXT: 0x30500 R_AARCH64_AUTH_ABS64 zed2 0x0 +// RELR-NEXT: 0x30401 R_AARCH64_AUTH_RELATIVE - 0x2 +// RELR-NEXT: 0x303F0 R_AARCH64_AUTH_ABS64 zed2 0x0 +// RELR-NEXT: 0x303F8 R_AARCH64_AUTH_ABS64 bar2 0x0 // RELR-NEXT: } // RELR-NEXT: Section ({{.+}}) .relr.auth.dyn { -// RELR-NEXT: 0x30480 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30488 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30490 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30498 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304A0 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304A8 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304B0 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304B8 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304C8 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304D0 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304D8 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304E0 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304E8 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304F0 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x304F8 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30510 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30518 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30520 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30528 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30530 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30538 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30540 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30548 R_AARCH64_RELATIVE - -// RELR-NEXT: 0x30550 R_AARCH64_RELATIVE - +// RELR-NEXT: 0x303E8 R_AARCH64_RELATIVE - // RELR-NEXT: } .section .test, "aw" .p2align 3 .quad (__ehdr_start + 1)@AUTH(da,42) -.quad (__ehdr_start + 2)@AUTH(da,42) -.quad (__ehdr_start + 3)@AUTH(da,42) -.quad (__ehdr_start + 4)@AUTH(da,42) -.quad (__ehdr_start + 5)@AUTH(da,42) -.quad (__ehdr_start + 6)@AUTH(da,42) -.quad (__ehdr_start + 7)@AUTH(da,42) -.quad (__ehdr_start + 8)@AUTH(da,42) -.quad (bar2 + 1)@AUTH(ia,42) - -.quad (__ehdr_start + 1)@AUTH(da,65535) -.quad (__ehdr_start + 2)@AUTH(da,65535) -.quad (__ehdr_start + 3)@AUTH(da,65535) -.quad (__ehdr_start + 4)@AUTH(da,65535) -.quad (__ehdr_start + 5)@AUTH(da,65535) -.quad (__ehdr_start + 6)@AUTH(da,65535) -.quad (__ehdr_start + 7)@AUTH(da,65535) .quad zed2@AUTH(da,42) .quad bar2@AUTH(ia,42) - -.quad (__ehdr_start + 1)@AUTH(da,0) -.quad (__ehdr_start + 2)@AUTH(da,0) -.quad (__ehdr_start + 3)@AUTH(da,0) -.quad (__ehdr_start + 4)@AUTH(da,0) -.quad (__ehdr_start + 5)@AUTH(da,0) -.quad (__ehdr_start + 6)@AUTH(da,0) -.quad (__ehdr_start + 7)@AUTH(da,0) -.quad (__ehdr_start + 8)@AUTH(da,0) -.quad (__ehdr_start + 9)@AUTH(da,0) .byte 00 -.quad (__ehdr_start + 10)@AUTH(da,0) -.quad bar2@AUTH(ia,42) -.quad bar2@AUTH(ia,42) -.quad (bar2 + 1)@AUTH(ia,42) -.quad (bar2 + 1)@AUTH(ia,42) -.quad bar2@AUTH(ia,42) +.quad (__ehdr_start + 2)@AUTH(da,42) From 594f8a0e8331b5d11f3efc58fcaa7eae4b9fd7b4 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Thu, 11 Jan 2024 03:19:14 +0300 Subject: [PATCH 06/34] Do not emit AUTH relocations in read-only sections --- lld/ELF/Relocations.cpp | 85 +++++++++++++++++++-------- lld/test/ELF/aarch64-reloc-pauth-ro.s | 21 +++++++ 2 files changed, 80 insertions(+), 26 deletions(-) create mode 100644 lld/test/ELF/aarch64-reloc-pauth-ro.s diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 166407d573252..53f638ae2f854 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1125,11 +1125,37 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, (isa(sec) && config->emachine != EM_MIPS)); if (canWrite) { RelType rel = target->getDynRel(type); + if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { + // Assume relocations from relocatable objects are RELA. + assert(config->isRela); + std::lock_guard lock(relocMutex); + // For a preemptible symbol, we can't use a relative relocation. For an + // undefined symbol, we can't compute offset at link-time and use a + // relative relocation. Use a symbolic relocation instead. + Partition &part = sec->getPartition(); + if (sym.isPreemptible || sym.isUndefined()) { + part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type); + } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 && + isInt<32>(sym.getVA(addend))) { + // Implicit addend is below 32-bits so we can use the compressed + // relative relocation section. The R_AARCH64_AUTH_RELATIVE + // has a smaller addend field as bits [63:32] encode the signing-schema. + sec->addReloc({expr, type, offset, addend, &sym}); + part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back( + {sec, offset}); + } else { + part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, + DynamicReloc::AddendOnlyWithTargetVA, sym, + addend, R_ABS}); + } + return; + } if (oneof(expr) || (rel == target->symbolicRel && !sym.isPreemptible)) { addRelativeReloc(*sec, offset, sym, addend, expr, type); return; - } else if (rel != 0) { + } + if (rel != 0) { if (config->emachine == EM_MIPS && rel == target->symbolicRel) rel = target->relativeRel; std::lock_guard lock(relocMutex); @@ -1157,6 +1183,12 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, } } + if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { + error("relocation " + toString(type) + " against symbol '" + toString(sym) + + "'" + " in read-only section" + getLocation(*sec, sym, offset)); + return; + } + // When producing an executable, we can perform copy relocations (for // STT_OBJECT) and canonical PLT (for STT_FUNC) if sym is defined by a DSO. if (!config->shared && sym.isShared()) { @@ -1444,31 +1476,32 @@ template void RelocationScanner::scanOne(RelTy *&i) { } } - if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { - // Assume relocations from relocatable objects are RELA. - assert(RelTy::IsRela); - std::lock_guard lock(relocMutex); - // For a preemptible symbol, we can't use a relative relocation. For an - // undefined symbol, we can't compute offset at link-time and use a relative - // relocation. Use a symbolic relocation instead. - Partition &part = sec->getPartition(); - if (sym.isPreemptible || sym.isUndefined()) { - part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type); - } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 && - isInt<32>(sym.getVA(addend))) { - // Implicit addend is below 32-bits so we can use the compressed - // relative relocation section. The R_AARCH64_AUTH_RELATIVE - // has a smaller addend fielf as bits [63:32] encode the signing-schema. - sec->addReloc({expr, type, offset, addend, &sym}); - part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back( - {sec, offset}); - } else { - part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, - DynamicReloc::AddendOnlyWithTargetVA, sym, addend, - R_ABS}); - } - return; - } + // if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { + // // Assume relocations from relocatable objects are RELA. + // assert(RelTy::IsRela); + // std::lock_guard lock(relocMutex); + // // For a preemptible symbol, we can't use a relative relocation. For an + // // undefined symbol, we can't compute offset at link-time and use a + // relative + // // relocation. Use a symbolic relocation instead. + // Partition &part = sec->getPartition(); + // if (sym.isPreemptible || sym.isUndefined()) { + // part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type); + // } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 && + // isInt<32>(sym.getVA(addend))) { + // // Implicit addend is below 32-bits so we can use the compressed + // // relative relocation section. The R_AARCH64_AUTH_RELATIVE + // // has a smaller addend fielf as bits [63:32] encode the + // signing-schema. sec->addReloc({expr, type, offset, addend, &sym}); + // part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back( + // {sec, offset}); + // } else { + // part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, + // DynamicReloc::AddendOnlyWithTargetVA, sym, + // addend, R_ABS}); + // } + // return; + // } // If the relocation does not emit a GOT or GOTPLT entry but its computation // uses their addresses, we need GOT or GOTPLT to be created. diff --git a/lld/test/ELF/aarch64-reloc-pauth-ro.s b/lld/test/ELF/aarch64-reloc-pauth-ro.s new file mode 100644 index 0000000000000..80afb921a5c26 --- /dev/null +++ b/lld/test/ELF/aarch64-reloc-pauth-ro.s @@ -0,0 +1,21 @@ +// REQUIRES: aarch64 + +// RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o +// RUN: ld.lld -shared %t.so.o -soname=so -o %t.so +// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +// RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck %s + +// CHECK: error: relocation R_AARCH64_AUTH_ABS64 against symbol 'zed2' in read-only section +// CHECK-NEXT: defined in +// CHECK-NEXT: referenced by +// CHECK-SAME: :(.test+0x0) + +// CHECK: error: relocation R_AARCH64_AUTH_ABS64 against symbol 'bar2' in read-only section +// CHECK-NEXT: defined in +// CHECK-NEXT: referenced by +// CHECK-SAME: :(.test+0x8) + +.section .test, "a" +.p2align 3 +.quad zed2@AUTH(da,42) +.quad bar2@AUTH(ia,42) From acb1730e74ce0ca8c55960018318e9943ec66bfd Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 31 Jan 2024 21:38:05 +0300 Subject: [PATCH 07/34] Apply fix from 37efa70 accidently deleted in d793c0c --- lld/ELF/Driver.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index f17ec7759482c..faf7dcd2d5e81 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -563,6 +563,7 @@ static void checkZOptions(opt::InputArgList &args) { // initialized yet. Claim them here. args::getZOptionValue(args, OPT_z, "max-page-size", 0); args::getZOptionValue(args, OPT_z, "common-page-size", 0); + getZFlag(args, "rel", "rela", false); for (auto *arg : args.filtered(OPT_z)) if (!arg->isClaimed()) warn("unknown -z value: " + StringRef(arg->getValue())); From de73eae53481bb805fbabe97a38055ebaad934de Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 31 Jan 2024 21:39:46 +0300 Subject: [PATCH 08/34] Address review comments --- lld/ELF/Relocations.cpp | 27 --------------------------- lld/ELF/SyntheticSections.h | 3 ++- lld/test/ELF/aarch64-feature-pauth.s | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 38 deletions(-) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 6e8191f7b4f55..16ab213b60234 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1493,33 +1493,6 @@ template void RelocationScanner::scanOne(RelTy *&i) { } } - // if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { - // // Assume relocations from relocatable objects are RELA. - // assert(RelTy::IsRela); - // std::lock_guard lock(relocMutex); - // // For a preemptible symbol, we can't use a relative relocation. For an - // // undefined symbol, we can't compute offset at link-time and use a - // relative - // // relocation. Use a symbolic relocation instead. - // Partition &part = sec->getPartition(); - // if (sym.isPreemptible || sym.isUndefined()) { - // part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type); - // } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 && - // isInt<32>(sym.getVA(addend))) { - // // Implicit addend is below 32-bits so we can use the compressed - // // relative relocation section. The R_AARCH64_AUTH_RELATIVE - // // has a smaller addend fielf as bits [63:32] encode the - // signing-schema. sec->addReloc({expr, type, offset, addend, &sym}); - // part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back( - // {sec, offset}); - // } else { - // part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, - // DynamicReloc::AddendOnlyWithTargetVA, sym, - // addend, R_ABS}); - // } - // return; - // } - // If the relocation does not emit a GOT or GOTPLT entry but its computation // uses their addresses, we need GOT or GOTPLT to be created. // diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 79fe636cc09ef..c36f08e26c2a7 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -554,7 +554,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 || - d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR); + (config->emachine == llvm::ELF::EM_AARCH64 && + d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR)); } int32_t dynamicTag, sizeDynamicTag; SmallVector relocs; diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 9060eb71f8175..4d1b9d9164004 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -13,20 +13,20 @@ # RUN: not ld.lld tag11.o tag12.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s # ERR1: error: incompatible values of AArch64 PAuth compatibility info found -# ERR1: {{.*}}: 0x2A000000000000000{{1|2}}00000000000000 -# ERR1: {{.*}}: 0x2A000000000000000{{1|2}}00000000000000 +# ERR1: tag11.o: 0x2A000000000000000{{1|2}}00000000000000 +# ERR1: tag2.o: 0x2A000000000000000{{1|2}}00000000000000 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o # RUN: not ld.lld errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s -# ERR2: error: {{.*}}: invalid type field value 42 (1 expected) -# ERR2-NEXT: error: {{.*}}: invalid name field value XXX (ARM expected) -# ERR2-NEXT: error: {{.*}}: AArch64 PAuth compatibility info is too short (at least 16 bytes expected) +# ERR2: error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): invalid type field value 42 (1 expected) +# ERR2-NEXT: error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): invalid name field value XXX (ARM expected) +# ERR2-NEXT: error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): AArch64 PAuth compatibility info is too short (at least 16 bytes expected) # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o short.o # RUN: not ld.lld short.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR3 %s -# ERR3: error: {{.*}}: section is too short +# ERR3: error: short.o:(.note.AARCH64-PAUTH-ABI-tag): section is too short # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu no-info.s -o noinfo1.o # RUN: cp noinfo1.o noinfo2.o @@ -34,10 +34,10 @@ # RUN: ld.lld -z pauth-report=warning tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s # RUN: ld.lld -z pauth-report=none tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix NONE %s -# ERR4: error: {{.*}}noinfo1.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it -# ERR4-NEXT: error: {{.*}}noinfo2.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it -# WARN: warning: {{.*}}noinfo1.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it -# WARN-NEXT: warning: {{.*}}noinfo2.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it +# ERR4: error: noinfo1.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it +# ERR4-NEXT: error: noinfo2.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it +# WARN: warning: noinfo1.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it +# WARN-NEXT: warning: noinfo2.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it # NONE-NOT: {{.*}} has no AArch64 PAuth compatibility info while {{.*}} has one; either all or no input files must have it #--- abi-tag-short.s From aff3a96d4383b6aa930d4d21db949b3b459f2163 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Thu, 15 Feb 2024 12:38:42 +0300 Subject: [PATCH 09/34] Address several review comments --- lld/ELF/Config.h | 2 +- lld/ELF/Driver.cpp | 21 ++++++++------------- lld/ELF/InputFiles.cpp | 2 +- lld/ELF/InputFiles.h | 2 +- lld/ELF/Relocations.cpp | 4 +--- lld/ELF/SyntheticSections.cpp | 2 +- lld/test/ELF/aarch64-reloc-pauth-ro.s | 12 +++++------- 7 files changed, 18 insertions(+), 27 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index eb76f72f2196f..22d706688334f 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -497,7 +497,7 @@ struct Ctx { llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &); - SmallVector aarch64PauthAbiTag; + ArrayRef aarch64PauthAbiTag; }; LLVM_LIBRARY_VISIBILITY extern Ctx ctx; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 096b9b2de401c..c1eb2df9e3716 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2624,9 +2624,6 @@ static uint32_t getAndFeatures() { } static void getAArch64PauthInfo() { - if (ctx.objectFiles.empty()) - return; - auto it = std::find_if( ctx.objectFiles.begin(), ctx.objectFiles.end(), [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); }); @@ -2635,11 +2632,11 @@ static void getAArch64PauthInfo() { ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag; StringRef f1 = (*it)->getName(); - for (ELFFileBase *f : ArrayRef(ctx.objectFiles)) { + for (ELFFileBase *f : ctx.objectFiles) { StringRef f2 = f->getName(); - const SmallVector &d1 = ctx.aarch64PauthAbiTag; - const SmallVector &d2 = f->aarch64PauthAbiTag; - if (d1.empty() != d2.empty()) { + ArrayRef d1 = ctx.aarch64PauthAbiTag; + ArrayRef d2 = f->aarch64PauthAbiTag; + if (d2.empty()) { auto helper = [](StringRef report, const Twine &msg) { if (report == "warning") warn(msg); @@ -2648,14 +2645,12 @@ static void getAArch64PauthInfo() { }; helper(config->zPauthReport, - (d1.empty() ? f1.str() : f2.str()) + - " has no AArch64 PAuth compatibility info while " + - (d1.empty() ? f2.str() : f1.str()) + + f2.str() + " has no AArch64 PAuth compatibility info while " + + f1.str() + " has one; either all or no input files must have it"); + continue; } - - if (!d1.empty() && !d2.empty() && - !std::equal(d1.begin(), d1.end(), d2.begin(), d2.end())) + if (!std::equal(d1.begin(), d1.end(), d2.begin(), d2.end())) errorOrWarn( "incompatible values of AArch64 PAuth compatibility info found" "\n" + diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 90480e142477e..3f7ef755a83af 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -997,7 +997,7 @@ static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile &f) { return; } - f.aarch64PauthAbiTag = SmallVector(iterator_range(desc)); + f.aarch64PauthAbiTag = desc; } template diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index c881a80118280..51db76dae1730 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -218,7 +218,7 @@ class ELFFileBase : public InputFile { public: uint32_t andFeatures = 0; bool hasCommonSyms = false; - SmallVector aarch64PauthAbiTag; + ArrayRef aarch64PauthAbiTag; }; // .o file. diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index fafabc0caf9d0..157c6b734c493 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1138,14 +1138,12 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, if (canWrite) { RelType rel = target->getDynRel(type); if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { - // Assume relocations from relocatable objects are RELA. - assert(config->isRela); std::lock_guard lock(relocMutex); // For a preemptible symbol, we can't use a relative relocation. For an // undefined symbol, we can't compute offset at link-time and use a // relative relocation. Use a symbolic relocation instead. Partition &part = sec->getPartition(); - if (sym.isPreemptible || sym.isUndefined()) { + if (sym.isPreemptible) { part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type); } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 && isInt<32>(sym.getVA(addend))) { diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 2dcb81d6f95d1..eea77295ae1a4 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -340,7 +340,7 @@ bool AArch64PauthAbiTag::isNeeded() const { } void AArch64PauthAbiTag::writeTo(uint8_t *buf) { - const SmallVector &data = ctx.aarch64PauthAbiTag; + ArrayRef data = ctx.aarch64PauthAbiTag; write32(buf, 4); // Name size write32(buf + 4, data.size()); // Content size write32(buf + 8, NT_ARM_TYPE_PAUTH_ABI_TAG); // Type diff --git a/lld/test/ELF/aarch64-reloc-pauth-ro.s b/lld/test/ELF/aarch64-reloc-pauth-ro.s index 80afb921a5c26..61a52a1e4f8af 100644 --- a/lld/test/ELF/aarch64-reloc-pauth-ro.s +++ b/lld/test/ELF/aarch64-reloc-pauth-ro.s @@ -3,17 +3,15 @@ // RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o // RUN: ld.lld -shared %t.so.o -soname=so -o %t.so // RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o -// RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck %s +// RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck -DFILE=%t %s // CHECK: error: relocation R_AARCH64_AUTH_ABS64 against symbol 'zed2' in read-only section -// CHECK-NEXT: defined in -// CHECK-NEXT: referenced by -// CHECK-SAME: :(.test+0x0) +// CHECK-NEXT: defined in [[FILE]].so +// CHECK-NEXT: referenced by [[FILE]].o:(.test+0x0) // CHECK: error: relocation R_AARCH64_AUTH_ABS64 against symbol 'bar2' in read-only section -// CHECK-NEXT: defined in -// CHECK-NEXT: referenced by -// CHECK-SAME: :(.test+0x8) +// CHECK-NEXT: defined in [[FILE]].so +// CHECK-NEXT: referenced by [[FILE]].o:(.test+0x8) .section .test, "a" .p2align 3 From 4e53afaa50e63466263d0697e0e2a335d281dbf6 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Thu, 15 Feb 2024 14:58:15 +0300 Subject: [PATCH 10/34] Address several review comments --- lld/ELF/InputFiles.cpp | 17 ++--- lld/ELF/Relocations.cpp | 5 +- lld/test/ELF/aarch64-feature-pauth.s | 29 +++---- lld/test/ELF/aarch64-reloc-pauth-ro.s | 22 +++--- lld/test/ELF/aarch64-reloc-pauth.s | 105 ++++++++++++-------------- 5 files changed, 85 insertions(+), 93 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 3f7ef755a83af..f8030d0f77369 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -971,28 +971,27 @@ static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile &f) { using Elf_Nhdr = typename ELFT::Nhdr; using Elf_Note = typename ELFT::Note; ArrayRef data = sec.content(); - auto reportError = [&](const Twine &msg) { - errorOrWarn(toString(sec.file) + ":(" + sec.name + "): " + msg); - }; auto *nhdr = reinterpret_cast(data.data()); if (data.size() < sizeof(Elf_Nhdr) || data.size() < nhdr->getSize(sec.addralign)) { - reportError("section is too short"); + errorOrWarn(toString(&sec) + ": section is too short"); return; } Elf_Note note(*nhdr); if (nhdr->n_type != NT_ARM_TYPE_PAUTH_ABI_TAG) - reportError("invalid type field value " + Twine(nhdr->n_type) + " (" + - Twine(NT_ARM_TYPE_PAUTH_ABI_TAG) + " expected)"); + errorOrWarn(toString(&sec) + ": invalid type field value " + + Twine(nhdr->n_type) + " (" + Twine(NT_ARM_TYPE_PAUTH_ABI_TAG) + + " expected)"); if (note.getName() != "ARM") - reportError("invalid name field value " + note.getName() + - " (ARM expected)"); + errorOrWarn(toString(&sec) + ": invalid name field value " + + note.getName() + " (ARM expected)"); ArrayRef desc = note.getDesc(sec.addralign); if (desc.size() < 16) { - reportError("AArch64 PAuth compatibility info is too short " + errorOrWarn(toString(&sec) + + ": AArch64 PAuth compatibility info is too short " "(at least 16 bytes expected)"); return; } diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 157c6b734c493..f5e00e4a8de59 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1194,8 +1194,9 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, } if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { - error("relocation " + toString(type) + " against symbol '" + toString(sym) + - "'" + " in read-only section" + getLocation(*sec, sym, offset)); + errorOrWarn("relocation " + toString(type) + " against symbol '" + + toString(sym) + "'" + " in read-only section" + + getLocation(*sec, sym, offset)); return; } diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 4d1b9d9164004..229b9203c4332 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -2,18 +2,18 @@ # RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag1.s -o tag11.o -# RUN: cp tag11.o tag12.o -# RUN: ld.lld -shared tag11.o tag12.o -o tagok.so +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag1.s -o tag1.o +# RUN: cp tag1.o tag1a.o +# RUN: ld.lld -shared tag1.o tag1a.o -o tagok.so # RUN: llvm-readelf -n tagok.so | FileCheck --check-prefix OK %s # OK: AArch64 PAuth ABI tag: platform 0x2a, version 0x1 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o -# RUN: not ld.lld tag11.o tag12.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s +# RUN: not ld.lld tag1.o tag1a.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s # ERR1: error: incompatible values of AArch64 PAuth compatibility info found -# ERR1: tag11.o: 0x2A000000000000000{{1|2}}00000000000000 +# ERR1: tag1.o: 0x2A000000000000000{{1|2}}00000000000000 # ERR1: tag2.o: 0x2A000000000000000{{1|2}}00000000000000 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o @@ -30,15 +30,14 @@ # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu no-info.s -o noinfo1.o # RUN: cp noinfo1.o noinfo2.o -# RUN: not ld.lld -z pauth-report=error tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s -# RUN: ld.lld -z pauth-report=warning tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s -# RUN: ld.lld -z pauth-report=none tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix NONE %s +# RUN: not ld.lld -z pauth-report=error tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s +# RUN: ld.lld -z pauth-report=warning tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s +# RUN: ld.lld -z pauth-report=none tag1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null -# ERR4: error: noinfo1.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it -# ERR4-NEXT: error: noinfo2.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it -# WARN: warning: noinfo1.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it -# WARN-NEXT: warning: noinfo2.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it -# NONE-NOT: {{.*}} has no AArch64 PAuth compatibility info while {{.*}} has one; either all or no input files must have it +# ERR4: error: noinfo1.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it +# ERR4-NEXT: error: noinfo2.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it +# WARN: warning: noinfo1.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it +# WARN-NEXT: warning: noinfo2.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it #--- abi-tag-short.s @@ -80,4 +79,8 @@ #--- no-info.s +.globl _start; // define _start to avoid missing entry warning and use --fatal-warnings to assert no diagnostic +.weak _start; // allow multiple definitions of _start for simplicity +_start: + .section ".test", "a" diff --git a/lld/test/ELF/aarch64-reloc-pauth-ro.s b/lld/test/ELF/aarch64-reloc-pauth-ro.s index 61a52a1e4f8af..4e496d52ab548 100644 --- a/lld/test/ELF/aarch64-reloc-pauth-ro.s +++ b/lld/test/ELF/aarch64-reloc-pauth-ro.s @@ -1,17 +1,17 @@ -// REQUIRES: aarch64 +# REQUIRES: aarch64 -// RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o -// RUN: ld.lld -shared %t.so.o -soname=so -o %t.so -// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o -// RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck -DFILE=%t %s +# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o +# RUN: ld.lld -shared %t.so.o -soname=so -o %t.so +# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +# RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck -DFILE=%t %s -// CHECK: error: relocation R_AARCH64_AUTH_ABS64 against symbol 'zed2' in read-only section -// CHECK-NEXT: defined in [[FILE]].so -// CHECK-NEXT: referenced by [[FILE]].o:(.test+0x0) +# CHECK: error: relocation R_AARCH64_AUTH_ABS64 against symbol 'zed2' in read-only section +# CHECK-NEXT: defined in [[FILE]].so +# CHECK-NEXT: referenced by [[FILE]].o:(.test+0x0) -// CHECK: error: relocation R_AARCH64_AUTH_ABS64 against symbol 'bar2' in read-only section -// CHECK-NEXT: defined in [[FILE]].so -// CHECK-NEXT: referenced by [[FILE]].o:(.test+0x8) +# CHECK: error: relocation R_AARCH64_AUTH_ABS64 against symbol 'bar2' in read-only section +# CHECK-NEXT: defined in [[FILE]].so +# CHECK-NEXT: referenced by [[FILE]].o:(.test+0x8) .section .test, "a" .p2align 3 diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index 79e6e4246cc45..8c0f147d783c5 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -1,61 +1,50 @@ -// REQUIRES: aarch64 - -// RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o -// RUN: ld.lld -shared %t.so.o -soname=so -o %t.so -// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o -// RUN: ld.lld -pie -z nopack-relative-relocs %t.o %t.so -o %t2 -// RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s - -// UNPACKED: Section ({{.+}}) .rela.dyn { -// UNPACKED-NEXT: 0x303C8 R_AARCH64_AUTH_RELATIVE - 0x1 -// UNPACKED-NEXT: 0x303E1 R_AARCH64_AUTH_RELATIVE - 0x2 -// UNPACKED-NEXT: 0x303D0 R_AARCH64_AUTH_ABS64 zed2 0x0 -// UNPACKED-NEXT: 0x303D8 R_AARCH64_AUTH_ABS64 bar2 0x0 -// UNPACKED-NEXT: } - -// RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2 -// RUN: llvm-readobj -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s -// RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s -// RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s - -// RELR-HEADERS: Index: 1 -// RELR-HEADERS-NEXT: Name: .dynsym - -// RELR-HEADERS: Name: .relr.auth.dyn -// RELR-HEADERS-NEXT: Type: SHT_AARCH64_AUTH_RELR -// RELR-HEADERS-NEXT: Flags [ (0x2) -// RELR-HEADERS-NEXT: SHF_ALLOC (0x2) -// RELR-HEADERS-NEXT: ] -// RELR-HEADERS-NEXT: Address: [[ADDR:.*]] -// RELR-HEADERS-NEXT: Offset: [[ADDR]] -// RELR-HEADERS-NEXT: Size: 8 -// RELR-HEADERS-NEXT: Link: 0 -// RELR-HEADERS-NEXT: Info: 0 -// RELR-HEADERS-NEXT: AddressAlignment: 8 -// RELR-HEADERS-NEXT: EntrySize: 8 - -// RELR-HEADERS: 0x0000000070000012 AARCH64_AUTH_RELR [[ADDR]] -// RELR-HEADERS: 0x0000000070000011 AARCH64_AUTH_RELRSZ 8 (bytes) -// RELR-HEADERS: 0x0000000070000013 AARCH64_AUTH_RELRENT 8 (bytes) - -/// SHT_RELR section contains address/bitmap entries -/// encoding the offsets for relative relocation. -// RAW-RELR: Section ({{.+}}) .relr.auth.dyn { -// RAW-RELR-NEXT: 0x303E8 -// RAW-RELR-NEXT: } - -/// Decoded SHT_RELR section is same as UNPACKED, -/// but contains only the relative relocations. -/// Any relative relocations with odd offset stay in SHT_RELA. - -// RELR: Section ({{.+}}) .rela.dyn { -// RELR-NEXT: 0x30401 R_AARCH64_AUTH_RELATIVE - 0x2 -// RELR-NEXT: 0x303F0 R_AARCH64_AUTH_ABS64 zed2 0x0 -// RELR-NEXT: 0x303F8 R_AARCH64_AUTH_ABS64 bar2 0x0 -// RELR-NEXT: } -// RELR-NEXT: Section ({{.+}}) .relr.auth.dyn { -// RELR-NEXT: 0x303E8 R_AARCH64_RELATIVE - -// RELR-NEXT: } +# REQUIRES: aarch64 + +# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o +# RUN: ld.lld -shared %t.so.o -soname=so -o %t.so +# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +# RUN: ld.lld -pie -z nopack-relative-relocs %t.o %t.so -o %t2 +# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s + +# UNPACKED: Section ({{.+}}) .rela.dyn { +# UNPACKED-NEXT: 0x303C8 R_AARCH64_AUTH_RELATIVE - 0x1 +# UNPACKED-NEXT: 0x303E1 R_AARCH64_AUTH_RELATIVE - 0x2 +# UNPACKED-NEXT: 0x303D0 R_AARCH64_AUTH_ABS64 zed2 0x0 +# UNPACKED-NEXT: 0x303D8 R_AARCH64_AUTH_ABS64 bar2 0x0 +# UNPACKED-NEXT: } + +# RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2 +# RUN: llvm-readelf -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s +# RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s +# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s + +# RELR-HEADERS: Section Headers: +# RELR-HEADERS-NEXT: Name Type Address Off Size ES Flg Lk Inf Al +# RELR-HEADERS: .relr.auth.dyn AARCH64_AUTH_RELR 0000000000[[ADDR:.*]] [[ADDR]] 000008 08 A 0 0 8 + +# RELR-HEADERS: Dynamic section at offset 0x2e8 contains 16 entries +# RELR-HEADERS: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x2e0 +# RELR-HEADERS-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 8 (bytes) +# RELR-HEADERS-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes) + +## SHT_RELR section contains address/bitmap entries +## encoding the offsets for relative relocation. +# RAW-RELR: Section ({{.+}}) .relr.auth.dyn { +# RAW-RELR-NEXT: 0x303E8 +# RAW-RELR-NEXT: } + +## Decoded SHT_RELR section is same as UNPACKED, +## but contains only the relative relocations. +## Any relative relocations with odd offset stay in SHT_RELA. + +# RELR: Section ({{.+}}) .rela.dyn { +# RELR-NEXT: 0x30401 R_AARCH64_AUTH_RELATIVE - 0x2 +# RELR-NEXT: 0x303F0 R_AARCH64_AUTH_ABS64 zed2 0x0 +# RELR-NEXT: 0x303F8 R_AARCH64_AUTH_ABS64 bar2 0x0 +# RELR-NEXT: } +# RELR-NEXT: Section ({{.+}}) .relr.auth.dyn { +# RELR-NEXT: 0x303E8 R_AARCH64_RELATIVE - +# RELR-NEXT: } .section .test, "aw" .p2align 3 From ec1c6322341f3f25f3ad0070810c4a90d188c3b5 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Sat, 17 Feb 2024 04:13:30 +0300 Subject: [PATCH 11/34] Address review comments --- lld/test/ELF/aarch64-reloc-pauth.s | 95 ++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 18 deletions(-) diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index 8c0f147d783c5..aeed86f42e88f 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -3,53 +3,112 @@ # RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o # RUN: ld.lld -shared %t.so.o -soname=so -o %t.so # RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o + # RUN: ld.lld -pie -z nopack-relative-relocs %t.o %t.so -o %t2 # RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s # UNPACKED: Section ({{.+}}) .rela.dyn { -# UNPACKED-NEXT: 0x303C8 R_AARCH64_AUTH_RELATIVE - 0x1 -# UNPACKED-NEXT: 0x303E1 R_AARCH64_AUTH_RELATIVE - 0x2 -# UNPACKED-NEXT: 0x303D0 R_AARCH64_AUTH_ABS64 zed2 0x0 -# UNPACKED-NEXT: 0x303D8 R_AARCH64_AUTH_ABS64 bar2 0x0 +# UNPACKED-NEXT: 0x30440 R_AARCH64_AUTH_RELATIVE - 0x1 +# UNPACKED-NEXT: 0x30448 R_AARCH64_AUTH_RELATIVE - 0x2 +# UNPACKED-NEXT: 0x30450 R_AARCH64_AUTH_RELATIVE - 0x3 +# UNPACKED-NEXT: 0x30458 R_AARCH64_AUTH_RELATIVE - 0x12345678 +# UNPACKED-NEXT: 0x30460 R_AARCH64_AUTH_RELATIVE - 0x123456789A +# UNPACKED-NEXT: 0x30479 R_AARCH64_AUTH_RELATIVE - 0x4 +# UNPACKED-NEXT: 0x30482 R_AARCH64_AUTH_RELATIVE - 0x5 +# UNPACKED-NEXT: 0x30468 R_AARCH64_AUTH_ABS64 zed2 0x0 +# UNPACKED-NEXT: 0x30470 R_AARCH64_AUTH_ABS64 bar2 0x0 # UNPACKED-NEXT: } # RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2 # RUN: llvm-readelf -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s -# RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s -# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s # RELR-HEADERS: Section Headers: # RELR-HEADERS-NEXT: Name Type Address Off Size ES Flg Lk Inf Al -# RELR-HEADERS: .relr.auth.dyn AARCH64_AUTH_RELR 0000000000[[ADDR:.*]] [[ADDR]] 000008 08 A 0 0 8 +# RELR-HEADERS: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR:.*]] {{0*}}[[ADDR]] 000018 08 A 0 0 8 -# RELR-HEADERS: Dynamic section at offset 0x2e8 contains 16 entries -# RELR-HEADERS: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x2e0 -# RELR-HEADERS-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 8 (bytes) +# RELR-HEADERS: Dynamic section at offset 0x310 contains 16 entries +# RELR-HEADERS: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR]] +# RELR-HEADERS-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes) # RELR-HEADERS-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes) +# RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --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: 0x303E8 +# RAW-RELR-NEXT: 0x30410 +# RAW-RELR-NEXT: 0xF +# RAW-RELR-NEXT: 0x30452 # RAW-RELR-NEXT: } +# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s + ## Decoded SHT_RELR section is same as UNPACKED, ## but contains only the relative relocations. ## Any relative relocations with odd offset stay in SHT_RELA. # RELR: Section ({{.+}}) .rela.dyn { -# RELR-NEXT: 0x30401 R_AARCH64_AUTH_RELATIVE - 0x2 -# RELR-NEXT: 0x303F0 R_AARCH64_AUTH_ABS64 zed2 0x0 -# RELR-NEXT: 0x303F8 R_AARCH64_AUTH_ABS64 bar2 0x0 +# RELR-NEXT: 0x30430 R_AARCH64_AUTH_RELATIVE - 0x123456789A +# RELR-NEXT: 0x30449 R_AARCH64_AUTH_RELATIVE - 0x4 +# RELR-NEXT: 0x30438 R_AARCH64_AUTH_ABS64 zed2 0x0 +# RELR-NEXT: 0x30440 R_AARCH64_AUTH_ABS64 bar2 0x0 # RELR-NEXT: } # RELR-NEXT: Section ({{.+}}) .relr.auth.dyn { -# RELR-NEXT: 0x303E8 R_AARCH64_RELATIVE - +# RELR-NEXT: 0x30410 R_AARCH64_RELATIVE - +# RELR-NEXT: 0x30418 R_AARCH64_RELATIVE - +# RELR-NEXT: 0x30420 R_AARCH64_RELATIVE - +# RELR-NEXT: 0x30428 R_AARCH64_RELATIVE - +# RELR-NEXT: 0x30452 R_AARCH64_RELATIVE - # RELR-NEXT: } +# RUN: llvm-readobj -x .test %t2 | FileCheck --check-prefix=HEX %s + +# HEX: Hex dump of section '.test': +# HEX-NEXT: 0x00030410 01000000 2a000020 02000000 2b000000 +## ^^^^^^^^ Addend = 1 +## ^^^^ Discr = 42 +## ^^ Key (bits 5..6) = DA +## ^^^^^^^^ Addend = 2 +## ^^^^ Discr = 43 +## ^^ Key (bits 5..6) = IA +# HEX-NEXT: 0x00030420 03000000 2c000080 78563412 2d000020 +## ^^^^^^^^ Addend = 3 +## ^^^^ Discr = 44 +## ^^ Key (bits 5..6) = IA +## ^^ Addr diversity (bit 7) = true +## ^^^^^^^^ Addend = 0x12345678 +## ^^^^ Discr = 45 +## ^^ Key (bits 5..6) = DA +# HEX-NEXT: 0x00030430 00000000 2e000020 00000000 2f000020 +## ^^^^^^^^ No implicit addend (rela reloc) +## ^^^^ Discr = 46 +## ^^ Key (bits 5..6) = DA +## ^^^^^^^^ Addend = 0 +## ^^^^ Discr = 47 +## ^^ Key (bits 5..6) = DA +# HEX-NEXT: 0x00030440 00000000 30000000 00000000 00310000 +## ^^^^^^^^ Addend = 0 +## ^^^^ Discr = 48 +## ^^ Key (bits 5..6) = IA +## ^^^^^^ ^^ No implicit addend (rela reloc) +## ^^^^ Discr = 49 +# HEX-NEXT: 0x00030450 20000500 00003200 0020{{\ }} +## ^^ Key (bits 5..6) = DA +## ^^^^ ^^^^ Addend = 5 +## ^^^^ Discr = 48 +## ^^ Key (bits 5..6) = DA + .section .test, "aw" .p2align 3 .quad (__ehdr_start + 1)@AUTH(da,42) -.quad zed2@AUTH(da,42) -.quad bar2@AUTH(ia,42) +.quad (__ehdr_start + 2)@AUTH(ia,43) +.quad (__ehdr_start + 3)@AUTH(ia,44,addr) +.quad (__ehdr_start + 0x12345678)@AUTH(da,45) +.quad (__ehdr_start + 0x123456789A)@AUTH(da,46) +.quad zed2@AUTH(da,47) +.quad bar2@AUTH(ia,48) +.byte 00 +.quad (__ehdr_start + 4)@AUTH(da,49) .byte 00 -.quad (__ehdr_start + 2)@AUTH(da,42) +.quad (__ehdr_start + 5)@AUTH(da,50) From 2136ad1f2c8e92d52fb0b96a77c4cbc7828916b3 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 19 Feb 2024 17:22:33 -0800 Subject: [PATCH 12/34] Simplify RelocationScanner::processAux --- lld/ELF/Arch/AArch64.cpp | 2 +- lld/ELF/Relocations.cpp | 48 +++++++++++++++++++--------------------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 79318637d85e9..20f637e49f187 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -205,7 +205,7 @@ bool AArch64::usesOnlyLowPageBits(RelType type) const { } RelType AArch64::getDynRel(RelType type) const { - if (type == R_AARCH64_ABS64) + if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64) return type; return R_AARCH64_NONE; } diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index f5e00e4a8de59..926de8748e72d 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1137,29 +1137,6 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, (isa(sec) && config->emachine != EM_MIPS)); if (canWrite) { RelType rel = target->getDynRel(type); - if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { - std::lock_guard lock(relocMutex); - // For a preemptible symbol, we can't use a relative relocation. For an - // undefined symbol, we can't compute offset at link-time and use a - // relative relocation. Use a symbolic relocation instead. - Partition &part = sec->getPartition(); - if (sym.isPreemptible) { - part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type); - } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 && - isInt<32>(sym.getVA(addend))) { - // Implicit addend is below 32-bits so we can use the compressed - // relative relocation section. The R_AARCH64_AUTH_RELATIVE - // has a smaller addend field as bits [63:32] encode the signing-schema. - sec->addReloc({expr, type, offset, addend, &sym}); - part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back( - {sec, offset}); - } else { - part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, - DynamicReloc::AddendOnlyWithTargetVA, sym, - addend, R_ABS}); - } - return; - } if (oneof(expr) || (rel == target->symbolicRel && !sym.isPreemptible)) { addRelativeReloc(*sec, offset, sym, addend, expr, type); @@ -1169,8 +1146,29 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, if (config->emachine == EM_MIPS && rel == target->symbolicRel) rel = target->relativeRel; std::lock_guard lock(relocMutex); - sec->getPartition().relaDyn->addSymbolReloc(rel, *sec, offset, sym, - addend, type); + Partition &part = sec->getPartition(); + if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { + // For a preemptible symbol, we can't use a relative relocation. For an + // undefined symbol, we can't compute offset at link-time and use a + // 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 && + isInt<32>(sym.getVA(addend))) { + // Implicit addend is below 32-bits so we can use the compressed + // relative relocation section. The R_AARCH64_AUTH_RELATIVE has a + // smaller addend field as bits [63:32] encode the signing-schema. + sec->addReloc({expr, type, offset, addend, &sym}); + part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back( + {sec, offset}); + } else { + part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, + DynamicReloc::AddendOnlyWithTargetVA, sym, + addend, R_ABS}); + } + return; + } + part.relaDyn->addSymbolReloc(rel, *sec, offset, sym, addend, type); // MIPS ABI turns using of GOT and dynamic relocations inside out. // While regular ABI uses dynamic relocations to fill up GOT entries From 9ea8c5c45f5615f5c09e54cb23290ae174b7c82a Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 19 Feb 2024 17:32:21 -0800 Subject: [PATCH 13/34] Fix error message in a read-only section when the symbol is local --- lld/ELF/Relocations.cpp | 12 ++++-------- lld/test/ELF/aarch64-reloc-pauth-ro.s | 17 ++++++++++------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 926de8748e72d..eb4b38a99c72f 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1191,16 +1191,12 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, } } - if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) { - errorOrWarn("relocation " + toString(type) + " against symbol '" + - toString(sym) + "'" + " in read-only section" + - getLocation(*sec, sym, offset)); - return; - } - // When producing an executable, we can perform copy relocations (for // STT_OBJECT) and canonical PLT (for STT_FUNC) if sym is defined by a DSO. - if (!config->shared && sym.isShared()) { + // Copy relocations/canonical PLT entries are unsupported for + // R_AARCH64_AUTH_ABS64. + if (!config->shared && sym.isShared() && + !(config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64)) { if (!canDefineSymbolInExecutable(sym)) { errorOrWarn("cannot preempt symbol: " + toString(sym) + getLocation(*sec, sym, offset)); diff --git a/lld/test/ELF/aarch64-reloc-pauth-ro.s b/lld/test/ELF/aarch64-reloc-pauth-ro.s index 4e496d52ab548..5bc9d805b481a 100644 --- a/lld/test/ELF/aarch64-reloc-pauth-ro.s +++ b/lld/test/ELF/aarch64-reloc-pauth-ro.s @@ -5,15 +5,18 @@ # RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o # RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck -DFILE=%t %s -# CHECK: error: relocation R_AARCH64_AUTH_ABS64 against symbol 'zed2' in read-only section -# CHECK-NEXT: defined in [[FILE]].so -# CHECK-NEXT: referenced by [[FILE]].o:(.test+0x0) +# CHECK: error: relocation R_AARCH64_AUTH_ABS64 cannot be used against symbol 'zed2'; recompile with -fPIC +# CHECK-NEXT: >>> defined in [[FILE]].so +# CHECK-NEXT: >>> referenced by [[FILE]].o:(.ro+0x0) -# CHECK: error: relocation R_AARCH64_AUTH_ABS64 against symbol 'bar2' in read-only section -# CHECK-NEXT: defined in [[FILE]].so -# CHECK-NEXT: referenced by [[FILE]].o:(.test+0x8) +# CHECK: error: relocation R_AARCH64_AUTH_ABS64 cannot be used against symbol 'bar2'; recompile with -fPIC +# CHECK: error: relocation R_AARCH64_AUTH_ABS64 cannot be used against local symbol; recompile with -fPIC -.section .test, "a" +foo: +.type foo, @function + +.section .ro, "a" .p2align 3 .quad zed2@AUTH(da,42) .quad bar2@AUTH(ia,42) +.quad foo@AUTH(ia,42) From e3a64d213c5f3d8f46a4b7fb304ba61c4bba390b Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 19 Feb 2024 18:20:15 -0800 Subject: [PATCH 14/34] Simplify aarch64-reloc-pauth.s --- lld/test/ELF/aarch64-reloc-pauth.s | 61 ++++++++++++++---------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index aeed86f42e88f..4bd305dc4f3e6 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -4,8 +4,8 @@ # RUN: ld.lld -shared %t.so.o -soname=so -o %t.so # RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o -# RUN: ld.lld -pie -z nopack-relative-relocs %t.o %t.so -o %t2 -# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s +# RUN: ld.lld -pie %t.o %t.so -o %t +# RUN: llvm-readobj -r %t | FileCheck --check-prefix=UNPACKED %s # UNPACKED: Section ({{.+}}) .rela.dyn { # UNPACKED-NEXT: 0x30440 R_AARCH64_AUTH_RELATIVE - 0x1 @@ -20,16 +20,35 @@ # UNPACKED-NEXT: } # RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2 -# RUN: llvm-readelf -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s +# RUN: llvm-readelf -S -d -r -x .test %t2 | FileCheck --check-prefixes=RELR,HEX %s -# RELR-HEADERS: Section Headers: -# RELR-HEADERS-NEXT: Name Type Address Off Size ES Flg Lk Inf Al -# RELR-HEADERS: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR:.*]] {{0*}}[[ADDR]] 000018 08 A 0 0 8 +# RELR: Section Headers: +# RELR-NEXT: Name Type Address Off Size ES Flg Lk Inf Al +# RELR: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR:.*]] {{0*}}[[ADDR]] 000018 08 A 0 0 8 -# RELR-HEADERS: Dynamic section at offset 0x310 contains 16 entries -# RELR-HEADERS: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR]] -# RELR-HEADERS-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes) -# RELR-HEADERS-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes) +# RELR: Dynamic section at offset 0x310 contains 16 entries +# RELR: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR]] +# 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 stay in SHT_RELA. + +# RELR: Relocation section '.rela.dyn' at offset {{.*}} contains 4 entries: +# RELR-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +# RELR-NEXT: 0000000000030430 0000000000000411 R_AARCH64_AUTH_RELATIVE 123456789a +# RELR-NEXT: 0000000000030449 0000000000000411 R_AARCH64_AUTH_RELATIVE 4 +# RELR-NEXT: 0000000000030438 0000000100000244 R_AARCH64_AUTH_ABS64 0000000000000000 zed2 + 0 +# RELR-NEXT: 0000000000030440 0000000200000244 R_AARCH64_AUTH_ABS64 0000000000000000 bar2 + 0 +# RELR-EMPTY: +# RELR-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 5 entries: +# RELR-NEXT: Offset Info Type Symbol's Value Symbol's Name +# RELR-NEXT: 0000000000030410 0000000000000403 R_AARCH64_RELATIVE +# RELR-NEXT: 0000000000030418 0000000000000403 R_AARCH64_RELATIVE +# RELR-NEXT: 0000000000030420 0000000000000403 R_AARCH64_RELATIVE +# RELR-NEXT: 0000000000030428 0000000000000403 R_AARCH64_RELATIVE +# RELR-NEXT: 0000000000030452 0000000000000403 R_AARCH64_RELATIVE # RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s @@ -42,28 +61,6 @@ # RAW-RELR-NEXT: 0x30452 # RAW-RELR-NEXT: } -# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s - -## Decoded SHT_RELR section is same as UNPACKED, -## but contains only the relative relocations. -## Any relative relocations with odd offset stay in SHT_RELA. - -# RELR: Section ({{.+}}) .rela.dyn { -# RELR-NEXT: 0x30430 R_AARCH64_AUTH_RELATIVE - 0x123456789A -# RELR-NEXT: 0x30449 R_AARCH64_AUTH_RELATIVE - 0x4 -# RELR-NEXT: 0x30438 R_AARCH64_AUTH_ABS64 zed2 0x0 -# RELR-NEXT: 0x30440 R_AARCH64_AUTH_ABS64 bar2 0x0 -# RELR-NEXT: } -# RELR-NEXT: Section ({{.+}}) .relr.auth.dyn { -# RELR-NEXT: 0x30410 R_AARCH64_RELATIVE - -# RELR-NEXT: 0x30418 R_AARCH64_RELATIVE - -# RELR-NEXT: 0x30420 R_AARCH64_RELATIVE - -# RELR-NEXT: 0x30428 R_AARCH64_RELATIVE - -# RELR-NEXT: 0x30452 R_AARCH64_RELATIVE - -# RELR-NEXT: } - -# RUN: llvm-readobj -x .test %t2 | FileCheck --check-prefix=HEX %s - # HEX: Hex dump of section '.test': # HEX-NEXT: 0x00030410 01000000 2a000020 02000000 2b000000 ## ^^^^^^^^ Addend = 1 From 865c9839d0186852f3adaae6ab33551e2ca98818 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 19 Feb 2024 18:34:01 -0800 Subject: [PATCH 15/34] Force dynamic relocation in -no-pie mode R_AARCH64_AUTH_ABS64 requires dynamic behavior, not resolvable by the linker. --- lld/ELF/Arch/AArch64.cpp | 5 +++-- lld/ELF/InputSection.cpp | 1 + lld/ELF/Relocations.cpp | 3 ++- lld/ELF/Relocations.h | 1 + lld/test/ELF/aarch64-reloc-pauth.s | 15 +++++++++++++++ 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 20f637e49f187..909fbdacdb303 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -112,8 +112,9 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, case R_AARCH64_MOVW_UABS_G2: case R_AARCH64_MOVW_UABS_G2_NC: case R_AARCH64_MOVW_UABS_G3: - case R_AARCH64_AUTH_ABS64: return R_ABS; + case R_AARCH64_AUTH_ABS64: + return R_AARCH64_AUTH; case R_AARCH64_TLSDESC_ADR_PAGE21: return R_AARCH64_TLSDESC_PAGE; case R_AARCH64_TLSDESC_LD64_LO12: @@ -400,7 +401,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, write64(loc, val); break; case R_AARCH64_AUTH_ABS64: - checkIntUInt(loc, val, 32, rel); + assert(isInt<32>(val)); write32(loc, val); break; case R_AARCH64_ADD_ABS_LO12_NC: diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index e033a715b5921..4a84842fabb64 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -674,6 +674,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type, case R_DTPREL: case R_RELAX_TLS_LD_TO_LE_ABS: case R_RELAX_GOT_PC_NOPIC: + case R_AARCH64_AUTH: case R_RISCV_ADD: case R_RISCV_LEB128: return sym.getVA(a); diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index eb4b38a99c72f..cac385b6f9fcc 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -995,7 +995,8 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type, if (e == R_GOT || e == R_PLT) return target->usesOnlyLowPageBits(type) || !config->isPic; - if (sym.isPreemptible) + // R_AARCH64_AUTH_ABS64 requires a dynamic relocation. + if (sym.isPreemptible || e == R_AARCH64_AUTH) return false; if (!config->isPic) return true; diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 7eb8a811e6934..b7b9c09e1b892 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -87,6 +87,7 @@ enum RelExpr { R_AARCH64_PAGE_PC, R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC, R_AARCH64_TLSDESC_PAGE, + R_AARCH64_AUTH, R_ARM_PCA, R_ARM_SBREL, R_MIPS_GOTREL, diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index 4bd305dc4f3e6..2c617f2899e65 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -19,6 +19,21 @@ # UNPACKED-NEXT: 0x30470 R_AARCH64_AUTH_ABS64 bar2 0x0 # UNPACKED-NEXT: } +# RUN: ld.lld %t.o %t.so -o %t.nopie +# RUN: llvm-readobj -r %t.nopie | FileCheck --check-prefix=NOPIE %s + +# NOPIE: Section ({{.+}}) .rela.dyn { +# NOPIE: 0x230430 R_AARCH64_AUTH_RELATIVE - 0x200001 +# NOPIE-NEXT: 0x230438 R_AARCH64_AUTH_RELATIVE - 0x200002 +# NOPIE-NEXT: 0x230440 R_AARCH64_AUTH_RELATIVE - 0x200003 +# NOPIE-NEXT: 0x230448 R_AARCH64_AUTH_RELATIVE - 0x12545678 +# NOPIE-NEXT: 0x230450 R_AARCH64_AUTH_RELATIVE - 0x123476789A +# NOPIE-NEXT: 0x230469 R_AARCH64_AUTH_RELATIVE - 0x200004 +# NOPIE-NEXT: 0x230472 R_AARCH64_AUTH_RELATIVE - 0x200005 +# NOPIE-NEXT: 0x230458 R_AARCH64_AUTH_ABS64 zed2 0x0 +# NOPIE-NEXT: 0x230460 R_AARCH64_AUTH_ABS64 bar2 0x0 +# NOPIE-NEXT: } + # RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2 # RUN: llvm-readelf -S -d -r -x .test %t2 | FileCheck --check-prefixes=RELR,HEX %s From 1448a4a4e0e3cb70358558579e97fce3f0990356 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 27 Feb 2024 12:28:59 +0300 Subject: [PATCH 16/34] Address the following review comments: - issues in lld/test/ELF/aarch64-feature-pauth.s; - "\n>>> " for error continuation lines; - `ArrayRef`-related stuff; - merge `getAndFeatures` and `getAArch64PauthInfo` into `readSecurityNotes`; - change '-z pauth-report' error message to match '-z cet-report' and '-z bti-report'. --- lld/ELF/Driver.cpp | 104 +++++++++++++-------------- lld/test/ELF/aarch64-feature-pauth.s | 21 +++--- 2 files changed, 62 insertions(+), 63 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index c1eb2df9e3716..3390c33e050c9 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2554,14 +2554,17 @@ static void redirectSymbols(ArrayRef wrapped) { symtab.wrap(w.sym, w.real, w.wrap); } +static void reportMissingFeature(StringRef config, const Twine &report) { + if (config == "error") + error(report); + else if (config == "warning") + warn(report); +} + static void checkAndReportMissingFeature(StringRef config, uint32_t features, uint32_t mask, const Twine &report) { - if (!(features & mask)) { - if (config == "error") - error(report); - else if (config == "warning") - warn(report); - } + if (!(features & mask)) + reportMissingFeature(config, report); } // To enable CET (x86's hardware-assisted control flow enforcement), each @@ -2572,12 +2575,28 @@ static void checkAndReportMissingFeature(StringRef config, uint32_t features, // // This is also the case with AARCH64's BTI and PAC which use the similar // GNU_PROPERTY_AARCH64_FEATURE_1_AND mechanism. -static uint32_t getAndFeatures() { +// +// For AArch64 PAuth-enabled object files, the compatibility info of all of them +// must match. Missing info for some object files with matching info for +// remaining ones can be allowed (see -z pauth-report). +static void readSecurityNotes() { if (config->emachine != EM_386 && config->emachine != EM_X86_64 && config->emachine != EM_AARCH64) - return 0; + return; + + config->andFeatures = -1; + + StringRef referenceFileName; + if (config->emachine == EM_AARCH64) { + auto it = std::find_if( + ctx.objectFiles.begin(), ctx.objectFiles.end(), + [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); }); + if (it != ctx.objectFiles.end()) { + ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag; + referenceFileName = (*it)->getName(); + } + } - uint32_t ret = -1; for (ELFFileBase *f : ctx.objectFiles) { uint32_t features = f->andFeatures; @@ -2613,50 +2632,31 @@ static uint32_t getAndFeatures() { "GNU_PROPERTY_AARCH64_FEATURE_1_PAC property"); features |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC; } - ret &= features; - } + config->andFeatures &= features; - // Force enable Shadow Stack. - if (config->zShstk) - ret |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; - - return ret; -} - -static void getAArch64PauthInfo() { - auto it = std::find_if( - ctx.objectFiles.begin(), ctx.objectFiles.end(), - [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); }); - if (it == ctx.objectFiles.end()) - return; + if (ctx.aarch64PauthAbiTag.empty()) + continue; - ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag; - StringRef f1 = (*it)->getName(); - for (ELFFileBase *f : ctx.objectFiles) { - StringRef f2 = f->getName(); - ArrayRef d1 = ctx.aarch64PauthAbiTag; - ArrayRef d2 = f->aarch64PauthAbiTag; - if (d2.empty()) { - auto helper = [](StringRef report, const Twine &msg) { - if (report == "warning") - warn(msg); - else if (report == "error") - error(msg); - }; - - helper(config->zPauthReport, - f2.str() + " has no AArch64 PAuth compatibility info while " + - f1.str() + - " has one; either all or no input files must have it"); + if (f->aarch64PauthAbiTag.empty()) { + reportMissingFeature(config->zPauthReport, + toString(f) + + ": -z pauth-report: file does not have AArch64 " + "PAuth compatibility info while " + + referenceFileName + " has one"); continue; } - if (!std::equal(d1.begin(), d1.end(), d2.begin(), d2.end())) + + if (ctx.aarch64PauthAbiTag != f->aarch64PauthAbiTag) errorOrWarn( "incompatible values of AArch64 PAuth compatibility info found" - "\n" + - f1 + ": 0x" + toHex(ArrayRef(d1.data(), d1.size())) + "\n" + f2 + - ": 0x" + toHex(ArrayRef(d2.data(), d2.size()))); + "\n>>> " + + referenceFileName + ": 0x" + toHex(ctx.aarch64PauthAbiTag) + + "\n>>> " + toString(f) + ": 0x" + toHex(f->aarch64PauthAbiTag)); } + + // Force enable Shadow Stack. + if (config->zShstk) + config->andFeatures |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; } static void initSectionsAndLocalSyms(ELFFileBase *file, bool ignoreComdats) { @@ -2994,12 +2994,12 @@ void LinkerDriver::link(opt::InputArgList &args) { // partition. mainPart = &partitions[0]; - // Read .note.gnu.property sections from input object files which - // contain a hint to tweak linker's and loader's behaviors. - config->andFeatures = getAndFeatures(); - - if (config->emachine == EM_AARCH64) - getAArch64PauthInfo(); + // Read: + // - .note.gnu.property sections from input object files which + // contain a hint to tweak linker's and loader's behaviors; + // - .note.AARCH64-PAUTH-ABI-tag sections contents from input object files + // which contain AArch64 PAuth compatibility info. + readSecurityNotes(); // The Target instance handles target-specific stuff, such as applying // relocations or writing a PLT section. It also contains target-dependent diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 229b9203c4332..25c43e6ad0180 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -12,9 +12,9 @@ # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o # RUN: not ld.lld tag1.o tag1a.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s -# ERR1: error: incompatible values of AArch64 PAuth compatibility info found -# ERR1: tag1.o: 0x2A000000000000000{{1|2}}00000000000000 -# ERR1: tag2.o: 0x2A000000000000000{{1|2}}00000000000000 +# ERR1: error: incompatible values of AArch64 PAuth compatibility info found +# ERR1-NEXT: >>> tag1.o: 0x2A000000000000000{{1|2}}00000000000000 +# ERR1-NEXT: >>> tag2.o: 0x2A000000000000000{{1|2}}00000000000000 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o # RUN: not ld.lld errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s @@ -34,10 +34,10 @@ # RUN: ld.lld -z pauth-report=warning tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s # RUN: ld.lld -z pauth-report=none tag1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null -# ERR4: error: noinfo1.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it -# ERR4-NEXT: error: noinfo2.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it -# WARN: warning: noinfo1.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it -# WARN-NEXT: warning: noinfo2.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it +# ERR4: error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one +# ERR4-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one +# WARN: warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one +# WARN-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one #--- abi-tag-short.s @@ -79,8 +79,7 @@ #--- no-info.s -.globl _start; // define _start to avoid missing entry warning and use --fatal-warnings to assert no diagnostic -.weak _start; // allow multiple definitions of _start for simplicity +## define _start to avoid missing entry warning and use --fatal-warnings to assert no diagnostic +## allow multiple definitions of _start for simplicity +.weak _start; _start: - -.section ".test", "a" From 203f61e5cc831f27fef8dde654972f0dfe7d47a0 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 28 Feb 2024 20:58:19 +0300 Subject: [PATCH 17/34] Use `relocs` instead of `relocsVec` inside `lock(relocMutex)` scope --- lld/ELF/Relocations.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index cac385b6f9fcc..040771789959b 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1160,8 +1160,7 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, // relative relocation section. The R_AARCH64_AUTH_RELATIVE has a // smaller addend field as bits [63:32] encode the signing-schema. sec->addReloc({expr, type, offset, addend, &sym}); - part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back( - {sec, offset}); + part.relrAuthDyn->relocs.push_back({sec, offset}); } else { part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, DynamicReloc::AddendOnlyWithTargetVA, sym, From 1b8c52b2b0a0cc87e63dc3ecfb0853aa279d9b8a Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 28 Feb 2024 21:05:57 +0300 Subject: [PATCH 18/34] Allow arbitrary offset for dynamic section: no need to rely on it in tests --- lld/test/ELF/aarch64-reloc-pauth.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index 2c617f2899e65..2a7c2c179fd51 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -41,7 +41,7 @@ # RELR-NEXT: Name Type Address Off Size ES Flg Lk Inf Al # RELR: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR:.*]] {{0*}}[[ADDR]] 000018 08 A 0 0 8 -# RELR: Dynamic section at offset 0x310 contains 16 entries +# RELR: Dynamic section at offset {{.*}} contains 16 entries # RELR: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR]] # RELR-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes) # RELR-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes) From e9b53374522fca221414aac3d5a3b225e7fc73d4 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 28 Feb 2024 22:17:29 +0300 Subject: [PATCH 19/34] Fix relocs with wide addends for non-preemptible symbols For packed AUTH relocs in .relr.auth.dyn section, the implicit value must fit 32 bits since other 32 bits are used for storing signing schema. During relocation scanning, we do not know the final layout and cannot comput the final VA. In `Writer::finalizeAddressDependentContent()`, we adjust the layout-dependent content and convert relr relocs with implicit values wider than 32 bits to regular rela relocs. Since .rela.dyn might be empty before this and non-empty after, we should skip it in `removeUnusedSyntheticSections`. It might result in an empty .rela.dyn section in the output. Similarly, an empty .relr.auth.dyn might also appear - see lld/test/ELF/aarch64-reloc-pauth.s for details and comments. --- lld/ELF/Arch/AArch64.cpp | 18 ++- lld/ELF/Relocations.cpp | 12 +- lld/ELF/SyntheticSections.h | 4 +- lld/ELF/Writer.cpp | 39 ++++- lld/test/ELF/aarch64-reloc-pauth.s | 244 ++++++++++++++++++++--------- 5 files changed, 236 insertions(+), 81 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 909fbdacdb303..d2134493fd71c 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -401,8 +401,22 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, write64(loc, val); break; case R_AARCH64_AUTH_ABS64: - assert(isInt<32>(val)); - write32(loc, val); + // - If val is wider than 32 bits, we must have converted the auth relr + // reloc to rela in Writer::finalizeAddressDependentContent(). If + // so, no need to write anything, the rela entry holds all the info. + // + // - If val fits 32 bits: + // + // - The relocation might still be rela instead of relr, for example, if + // the relr -> rela conversion was performed during an iteration in + // finalizeAddressDependentContent, but further iterations made the val + // fitting 32 bits. In such case, there is no trouble with writing the + // val since it will be treated as garbage and have no effect during + // dynamic linking. + // + // - If the relocation is actually relr, write the 32-bit val as expected. + if (isInt<32>(val)) + write32(loc, val); break; case R_AARCH64_ADD_ABS_LO12_NC: or32AArch64Imm(loc, val); diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 040771789959b..c6f702dbabaca 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().back()}); else - part.relrDyn->relocs.push_back({&isec, offsetInSec}); + part.relrDyn->relocs.push_back({&isec, &isec.relocs().back()}); return; } part.relaDyn->addRelativeReloc(target->relativeRel, isec, offsetInSec, @@ -1158,9 +1158,13 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, isInt<32>(sym.getVA(addend))) { // Implicit addend is below 32-bits so we can use the compressed // relative relocation section. The R_AARCH64_AUTH_RELATIVE has a - // smaller addend field as bits [63:32] encode the signing-schema. + // smaller addend field as bits [63:32] encode the signing schema. + // The final VA might differ from the one calculated now since it + // might depend on the final layout. If the final VA does not fit 32 + // bits, the packed AUTH reloc will be converted to rela in + // Writer::finalizeAddressDependentContent(). sec->addReloc({expr, type, offset, addend, &sym}); - part.relrAuthDyn->relocs.push_back({sec, offset}); + part.relrAuthDyn->relocs.push_back({sec, &sec->relocs().back()}); } else { part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, DynamicReloc::AddendOnlyWithTargetVA, sym, diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index c36f08e26c2a7..6b35178c0c21d 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -603,10 +603,10 @@ class AndroidPackedRelocationSection final : public RelocationBaseSection { }; struct RelativeReloc { - uint64_t getOffset() const { return inputSec->getVA(offsetInSec); } + uint64_t getOffset() const { return inputSec->getVA(reloc->offset); } const InputSectionBase *inputSec; - uint64_t offsetInSec; + Relocation *reloc; }; class RelrBaseSection : public SyntheticSection { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 5c8195e6448d7..c29ec4c11ce97 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1742,6 +1742,29 @@ template void Writer::finalizeAddressDependentContent() { in.mipsGot->updateAllocSize(); for (Partition &part : partitions) { + // We've put relocations in relrAuthDyn during + // RelocationScanner::processAux, but the target VA for some of them might + // be wider than 32 bits which does not fit the place for implicit value + // of relr AUTH reloc. We can only know the final VA at this point, so + // move relocations with large values from relr to rela. + if (part.relrAuthDyn) { + for (auto it = part.relrAuthDyn->relocs.begin(); + it != part.relrAuthDyn->relocs.end();) { + if (isInt<32>(it->reloc->sym->getVA(it->reloc->addend))) { + ++it; + continue; + } + part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, it->inputSec, + it->reloc->offset, + DynamicReloc::AddendOnlyWithTargetVA, + *it->reloc->sym, it->reloc->addend, R_ABS}); + part.relrAuthDyn->relocs.erase(it); + // We keep the relocation in the it->inputSec->relocations so pointers + // to them in part.relrAuthDyn->relocs items remain valid. See + // corresponding comment AArch64::relocate for details. + changed = true; + } + } changed |= part.relaDyn->updateAllocSize(); if (part.relrDyn) changed |= part.relrDyn->updateAllocSize(); @@ -1881,7 +1904,7 @@ template void Writer::optimizeBasicBlockJumps() { // To deal with the above problem, this function is called after // scanRelocations is called to remove synthetic sections that turn // out to be empty. -static void removeUnusedSyntheticSections() { +template static void removeUnusedSyntheticSections() { // All input synthetic sections that can be empty are placed after // all regular ones. Reverse iterate to find the first synthetic section // after a non-synthetic one which will be our starting point. @@ -1897,6 +1920,18 @@ static void removeUnusedSyntheticSections() { auto *sec = cast(s); if (sec->getParent() && sec->isNeeded()) return false; + // Packed AArch64 AUTH relocs might be moved from .relr.auth.dyn to + // .rela.dyn further in finalizeAddressDependentContent(). It is called + // later since removing unused synthetic sections changes the final + // layout. So, .rela.dyn should be kept now in such a case even if it's + // currently empty. A possible side effect is having empty + // .relr.auth.dyn (if all the packed AUTH relocs were moved to + // .rela.dyn) or empty .rela.dyn (if no rela relocs were there and no + // packed AUTH relocs were moved to it) in the output binary. + if (config->emachine == EM_AARCH64 && config->relrPackDynRelocs) + if (auto *relSec = dyn_cast>(sec)) + if (relSec->name == ".rela.dyn") + return false; unused.insert(sec); return true; }); @@ -2102,7 +2137,7 @@ template void Writer::finalizeSections() { if (in.mipsGot) in.mipsGot->build(); - removeUnusedSyntheticSections(); + removeUnusedSyntheticSections(); script->diagnoseOrphanHandling(); script->diagnoseMissingSGSectionAddress(); diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index 2a7c2c179fd51..370600384e067 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -1,126 +1,228 @@ # REQUIRES: aarch64 -# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o -# RUN: ld.lld -shared %t.so.o -soname=so -o %t.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.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 main.so.o +# RUN: ld.lld -shared main.so.o -soname=so -o main.so +# RUN: llvm-mc -filetype=obj -triple=aarch64 main.s -o main.o + +# RUN: ld.lld -pie main.o main.so -o main +# RUN: llvm-readobj -r main | FileCheck --check-prefix=UNPACKED %s # UNPACKED: Section ({{.+}}) .rela.dyn { -# UNPACKED-NEXT: 0x30440 R_AARCH64_AUTH_RELATIVE - 0x1 -# UNPACKED-NEXT: 0x30448 R_AARCH64_AUTH_RELATIVE - 0x2 -# UNPACKED-NEXT: 0x30450 R_AARCH64_AUTH_RELATIVE - 0x3 -# UNPACKED-NEXT: 0x30458 R_AARCH64_AUTH_RELATIVE - 0x12345678 -# UNPACKED-NEXT: 0x30460 R_AARCH64_AUTH_RELATIVE - 0x123456789A -# UNPACKED-NEXT: 0x30479 R_AARCH64_AUTH_RELATIVE - 0x4 -# UNPACKED-NEXT: 0x30482 R_AARCH64_AUTH_RELATIVE - 0x5 -# UNPACKED-NEXT: 0x30468 R_AARCH64_AUTH_ABS64 zed2 0x0 -# UNPACKED-NEXT: 0x30470 R_AARCH64_AUTH_ABS64 bar2 0x0 +# UNPACKED-NEXT: 0x30470 R_AARCH64_AUTH_RELATIVE - 0x1 +# UNPACKED-NEXT: 0x30478 R_AARCH64_AUTH_RELATIVE - 0x30472 +# UNPACKED-NEXT: 0x30480 R_AARCH64_AUTH_RELATIVE - 0xFFFFFFFFFFFFFFFD +# UNPACKED-NEXT: 0x30488 R_AARCH64_AUTH_RELATIVE - 0x12345678 +# UNPACKED-NEXT: 0x30490 R_AARCH64_AUTH_RELATIVE - 0x123456789A +# UNPACKED-NEXT: 0x30498 R_AARCH64_AUTH_RELATIVE - 0xFFFFFFEDCBA98766 +# UNPACKED-NEXT: 0x304A0 R_AARCH64_AUTH_RELATIVE - 0x8003046F +# UNPACKED-NEXT: 0x304B9 R_AARCH64_AUTH_RELATIVE - 0x4 +# UNPACKED-NEXT: 0x304C2 R_AARCH64_AUTH_RELATIVE - 0x30475 +# UNPACKED-NEXT: 0x304A8 R_AARCH64_AUTH_ABS64 zed2 0x1111 +# UNPACKED-NEXT: 0x304B0 R_AARCH64_AUTH_ABS64 bar2 0x0 # UNPACKED-NEXT: } -# RUN: ld.lld %t.o %t.so -o %t.nopie -# RUN: llvm-readobj -r %t.nopie | FileCheck --check-prefix=NOPIE %s +# RUN: ld.lld main.o main.so -o main.nopie +# RUN: llvm-readobj -r main.nopie | FileCheck --check-prefix=NOPIE %s # NOPIE: Section ({{.+}}) .rela.dyn { -# NOPIE: 0x230430 R_AARCH64_AUTH_RELATIVE - 0x200001 -# NOPIE-NEXT: 0x230438 R_AARCH64_AUTH_RELATIVE - 0x200002 -# NOPIE-NEXT: 0x230440 R_AARCH64_AUTH_RELATIVE - 0x200003 -# NOPIE-NEXT: 0x230448 R_AARCH64_AUTH_RELATIVE - 0x12545678 -# NOPIE-NEXT: 0x230450 R_AARCH64_AUTH_RELATIVE - 0x123476789A -# NOPIE-NEXT: 0x230469 R_AARCH64_AUTH_RELATIVE - 0x200004 -# NOPIE-NEXT: 0x230472 R_AARCH64_AUTH_RELATIVE - 0x200005 -# NOPIE-NEXT: 0x230458 R_AARCH64_AUTH_ABS64 zed2 0x0 -# NOPIE-NEXT: 0x230460 R_AARCH64_AUTH_ABS64 bar2 0x0 +# NOPIE: 0x230460 R_AARCH64_AUTH_RELATIVE - 0x200001 +# NOPIE-NEXT: 0x230468 R_AARCH64_AUTH_RELATIVE - 0x230462 +# NOPIE-NEXT: 0x230470 R_AARCH64_AUTH_RELATIVE - 0x1FFFFD +# NOPIE-NEXT: 0x230478 R_AARCH64_AUTH_RELATIVE - 0x12545678 +# NOPIE-NEXT: 0x230480 R_AARCH64_AUTH_RELATIVE - 0x123476789A +# NOPIE-NEXT: 0x230488 R_AARCH64_AUTH_RELATIVE - 0xFFFFFFEDCBC98766 +# NOPIE-NEXT: 0x230490 R_AARCH64_AUTH_RELATIVE - 0x8023045F +# NOPIE-NEXT: 0x2304A9 R_AARCH64_AUTH_RELATIVE - 0x200004 +# NOPIE-NEXT: 0x2304B2 R_AARCH64_AUTH_RELATIVE - 0x230465 +# NOPIE-NEXT: 0x230498 R_AARCH64_AUTH_ABS64 zed2 0x1111 +# NOPIE-NEXT: 0x2304A0 R_AARCH64_AUTH_ABS64 bar2 0x0 # NOPIE-NEXT: } -# RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2 -# RUN: llvm-readelf -S -d -r -x .test %t2 | FileCheck --check-prefixes=RELR,HEX %s +# RUN: ld.lld -pie -z pack-relative-relocs main.o main.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: .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR:.*]] {{0*}}[[ADDR]] 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: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR]] +# 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 stay in SHT_RELA. +## Any relative relocations with odd offset or value wider than 32 bits stay in SHT_RELA. -# RELR: Relocation section '.rela.dyn' at offset {{.*}} contains 4 entries: +# 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: 0000000000030430 0000000000000411 R_AARCH64_AUTH_RELATIVE 123456789a -# RELR-NEXT: 0000000000030449 0000000000000411 R_AARCH64_AUTH_RELATIVE 4 -# RELR-NEXT: 0000000000030438 0000000100000244 R_AARCH64_AUTH_ABS64 0000000000000000 zed2 + 0 -# RELR-NEXT: 0000000000030440 0000000200000244 R_AARCH64_AUTH_ABS64 0000000000000000 bar2 + 0 +# 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 {{.*}} contains 5 entries: +# 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: 0000000000030410 0000000000000403 R_AARCH64_RELATIVE -# RELR-NEXT: 0000000000030418 0000000000000403 R_AARCH64_RELATIVE -# RELR-NEXT: 0000000000030420 0000000000000403 R_AARCH64_RELATIVE -# RELR-NEXT: 0000000000030428 0000000000000403 R_AARCH64_RELATIVE -# RELR-NEXT: 0000000000030452 0000000000000403 R_AARCH64_RELATIVE +# 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 %t2 | FileCheck --check-prefix=RAW-RELR %s +# 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: 0x30410 -# RAW-RELR-NEXT: 0xF -# RAW-RELR-NEXT: 0x30452 -# RAW-RELR-NEXT: } +# 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: 0x00030410 01000000 2a000020 02000000 2b000000 -## ^^^^^^^^ Addend = 1 +# HEX-NEXT: 0x00030440 01000000 2a000020 42040300 2b000000 +## ^^^^^^^^ Implicit val = 1 = __ehdr_start + 1 ## ^^^^ Discr = 42 ## ^^ Key (bits 5..6) = DA -## ^^^^^^^^ Addend = 2 +## ^^^^^^^^ Implicit val = 0x30442 = 0x30440 + 2 = .test + 2 ## ^^^^ Discr = 43 ## ^^ Key (bits 5..6) = IA -# HEX-NEXT: 0x00030420 03000000 2c000080 78563412 2d000020 -## ^^^^^^^^ Addend = 3 +# 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 -## ^^^^^^^^ Addend = 0x12345678 +## ^^^^^^^^ Implicit val = 0x12345678 = __ehdr_start + 0x12345678 ## ^^^^ Discr = 45 ## ^^ Key (bits 5..6) = DA -# HEX-NEXT: 0x00030430 00000000 2e000020 00000000 2f000020 -## ^^^^^^^^ No implicit addend (rela reloc) +# 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 -## ^^^^^^^^ Addend = 0 +## ^^^^^^^^ No implicit val (rela reloc due to val wider than 32 bits) ## ^^^^ Discr = 47 ## ^^ Key (bits 5..6) = DA -# HEX-NEXT: 0x00030440 00000000 30000000 00000000 00310000 -## ^^^^^^^^ Addend = 0 +# 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: 0x00030480 00000000 32000000 77000000 00330000 +## ^^^^^^^^ No implicit val (rela reloc due to a preemptible symbol) +## ^^^^ Discr = 50 ## ^^ Key (bits 5..6) = IA -## ^^^^^^ ^^ No implicit addend (rela reloc) -## ^^^^ Discr = 49 -# HEX-NEXT: 0x00030450 20000500 00003200 0020{{\ }} +## ^^^^^^ ^^ No implicit val (rela reloc due to odd offset) +## ^^^^ Discr = 51 +# HEX-NEXT: 0x00030490 20774504 03003400 0020{{\ }} ## ^^ Key (bits 5..6) = DA -## ^^^^ ^^^^ Addend = 5 -## ^^^^ Discr = 48 +## ^^^^ ^^^^ 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 (__ehdr_start + 2)@AUTH(ia,43) -.quad (__ehdr_start + 3)@AUTH(ia,44,addr) +.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) -.quad zed2@AUTH(da,47) -.quad bar2@AUTH(ia,48) -.byte 00 -.quad (__ehdr_start + 4)@AUTH(da,49) -.byte 00 -.quad (__ehdr_start + 5)@AUTH(da,50) +## 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) +.byte 0x77 +.quad (__ehdr_start + 4)@AUTH(da,51) +.byte 0x77 +.quad (.test + 5)@AUTH(da,52) + +#--- empty-relr.s + +## During relocation scanning, we might put some AUTH relocs into the packed +## relocation section when not knowing the final implicit value to be stored in +## the place to be relocated. If the value turns out to be wider than 32 bits +## after computing the final layout, we convert the relocation from relr to +## rela. A side effect is having an empty .relr.auth.dyn section if all the +## packed relocations were converted to rela. +## TODO: avoid empty .relr.auth.dyn in the output binary + +# 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 + +## (See comment in empty-relr.s for context) +## If all the packed relocation remain in .relr.auth.dyn and none of them is +## converted to rela while there were no other rela relocs in .rela.dyn, the +## latter would be empty in the output binary. +## TODO: avoid empty .rela.dyn in the output binary + +# 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 b215b0d60ac0c2ac29aeb318da7c95725be6ef86 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Fri, 8 Mar 2024 13:47:04 +0300 Subject: [PATCH 20/34] Address review comments --- lld/ELF/Driver.cpp | 14 +++++---- lld/ELF/Relocations.cpp | 19 +++++------- lld/ELF/SyntheticSections.h | 6 ++-- lld/ELF/Writer.cpp | 43 ++++++++++++++-------------- lld/test/ELF/aarch64-feature-pauth.s | 4 +-- 5 files changed, 42 insertions(+), 44 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 860c85a5782e6..a365a3585c9da 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -46,6 +46,7 @@ #include "lld/Common/Strings.h" #include "lld/Common/TargetOptionsCommandFlags.h" #include "lld/Common/Version.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" @@ -65,7 +66,6 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" -#include #include #include #include @@ -2590,9 +2590,9 @@ static void readSecurityNotes() { StringRef referenceFileName; if (config->emachine == EM_AARCH64) { - auto it = std::find_if( - ctx.objectFiles.begin(), ctx.objectFiles.end(), - [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); }); + auto it = llvm::find_if(ctx.objectFiles, [](const ELFFileBase *f) { + return !f->aarch64PauthAbiTag.empty(); + }); if (it != ctx.objectFiles.end()) { ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag; referenceFileName = (*it)->getName(); @@ -2652,8 +2652,10 @@ static void readSecurityNotes() { errorOrWarn( "incompatible values of AArch64 PAuth compatibility info found" "\n>>> " + - referenceFileName + ": 0x" + toHex(ctx.aarch64PauthAbiTag) + - "\n>>> " + toString(f) + ": 0x" + toHex(f->aarch64PauthAbiTag)); + referenceFileName + ": 0x" + + toHex(ctx.aarch64PauthAbiTag, /*LowerCase=*/true) + "\n>>> " + + toString(f) + ": 0x" + + toHex(f->aarch64PauthAbiTag, /*LowerCase=*/true)); } // Force enable Shadow Stack. diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index c6f702dbabaca..eca232526ee1b 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, &isec.relocs().back()}); + {&isec, isec.relocs().size() - 1}); else - part.relrDyn->relocs.push_back({&isec, &isec.relocs().back()}); + part.relrDyn->relocs.push_back({&isec, isec.relocs().size() - 1}); return; } part.relaDyn->addRelativeReloc(target->relativeRel, isec, offsetInSec, @@ -1154,17 +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 && - isInt<32>(sym.getVA(addend))) { - // Implicit addend is below 32-bits so we can use the compressed - // relative relocation section. The R_AARCH64_AUTH_RELATIVE has a - // smaller addend field as bits [63:32] encode the signing schema. - // The final VA might differ from the one calculated now since it - // might depend on the final layout. If the final VA does not fit 32 - // bits, the packed AUTH reloc will be converted to rela in - // Writer::finalizeAddressDependentContent(). + } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0) { + // When symbol values are determined in + // finalizeAddressDependentContent, some relrAuthDyn relocations may + // be moved to relaDyn. sec->addReloc({expr, type, offset, addend, &sym}); - part.relrAuthDyn->relocs.push_back({sec, &sec->relocs().back()}); + 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.h b/lld/ELF/SyntheticSections.h index 6b35178c0c21d..6f13b331f1bd1 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -603,10 +603,12 @@ class AndroidPackedRelocationSection final : public RelocationBaseSection { }; struct RelativeReloc { - uint64_t getOffset() const { return inputSec->getVA(reloc->offset); } + uint64_t getOffset() const { + return inputSec->getVA(inputSec->relocs()[relocIdx].offset); + } const InputSectionBase *inputSec; - Relocation *reloc; + size_t relocIdx; }; class RelrBaseSection : public SyntheticSection { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index a724b1c3135d9..faa441ce30d40 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -24,6 +24,7 @@ #include "lld/Common/CommonLinkerContext.h" #include "lld/Common/Filesystem.h" #include "lld/Common/Strings.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/BLAKE3.h" #include "llvm/Support/Parallel.h" @@ -1755,28 +1756,26 @@ template void Writer::finalizeAddressDependentContent() { in.mipsGot->updateAllocSize(); for (Partition &part : partitions) { - // We've put relocations in relrAuthDyn during + // The R_AARCH64_AUTH_RELATIVE has a smaller addend field as bits [63:32] + // encode the signing schema. We've put relocations in relrAuthDyn during // RelocationScanner::processAux, but the target VA for some of them might - // be wider than 32 bits which does not fit the place for implicit value - // of relr AUTH reloc. We can only know the final VA at this point, so + // be wider than 32 bits. We can only know the final VA at this point, so // move relocations with large values from relr to rela. if (part.relrAuthDyn) { - for (auto it = part.relrAuthDyn->relocs.begin(); - it != part.relrAuthDyn->relocs.end();) { - if (isInt<32>(it->reloc->sym->getVA(it->reloc->addend))) { - ++it; - continue; - } - part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, it->inputSec, - it->reloc->offset, - DynamicReloc::AddendOnlyWithTargetVA, - *it->reloc->sym, it->reloc->addend, R_ABS}); - part.relrAuthDyn->relocs.erase(it); - // We keep the relocation in the it->inputSec->relocations so pointers - // to them in part.relrAuthDyn->relocs items remain valid. See - // corresponding comment AArch64::relocate for details. - changed = true; - } + 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) @@ -1917,7 +1916,7 @@ template void Writer::optimizeBasicBlockJumps() { // To deal with the above problem, this function is called after // scanRelocations is called to remove synthetic sections that turn // out to be empty. -template static void removeUnusedSyntheticSections() { +static void removeUnusedSyntheticSections() { // All input synthetic sections that can be empty are placed after // all regular ones. Reverse iterate to find the first synthetic section // after a non-synthetic one which will be our starting point. @@ -1942,7 +1941,7 @@ template static void removeUnusedSyntheticSections() { // .rela.dyn) or empty .rela.dyn (if no rela relocs were there and no // packed AUTH relocs were moved to it) in the output binary. if (config->emachine == EM_AARCH64 && config->relrPackDynRelocs) - if (auto *relSec = dyn_cast>(sec)) + if (auto *relSec = dyn_cast(sec)) if (relSec->name == ".rela.dyn") return false; unused.insert(sec); @@ -2151,7 +2150,7 @@ template void Writer::finalizeSections() { if (in.mipsGot) in.mipsGot->build(); - removeUnusedSyntheticSections(); + removeUnusedSyntheticSections(); script->diagnoseOrphanHandling(); script->diagnoseMissingSGSectionAddress(); diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 25c43e6ad0180..44a7479482273 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -13,8 +13,8 @@ # RUN: not ld.lld tag1.o tag1a.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s # ERR1: error: incompatible values of AArch64 PAuth compatibility info found -# ERR1-NEXT: >>> tag1.o: 0x2A000000000000000{{1|2}}00000000000000 -# ERR1-NEXT: >>> tag2.o: 0x2A000000000000000{{1|2}}00000000000000 +# ERR1-NEXT: >>> tag1.o: 0x2a000000000000000{{1|2}}00000000000000 +# ERR1-NEXT: >>> tag2.o: 0x2a000000000000000{{1|2}}00000000000000 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o # RUN: not ld.lld errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s From d32b8e32fc1c938e5a005997b832d215a308037d Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Mon, 18 Mar 2024 12:59:20 +0300 Subject: [PATCH 21/34] Address some review comments --- lld/ELF/Arch/AArch64.cpp | 21 ++++++++------------- lld/ELF/Writer.cpp | 14 +++++--------- lld/test/ELF/aarch64-reloc-pauth.s | 30 ++++++++++++------------------ 3 files changed, 25 insertions(+), 40 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 16de7b738dbdd..a60f595f10aee 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -401,20 +401,15 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, write64(loc, val); break; case R_AARCH64_AUTH_ABS64: - // - If val is wider than 32 bits, we must have converted the auth relr - // reloc to rela in Writer::finalizeAddressDependentContent(). If - // so, no need to write anything, the rela entry holds all the info. + // 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 32 bits: - // - // - The relocation might still be rela instead of relr, for example, if - // the relr -> rela conversion was performed during an iteration in - // finalizeAddressDependentContent, but further iterations made the val - // fitting 32 bits. In such case, there is no trouble with writing the - // val since it will be treated as garbage and have no effect during - // dynamic linking. - // - // - If the relocation is actually relr, write the 32-bit val as expected. + // 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; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 5dbb806484f65..ef51d6eb0fe1c 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1935,17 +1935,13 @@ static void removeUnusedSyntheticSections() { auto *sec = cast(s); if (sec->getParent() && sec->isNeeded()) return false; - // Packed AArch64 AUTH relocs might be moved from .relr.auth.dyn to - // .rela.dyn further in finalizeAddressDependentContent(). It is called - // later since removing unused synthetic sections changes the final - // layout. So, .rela.dyn should be kept now in such a case even if it's - // currently empty. A possible side effect is having empty - // .relr.auth.dyn (if all the packed AUTH relocs were moved to - // .rela.dyn) or empty .rela.dyn (if no rela relocs were there and no - // packed AUTH relocs were moved to it) in the output binary. + // .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->name == ".rela.dyn") + if (relSec == mainPart->relaDyn.get()) return false; unused.insert(sec); return true; diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index 370600384e067..55e8803f3d571 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -2,11 +2,11 @@ # RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o main.so.o -# RUN: ld.lld -shared main.so.o -soname=so -o main.so +# 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 main.so -o main +# RUN: ld.lld -pie main.o a.so -o main # RUN: llvm-readobj -r main | FileCheck --check-prefix=UNPACKED %s # UNPACKED: Section ({{.+}}) .rela.dyn { @@ -23,7 +23,7 @@ # UNPACKED-NEXT: 0x304B0 R_AARCH64_AUTH_ABS64 bar2 0x0 # UNPACKED-NEXT: } -# RUN: ld.lld main.o main.so -o main.nopie +# 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 { @@ -40,7 +40,7 @@ # NOPIE-NEXT: 0x2304A0 R_AARCH64_AUTH_ABS64 bar2 0x0 # NOPIE-NEXT: } -# RUN: ld.lld -pie -z pack-relative-relocs main.o main.so -o main.pie +# 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: @@ -84,7 +84,7 @@ # RAW-RELR-NEXT: 0x30440 # RAW-RELR-NEXT: 0xF ## 0xF = 0b111100..00 -## lsb hsb +## 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 ^^^^^^^ @@ -155,13 +155,9 @@ #--- empty-relr.s -## During relocation scanning, we might put some AUTH relocs into the packed -## relocation section when not knowing the final implicit value to be stored in -## the place to be relocated. If the value turns out to be wider than 32 bits -## after computing the final layout, we convert the relocation from relr to -## rela. A side effect is having an empty .relr.auth.dyn section if all the -## packed relocations were converted to rela. -## TODO: avoid empty .relr.auth.dyn in the output binary +## .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 @@ -193,11 +189,9 @@ #--- empty-rela.s -## (See comment in empty-relr.s for context) -## If all the packed relocation remain in .relr.auth.dyn and none of them is -## converted to rela while there were no other rela relocs in .rela.dyn, the -## latter would be empty in the output binary. -## TODO: avoid empty .rela.dyn in the output binary +## .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 From 978ed06259a3b6ea035dde2c07581f62c45cfd4a Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Mon, 18 Mar 2024 17:36:26 +0300 Subject: [PATCH 22/34] Use `.note.gnu.property` instead of `.note.AARCH64-PAUTH-ABI-tag` --- lld/ELF/InputFiles.cpp | 85 +++++++------------------ lld/ELF/SyntheticSections.cpp | 58 ++++++++--------- lld/ELF/SyntheticSections.h | 11 ---- lld/ELF/Writer.cpp | 7 +- lld/test/ELF/aarch64-feature-pauth.s | 95 ++++++++++++++++++---------- 5 files changed, 114 insertions(+), 142 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index e0639f8528ba3..89dc1afa5e953 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -914,25 +914,18 @@ void ObjFile::initializeSections(bool ignoreComdats, handleSectionGroup(this->sections, entries); } -// If a source file is compiled with x86 hardware-assisted call flow control -// enabled, the generated object file contains feature flags indicating that -// fact. This function reads the feature flags and returns it. -// -// Essentially we want to read a single 32-bit value in this function, but this -// function is rather complicated because the value is buried deep inside a -// .note.gnu.property section. -// -// The section consists of one or more NOTE records. Each NOTE record consists -// of zero or more type-length-value fields. We want to find a field of a -// certain type. It seems a bit too much to just store a 32-bit value, perhaps -// the ABI is unnecessarily complicated. -template static uint32_t readAndFeatures(const InputSection &sec) { +// Read the following info from the .note.gnu.property section and write it to +// the corresponding fields in `ObjFile`: +// - Feature flags (32 bits) representing x86 or AArch64 features for +// hardware-assisted call flow control; +// - AArch64 PAuth ABI compatibility info (16 bytes). +template +void readGnuProperty(const InputSection &sec, ObjFile &f) { using Elf_Nhdr = typename ELFT::Nhdr; using Elf_Note = typename ELFT::Note; - uint32_t featuresSet = 0; ArrayRef data = sec.content(); - auto reportFatal = [&](const uint8_t *place, const char *msg) { + auto reportFatal = [&](const uint8_t *place, const Twine &msg) { fatal(toString(sec.file) + ":(" + sec.name + "+0x" + Twine::utohexstr(place - sec.content().data()) + "): " + msg); }; @@ -971,7 +964,20 @@ template static uint32_t readAndFeatures(const InputSection &sec) { // accumulate the bits set. if (size < 4) reportFatal(place, "FEATURE_1_AND entry is too short"); - featuresSet |= read32(desc.data()); + f.andFeatures |= read32(desc.data()); + } else if (config->emachine == EM_AARCH64 && + type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) { + if (!f.aarch64PauthAbiTag.empty()) + reportFatal(data.data(), + "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are " + "not supported"); + if (size != 16) + reportFatal( + data.data(), + Twine("GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too ") + + (size < 16 ? "short" : "long") + + ": expected 16 bytes, but got " + Twine(size)); + f.aarch64PauthAbiTag = desc; } // Padding is present in the note descriptor, if necessary. @@ -981,45 +987,6 @@ template static uint32_t readAndFeatures(const InputSection &sec) { // Go to next NOTE record to look for more FEATURE_1_AND descriptions. data = data.slice(nhdr->getSize(sec.addralign)); } - - return featuresSet; -} - -// Extract compatibility info for aarch64 pointer authentication from the -// .note.AARCH64-PAUTH-ABI-tag section and write it to the corresponding ObjFile -// field. See the following ABI documentation: -// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking -template -static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile &f) { - using Elf_Nhdr = typename ELFT::Nhdr; - using Elf_Note = typename ELFT::Note; - ArrayRef data = sec.content(); - - auto *nhdr = reinterpret_cast(data.data()); - if (data.size() < sizeof(Elf_Nhdr) || - data.size() < nhdr->getSize(sec.addralign)) { - errorOrWarn(toString(&sec) + ": section is too short"); - return; - } - - Elf_Note note(*nhdr); - if (nhdr->n_type != NT_ARM_TYPE_PAUTH_ABI_TAG) - errorOrWarn(toString(&sec) + ": invalid type field value " + - Twine(nhdr->n_type) + " (" + Twine(NT_ARM_TYPE_PAUTH_ABI_TAG) + - " expected)"); - if (note.getName() != "ARM") - errorOrWarn(toString(&sec) + ": invalid name field value " + - note.getName() + " (ARM expected)"); - - ArrayRef desc = note.getDesc(sec.addralign); - if (desc.size() < 16) { - errorOrWarn(toString(&sec) + - ": AArch64 PAuth compatibility info is too short " - "(at least 16 bytes expected)"); - return; - } - - f.aarch64PauthAbiTag = desc; } template @@ -1076,13 +1043,7 @@ InputSectionBase *ObjFile::createInputSection(uint32_t idx, // .note.gnu.property containing a single AND'ed bitmap, we discard an input // file's .note.gnu.property section. if (name == ".note.gnu.property") { - this->andFeatures = readAndFeatures(InputSection(*this, sec, name)); - return &InputSection::discarded; - } - - if (config->emachine == EM_AARCH64 && - name == ".note.AARCH64-PAUTH-ABI-tag") { - readAArch64PauthAbiTag(InputSection(*this, sec, name), *this); + readGnuProperty(InputSection(*this, sec, name), *this); return &InputSection::discarded; } diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index faab4bdc83748..9a8f54b42b841 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -314,44 +314,42 @@ GnuPropertySection::GnuPropertySection() config->wordsize, ".note.gnu.property") {} void GnuPropertySection::writeTo(uint8_t *buf) { + write32(buf, 4); // Name size + write32(buf + 4, getSize() - 16); // Content size + write32(buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type + memcpy(buf + 12, "GNU", 4); // Name string + uint32_t featureAndType = config->emachine == EM_AARCH64 ? GNU_PROPERTY_AARCH64_FEATURE_1_AND : GNU_PROPERTY_X86_FEATURE_1_AND; - write32(buf, 4); // Name size - write32(buf + 4, config->is64 ? 16 : 12); // Content size - write32(buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type - memcpy(buf + 12, "GNU", 4); // Name string - write32(buf + 16, featureAndType); // Feature type - write32(buf + 20, 4); // Feature size - write32(buf + 24, config->andFeatures); // Feature flags - if (config->is64) - write32(buf + 28, 0); // Padding -} + unsigned offset = 16; -size_t GnuPropertySection::getSize() const { return config->is64 ? 32 : 28; } - -AArch64PauthAbiTag::AArch64PauthAbiTag() - : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE, - config->wordsize, ".note.AARCH64-PAUTH-ABI-tag") {} - -bool AArch64PauthAbiTag::isNeeded() const { - return !ctx.aarch64PauthAbiTag.empty(); -} + if (config->andFeatures != 0) { + write32(buf + offset + 0, featureAndType); // Feature type + write32(buf + offset + 4, 4); // Feature size + write32(buf + offset + 8, config->andFeatures); // Feature flags + if (config->is64) + write32(buf + offset + 12, 0); // Padding + offset += 16; + } -void AArch64PauthAbiTag::writeTo(uint8_t *buf) { - ArrayRef data = ctx.aarch64PauthAbiTag; - write32(buf, 4); // Name size - write32(buf + 4, data.size()); // Content size - write32(buf + 8, NT_ARM_TYPE_PAUTH_ABI_TAG); // Type - memcpy(buf + 12, "ARM", 4); // Name string - memcpy(buf + 16, data.data(), data.size()); - memset(buf + 16 + data.size(), 0, getSize() - 16 - data.size()); // Padding + if (!ctx.aarch64PauthAbiTag.empty()) { + write32(buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH); + write32(buf + offset + 4, ctx.aarch64PauthAbiTag.size()); + memcpy(buf + offset + 8, ctx.aarch64PauthAbiTag.data(), + ctx.aarch64PauthAbiTag.size()); + } } -size_t AArch64PauthAbiTag::getSize() const { - return alignToPowerOf2(16 + ctx.aarch64PauthAbiTag.size(), - config->is64 ? 8 : 4); +size_t GnuPropertySection::getSize() const { + uint32_t contentSize = 0; + if (config->andFeatures != 0) + contentSize += config->is64 ? 16 : 12; + if (!ctx.aarch64PauthAbiTag.empty()) + contentSize += 4 + 4 + ctx.aarch64PauthAbiTag.size(); + assert(contentSize != 0); + return contentSize + 16; } BuildIdSection::BuildIdSection() diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 6f13b331f1bd1..44ec306895549 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -144,16 +144,6 @@ class GnuPropertySection final : public SyntheticSection { size_t getSize() const override; }; -// .note.AARCH64-PAUTH-ABI-tag section. See -// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking -class AArch64PauthAbiTag final : public SyntheticSection { -public: - AArch64PauthAbiTag(); - void writeTo(uint8_t *buf) override; - size_t getSize() const override; - bool isNeeded() const override; -}; - // .note.gnu.build-id section. class BuildIdSection : public SyntheticSection { // First 16 bytes are a header. @@ -1378,7 +1368,6 @@ struct InStruct { std::unique_ptr strTab; std::unique_ptr symTab; std::unique_ptr symTabShndx; - std::unique_ptr aarch64PauthAbiTag; void reset(); }; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index ef51d6eb0fe1c..c155ae709da65 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -579,14 +579,9 @@ template void elf::createSyntheticSections() { in.iplt = std::make_unique(); add(*in.iplt); - if (config->andFeatures) + if (config->andFeatures || !ctx.aarch64PauthAbiTag.empty()) add(*make()); - if (!ctx.aarch64PauthAbiTag.empty()) { - in.aarch64PauthAbiTag = std::make_unique(); - add(*in.aarch64PauthAbiTag); - } - // .note.GNU-stack is always added when we are creating a re-linkable // object file. Other linkers are using the presence of this marker // section to control the executable-ness of the stack area, but that diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 44a7479482273..a0bc823b477ad 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -7,7 +7,7 @@ # RUN: ld.lld -shared tag1.o tag1a.o -o tagok.so # RUN: llvm-readelf -n tagok.so | FileCheck --check-prefix OK %s -# OK: AArch64 PAuth ABI tag: platform 0x2a, version 0x1 +# OK: AArch64 PAuth ABI tag: platform 0x2a (unknown), version 0x1 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o # RUN: not ld.lld tag1.o tag1a.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s @@ -16,66 +16,95 @@ # ERR1-NEXT: >>> tag1.o: 0x2a000000000000000{{1|2}}00000000000000 # ERR1-NEXT: >>> tag2.o: 0x2a000000000000000{{1|2}}00000000000000 -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o -# RUN: not ld.lld errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o short.o +# RUN: not ld.lld short.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s -# ERR2: error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): invalid type field value 42 (1 expected) -# ERR2-NEXT: error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): invalid name field value XXX (ARM expected) -# ERR2-NEXT: error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): AArch64 PAuth compatibility info is too short (at least 16 bytes expected) +# ERR2: error: short.o:(.note.gnu.property+0x0): GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too short: expected 16 bytes, but got 12 -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o short.o -# RUN: not ld.lld short.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR3 %s +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-long.s -o long.o +# RUN: not ld.lld long.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR3 %s + +# ERR3: error: long.o:(.note.gnu.property+0x0): GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too long: expected 16 bytes, but got 24 -# ERR3: error: short.o:(.note.AARCH64-PAUTH-ABI-tag): section is too short +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-multiple.s -o multiple.o +# RUN: not ld.lld multiple.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s +# ERR4: error: multiple.o:(.note.gnu.property+0x0): multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are not supported # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu no-info.s -o noinfo1.o # RUN: cp noinfo1.o noinfo2.o -# RUN: not ld.lld -z pauth-report=error tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s +# RUN: not ld.lld -z pauth-report=error tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR5 %s # RUN: ld.lld -z pauth-report=warning tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s # RUN: ld.lld -z pauth-report=none tag1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null -# ERR4: error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one -# ERR4-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one +# ERR5: error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one +# ERR5-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one # WARN: warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one # WARN-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one #--- abi-tag-short.s -.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.section ".note.gnu.property", "a" .long 4 -.long 8 +.long 20 +.long 5 +.asciz "GNU" +.long 0xc0000001 +.long 12 +.quad 2 +.long 31 -#--- abi-tag-errs.s +#--- abi-tag-long.s -.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.section ".note.gnu.property", "a" .long 4 -.long 8 -.long 42 -.asciz "XXX" - -.quad 42 +.long 32 +.long 5 +.asciz "GNU" +.long 0xc0000001 +.long 24 +.quad 2 +.quad 31 +.quad 0 + +#--- abi-tag-multiple.s + +.section ".note.gnu.property", "a" +.long 4 +.long 48 +.long 5 +.asciz "GNU" +.long 0xc0000001 +.long 16 +.quad 42 // platform +.quad 1 // version +.long 0xc0000001 +.long 16 +.quad 42 // platform +.quad 1 // version #--- abi-tag1.s -.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.section ".note.gnu.property", "a" .long 4 +.long 24 +.long 5 +.asciz "GNU" +.long 0xc0000001 .long 16 -.long 1 -.asciz "ARM" - -.quad 42 // platform -.quad 1 // version +.quad 42 // platform +.quad 1 // version #--- abi-tag2.s -.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.section ".note.gnu.property", "a" .long 4 +.long 24 +.long 5 +.asciz "GNU" +.long 0xc0000001 .long 16 -.long 1 -.asciz "ARM" - -.quad 42 // platform -.quad 2 // version +.quad 42 // platform +.quad 2 // version #--- no-info.s From 728c93355150ef5ad712aca3910def600d68ee86 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 19 Mar 2024 17:37:59 +0300 Subject: [PATCH 23/34] Rename PAuth ABI Tag to PAuth ABI Core Info --- lld/ELF/Config.h | 2 +- lld/ELF/Driver.cpp | 14 +++++++------- lld/ELF/InputFiles.cpp | 4 ++-- lld/ELF/InputFiles.h | 2 +- lld/ELF/SyntheticSections.cpp | 12 ++++++------ lld/ELF/Writer.cpp | 2 +- lld/test/ELF/aarch64-feature-pauth.s | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index f7d0923f08342..615d267b6e0e1 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -501,7 +501,7 @@ struct Ctx { llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &); - ArrayRef aarch64PauthAbiTag; + ArrayRef aarch64PauthAbiCoreInfo; }; LLVM_LIBRARY_VISIBILITY extern Ctx ctx; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 16d0139b66438..e5a62125a10bf 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2610,10 +2610,10 @@ static void readSecurityNotes() { StringRef referenceFileName; if (config->emachine == EM_AARCH64) { auto it = llvm::find_if(ctx.objectFiles, [](const ELFFileBase *f) { - return !f->aarch64PauthAbiTag.empty(); + return !f->aarch64PauthAbiCoreInfo.empty(); }); if (it != ctx.objectFiles.end()) { - ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag; + ctx.aarch64PauthAbiCoreInfo = (*it)->aarch64PauthAbiCoreInfo; referenceFileName = (*it)->getName(); } } @@ -2655,10 +2655,10 @@ static void readSecurityNotes() { } config->andFeatures &= features; - if (ctx.aarch64PauthAbiTag.empty()) + if (ctx.aarch64PauthAbiCoreInfo.empty()) continue; - if (f->aarch64PauthAbiTag.empty()) { + if (f->aarch64PauthAbiCoreInfo.empty()) { reportMissingFeature(config->zPauthReport, toString(f) + ": -z pauth-report: file does not have AArch64 " @@ -2667,14 +2667,14 @@ static void readSecurityNotes() { continue; } - if (ctx.aarch64PauthAbiTag != f->aarch64PauthAbiTag) + if (ctx.aarch64PauthAbiCoreInfo != f->aarch64PauthAbiCoreInfo) errorOrWarn( "incompatible values of AArch64 PAuth compatibility info found" "\n>>> " + referenceFileName + ": 0x" + - toHex(ctx.aarch64PauthAbiTag, /*LowerCase=*/true) + "\n>>> " + + toHex(ctx.aarch64PauthAbiCoreInfo, /*LowerCase=*/true) + "\n>>> " + toString(f) + ": 0x" + - toHex(f->aarch64PauthAbiTag, /*LowerCase=*/true)); + toHex(f->aarch64PauthAbiCoreInfo, /*LowerCase=*/true)); } // Force enable Shadow Stack. diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 89dc1afa5e953..b4bb18abbb0dc 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -967,7 +967,7 @@ void readGnuProperty(const InputSection &sec, ObjFile &f) { f.andFeatures |= read32(desc.data()); } else if (config->emachine == EM_AARCH64 && type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) { - if (!f.aarch64PauthAbiTag.empty()) + if (!f.aarch64PauthAbiCoreInfo.empty()) reportFatal(data.data(), "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are " "not supported"); @@ -977,7 +977,7 @@ void readGnuProperty(const InputSection &sec, ObjFile &f) { Twine("GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too ") + (size < 16 ? "short" : "long") + ": expected 16 bytes, but got " + Twine(size)); - f.aarch64PauthAbiTag = desc; + f.aarch64PauthAbiCoreInfo = desc; } // Padding is present in the note descriptor, if necessary. diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index dd43759f7fc2e..7d2a664a6e806 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -230,7 +230,7 @@ class ELFFileBase : public InputFile { public: uint32_t andFeatures = 0; bool hasCommonSyms = false; - ArrayRef aarch64PauthAbiTag; + ArrayRef aarch64PauthAbiCoreInfo; }; // .o file. diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index dd0bb2abbde2a..a53797259be3d 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -334,11 +334,11 @@ void GnuPropertySection::writeTo(uint8_t *buf) { offset += 16; } - if (!ctx.aarch64PauthAbiTag.empty()) { + if (!ctx.aarch64PauthAbiCoreInfo.empty()) { write32(buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH); - write32(buf + offset + 4, ctx.aarch64PauthAbiTag.size()); - memcpy(buf + offset + 8, ctx.aarch64PauthAbiTag.data(), - ctx.aarch64PauthAbiTag.size()); + write32(buf + offset + 4, ctx.aarch64PauthAbiCoreInfo.size()); + memcpy(buf + offset + 8, ctx.aarch64PauthAbiCoreInfo.data(), + ctx.aarch64PauthAbiCoreInfo.size()); } } @@ -346,8 +346,8 @@ size_t GnuPropertySection::getSize() const { uint32_t contentSize = 0; if (config->andFeatures != 0) contentSize += config->is64 ? 16 : 12; - if (!ctx.aarch64PauthAbiTag.empty()) - contentSize += 4 + 4 + ctx.aarch64PauthAbiTag.size(); + if (!ctx.aarch64PauthAbiCoreInfo.empty()) + contentSize += 4 + 4 + ctx.aarch64PauthAbiCoreInfo.size(); assert(contentSize != 0); return contentSize + 16; } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index c155ae709da65..c9c77812588fa 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -579,7 +579,7 @@ template void elf::createSyntheticSections() { in.iplt = std::make_unique(); add(*in.iplt); - if (config->andFeatures || !ctx.aarch64PauthAbiTag.empty()) + if (config->andFeatures || !ctx.aarch64PauthAbiCoreInfo.empty()) add(*make()); // .note.GNU-stack is always added when we are creating a re-linkable diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index a0bc823b477ad..5fc49880d3e9e 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -7,7 +7,7 @@ # RUN: ld.lld -shared tag1.o tag1a.o -o tagok.so # RUN: llvm-readelf -n tagok.so | FileCheck --check-prefix OK %s -# OK: AArch64 PAuth ABI tag: platform 0x2a (unknown), version 0x1 +# OK: AArch64 PAuth ABI core info: platform 0x2a (unknown), version 0x1 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o # RUN: not ld.lld tag1.o tag1a.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s From 4409838992a87a325843393be1ff30c67cdabc7b Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 19 Mar 2024 17:45:28 +0300 Subject: [PATCH 24/34] Update comments - Delete `.note.AARCH64-PAUTH-ABI-tag`-related one - Use `.relr.auth.dyn` and `.rela.dyn` instead of similar terms --- lld/ELF/Driver.cpp | 7 ++----- lld/ELF/Relocations.cpp | 4 ++-- lld/ELF/Writer.cpp | 9 +++++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index e5a62125a10bf..b03b54b03367b 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -3017,11 +3017,8 @@ void LinkerDriver::link(opt::InputArgList &args) { // partition. mainPart = &partitions[0]; - // Read: - // - .note.gnu.property sections from input object files which - // contain a hint to tweak linker's and loader's behaviors; - // - .note.AARCH64-PAUTH-ABI-tag sections contents from input object files - // which contain AArch64 PAuth compatibility info. + // Read .note.gnu.property sections from input object files which + // contain a hint to tweak linker's and loader's behaviors. readSecurityNotes(); // The Target instance handles target-specific stuff, such as applying diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index eca232526ee1b..e6a77c7885e46 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1156,8 +1156,8 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, 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 relrAuthDyn relocations may - // be moved to relaDyn. + // 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 { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index c9c77812588fa..35fdd1d73da94 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1755,10 +1755,11 @@ template void Writer::finalizeAddressDependentContent() { 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 relrAuthDyn 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 to rela. + // 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) { From 128831c02cb54ed7b0b9afa7c17b3f8d3ffb6f7c Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 19 Mar 2024 17:57:55 +0300 Subject: [PATCH 25/34] Rename PAuth ABI compatibility info to PAuth ABI core info --- lld/ELF/Driver.cpp | 20 +++++++++----------- lld/ELF/InputFiles.cpp | 2 +- lld/test/ELF/aarch64-feature-pauth.s | 10 +++++----- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index b03b54b03367b..f53670fd76a67 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2597,9 +2597,9 @@ static void checkAndReportMissingFeature(StringRef config, uint32_t features, // This is also the case with AARCH64's BTI and PAC which use the similar // GNU_PROPERTY_AARCH64_FEATURE_1_AND mechanism. // -// For AArch64 PAuth-enabled object files, the compatibility info of all of them -// must match. Missing info for some object files with matching info for -// remaining ones can be allowed (see -z pauth-report). +// For AArch64 PAuth-enabled object files, the core info of all of them must +// match. Missing info for some object files with matching info for remaining +// ones can be allowed (see -z pauth-report). static void readSecurityNotes() { if (config->emachine != EM_386 && config->emachine != EM_X86_64 && config->emachine != EM_AARCH64) @@ -2662,19 +2662,17 @@ static void readSecurityNotes() { reportMissingFeature(config->zPauthReport, toString(f) + ": -z pauth-report: file does not have AArch64 " - "PAuth compatibility info while " + + "PAuth core info while " + referenceFileName + " has one"); continue; } if (ctx.aarch64PauthAbiCoreInfo != f->aarch64PauthAbiCoreInfo) - errorOrWarn( - "incompatible values of AArch64 PAuth compatibility info found" - "\n>>> " + - referenceFileName + ": 0x" + - toHex(ctx.aarch64PauthAbiCoreInfo, /*LowerCase=*/true) + "\n>>> " + - toString(f) + ": 0x" + - toHex(f->aarch64PauthAbiCoreInfo, /*LowerCase=*/true)); + errorOrWarn("incompatible values of AArch64 PAuth core info found\n>>> " + + referenceFileName + ": 0x" + + toHex(ctx.aarch64PauthAbiCoreInfo, /*LowerCase=*/true) + + "\n>>> " + toString(f) + ": 0x" + + toHex(f->aarch64PauthAbiCoreInfo, /*LowerCase=*/true)); } // Force enable Shadow Stack. diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index b4bb18abbb0dc..93616f4ec6baf 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -918,7 +918,7 @@ void ObjFile::initializeSections(bool ignoreComdats, // the corresponding fields in `ObjFile`: // - Feature flags (32 bits) representing x86 or AArch64 features for // hardware-assisted call flow control; -// - AArch64 PAuth ABI compatibility info (16 bytes). +// - AArch64 PAuth ABI core info (16 bytes). template void readGnuProperty(const InputSection &sec, ObjFile &f) { using Elf_Nhdr = typename ELFT::Nhdr; diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 5fc49880d3e9e..4d6e16506d321 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -12,7 +12,7 @@ # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o # RUN: not ld.lld tag1.o tag1a.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s -# ERR1: error: incompatible values of AArch64 PAuth compatibility info found +# ERR1: error: incompatible values of AArch64 PAuth core info found # ERR1-NEXT: >>> tag1.o: 0x2a000000000000000{{1|2}}00000000000000 # ERR1-NEXT: >>> tag2.o: 0x2a000000000000000{{1|2}}00000000000000 @@ -36,10 +36,10 @@ # RUN: ld.lld -z pauth-report=warning tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s # RUN: ld.lld -z pauth-report=none tag1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null -# ERR5: error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one -# ERR5-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one -# WARN: warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one -# WARN-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one +# ERR5: error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth core info while tag1.o has one +# ERR5-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth core info while tag1.o has one +# WARN: warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth core info while tag1.o has one +# WARN-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth core info while tag1.o has one #--- abi-tag-short.s From 05cf361d5278f3e423ab40835c47070cdbb494b8 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 3 Apr 2024 02:50:40 +0300 Subject: [PATCH 26/34] Delete RELR-related changes --- 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 | 181 ++++++----------------------- 6 files changed, 46 insertions(+), 233 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index a60f595f10aee..017c17c2b03d8 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -400,19 +400,6 @@ 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 5f66b98fac687..55274344f8811 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, isec.relocs().size() - 1}); + {&isec, offsetInSec}); else - part.relrDyn->relocs.push_back({&isec, isec.relocs().size() - 1}); + part.relrDyn->relocs.push_back({&isec, offsetInSec}); return; } part.relaDyn->addRelativeReloc(target->relativeRel, isec, offsetInSec, @@ -1154,12 +1154,6 @@ 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 a24aa2ca8b15a..bc59b4353e183 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1417,12 +1417,6 @@ 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()); @@ -1733,13 +1727,10 @@ template void RelocationSection::writeTo(uint8_t *buf) { } } -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"), +RelrBaseSection::RelrBaseSection(unsigned concurrency) + : SyntheticSection(SHF_ALLOC, + config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR, + config->wordsize, ".relr.dyn"), relocsVec(concurrency) {} void RelrBaseSection::mergeRels() { @@ -2007,8 +1998,8 @@ bool AndroidPackedRelocationSection::updateAllocSize() { } template -RelrSection::RelrSection(unsigned concurrency, bool isAArch64Auth) - : RelrBaseSection(concurrency, isAArch64Auth) { +RelrSection::RelrSection(unsigned concurrency) + : RelrBaseSection(concurrency) { this->entsize = config->wordsize; } diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 04e8d1992ecf7..02a669b01d152 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -543,9 +543,7 @@ 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 || - (config->emachine == llvm::ELF::EM_AARCH64 && - d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR)); + d->type == llvm::ELF::SHT_RELR); } int32_t dynamicTag, sizeDynamicTag; SmallVector relocs; @@ -593,17 +591,15 @@ class AndroidPackedRelocationSection final : public RelocationBaseSection { }; struct RelativeReloc { - uint64_t getOffset() const { - return inputSec->getVA(inputSec->relocs()[relocIdx].offset); - } + uint64_t getOffset() const { return inputSec->getVA(offsetInSec); } const InputSectionBase *inputSec; - size_t relocIdx; + uint64_t offsetInSec; }; class RelrBaseSection : public SyntheticSection { public: - RelrBaseSection(unsigned concurrency, bool isAArch64Auth = false); + RelrBaseSection(unsigned concurrency); void mergeRels(); bool isNeeded() const override { return !relocs.empty() || @@ -621,7 +617,7 @@ template class RelrSection final : public RelrBaseSection { using Elf_Relr = typename ELFT::Relr; public: - RelrSection(unsigned concurrency, bool isAArch64Auth = false); + RelrSection(unsigned concurrency); bool updateAllocSize() override; size_t getSize() const override { return relrRelocs.size() * this->entsize; } @@ -1323,7 +1319,6 @@ 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 9ea5ff5ba716a..fc9084f40044d 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -456,9 +456,6 @@ 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) { @@ -1733,33 +1730,9 @@ 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(); } @@ -1910,14 +1883,6 @@ 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; }); @@ -2230,10 +2195,6 @@ 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 55e8803f3d571..399dae25817f9 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -1,13 +1,11 @@ # REQUIRES: aarch64 -# RUN: rm -rf %t && split-file %s %t && cd %t +# 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: 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 +# RUN: ld.lld -pie %t.o %t.a.so -o %t +# RUN: llvm-readobj -r %t | FileCheck --check-prefix=UNPACKED %s # UNPACKED: Section ({{.+}}) .rela.dyn { # UNPACKED-NEXT: 0x30470 R_AARCH64_AUTH_RELATIVE - 0x1 @@ -23,8 +21,8 @@ # UNPACKED-NEXT: 0x304B0 R_AARCH64_AUTH_ABS64 bar2 0x0 # UNPACKED-NEXT: } -# RUN: ld.lld main.o a.so -o main.nopie -# RUN: llvm-readobj -r main.nopie | FileCheck --check-prefix=NOPIE %s +# RUN: ld.lld %t.o %t.a.so -o %t.nopie +# RUN: llvm-readobj -r %t.nopie | FileCheck --check-prefix=NOPIE %s # NOPIE: Section ({{.+}}) .rela.dyn { # NOPIE: 0x230460 R_AARCH64_AUTH_RELATIVE - 0x200001 @@ -40,111 +38,66 @@ # NOPIE-NEXT: 0x2304A0 R_AARCH64_AUTH_ABS64 bar2 0x0 # NOPIE-NEXT: } -# 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: } +# 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*}}[[ADDR1:.*]] {{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 # HEX: Hex dump of section '.test': -# HEX-NEXT: 0x00030440 01000000 2a000020 42040300 2b000000 -## ^^^^^^^^ Implicit val = 1 = __ehdr_start + 1 +# HEX-NEXT: 0x00030470 00000000 2a000020 00000000 2b000000 ## ^^^^ Discr = 42 ## ^^ Key (bits 5..6) = DA -## ^^^^^^^^ Implicit val = 0x30442 = 0x30440 + 2 = .test + 2 ## ^^^^ Discr = 43 ## ^^ Key (bits 5..6) = IA -# HEX-NEXT: 0x00030450 fdffffff 2c000080 78563412 2d000020 -## ^^^^^^^^ Implicit val = -3 = __ehdr_start - 3 +# HEX-NEXT: 0x00030480 00000000 2c000080 00000000 2d000020 ## ^^^^ 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: 0x00030460 00000000 2e000020 00000000 2f000020 -## ^^^^^^^^ No implicit val (rela reloc due val wider than 32 bits) +# HEX-NEXT: 0x00030490 00000000 2e000020 00000000 2f000020 ## ^^^^ 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: 0x00030470 00000000 30000020 00000000 31000020 -## ^^^^^^^^ No implicit val (rela reloc due val wider than 32 bits) +# HEX-NEXT: 0x000304a0 00000000 30000020 00000000 31000020 ## ^^^^ 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: 0x00030480 00000000 32000000 77000000 00330000 -## ^^^^^^^^ No implicit val (rela reloc due to a preemptible symbol) +# HEX-NEXT: 0x000304b0 00000000 32000000 77000000 00330000 ## ^^^^ Discr = 50 ## ^^ Key (bits 5..6) = IA -## ^^^^^^ ^^ No implicit val (rela reloc due to odd offset) ## ^^^^ Discr = 51 -# HEX-NEXT: 0x00030490 20774504 03003400 0020{{\ }} +# HEX-NEXT: 0x000304c0 20770000 00003400 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) @@ -152,71 +105,3 @@ .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 f4595272e7afd809e3bf65948037dfaebc216a91 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 2 Apr 2024 22:50:37 -0700 Subject: [PATCH 27/34] Simplify a short/long message with just "invalid" --- lld/ELF/InputFiles.cpp | 13 ++++++------- lld/test/ELF/aarch64-feature-pauth.s | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 06a2ae1ff48fa..1f496026d3ae2 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -979,16 +979,15 @@ void readGnuProperty(const InputSection &sec, ObjFile &f) { f.andFeatures |= read32(desc.data()); } else if (config->emachine == EM_AARCH64 && type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) { - if (!f.aarch64PauthAbiCoreInfo.empty()) + if (!f.aarch64PauthAbiCoreInfo.empty()) { reportFatal(data.data(), "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are " "not supported"); - if (size != 16) - reportFatal( - data.data(), - Twine("GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too ") + - (size < 16 ? "short" : "long") + - ": expected 16 bytes, but got " + Twine(size)); + } else if (size != 16) { + reportFatal(data.data(), "GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry " + "is invalid: expected 16 bytes, but got " + + Twine(size)); + } f.aarch64PauthAbiCoreInfo = desc; } diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 4d6e16506d321..2a6faf74a8f22 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -19,12 +19,12 @@ # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o short.o # RUN: not ld.lld short.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s -# ERR2: error: short.o:(.note.gnu.property+0x0): GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too short: expected 16 bytes, but got 12 +# ERR2: error: short.o:(.note.gnu.property+0x0): GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is invalid: expected 16 bytes, but got 12 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-long.s -o long.o # RUN: not ld.lld long.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR3 %s -# ERR3: error: long.o:(.note.gnu.property+0x0): GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too long: expected 16 bytes, but got 24 +# ERR3: error: long.o:(.note.gnu.property+0x0): GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is invalid: expected 16 bytes, but got 24 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-multiple.s -o multiple.o # RUN: not ld.lld multiple.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s From 2846e7674b74130ec3f1ec01520a443747c50d0d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 2 Apr 2024 22:54:22 -0700 Subject: [PATCH 28/34] [test] add --implicit-check-not=error and avoid expensive .* regex --- lld/test/ELF/aarch64-reloc-pauth-ro.s | 2 +- lld/test/ELF/aarch64-reloc-pauth.s | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lld/test/ELF/aarch64-reloc-pauth-ro.s b/lld/test/ELF/aarch64-reloc-pauth-ro.s index 5bc9d805b481a..1be78ba4666e9 100644 --- a/lld/test/ELF/aarch64-reloc-pauth-ro.s +++ b/lld/test/ELF/aarch64-reloc-pauth-ro.s @@ -3,7 +3,7 @@ # RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o # RUN: ld.lld -shared %t.so.o -soname=so -o %t.so # RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o -# RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck -DFILE=%t %s +# RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck -DFILE=%t %s --implicit-check-not=error: # CHECK: error: relocation R_AARCH64_AUTH_ABS64 cannot be used against symbol 'zed2'; recompile with -fPIC # CHECK-NEXT: >>> defined in [[FILE]].so diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s index 399dae25817f9..b603d8ffdcabd 100644 --- a/lld/test/ELF/aarch64-reloc-pauth.s +++ b/lld/test/ELF/aarch64-reloc-pauth.s @@ -43,9 +43,10 @@ # PIE: Section Headers: # PIE-NEXT: Name Type Address Off Size ES Flg Lk Inf Al -# PIE: .rela.dyn RELA {{0*}}[[ADDR1:.*]] {{0*}}[[ADDR1]] 000108 18 A 1 0 8 +# 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: 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 From 45fcbb95a404f2e2d42d8768a2bd6526678f4aa9 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 2 Apr 2024 22:57:56 -0700 Subject: [PATCH 29/34] add release note --- lld/docs/ReleaseNotes.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 97ed060489100..13459cf9cca01 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -29,6 +29,9 @@ ELF Improvements * ``--compress-sections =[none|zlib|zstd]`` is added to compress matched output sections without the ``SHF_ALLOC`` flag. (`#84855 `_) +* ``GNU_PROPERTY_AARCH64_FEATURE_PAUTH`` notes and ``R_AARCH64_AUTH_ABS64`` + relocations are now supported. + (`#72714 `_) Breaking changes ---------------- From 0eb272af25cb8702f53828f8bf06989939b5240b Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 3 Apr 2024 10:49:17 +0300 Subject: [PATCH 30/34] Mention `R_AARCH64_AUTH_RELATIVE` in release notes --- lld/docs/ReleaseNotes.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 13459cf9cca01..bf0c8e55d103e 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -29,8 +29,8 @@ ELF Improvements * ``--compress-sections =[none|zlib|zstd]`` is added to compress matched output sections without the ``SHF_ALLOC`` flag. (`#84855 `_) -* ``GNU_PROPERTY_AARCH64_FEATURE_PAUTH`` notes and ``R_AARCH64_AUTH_ABS64`` - relocations are now supported. +* ``GNU_PROPERTY_AARCH64_FEATURE_PAUTH`` notes, ``R_AARCH64_AUTH_ABS64`` and + ``R_AARCH64_AUTH_RELATIVE`` relocations are now supported. (`#72714 `_) Breaking changes From 964e9fe6e6c611ce4a4b40ca6f963b8fb1b299a3 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 3 Apr 2024 10:55:10 +0300 Subject: [PATCH 31/34] Add `-z pauth-report` description to lld's man page --- lld/docs/ld.lld.1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index 65e50e349c8cc..e0316730f442e 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -762,6 +762,11 @@ Specify how to report the missing GNU_PROPERTY_X86_FEATURE_1_IBT or GNU_PROPERTY .Cm none is the default, linker will not report the missing property otherwise will be reported as a warning or an error. .Pp +.It Cm pauth-report Ns = Ns Ar [none|warning|error] +Specify how to report the missing GNU_PROPERTY_AARCH64_FEATURE_PAUTH property. +.Cm none +is the default, linker will not report the missing property otherwise will be reported as a warning or an error. +.Pp .It Cm force-bti Force enable AArch64 BTI instruction in PLT, warn if Input ELF file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property. .Pp From 2e8ec834dca949cb81dec24f2297fd0447087a2c Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 3 Apr 2024 10:57:12 +0300 Subject: [PATCH 32/34] Remove unneeded blank line --- lld/ELF/SyntheticSections.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index f460d75981047..4427a12008680 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -324,7 +324,6 @@ void GnuPropertySection::writeTo(uint8_t *buf) { : GNU_PROPERTY_X86_FEATURE_1_AND; unsigned offset = 16; - if (config->andFeatures != 0) { write32(buf + offset + 0, featureAndType); // Feature type write32(buf + offset + 4, 4); // Feature size From 99df511447bd430a7f9a5d2e0b33aa89a1e0e2b4 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Wed, 3 Apr 2024 10:58:19 +0300 Subject: [PATCH 33/34] Update test run line for `-z pauth-report` --- lld/test/ELF/aarch64-feature-pauth.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 2a6faf74a8f22..144b80734759f 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -32,9 +32,9 @@ # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu no-info.s -o noinfo1.o # RUN: cp noinfo1.o noinfo2.o -# RUN: not ld.lld -z pauth-report=error tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR5 %s -# RUN: ld.lld -z pauth-report=warning tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s -# RUN: ld.lld -z pauth-report=none tag1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null +# RUN: not ld.lld -z pauth-report=error noinfo1.o tag1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR5 %s +# RUN: ld.lld -z pauth-report=warning noinfo1.o tag1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s +# RUN: ld.lld -z pauth-report=none noinfo1.o tag1.o noinfo2.o --fatal-warnings -o /dev/null # ERR5: error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth core info while tag1.o has one # ERR5-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth core info while tag1.o has one From cbc380a2b75a2a610126e9edea025e24f62b8ec9 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Thu, 4 Apr 2024 08:41:39 +0300 Subject: [PATCH 34/34] Add single quotes around `referenceFileName` --- lld/ELF/Driver.cpp | 4 ++-- lld/test/ELF/aarch64-feature-pauth.s | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index f6732def8db99..8dbff7fb86e76 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2690,8 +2690,8 @@ static void readSecurityNotes() { reportMissingFeature(config->zPauthReport, toString(f) + ": -z pauth-report: file does not have AArch64 " - "PAuth core info while " + - referenceFileName + " has one"); + "PAuth core info while '" + + referenceFileName + "' has one"); continue; } diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 144b80734759f..699a650d72295 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -36,10 +36,10 @@ # RUN: ld.lld -z pauth-report=warning noinfo1.o tag1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s # RUN: ld.lld -z pauth-report=none noinfo1.o tag1.o noinfo2.o --fatal-warnings -o /dev/null -# ERR5: error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth core info while tag1.o has one -# ERR5-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth core info while tag1.o has one -# WARN: warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth core info while tag1.o has one -# WARN-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth core info while tag1.o has one +# ERR5: error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth core info while 'tag1.o' has one +# ERR5-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth core info while 'tag1.o' has one +# WARN: warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth core info while 'tag1.o' has one +# WARN-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth core info while 'tag1.o' has one #--- abi-tag-short.s