From f98c952a819a5f77648d2243276e5443053a8768 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Tue, 18 Mar 2025 18:55:26 +0000 Subject: [PATCH 01/89] [lld][AArch64][Build Attributes] Add support for converting AArch64 Build Attributes to GNU Properties This patch enables `lld` to read AArch64 Build Attributes and convert them into GNU Properties. Changes: - Parses AArch64 Build Attributes from input object files. - Converts known attributes into corresponding GNU Properties. - Merges attributes when linking multiple objects. --- lld/ELF/Config.h | 5 + lld/ELF/InputFiles.cpp | 243 +++++++++++++++++- lld/ELF/InputFiles.h | 3 + .../llvm/Support/ELFAttrParserExtended.h | 5 + llvm/include/llvm/Support/ELFAttributes.h | 8 +- .../build-attributes-to-gnu_properties-2.s | 10 + .../build-attributes-to-gnu_properties-3.s | 10 + .../build-attributes-to-gnu_properties-1.s | 21 ++ 8 files changed, 292 insertions(+), 13 deletions(-) create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index e07c7dd4ca1b6..9969a9dec5c35 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -24,6 +24,7 @@ #include "llvm/Support/CodeGen.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Compression.h" +#include "llvm/Support/ELFAttributes.h" #include "llvm/Support/Endian.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/GlobPattern.h" @@ -694,6 +695,10 @@ struct Ctx : CommonLinkerContext { llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &); ArrayRef aarch64PauthAbiCoreInfo; + + // AArch64 Build Attributes data + std::optional mergedPauthSubSection; + std::optional mergedFAndBSubSection; }; // The first two elements of versionDefinitions represent VER_NDX_LOCAL and diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 5f6d2b6b647ee..7ae91729ee4df 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -20,16 +20,21 @@ #include "lld/Common/DWARF.h" #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/LTO/LTO.h" #include "llvm/Object/IRObjectFile.h" +#include "llvm/Support/AArch64AttributeParser.h" #include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/ELFAttributes.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/RISCVAttributeParser.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" +#include #include using namespace llvm; @@ -207,6 +212,166 @@ static void updateSupportedARMFeatures(Ctx &ctx, ctx.arg.armHasThumb2ISA |= thumb && *thumb >= ARMBuildAttrs::AllowThumb32; } +// Sanitize pauth values +static void sanitizePauthSubSection( + Ctx &ctx, std::optional &pauthSubSection, + InputSection isec) { + /* + Incomplete data: ignore + */ + if (!pauthSubSection) + return; + // Currently there are 2 known tags defined for the pauth subsection, + // however, user is allowed to add other, unknown tag. If such tags exists, + // remove them. (no need to check for duplicates, they should not be possible) + pauthSubSection->Content.erase( + std::remove_if(pauthSubSection->Content.begin(), + pauthSubSection->Content.end(), + [](const BuildAttributeItem &item) { + return item.Tag != 1 && item.Tag != 2; + }), + pauthSubSection->Content.end()); + + if (pauthSubSection->Content.size() < 2) { + if (0 == pauthSubSection->Content.size()) + Warn(ctx) << &isec + << ": AArch64 Build Attributes: empty 'aeabi_pauthabi' " + "subsection detected; ignoring subsection"; + if (1 == pauthSubSection->Content.size()) { + if (1 == pauthSubSection->Content[0].Tag) + Warn(ctx) + << &isec + << ": AArch64 Build Attributes: 'aeabi_pauthabi' subsection " + "contains only an ID (scheme missing); ignoring subsection"; + if (2 == pauthSubSection->Content[0].Tag) + Warn(ctx) << &isec + << ": AArch64 Build Attributes: 'aeabi_pauthabi' subsection " + "contains only a scheme (ID missing); ignoring subsection"; + } + pauthSubSection = std::nullopt; + return; + } + // printvec(*pauthSubSection); + assert(2 == pauthSubSection->Content.size() && "vector size should be 2"); + std::sort(pauthSubSection->Content.begin(), pauthSubSection->Content.end(), + [](const auto &a, const auto &b) { return a.Tag < b.Tag; }); + assert(1 == pauthSubSection->Content[0].Tag && "first tag should be 1"); + assert(2 == pauthSubSection->Content[1].Tag && "first tag should be 2"); +} + +// Sanitize features bits +static void sanitizeFAndBSubSection( + std::optional &fAndBSubSection) { + /* + Same as gnu properties: treat a missing 'aeabi_feature_and_bits' feature as + being set to 0 + */ + if (!fAndBSubSection) { + fAndBSubSection.emplace("aeabi_feature_and_bits", 1, 0, + SmallVector()); + } else { + // Currently there are 3 known tags defined for the features and bits + // subsection, however, user is allowed to add other, unknown tag. If such + // tags exists, remove them. (duplicates are not possible) + fAndBSubSection->Content.erase( + std::remove_if(fAndBSubSection->Content.begin(), + fAndBSubSection->Content.end(), + [](const BuildAttributeItem &item) { + return item.Tag != 0 && item.Tag != 1 && item.Tag != 2; + }), + fAndBSubSection->Content.end()); + } + + constexpr unsigned tagBTI = 0, tagPAC = 1, tagGCS = 2; + // Find missing tags + std::set requiredTags = {tagBTI, tagPAC, tagGCS}; + for (const auto &item : fAndBSubSection->Content) + requiredTags.erase(item.Tag); + + // Add missing tags + for (const auto &tag : requiredTags) + fAndBSubSection->Content.push_back( + BuildAttributeItem(BuildAttributeItem::NumericAttribute, tag, 0, "")); + + assert(3 == fAndBSubSection->Content.size() && "vector size should be 3"); + std::sort(fAndBSubSection->Content.begin(), fAndBSubSection->Content.end(), + [](const auto &a, const auto &b) { return a.Tag < b.Tag; }); + assert(0 == fAndBSubSection->Content[0].Tag && "first tag should be 0"); + assert(1 == fAndBSubSection->Content[1].Tag && "first tag should be 1"); + assert(2 == fAndBSubSection->Content[2].Tag && "first tag should be 2"); +} + +static std::array, 2> +extractBuildAttributesSubsection( + Ctx &ctx, + const SmallVector + &buildAttributesSubsections, + InputSection isec) { + + std::optional newPauthSubSection; + std::optional newFAndBSubSection; + + for (const auto &newSubSection : buildAttributesSubsections) { + if (newPauthSubSection && newFAndBSubSection) + break; + if ("aeabi_pauthabi" == newSubSection.Name) { + newPauthSubSection.emplace(newSubSection); + continue; + } + if ("aeabi_feature_and_bits" == newSubSection.Name) { + newFAndBSubSection.emplace(newSubSection); + } + } + sanitizePauthSubSection(ctx, newPauthSubSection, isec); + sanitizeFAndBSubSection(newFAndBSubSection); + + return {std::move(newPauthSubSection), std::move(newFAndBSubSection)}; +} + +// Merge AArch64 Build Attributes subsection +static void mergeAArch64BuildAttributes( + Ctx &ctx, + const std::array, 2> + &buildAttributesSubsections, + InputSection isec) { + + auto [newPauthSubSection, newFAndBSubSection] = buildAttributesSubsections; + + if (ctx.mergedPauthSubSection == std::nullopt) { + ctx.mergedPauthSubSection = newPauthSubSection; + } + + if (ctx.mergedFAndBSubSection == std::nullopt) + ctx.mergedFAndBSubSection = newFAndBSubSection; + + if (newPauthSubSection) { + // Since sanitizePauthSubSection sorts, we know that both vectors align. + // Merge pauth (values has to match) + if ((ctx.mergedPauthSubSection->Content[0].IntValue != + newPauthSubSection->Content[0].IntValue) || + ctx.mergedPauthSubSection->Content[1].IntValue != + newPauthSubSection->Content[1].IntValue) { + ctx.mergedPauthSubSection->Content[0].IntValue = + std::numeric_limits::max(); + ctx.mergedPauthSubSection->Content[1].IntValue = + std::numeric_limits::max(); + Warn(ctx) + << &isec + << ": AArch64 Build Attributes: mismatch in 'aeabi_pauthabi' values " + "detected; marking 'aeabi_pauthabi' as invalid for this project"; + } + } + + // Since sanitizeFAndBSubSection sorts, we know that both vectors align. + // Merge Features and Bits + ctx.mergedFAndBSubSection->Content[0].IntValue &= + newFAndBSubSection->Content[0].IntValue; + ctx.mergedFAndBSubSection->Content[1].IntValue &= + newFAndBSubSection->Content[1].IntValue; + ctx.mergedFAndBSubSection->Content[2].IntValue &= + newFAndBSubSection->Content[2].IntValue; +} + InputFile::InputFile(Ctx &ctx, Kind k, MemoryBufferRef m) : ctx(ctx), mb(m), groupId(ctx.driver.nextGroupId), fileKind(k) { // All files within the same --{start,end}-group get the same group ID. @@ -552,6 +717,7 @@ template void ObjFile::parse(bool ignoreComdats) { // done in parallel. ArrayRef objSections = getELFShdrs(); StringRef shstrtab = CHECK2(obj.getSectionStringTable(objSections), this); + bool hasGnuProperties = false; uint64_t size = objSections.size(); sections.resize(size); for (size_t i = 0; i != size; ++i) { @@ -574,9 +740,12 @@ template void ObjFile::parse(bool ignoreComdats) { .try_emplace(CachedHashStringRef(signature), this) .second; if (keepGroup) { - if (!ctx.arg.resolveGroups) - sections[i] = createInputSection( - i, sec, check(obj.getSectionName(sec, shstrtab))); + if (!ctx.arg.resolveGroups) { + StringRef name = check(obj.getSectionName(sec, shstrtab)); + if (name == ".note.gnu.property") + hasGnuProperties = true; + sections[i] = createInputSection(i, sec, name); + } } else { // Otherwise, discard group members. for (uint32_t secIndex : entries.slice(1)) { @@ -638,27 +807,77 @@ template void ObjFile::parse(bool ignoreComdats) { } } break; - case EM_AARCH64: - // FIXME: BuildAttributes have been implemented in llvm, but not yet in - // lld. Remove the section so that it does not accumulate in the output - // file. When support is implemented we expect not to output a build - // attributes section in files of type ET_EXEC or ET_SHARED, but ld -r - // ouptut will need a single merged attributes section. - if (sec.sh_type == SHT_AARCH64_ATTRIBUTES) + case EM_AARCH64: { + // The specification states that if a file contains both GNU properties + // and AArch64 build attributes, they must be identical. Therefore, if a + // file contains GNU properties, the AArch64 build attributes are ignored. + // If a file does not contain GNU properties, we leverage the existing GNU + // properties mechanism by populating the corresponding data structures, + // which will later be handled by Driver.cpp::readSecurityNotes. This + // ensures that AArch64 build attributes are represented in the linked + // object file as GNU properties, which are already supported by the Linux + // kernel and the dynamic dispatcher. + if (sec.sh_type == SHT_AARCH64_ATTRIBUTES) { + StringRef name = check(obj.getSectionName(sec, shstrtab)); + AArch64AttributeParser attributes; + ArrayRef contents = check(obj.getSectionContents(sec)); + if (Error e = attributes.parse(contents, ELFT::Endianness)) { + InputSection isec(*this, sec, name); + Warn(ctx) << &isec << ": " << std::move(e); + } else { + // for functions that has to warn/err/report + InputSection isec(*this, sec, name); + const SmallVector + buildAttributesSubSections = + attributes.getBuildAttributesSection(); + auto subsections = extractBuildAttributesSubsection( + ctx, buildAttributesSubSections, isec); + mergeAArch64BuildAttributes(ctx, subsections, isec); + if (!hasGnuProperties) { + ObjFile &f = *this; + auto [pauthSubSection, fAndBSubSection] = subsections; + if (pauthSubSection) { + assert( + (pauthSubSection->Content.size() == 2) && + "pauthSubSection must contain exactly two build attributes"); + // sanitizePauthSubSection already sorts + f.aarch64PauthAbiCoreInfoStorage = + std::make_unique>(); + uint64_t values[2] = { + static_cast(pauthSubSection->Content[0].IntValue), + static_cast(pauthSubSection->Content[1].IntValue)}; + std::memcpy(f.aarch64PauthAbiCoreInfoStorage->data(), &values[0], + sizeof(values)); + f.aarch64PauthAbiCoreInfo = *f.aarch64PauthAbiCoreInfoStorage; + } + if (fAndBSubSection) { + assert((fAndBSubSection->Content.size() == 3) && + "fAndBSubSection must contain exactly three build " + "attributes"); + // sanitizeFAndBSubSection already sorts + f.andFeatures = 0; + f.andFeatures |= (fAndBSubSection->Content[0].IntValue) << 0; + f.andFeatures |= (fAndBSubSection->Content[1].IntValue) << 1; + f.andFeatures |= (fAndBSubSection->Content[2].IntValue) << 2; + } + } + } sections[i] = &InputSection::discarded; // Producing a static binary with MTE globals is not currently supported, // remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as they're unused - // medatada, and we don't want them to end up in the output file for + // metadata, and we don't want them to end up in the output file for // static executables. if (sec.sh_type == SHT_AARCH64_MEMTAG_GLOBALS_STATIC && !canHaveMemtagGlobals(ctx)) sections[i] = &InputSection::discarded; - break; + } } + break; } // Read a symbol table. initializeSymbols(obj); + } } // Sections with SHT_GROUP and comdat bits define comdat section groups. diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 808cb5d24079f..8164594e9c41a 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -19,6 +19,7 @@ #include "llvm/Object/ELF.h" #include "llvm/Support/MemoryBufferRef.h" #include "llvm/Support/Threading.h" +#include namespace llvm { struct DILineInfo; @@ -239,9 +240,11 @@ class ELFFileBase : public InputFile { public: // Name of source file obtained from STT_FILE, if present. StringRef sourceFile; + std::unique_ptr sourceFileStorage; uint32_t andFeatures = 0; bool hasCommonSyms = false; ArrayRef aarch64PauthAbiCoreInfo; + std::unique_ptr> aarch64PauthAbiCoreInfoStorage; }; // .o file. diff --git a/llvm/include/llvm/Support/ELFAttrParserExtended.h b/llvm/include/llvm/Support/ELFAttrParserExtended.h index 68f45fb7f368a..6ae43fb0ed75a 100644 --- a/llvm/include/llvm/Support/ELFAttrParserExtended.h +++ b/llvm/include/llvm/Support/ELFAttrParserExtended.h @@ -38,6 +38,11 @@ class ELFExtendedAttrParser : public ELFAttributeParser { virtual ~ELFExtendedAttrParser() { static_cast(!Cursor.takeError()); } Error parse(ArrayRef Section, llvm::endianness Endian) override; + const SmallVector & + getBuildAttributesSection() const { + return SubSectionVec; + } + std::optional getAttributeValue(unsigned Tag) const override; std::optional getAttributeValue(StringRef BuildAttrSubsectionName, unsigned Tag) const override; diff --git a/llvm/include/llvm/Support/ELFAttributes.h b/llvm/include/llvm/Support/ELFAttributes.h index 6782aec6050ad..95e4598b2a2b4 100644 --- a/llvm/include/llvm/Support/ELFAttributes.h +++ b/llvm/include/llvm/Support/ELFAttributes.h @@ -32,14 +32,20 @@ struct BuildAttributeItem { unsigned Tag; unsigned IntValue; std::string StringValue; + BuildAttributeItem(){}; BuildAttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV) : Type(Ty), Tag(Tg), IntValue(IV), StringValue(std::move(SV)) {} }; struct BuildAttributeSubSection { - StringRef Name; + std::string Name; unsigned IsOptional; unsigned ParameterType; SmallVector Content; + BuildAttributeSubSection(){}; + BuildAttributeSubSection(const std::string &N, unsigned Opt, unsigned Type, + SmallVector &&Content) + : Name(N), IsOptional(Opt), ParameterType(Type), + Content(std::move(Content)) {} }; // Tag to string: ELF extended build attribute section diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s new file mode 100644 index 0000000000000..d3e677eee0360 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s @@ -0,0 +1,10 @@ +# REQUIRES: aarch64 + +.section .note.gnu.property, "a" +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 0 +.aeabi_attribute Tag_Feature_GCS, 1 diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s new file mode 100644 index 0000000000000..8763000b786c0 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s @@ -0,0 +1,10 @@ +# REQUIRES: aarch64 + +.section .note.gnu.property, "a" +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 0 diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s new file mode 100644 index 0000000000000..5ff5f12269333 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-to-gnu_properties-2.s -o %t2.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-to-gnu_properties-3.s -o %t3.o +# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o +# RUN: llvm-readelf -n %t.merged.o | FileCheck %s + +# CHECK: Displaying notes found in: .note.gnu.property +# CHECK-NEXT: Owner Data size Description +# CHECK-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +# CHECK-NEXT: Properties: aarch64 feature: BTI +# CHECK-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 + + +.section .note.gnu.property, "a" +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 1 From d4299e93dc4ebd7de490d898d059d00809527b7a Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 19 Mar 2025 10:24:46 +0000 Subject: [PATCH 02/89] fix formatting --- lld/ELF/InputFiles.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 7ae91729ee4df..cada5c63549c7 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -863,16 +863,15 @@ template void ObjFile::parse(bool ignoreComdats) { } } sections[i] = &InputSection::discarded; - // Producing a static binary with MTE globals is not currently supported, - // remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as they're unused - // metadata, and we don't want them to end up in the output file for - // static executables. - if (sec.sh_type == SHT_AARCH64_MEMTAG_GLOBALS_STATIC && - !canHaveMemtagGlobals(ctx)) - sections[i] = &InputSection::discarded; + // Producing a static binary with MTE globals is not currently + // supported, remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as + // they're unused metadata, and we don't want them to end up in the + // output file for static executables. + if (sec.sh_type == SHT_AARCH64_MEMTAG_GLOBALS_STATIC && + !canHaveMemtagGlobals(ctx)) + sections[i] = &InputSection::discarded; } - } - break; + } break; } // Read a symbol table. From 783dbf97a61e01217a0a4415e164c9b658ea33eb Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 19 Mar 2025 10:31:32 +0000 Subject: [PATCH 03/89] remove stand alone condition out of braces of prevoius condition --- lld/ELF/InputFiles.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index cada5c63549c7..825da3c6923b3 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -863,14 +863,14 @@ template void ObjFile::parse(bool ignoreComdats) { } } sections[i] = &InputSection::discarded; + } // Producing a static binary with MTE globals is not currently // supported, remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as // they're unused metadata, and we don't want them to end up in the // output file for static executables. - if (sec.sh_type == SHT_AARCH64_MEMTAG_GLOBALS_STATIC && - !canHaveMemtagGlobals(ctx)) - sections[i] = &InputSection::discarded; - } + if (sec.sh_type == SHT_AARCH64_MEMTAG_GLOBALS_STATIC && + !canHaveMemtagGlobals(ctx)) + sections[i] = &InputSection::discarded; } break; } From 5dfca32cc8dd8ce358323d813bb4e2fefdd6a38b Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 19 Mar 2025 10:38:22 +0000 Subject: [PATCH 04/89] formatting --- lld/ELF/InputFiles.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 825da3c6923b3..5fdf0c20ae676 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -864,10 +864,10 @@ template void ObjFile::parse(bool ignoreComdats) { } sections[i] = &InputSection::discarded; } - // Producing a static binary with MTE globals is not currently - // supported, remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as - // they're unused metadata, and we don't want them to end up in the - // output file for static executables. + // Producing a static binary with MTE globals is not currently + // supported, remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as + // they're unused metadata, and we don't want them to end up in the + // output file for static executables. if (sec.sh_type == SHT_AARCH64_MEMTAG_GLOBALS_STATIC && !canHaveMemtagGlobals(ctx)) sections[i] = &InputSection::discarded; From 8b6377a1bd1e368c372031c8e573e892f86276c6 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 19 Mar 2025 10:49:51 +0000 Subject: [PATCH 05/89] formatting --- llvm/include/llvm/Support/ELFAttributes.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/Support/ELFAttributes.h b/llvm/include/llvm/Support/ELFAttributes.h index 95e4598b2a2b4..8171043288713 100644 --- a/llvm/include/llvm/Support/ELFAttributes.h +++ b/llvm/include/llvm/Support/ELFAttributes.h @@ -63,7 +63,8 @@ enum AttrType : unsigned { File = 1, Section = 2, Symbol = 3 }; StringRef attrTypeAsString(unsigned attr, TagNameMap tagNameMap, bool hasTagPrefix = true); -std::optional attrTypeFromString(StringRef tag, TagNameMap tagNameMap); +std::optional attrTypeFromString(StringRef tag, + TagNameMap tagNameMap); // Magic numbers for ELF attributes. enum AttrMagic { Format_Version = 0x41 }; From 9d81bc014afdd72249f2c05be520980ec898755b Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 19 Mar 2025 10:57:50 +0000 Subject: [PATCH 06/89] formatting --- lld/ELF/Config.h | 5 +++-- lld/ELF/InputFiles.cpp | 6 +++--- lld/ELF/InputFiles.h | 3 +-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 9969a9dec5c35..ba99c386d91c6 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -132,7 +132,7 @@ enum class SeparateSegmentKind { None, Code, Loadable }; enum class GnuStackKind { None, Exec, NoExec }; // For --lto= -enum LtoKind : uint8_t {UnifiedThin, UnifiedRegular, Default}; +enum LtoKind : uint8_t { UnifiedThin, UnifiedRegular, Default }; // For -z gcs= enum class GcsPolicy { Implicit, Never, Always }; @@ -196,7 +196,8 @@ struct Config { uint8_t osabi = 0; uint32_t andFeatures = 0; llvm::CachePruningPolicy thinLTOCachePolicy; - llvm::SetVector dependencyFiles; // for --dependency-file + llvm::SetVector + dependencyFiles; // for --dependency-file llvm::StringMap sectionStartMap; llvm::StringRef bfdname; llvm::StringRef chroot; diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 5fdf0c20ae676..5bb5aaad06aaf 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -872,10 +872,10 @@ template void ObjFile::parse(bool ignoreComdats) { !canHaveMemtagGlobals(ctx)) sections[i] = &InputSection::discarded; } break; - } + } - // Read a symbol table. - initializeSymbols(obj); + // Read a symbol table. + initializeSymbols(obj); } } diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 8164594e9c41a..e15632b6c8081 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -200,7 +200,7 @@ class ELFFileBase : public InputFile { } MutableArrayRef getMutableGlobalSymbols() { return llvm::MutableArrayRef(symbols.get() + firstGlobal, - numSymbols - firstGlobal); + numSymbols - firstGlobal); } template typename ELFT::ShdrRange getELFShdrs() const { @@ -271,7 +271,6 @@ template class ObjFile : public ELFFileBase { uint32_t getSectionIndex(const Elf_Sym &sym) const; - // Pointer to this input file's .llvm_addrsig section, if it has one. const Elf_Shdr *addrsigSec = nullptr; From 9c8f950b9dbab8cfe9157a6d86c48070c590de6e Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 19 Mar 2025 11:11:21 +0000 Subject: [PATCH 07/89] format --- llvm/include/llvm/Support/ELFAttributes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/include/llvm/Support/ELFAttributes.h b/llvm/include/llvm/Support/ELFAttributes.h index 8171043288713..1054ebccb9eef 100644 --- a/llvm/include/llvm/Support/ELFAttributes.h +++ b/llvm/include/llvm/Support/ELFAttributes.h @@ -36,6 +36,7 @@ struct BuildAttributeItem { BuildAttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV) : Type(Ty), Tag(Tg), IntValue(IV), StringValue(std::move(SV)) {} }; + struct BuildAttributeSubSection { std::string Name; unsigned IsOptional; From 94bebe091d34e6fc43ad8a29c888d70e55f72599 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 19 Mar 2025 11:19:04 +0000 Subject: [PATCH 08/89] format --- llvm/include/llvm/Support/ELFAttributes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/ELFAttributes.h b/llvm/include/llvm/Support/ELFAttributes.h index 1054ebccb9eef..f3a304babb0ec 100644 --- a/llvm/include/llvm/Support/ELFAttributes.h +++ b/llvm/include/llvm/Support/ELFAttributes.h @@ -32,7 +32,7 @@ struct BuildAttributeItem { unsigned Tag; unsigned IntValue; std::string StringValue; - BuildAttributeItem(){}; + BuildAttributeItem() {}; BuildAttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV) : Type(Ty), Tag(Tg), IntValue(IV), StringValue(std::move(SV)) {} }; @@ -42,7 +42,7 @@ struct BuildAttributeSubSection { unsigned IsOptional; unsigned ParameterType; SmallVector Content; - BuildAttributeSubSection(){}; + BuildAttributeSubSection() {}; BuildAttributeSubSection(const std::string &N, unsigned Opt, unsigned Type, SmallVector &&Content) : Name(N), IsOptional(Opt), ParameterType(Type), From e73a6bd8fce570feb8e55a0898a6dd6eea3ae4f5 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 19 Mar 2025 17:19:26 +0000 Subject: [PATCH 09/89] fix: readig symbol table should be done once per file, not per symbol section! --- lld/ELF/InputFiles.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 5bb5aaad06aaf..5c515940e94d6 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -873,10 +873,9 @@ template void ObjFile::parse(bool ignoreComdats) { sections[i] = &InputSection::discarded; } break; } - - // Read a symbol table. - initializeSymbols(obj); } + // Read a symbol table. + initializeSymbols(obj); } // Sections with SHT_GROUP and comdat bits define comdat section groups. From 60a5eeae30ef6b1c60b05da7d88e9c4894551178 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 08:38:00 +0000 Subject: [PATCH 10/89] remove memory header --- lld/ELF/InputFiles.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index e15632b6c8081..70203a9ce6259 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -19,7 +19,6 @@ #include "llvm/Object/ELF.h" #include "llvm/Support/MemoryBufferRef.h" #include "llvm/Support/Threading.h" -#include namespace llvm { struct DILineInfo; From 9052abfb5ab54733ed021dd6be0695e40ce50469 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 08:42:53 +0000 Subject: [PATCH 11/89] undo unrealted formatting --- lld/ELF/InputFiles.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 5c515940e94d6..b228023c2bcc4 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -864,10 +864,10 @@ template void ObjFile::parse(bool ignoreComdats) { } sections[i] = &InputSection::discarded; } - // Producing a static binary with MTE globals is not currently - // supported, remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as - // they're unused metadata, and we don't want them to end up in the - // output file for static executables. + // Producing a static binary with MTE globals is not currently supported, + // remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as they're unused + // medatada, and we don't want them to end up in the output file for + // static executables. if (sec.sh_type == SHT_AARCH64_MEMTAG_GLOBALS_STATIC && !canHaveMemtagGlobals(ctx)) sections[i] = &InputSection::discarded; From 52869a11f32dab527268559703fad9baab456124 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 08:49:25 +0000 Subject: [PATCH 12/89] remove unused variable --- lld/ELF/InputFiles.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 70203a9ce6259..09e1525394253 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -239,7 +239,6 @@ class ELFFileBase : public InputFile { public: // Name of source file obtained from STT_FILE, if present. StringRef sourceFile; - std::unique_ptr sourceFileStorage; uint32_t andFeatures = 0; bool hasCommonSyms = false; ArrayRef aarch64PauthAbiCoreInfo; From 534e55ef2d12d587bc02a9bfba22c9e103e0b3f0 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 08:53:44 +0000 Subject: [PATCH 13/89] clarify what is being sanitized in comments --- lld/ELF/InputFiles.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index b228023c2bcc4..4797b6ec21dac 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -212,7 +212,12 @@ static void updateSupportedARMFeatures(Ctx &ctx, ctx.arg.armHasThumb2ISA |= thumb && *thumb >= ARMBuildAttrs::AllowThumb32; } -// Sanitize pauth values +// Sanitize pauth values. +// Ensure that pauthSubSection is either std::nullopt or contains exactly two build attributes: ID and Scheme. +// - Content[0]: ID, Content[1]: Scheme. +// - Remove build attributes with unknown tags. +// - Set pauthSubSection to std::nullopt if any required attributes are missing. +// - Sort the content vector so that ID is at Content[0] and Scheme at Content[1]. static void sanitizePauthSubSection( Ctx &ctx, std::optional &pauthSubSection, InputSection isec) { @@ -259,7 +264,12 @@ static void sanitizePauthSubSection( assert(2 == pauthSubSection->Content[1].Tag && "first tag should be 2"); } -// Sanitize features bits +// Sanitize feature bits. +// Ensure that fAndBSubSection always contains exactly three build attributes: BTI, PAC, and GCS. +// - Content[0]: BTI, Content[1]: PAC, Content[2]: GCS. +// - Remove build attributes with unknown tags. +// - If any attribute is missing, add it with its value set to `0`. +// - Sort the content vector so that Content[0] is BTI, Content[1] is PAC, and Content[2] is GCS. static void sanitizeFAndBSubSection( std::optional &fAndBSubSection) { /* From 02a1fa7c2a4cffa8f8bc3c4e46d3b9eccec7449d Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 09:00:44 +0000 Subject: [PATCH 14/89] change SmallVector to SmallVectorImpl --- lld/ELF/InputFiles.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 4797b6ec21dac..16fb4ac354071 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -213,11 +213,13 @@ static void updateSupportedARMFeatures(Ctx &ctx, } // Sanitize pauth values. -// Ensure that pauthSubSection is either std::nullopt or contains exactly two build attributes: ID and Scheme. +// Ensure that pauthSubSection is either std::nullopt or contains exactly two +// build attributes: ID and Scheme. // - Content[0]: ID, Content[1]: Scheme. // - Remove build attributes with unknown tags. // - Set pauthSubSection to std::nullopt if any required attributes are missing. -// - Sort the content vector so that ID is at Content[0] and Scheme at Content[1]. +// - Sort the content vector so that ID is at Content[0] and Scheme at +// Content[1]. static void sanitizePauthSubSection( Ctx &ctx, std::optional &pauthSubSection, InputSection isec) { @@ -265,11 +267,13 @@ static void sanitizePauthSubSection( } // Sanitize feature bits. -// Ensure that fAndBSubSection always contains exactly three build attributes: BTI, PAC, and GCS. +// Ensure that fAndBSubSection always contains exactly three build attributes: +// BTI, PAC, and GCS. // - Content[0]: BTI, Content[1]: PAC, Content[2]: GCS. // - Remove build attributes with unknown tags. // - If any attribute is missing, add it with its value set to `0`. -// - Sort the content vector so that Content[0] is BTI, Content[1] is PAC, and Content[2] is GCS. +// - Sort the content vector so that Content[0] is BTI, Content[1] is PAC, and +// Content[2] is GCS. static void sanitizeFAndBSubSection( std::optional &fAndBSubSection) { /* @@ -314,7 +318,7 @@ static void sanitizeFAndBSubSection( static std::array, 2> extractBuildAttributesSubsection( Ctx &ctx, - const SmallVector + const SmallVectorImpl &buildAttributesSubsections, InputSection isec) { From ec89018e0434a17114343b153d5ea4721fa567b1 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 09:15:27 +0000 Subject: [PATCH 15/89] undo unrelated formatting --- lld/ELF/Config.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index ba99c386d91c6..dcabc21c1337e 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -123,7 +123,7 @@ enum class SortSectionPolicy { enum class Target2Policy { Abs, Rel, GotRel }; // For tracking ARM Float Argument PCS -enum class ARMVFPArgKind { Default, Base, VFP, ToolChain }; +enum class ARMVFPArgKind {Default, Base, VFP, ToolChain}; // For -z noseparate-code, -z separate-code and -z separate-loadable-segments. enum class SeparateSegmentKind { None, Code, Loadable }; @@ -196,8 +196,7 @@ struct Config { uint8_t osabi = 0; uint32_t andFeatures = 0; llvm::CachePruningPolicy thinLTOCachePolicy; - llvm::SetVector - dependencyFiles; // for --dependency-file + llvm::SetVector dependencyFiles; // for --dependency-file llvm::StringMap sectionStartMap; llvm::StringRef bfdname; llvm::StringRef chroot; From 7292c3616cb65db9432950f81b85a8aeab3b5213 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 09:33:46 +0000 Subject: [PATCH 16/89] fix formating fail --- lld/ELF/Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index dcabc21c1337e..7d83336e0d95d 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -123,7 +123,7 @@ enum class SortSectionPolicy { enum class Target2Policy { Abs, Rel, GotRel }; // For tracking ARM Float Argument PCS -enum class ARMVFPArgKind {Default, Base, VFP, ToolChain}; +enum class ARMVFPArgKind { Default, Base, VFP, ToolChain }; // For -z noseparate-code, -z separate-code and -z separate-loadable-segments. enum class SeparateSegmentKind { None, Code, Loadable }; From d0267260023252b4d7cba618baf1f969f6f48814 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 09:41:24 +0000 Subject: [PATCH 17/89] use instead of asigning auto f =(*this) --- lld/ELF/InputFiles.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 16fb4ac354071..18f5288daec74 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -848,31 +848,34 @@ template void ObjFile::parse(bool ignoreComdats) { ctx, buildAttributesSubSections, isec); mergeAArch64BuildAttributes(ctx, subsections, isec); if (!hasGnuProperties) { - ObjFile &f = *this; auto [pauthSubSection, fAndBSubSection] = subsections; if (pauthSubSection) { assert( (pauthSubSection->Content.size() == 2) && "pauthSubSection must contain exactly two build attributes"); // sanitizePauthSubSection already sorts - f.aarch64PauthAbiCoreInfoStorage = + (*this).aarch64PauthAbiCoreInfoStorage = std::make_unique>(); uint64_t values[2] = { static_cast(pauthSubSection->Content[0].IntValue), static_cast(pauthSubSection->Content[1].IntValue)}; - std::memcpy(f.aarch64PauthAbiCoreInfoStorage->data(), &values[0], - sizeof(values)); - f.aarch64PauthAbiCoreInfo = *f.aarch64PauthAbiCoreInfoStorage; + std::memcpy((*this).aarch64PauthAbiCoreInfoStorage->data(), + &values[0], sizeof(values)); + (*this).aarch64PauthAbiCoreInfo = + *(*this).aarch64PauthAbiCoreInfoStorage; } if (fAndBSubSection) { assert((fAndBSubSection->Content.size() == 3) && "fAndBSubSection must contain exactly three build " "attributes"); // sanitizeFAndBSubSection already sorts - f.andFeatures = 0; - f.andFeatures |= (fAndBSubSection->Content[0].IntValue) << 0; - f.andFeatures |= (fAndBSubSection->Content[1].IntValue) << 1; - f.andFeatures |= (fAndBSubSection->Content[2].IntValue) << 2; + (*this).andFeatures = 0; + (*this).andFeatures |= (fAndBSubSection->Content[0].IntValue) + << 0; + (*this).andFeatures |= (fAndBSubSection->Content[1].IntValue) + << 1; + (*this).andFeatures |= (fAndBSubSection->Content[2].IntValue) + << 2; } } } From 6709e9a44fa66be36a5a6809f91171c93eda0750 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 09:53:12 +0000 Subject: [PATCH 18/89] pass InputSection by reference --- lld/ELF/InputFiles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 18f5288daec74..b93c9126bee56 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -222,7 +222,7 @@ static void updateSupportedARMFeatures(Ctx &ctx, // Content[1]. static void sanitizePauthSubSection( Ctx &ctx, std::optional &pauthSubSection, - InputSection isec) { + const InputSection &isec) { /* Incomplete data: ignore */ From 04e2a16d905c8b3b5f5a712f76cdd103b6fa7bd1 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 10:00:06 +0000 Subject: [PATCH 19/89] remove unnecessery headers --- lld/ELF/InputFiles.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index b93c9126bee56..213cb10c90725 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -20,21 +20,17 @@ #include "lld/Common/DWARF.h" #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" #include "llvm/LTO/LTO.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Support/AArch64AttributeParser.h" #include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/ARMBuildAttributes.h" -#include "llvm/Support/ELFAttributes.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/RISCVAttributeParser.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" -#include #include using namespace llvm; From eb2abbca50b94c17fde78620feaa592b9d9201e4 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 10:09:26 +0000 Subject: [PATCH 20/89] err on unknown tags for non-optional subsection --- lld/ELF/InputFiles.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 213cb10c90725..61bd0ea599bf2 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -219,22 +219,20 @@ static void updateSupportedARMFeatures(Ctx &ctx, static void sanitizePauthSubSection( Ctx &ctx, std::optional &pauthSubSection, const InputSection &isec) { + if (!pauthSubSection) + return; + // The pauth subsection is non-optional, therefore unknown tags should + // generate an error. + auto *it = llvm::find_if(pauthSubSection->Content, [](const auto &e) { + return e.Tag != 1 && e.Tag != 2; + }); + if (it != pauthSubSection->Content.end()) { + Err(ctx) << &isec << ": AArch64 Build Attributes: unknown tag: " << it->Tag + << "inside a non-optional subsection aeabi_pauthabi"; + }; /* Incomplete data: ignore */ - if (!pauthSubSection) - return; - // Currently there are 2 known tags defined for the pauth subsection, - // however, user is allowed to add other, unknown tag. If such tags exists, - // remove them. (no need to check for duplicates, they should not be possible) - pauthSubSection->Content.erase( - std::remove_if(pauthSubSection->Content.begin(), - pauthSubSection->Content.end(), - [](const BuildAttributeItem &item) { - return item.Tag != 1 && item.Tag != 2; - }), - pauthSubSection->Content.end()); - if (pauthSubSection->Content.size() < 2) { if (0 == pauthSubSection->Content.size()) Warn(ctx) << &isec From eb84c8cc998b8f8d5006706118fd6ec9187e4129 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 10:14:14 +0000 Subject: [PATCH 21/89] use vector.empty() instead of 0 == vector.size() --- lld/ELF/InputFiles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 61bd0ea599bf2..ab4602e47bd77 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -234,7 +234,7 @@ static void sanitizePauthSubSection( Incomplete data: ignore */ if (pauthSubSection->Content.size() < 2) { - if (0 == pauthSubSection->Content.size()) + if (!pauthSubSection->Content.empty()) Warn(ctx) << &isec << ": AArch64 Build Attributes: empty 'aeabi_pauthabi' " "subsection detected; ignoring subsection"; From be821a52d2dd1bd9f269695870633475f2d6a0ed Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 10:16:51 +0000 Subject: [PATCH 22/89] remove warnig on empty pauth subsection --- lld/ELF/InputFiles.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index ab4602e47bd77..7489df0a29426 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -234,10 +234,6 @@ static void sanitizePauthSubSection( Incomplete data: ignore */ if (pauthSubSection->Content.size() < 2) { - if (!pauthSubSection->Content.empty()) - Warn(ctx) << &isec - << ": AArch64 Build Attributes: empty 'aeabi_pauthabi' " - "subsection detected; ignoring subsection"; if (1 == pauthSubSection->Content.size()) { if (1 == pauthSubSection->Content[0].Tag) Warn(ctx) From f9a0fcb4bb24487fd5812884abf681ebab8df4bb Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 10:25:42 +0000 Subject: [PATCH 23/89] enum instead of numbers --- lld/ELF/InputFiles.cpp | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 7489df0a29426..e6a3bf374db10 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -23,6 +23,7 @@ #include "llvm/LTO/LTO.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Support/AArch64AttributeParser.h" +#include "llvm/Support/AArch64BuildAttributes.h" #include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/Endian.h" @@ -235,12 +236,14 @@ static void sanitizePauthSubSection( */ if (pauthSubSection->Content.size() < 2) { if (1 == pauthSubSection->Content.size()) { - if (1 == pauthSubSection->Content[0].Tag) + if (llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM == + pauthSubSection->Content[0].Tag) Warn(ctx) << &isec << ": AArch64 Build Attributes: 'aeabi_pauthabi' subsection " "contains only an ID (scheme missing); ignoring subsection"; - if (2 == pauthSubSection->Content[0].Tag) + if (llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA == + pauthSubSection->Content[0].Tag) Warn(ctx) << &isec << ": AArch64 Build Attributes: 'aeabi_pauthabi' subsection " "contains only a scheme (ID missing); ignoring subsection"; @@ -278,17 +281,23 @@ static void sanitizeFAndBSubSection( // subsection, however, user is allowed to add other, unknown tag. If such // tags exists, remove them. (duplicates are not possible) fAndBSubSection->Content.erase( - std::remove_if(fAndBSubSection->Content.begin(), - fAndBSubSection->Content.end(), - [](const BuildAttributeItem &item) { - return item.Tag != 0 && item.Tag != 1 && item.Tag != 2; - }), + std::remove_if( + fAndBSubSection->Content.begin(), fAndBSubSection->Content.end(), + [](const BuildAttributeItem &item) { + return item.Tag != + llvm::AArch64BuildAttributes::TAG_FEATURE_BTI && + item.Tag != + llvm::AArch64BuildAttributes::TAG_FEATURE_PAC && + item.Tag != llvm::AArch64BuildAttributes::TAG_FEATURE_GCS; + }), fAndBSubSection->Content.end()); } - constexpr unsigned tagBTI = 0, tagPAC = 1, tagGCS = 2; // Find missing tags - std::set requiredTags = {tagBTI, tagPAC, tagGCS}; + std::set requiredTags = { + llvm::AArch64BuildAttributes::TAG_FEATURE_BTI, + llvm::AArch64BuildAttributes::TAG_FEATURE_PAC, + llvm::AArch64BuildAttributes::TAG_FEATURE_GCS}; for (const auto &item : fAndBSubSection->Content) requiredTags.erase(item.Tag); @@ -300,9 +309,15 @@ static void sanitizeFAndBSubSection( assert(3 == fAndBSubSection->Content.size() && "vector size should be 3"); std::sort(fAndBSubSection->Content.begin(), fAndBSubSection->Content.end(), [](const auto &a, const auto &b) { return a.Tag < b.Tag; }); - assert(0 == fAndBSubSection->Content[0].Tag && "first tag should be 0"); - assert(1 == fAndBSubSection->Content[1].Tag && "first tag should be 1"); - assert(2 == fAndBSubSection->Content[2].Tag && "first tag should be 2"); + assert(llvm::AArch64BuildAttributes::TAG_FEATURE_PAC == + fAndBSubSection->Content[0].Tag && + "first tag should be 0"); + assert(llvm::AArch64BuildAttributes::TAG_FEATURE_BTI == + fAndBSubSection->Content[1].Tag && + "first tag should be 1"); + assert(llvm::AArch64BuildAttributes::TAG_FEATURE_GCS == + fAndBSubSection->Content[2].Tag && + "first tag should be 2"); } static std::array, 2> From ab6dc737df9b37727c8085230c7f3d5c7d0f81dc Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 14:00:15 +0000 Subject: [PATCH 24/89] simplify: use struct to hold attributes instead of needlesly over-complicated vectors --- lld/ELF/InputFiles.cpp | 243 +++++++++++------------------------------ 1 file changed, 64 insertions(+), 179 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index e6a3bf374db10..b99183dee34bf 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -209,142 +209,46 @@ static void updateSupportedARMFeatures(Ctx &ctx, ctx.arg.armHasThumb2ISA |= thumb && *thumb >= ARMBuildAttrs::AllowThumb32; } -// Sanitize pauth values. -// Ensure that pauthSubSection is either std::nullopt or contains exactly two -// build attributes: ID and Scheme. -// - Content[0]: ID, Content[1]: Scheme. -// - Remove build attributes with unknown tags. -// - Set pauthSubSection to std::nullopt if any required attributes are missing. -// - Sort the content vector so that ID is at Content[0] and Scheme at -// Content[1]. -static void sanitizePauthSubSection( - Ctx &ctx, std::optional &pauthSubSection, - const InputSection &isec) { - if (!pauthSubSection) - return; - // The pauth subsection is non-optional, therefore unknown tags should - // generate an error. - auto *it = llvm::find_if(pauthSubSection->Content, [](const auto &e) { - return e.Tag != 1 && e.Tag != 2; - }); - if (it != pauthSubSection->Content.end()) { - Err(ctx) << &isec << ": AArch64 Build Attributes: unknown tag: " << it->Tag - << "inside a non-optional subsection aeabi_pauthabi"; - }; - /* - Incomplete data: ignore - */ - if (pauthSubSection->Content.size() < 2) { - if (1 == pauthSubSection->Content.size()) { - if (llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM == - pauthSubSection->Content[0].Tag) - Warn(ctx) - << &isec - << ": AArch64 Build Attributes: 'aeabi_pauthabi' subsection " - "contains only an ID (scheme missing); ignoring subsection"; - if (llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA == - pauthSubSection->Content[0].Tag) - Warn(ctx) << &isec - << ": AArch64 Build Attributes: 'aeabi_pauthabi' subsection " - "contains only a scheme (ID missing); ignoring subsection"; - } - pauthSubSection = std::nullopt; - return; - } - // printvec(*pauthSubSection); - assert(2 == pauthSubSection->Content.size() && "vector size should be 2"); - std::sort(pauthSubSection->Content.begin(), pauthSubSection->Content.end(), - [](const auto &a, const auto &b) { return a.Tag < b.Tag; }); - assert(1 == pauthSubSection->Content[0].Tag && "first tag should be 1"); - assert(2 == pauthSubSection->Content[1].Tag && "first tag should be 2"); -} - -// Sanitize feature bits. -// Ensure that fAndBSubSection always contains exactly three build attributes: -// BTI, PAC, and GCS. -// - Content[0]: BTI, Content[1]: PAC, Content[2]: GCS. -// - Remove build attributes with unknown tags. -// - If any attribute is missing, add it with its value set to `0`. -// - Sort the content vector so that Content[0] is BTI, Content[1] is PAC, and -// Content[2] is GCS. -static void sanitizeFAndBSubSection( - std::optional &fAndBSubSection) { - /* - Same as gnu properties: treat a missing 'aeabi_feature_and_bits' feature as - being set to 0 - */ - if (!fAndBSubSection) { - fAndBSubSection.emplace("aeabi_feature_and_bits", 1, 0, - SmallVector()); - } else { - // Currently there are 3 known tags defined for the features and bits - // subsection, however, user is allowed to add other, unknown tag. If such - // tags exists, remove them. (duplicates are not possible) - fAndBSubSection->Content.erase( - std::remove_if( - fAndBSubSection->Content.begin(), fAndBSubSection->Content.end(), - [](const BuildAttributeItem &item) { - return item.Tag != - llvm::AArch64BuildAttributes::TAG_FEATURE_BTI && - item.Tag != - llvm::AArch64BuildAttributes::TAG_FEATURE_PAC && - item.Tag != llvm::AArch64BuildAttributes::TAG_FEATURE_GCS; - }), - fAndBSubSection->Content.end()); - } - - // Find missing tags - std::set requiredTags = { - llvm::AArch64BuildAttributes::TAG_FEATURE_BTI, - llvm::AArch64BuildAttributes::TAG_FEATURE_PAC, - llvm::AArch64BuildAttributes::TAG_FEATURE_GCS}; - for (const auto &item : fAndBSubSection->Content) - requiredTags.erase(item.Tag); - - // Add missing tags - for (const auto &tag : requiredTags) - fAndBSubSection->Content.push_back( - BuildAttributeItem(BuildAttributeItem::NumericAttribute, tag, 0, "")); - - assert(3 == fAndBSubSection->Content.size() && "vector size should be 3"); - std::sort(fAndBSubSection->Content.begin(), fAndBSubSection->Content.end(), - [](const auto &a, const auto &b) { return a.Tag < b.Tag; }); - assert(llvm::AArch64BuildAttributes::TAG_FEATURE_PAC == - fAndBSubSection->Content[0].Tag && - "first tag should be 0"); - assert(llvm::AArch64BuildAttributes::TAG_FEATURE_BTI == - fAndBSubSection->Content[1].Tag && - "first tag should be 1"); - assert(llvm::AArch64BuildAttributes::TAG_FEATURE_GCS == - fAndBSubSection->Content[2].Tag && - "first tag should be 2"); -} - -static std::array, 2> -extractBuildAttributesSubsection( - Ctx &ctx, - const SmallVectorImpl - &buildAttributesSubsections, - InputSection isec) { - - std::optional newPauthSubSection; - std::optional newFAndBSubSection; - - for (const auto &newSubSection : buildAttributesSubsections) { - if (newPauthSubSection && newFAndBSubSection) - break; - if ("aeabi_pauthabi" == newSubSection.Name) { - newPauthSubSection.emplace(newSubSection); - continue; - } - if ("aeabi_feature_and_bits" == newSubSection.Name) { - newFAndBSubSection.emplace(newSubSection); - } - } - sanitizePauthSubSection(ctx, newPauthSubSection, isec); - sanitizeFAndBSubSection(newFAndBSubSection); - - return {std::move(newPauthSubSection), std::move(newFAndBSubSection)}; +struct KnownAArch64BuildAttrSubsections { + struct PauthSubSection { + std::optional tagPlatform = 0; + std::optional tagScheme = 0; + bool ignore = 1; + } pauth; + struct FAndBSubSection { + std::optional tagBTI = 0; + std::optional tagPAC = 0; + std::optional tagGCS = 0; + bool ignore = 1; + } fAndB; +}; + +static KnownAArch64BuildAttrSubsections extractBuildAttributesSubsections( + Ctx &ctx, const AArch64AttributeParser &attributes, InputSection isec) { + + KnownAArch64BuildAttrSubsections subSections; + subSections.pauth.tagPlatform = attributes.getAttributeValue( + "aeabi_pauthabi", llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM); + if (std::nullopt == subSections.pauth.tagPlatform) + subSections.pauth.tagPlatform = 0; + subSections.pauth.tagScheme = attributes.getAttributeValue( + "aeabi_pauthabi", llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA); + if (std::nullopt == subSections.pauth.tagScheme) + subSections.pauth.tagPlatform = 0; + subSections.fAndB.tagBTI = attributes.getAttributeValue( + "aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_BTI); + if (std::nullopt == subSections.fAndB.tagPAC) + subSections.pauth.tagPlatform = 0; + subSections.fAndB.tagPAC = attributes.getAttributeValue( + "aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_PAC); + if (std::nullopt == subSections.fAndB.tagBTI) + subSections.pauth.tagPlatform = 0; + subSections.fAndB.tagGCS = attributes.getAttributeValue( + "aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_GCS); + if (std::nullopt == subSections.fAndB.tagGCS) + subSections.pauth.tagPlatform = 0; + + return subSections; } // Merge AArch64 Build Attributes subsection @@ -828,14 +732,15 @@ template void ObjFile::parse(bool ignoreComdats) { break; case EM_AARCH64: { // The specification states that if a file contains both GNU properties - // and AArch64 build attributes, they must be identical. Therefore, if a - // file contains GNU properties, the AArch64 build attributes are ignored. - // If a file does not contain GNU properties, we leverage the existing GNU - // properties mechanism by populating the corresponding data structures, - // which will later be handled by Driver.cpp::readSecurityNotes. This - // ensures that AArch64 build attributes are represented in the linked - // object file as GNU properties, which are already supported by the Linux - // kernel and the dynamic dispatcher. + // and AArch64 build attributes, they can be assumed to be identical. + // Therefore, if a file contains GNU properties, the AArch64 build + // attributes are ignored. If a file does not contain GNU properties, we + // leverage the existing GNU properties mechanism by populating the + // corresponding data structures, which will later be handled by + // Driver.cpp::readSecurityNotes. This ensures that AArch64 build + // attributes are represented in the linked object file as GNU properties, + // which are already supported by the Linux kernel and the dynamic + // dispatcher. if (sec.sh_type == SHT_AARCH64_ATTRIBUTES) { StringRef name = check(obj.getSectionName(sec, shstrtab)); AArch64AttributeParser attributes; @@ -846,42 +751,22 @@ template void ObjFile::parse(bool ignoreComdats) { } else { // for functions that has to warn/err/report InputSection isec(*this, sec, name); - const SmallVector - buildAttributesSubSections = - attributes.getBuildAttributesSection(); - auto subsections = extractBuildAttributesSubsection( - ctx, buildAttributesSubSections, isec); - mergeAArch64BuildAttributes(ctx, subsections, isec); + KnownAArch64BuildAttrSubsections subSections = + extractBuildAttributesSubsections(ctx, attributes, isec); if (!hasGnuProperties) { - auto [pauthSubSection, fAndBSubSection] = subsections; - if (pauthSubSection) { - assert( - (pauthSubSection->Content.size() == 2) && - "pauthSubSection must contain exactly two build attributes"); - // sanitizePauthSubSection already sorts - (*this).aarch64PauthAbiCoreInfoStorage = - std::make_unique>(); - uint64_t values[2] = { - static_cast(pauthSubSection->Content[0].IntValue), - static_cast(pauthSubSection->Content[1].IntValue)}; - std::memcpy((*this).aarch64PauthAbiCoreInfoStorage->data(), - &values[0], sizeof(values)); - (*this).aarch64PauthAbiCoreInfo = - *(*this).aarch64PauthAbiCoreInfoStorage; - } - if (fAndBSubSection) { - assert((fAndBSubSection->Content.size() == 3) && - "fAndBSubSection must contain exactly three build " - "attributes"); - // sanitizeFAndBSubSection already sorts - (*this).andFeatures = 0; - (*this).andFeatures |= (fAndBSubSection->Content[0].IntValue) - << 0; - (*this).andFeatures |= (fAndBSubSection->Content[1].IntValue) - << 1; - (*this).andFeatures |= (fAndBSubSection->Content[2].IntValue) - << 2; - } + (*this).aarch64PauthAbiCoreInfoStorage = + std::make_unique>(); + uint64_t values[2] = { + static_cast(*subSections.pauth.tagPlatform), + static_cast(*subSections.pauth.tagScheme)}; + std::memcpy((*this).aarch64PauthAbiCoreInfoStorage->data(), + &values[0], sizeof(values)); + (*this).aarch64PauthAbiCoreInfo = + *(*this).aarch64PauthAbiCoreInfoStorage; + (*this).andFeatures = 0; + (*this).andFeatures |= (*subSections.fAndB.tagBTI) << 0; + (*this).andFeatures |= (*subSections.fAndB.tagPAC) << 1; + (*this).andFeatures |= (*subSections.fAndB.tagGCS) << 2; } } sections[i] = &InputSection::discarded; From 8a21905cacd6ef00aa65c576e25eadc12d190cc4 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 14:06:53 +0000 Subject: [PATCH 25/89] remove merging --- lld/ELF/InputFiles.cpp | 46 ++---------------------------------------- 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index b99183dee34bf..f18983e019874 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -229,6 +229,8 @@ static KnownAArch64BuildAttrSubsections extractBuildAttributesSubsections( KnownAArch64BuildAttrSubsections subSections; subSections.pauth.tagPlatform = attributes.getAttributeValue( "aeabi_pauthabi", llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM); + // Rather do this explicitly here, so behaviour in case of missing tags can be + // change in the future. if (std::nullopt == subSections.pauth.tagPlatform) subSections.pauth.tagPlatform = 0; subSections.pauth.tagScheme = attributes.getAttributeValue( @@ -251,50 +253,6 @@ static KnownAArch64BuildAttrSubsections extractBuildAttributesSubsections( return subSections; } -// Merge AArch64 Build Attributes subsection -static void mergeAArch64BuildAttributes( - Ctx &ctx, - const std::array, 2> - &buildAttributesSubsections, - InputSection isec) { - - auto [newPauthSubSection, newFAndBSubSection] = buildAttributesSubsections; - - if (ctx.mergedPauthSubSection == std::nullopt) { - ctx.mergedPauthSubSection = newPauthSubSection; - } - - if (ctx.mergedFAndBSubSection == std::nullopt) - ctx.mergedFAndBSubSection = newFAndBSubSection; - - if (newPauthSubSection) { - // Since sanitizePauthSubSection sorts, we know that both vectors align. - // Merge pauth (values has to match) - if ((ctx.mergedPauthSubSection->Content[0].IntValue != - newPauthSubSection->Content[0].IntValue) || - ctx.mergedPauthSubSection->Content[1].IntValue != - newPauthSubSection->Content[1].IntValue) { - ctx.mergedPauthSubSection->Content[0].IntValue = - std::numeric_limits::max(); - ctx.mergedPauthSubSection->Content[1].IntValue = - std::numeric_limits::max(); - Warn(ctx) - << &isec - << ": AArch64 Build Attributes: mismatch in 'aeabi_pauthabi' values " - "detected; marking 'aeabi_pauthabi' as invalid for this project"; - } - } - - // Since sanitizeFAndBSubSection sorts, we know that both vectors align. - // Merge Features and Bits - ctx.mergedFAndBSubSection->Content[0].IntValue &= - newFAndBSubSection->Content[0].IntValue; - ctx.mergedFAndBSubSection->Content[1].IntValue &= - newFAndBSubSection->Content[1].IntValue; - ctx.mergedFAndBSubSection->Content[2].IntValue &= - newFAndBSubSection->Content[2].IntValue; -} - InputFile::InputFile(Ctx &ctx, Kind k, MemoryBufferRef m) : ctx(ctx), mb(m), groupId(ctx.driver.nextGroupId), fileKind(k) { // All files within the same --{start,end}-group get the same group ID. From fd365cb59ef2bec7e8659d87050b685252ef470a Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 14:22:17 +0000 Subject: [PATCH 26/89] check for gnu properties section in a separate loop before the main loop --- lld/ELF/InputFiles.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index f18983e019874..9786b29eca319 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -598,9 +598,19 @@ template void ObjFile::parse(bool ignoreComdats) { // done in parallel. ArrayRef objSections = getELFShdrs(); StringRef shstrtab = CHECK2(obj.getSectionStringTable(objSections), this); - bool hasGnuProperties = false; uint64_t size = objSections.size(); sections.resize(size); + + // check whether gun properties section present + bool hasGnuProperties = false; + for (size_t i = 0; i != size; ++i) { + const Elf_Shdr &sec = objSections[i]; + hasGnuProperties = + check(obj.getSectionName(sec, shstrtab)) == ".note.gnu.property" + ? true + : false; + } + for (size_t i = 0; i != size; ++i) { const Elf_Shdr &sec = objSections[i]; if (LLVM_LIKELY(sec.sh_type == SHT_PROGBITS)) @@ -622,10 +632,8 @@ template void ObjFile::parse(bool ignoreComdats) { .second; if (keepGroup) { if (!ctx.arg.resolveGroups) { - StringRef name = check(obj.getSectionName(sec, shstrtab)); - if (name == ".note.gnu.property") - hasGnuProperties = true; - sections[i] = createInputSection(i, sec, name); + sections[i] = createInputSection( + i, sec, check(obj.getSectionName(sec, shstrtab))); } } else { // Otherwise, discard group members. From 024847d6d85738da7dbac961c89b4c7e0a3980a9 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 14:55:03 +0000 Subject: [PATCH 27/89] fix asignment to wrong values --- lld/ELF/InputFiles.cpp | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 9786b29eca319..a1e6a0beaa497 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -229,26 +229,30 @@ static KnownAArch64BuildAttrSubsections extractBuildAttributesSubsections( KnownAArch64BuildAttrSubsections subSections; subSections.pauth.tagPlatform = attributes.getAttributeValue( "aeabi_pauthabi", llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM); - // Rather do this explicitly here, so behaviour in case of missing tags can be - // change in the future. + // Rather do this check explicitly here, so behaviour in case of missing tags + // can be change in the future. if (std::nullopt == subSections.pauth.tagPlatform) subSections.pauth.tagPlatform = 0; + subSections.pauth.tagScheme = attributes.getAttributeValue( "aeabi_pauthabi", llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA); if (std::nullopt == subSections.pauth.tagScheme) - subSections.pauth.tagPlatform = 0; + subSections.pauth.tagScheme = 0; + subSections.fAndB.tagBTI = attributes.getAttributeValue( "aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_BTI); - if (std::nullopt == subSections.fAndB.tagPAC) - subSections.pauth.tagPlatform = 0; + if (std::nullopt == subSections.fAndB.tagBTI) + subSections.fAndB.tagBTI = 0; + subSections.fAndB.tagPAC = attributes.getAttributeValue( "aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_PAC); - if (std::nullopt == subSections.fAndB.tagBTI) - subSections.pauth.tagPlatform = 0; + if (std::nullopt == subSections.fAndB.tagPAC) + subSections.fAndB.tagPAC = 0; + subSections.fAndB.tagGCS = attributes.getAttributeValue( "aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_GCS); if (std::nullopt == subSections.fAndB.tagGCS) - subSections.pauth.tagPlatform = 0; + subSections.fAndB.tagGCS = 0; return subSections; } @@ -709,8 +713,8 @@ template void ObjFile::parse(bool ignoreComdats) { // dispatcher. if (sec.sh_type == SHT_AARCH64_ATTRIBUTES) { StringRef name = check(obj.getSectionName(sec, shstrtab)); - AArch64AttributeParser attributes; ArrayRef contents = check(obj.getSectionContents(sec)); + AArch64AttributeParser attributes; if (Error e = attributes.parse(contents, ELFT::Endianness)) { InputSection isec(*this, sec, name); Warn(ctx) << &isec << ": " << std::move(e); @@ -720,19 +724,19 @@ template void ObjFile::parse(bool ignoreComdats) { KnownAArch64BuildAttrSubsections subSections = extractBuildAttributesSubsections(ctx, attributes, isec); if (!hasGnuProperties) { - (*this).aarch64PauthAbiCoreInfoStorage = + this->aarch64PauthAbiCoreInfoStorage = std::make_unique>(); uint64_t values[2] = { static_cast(*subSections.pauth.tagPlatform), static_cast(*subSections.pauth.tagScheme)}; - std::memcpy((*this).aarch64PauthAbiCoreInfoStorage->data(), - &values[0], sizeof(values)); - (*this).aarch64PauthAbiCoreInfo = - *(*this).aarch64PauthAbiCoreInfoStorage; - (*this).andFeatures = 0; - (*this).andFeatures |= (*subSections.fAndB.tagBTI) << 0; - (*this).andFeatures |= (*subSections.fAndB.tagPAC) << 1; - (*this).andFeatures |= (*subSections.fAndB.tagGCS) << 2; + std::memcpy(this->aarch64PauthAbiCoreInfoStorage->data(), values, + sizeof(values)); + this->aarch64PauthAbiCoreInfo = + *(this->aarch64PauthAbiCoreInfoStorage); + this->andFeatures = 0; + this->andFeatures |= (*subSections.fAndB.tagBTI) << 0; + this->andFeatures |= (*subSections.fAndB.tagPAC) << 1; + this->andFeatures |= (*subSections.fAndB.tagGCS) << 2; } } sections[i] = &InputSection::discarded; From f9d7aa8dac4969ba41cd6b4f66a946553e1bc1c2 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 14:56:38 +0000 Subject: [PATCH 28/89] scheme --> schema --- lld/ELF/InputFiles.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index a1e6a0beaa497..1824e1fb358e1 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -212,7 +212,7 @@ static void updateSupportedARMFeatures(Ctx &ctx, struct KnownAArch64BuildAttrSubsections { struct PauthSubSection { std::optional tagPlatform = 0; - std::optional tagScheme = 0; + std::optional tagSchema = 0; bool ignore = 1; } pauth; struct FAndBSubSection { @@ -234,10 +234,10 @@ static KnownAArch64BuildAttrSubsections extractBuildAttributesSubsections( if (std::nullopt == subSections.pauth.tagPlatform) subSections.pauth.tagPlatform = 0; - subSections.pauth.tagScheme = attributes.getAttributeValue( + subSections.pauth.tagSchema = attributes.getAttributeValue( "aeabi_pauthabi", llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA); - if (std::nullopt == subSections.pauth.tagScheme) - subSections.pauth.tagScheme = 0; + if (std::nullopt == subSections.pauth.tagSchema) + subSections.pauth.tagSchema = 0; subSections.fAndB.tagBTI = attributes.getAttributeValue( "aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_BTI); @@ -728,7 +728,7 @@ template void ObjFile::parse(bool ignoreComdats) { std::make_unique>(); uint64_t values[2] = { static_cast(*subSections.pauth.tagPlatform), - static_cast(*subSections.pauth.tagScheme)}; + static_cast(*subSections.pauth.tagSchema)}; std::memcpy(this->aarch64PauthAbiCoreInfoStorage->data(), values, sizeof(values)); this->aarch64PauthAbiCoreInfo = From 79038178521a43a6f2cdf257bc5f9ecff75b8f38 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 15:03:17 +0000 Subject: [PATCH 29/89] use value_or() for optionals --- lld/ELF/InputFiles.cpp | 57 +++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 1824e1fb358e1..af53fd0734fa9 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -223,36 +223,37 @@ struct KnownAArch64BuildAttrSubsections { } fAndB; }; -static KnownAArch64BuildAttrSubsections extractBuildAttributesSubsections( - Ctx &ctx, const AArch64AttributeParser &attributes, InputSection isec) { +static KnownAArch64BuildAttrSubsections +extractBuildAttributesSubsections(Ctx &ctx, + const AArch64AttributeParser &attributes, + const InputSection &isec) { KnownAArch64BuildAttrSubsections subSections; - subSections.pauth.tagPlatform = attributes.getAttributeValue( - "aeabi_pauthabi", llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM); - // Rather do this check explicitly here, so behaviour in case of missing tags - // can be change in the future. - if (std::nullopt == subSections.pauth.tagPlatform) - subSections.pauth.tagPlatform = 0; - - subSections.pauth.tagSchema = attributes.getAttributeValue( - "aeabi_pauthabi", llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA); - if (std::nullopt == subSections.pauth.tagSchema) - subSections.pauth.tagSchema = 0; - - subSections.fAndB.tagBTI = attributes.getAttributeValue( - "aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_BTI); - if (std::nullopt == subSections.fAndB.tagBTI) - subSections.fAndB.tagBTI = 0; - - subSections.fAndB.tagPAC = attributes.getAttributeValue( - "aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_PAC); - if (std::nullopt == subSections.fAndB.tagPAC) - subSections.fAndB.tagPAC = 0; - - subSections.fAndB.tagGCS = attributes.getAttributeValue( - "aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_GCS); - if (std::nullopt == subSections.fAndB.tagGCS) - subSections.fAndB.tagGCS = 0; + subSections.pauth.tagPlatform = + attributes + .getAttributeValue("aeabi_pauthabi", + llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM) + .value_or(0); + subSections.pauth.tagSchema = + attributes + .getAttributeValue("aeabi_pauthabi", + llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA) + .value_or(0); + subSections.fAndB.tagBTI = + attributes + .getAttributeValue("aeabi_feature_and_bits", + llvm::AArch64BuildAttributes::TAG_FEATURE_BTI) + .value_or(0); + subSections.fAndB.tagPAC = + attributes + .getAttributeValue("aeabi_feature_and_bits", + llvm::AArch64BuildAttributes::TAG_FEATURE_PAC) + .value_or(0); + subSections.fAndB.tagGCS = + attributes + .getAttributeValue("aeabi_feature_and_bits", + llvm::AArch64BuildAttributes::TAG_FEATURE_GCS) + .value_or(0); return subSections; } From f225428b619b9466cc8fb8ec9d739b414d63e8d0 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 15:25:15 +0000 Subject: [PATCH 30/89] warn when both gnu properties and aarch64 build attributes exist --- lld/ELF/InputFiles.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index af53fd0734fa9..c7d85f8ac343d 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -738,6 +738,11 @@ template void ObjFile::parse(bool ignoreComdats) { this->andFeatures |= (*subSections.fAndB.tagBTI) << 0; this->andFeatures |= (*subSections.fAndB.tagPAC) << 1; this->andFeatures |= (*subSections.fAndB.tagGCS) << 2; + } else { + Warn(ctx) << &isec + << ": object file conatains both `.note.gnu.property` " + "and `.ARM.attributes` subsections. `.ARM.attributes` " + "subsection ignored."; } } sections[i] = &InputSection::discarded; From 0e643e5e625540db8f99a4ffbff6799f3e8c5253 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 16:44:36 +0000 Subject: [PATCH 31/89] add test files --- lld/ELF/InputFiles.cpp | 6 ++-- .../build-attributes-to-gnu_properties-2.s | 2 +- .../build-attributes-to-gnu_properties-3.s | 2 +- ...tributes-with-gnu_properties-multifile-2.s | 15 ++++++++ ...tributes-with-gnu_properties-multifile-3.s | 10 ++++++ .../build-attributes-to-gnu_properties-1.s | 1 - ...tributes-with-gnu_properties-multifile-1.s | 19 ++++++++++ ...uild-attributes-with-gnu_properties-warn.s | 36 +++++++++++++++++++ 8 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-2.s create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-3.s create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-multifile-1.s create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-warn.s diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index c7d85f8ac343d..af449d2c43b86 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -610,10 +610,8 @@ template void ObjFile::parse(bool ignoreComdats) { bool hasGnuProperties = false; for (size_t i = 0; i != size; ++i) { const Elf_Shdr &sec = objSections[i]; - hasGnuProperties = - check(obj.getSectionName(sec, shstrtab)) == ".note.gnu.property" - ? true - : false; + if (check(obj.getSectionName(sec, shstrtab)) == ".note.gnu.property") + hasGnuProperties = true; } for (size_t i = 0; i != size; ++i) { diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s index d3e677eee0360..e867784e280d5 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s @@ -1,6 +1,6 @@ # REQUIRES: aarch64 -.section .note.gnu.property, "a" + .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 49 .aeabi_attribute Tag_PAuth_Schema, 19 diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s index 8763000b786c0..c027492e4d1b1 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s @@ -1,6 +1,6 @@ # REQUIRES: aarch64 -.section .note.gnu.property, "a" + .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 49 .aeabi_attribute Tag_PAuth_Schema, 19 diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-2.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-2.s new file mode 100644 index 0000000000000..418688de714e9 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-2.s @@ -0,0 +1,15 @@ + +.section ".note.gnu.property", "a" + .long 4 // Name length is always 4 ("GNU") + .long end - begin // Data length + .long 5 // Type: NT_GNU_PROPERTY_TYPE_0 + .asciz "GNU" // Name + .p2align 3 +begin: + # PAuth ABI property note + .long 0xc0000001 // Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH + .long 16 // Data size + .quad 49 // PAuth ABI platform + .quad 19 // PAuth ABI version + .p2align 3 // Align to 8 byte for 64 bit +end: diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-3.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-3.s new file mode 100644 index 0000000000000..22fd19c2c953c --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-3.s @@ -0,0 +1,10 @@ + +.section ".note.gnu.property", "a" +.long 4 +.long 0x10 +.long 0x5 +.asciz "GNU" +.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND +.long 4 +.long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI and PAC +.long 0 diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s index 5ff5f12269333..3f40ce5605fca 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s @@ -11,7 +11,6 @@ # CHECK-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 -.section .note.gnu.property, "a" .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 49 .aeabi_attribute Tag_PAuth_Schema, 19 diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-multifile-1.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-multifile-1.s new file mode 100644 index 0000000000000..f6843055c2236 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-multifile-1.s @@ -0,0 +1,19 @@ +# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-with-gnu_properties-multifile-2.s -o %t2.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-with-gnu_properties-multifile-3.s -o %t3.o +# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o +# RUN: llvm-readelf -n %t.merged.o | FileCheck %s + +# CHECK: Displaying notes found in: .note.gnu.property +# CHECK: Owner Data size Description +# CHECK: GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 (property note) +# CHECK: Properties: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 + + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 1 diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-warn.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-warn.s new file mode 100644 index 0000000000000..58c887430c0ca --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-warn.s @@ -0,0 +1,36 @@ +# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t.o +# RUN: ld.lld -r %t.o 2>&1 | FileCheck --check-prefix=WARN %s + +# WARN: (.ARM.attributes): object file conatains both `.note.gnu.property` and `.ARM.attributes` subsections. `.ARM.attributes` subsection ignored. + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 1 + +.section ".note.gnu.property", "a" + .long 4 // Name length is always 4 ("GNU") + .long end - begin // Data length + .long 5 // Type: NT_GNU_PROPERTY_TYPE_0 + .asciz "GNU" // Name + .p2align 3 +begin: + # PAuth ABI property note + .long 0xc0000001 // Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH + .long 16 // Data size + .quad 0 // PAuth ABI platform + .quad 0 // PAuth ABI version + .p2align 3 // Align to 8 byte for 64 bit +end: +.section ".note.gnu.property", "a" +.long 4 +.long 0x10 +.long 0x5 +.asciz "GNU" +.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND +.long 4 +.long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI and PAC +.long 0 From f187b20c05ec498bdd5e6cb6ce12298eb195a4e1 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 20 Mar 2025 17:16:02 +0000 Subject: [PATCH 32/89] remove required from test files in AArch64 folder --- .../ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s | 2 -- .../ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s | 2 -- 2 files changed, 4 deletions(-) diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s index e867784e280d5..8210b5fba596d 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s @@ -1,5 +1,3 @@ -# REQUIRES: aarch64 - .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 49 diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s index c027492e4d1b1..4f09184aa7a08 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s @@ -1,5 +1,3 @@ -# REQUIRES: aarch64 - .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 49 From 81a86d8be724b56d8b8041794c11054f0f6f92a7 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Tue, 1 Apr 2025 16:19:10 +0100 Subject: [PATCH 33/89] add test files for drop-in aarch64 BA replacement for gnu properties --- .../ELF/Inputs/build-attributes-merged-2.s | 0 .../ELF/Inputs/build-attributes-merged-3.s | 0 .../Inputs/build-attributes-merged-mixed-2.s | 8 +- .../Inputs/build-attributes-merged-mixed-3.s | 0 lld/test/ELF/aarch64-build-attributes.s | 26 --- lld/test/ELF/aarch64-feature-pac-replace.s | 134 +++++++++++++++ lld/test/ELF/aarch64-feature-pauth-replace.s | 157 ++++++++++++++++++ .../test/ELF/build-attributes-merged-1.s | 4 +- .../ELF/build-attributes-merged-mixed-1.s | 11 +- .../test/ELF/build-attributes-warn.s | 0 lld/test/ELF/build-attributes.s | 40 +++++ 11 files changed, 345 insertions(+), 35 deletions(-) rename llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s => lld/test/ELF/Inputs/build-attributes-merged-2.s (100%) rename llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s => lld/test/ELF/Inputs/build-attributes-merged-3.s (100%) rename llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-2.s => lld/test/ELF/Inputs/build-attributes-merged-mixed-2.s (64%) rename llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-3.s => lld/test/ELF/Inputs/build-attributes-merged-mixed-3.s (100%) delete mode 100644 lld/test/ELF/aarch64-build-attributes.s create mode 100644 lld/test/ELF/aarch64-feature-pac-replace.s create mode 100644 lld/test/ELF/aarch64-feature-pauth-replace.s rename llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s => lld/test/ELF/build-attributes-merged-1.s (92%) rename llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-multifile-1.s => lld/test/ELF/build-attributes-merged-mixed-1.s (63%) rename llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-warn.s => lld/test/ELF/build-attributes-warn.s (100%) create mode 100644 lld/test/ELF/build-attributes.s diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s b/lld/test/ELF/Inputs/build-attributes-merged-2.s similarity index 100% rename from llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-2.s rename to lld/test/ELF/Inputs/build-attributes-merged-2.s diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s b/lld/test/ELF/Inputs/build-attributes-merged-3.s similarity index 100% rename from llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-to-gnu_properties-3.s rename to lld/test/ELF/Inputs/build-attributes-merged-3.s diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-2.s b/lld/test/ELF/Inputs/build-attributes-merged-mixed-2.s similarity index 64% rename from llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-2.s rename to lld/test/ELF/Inputs/build-attributes-merged-mixed-2.s index 418688de714e9..da1e5dbc0b450 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-2.s +++ b/lld/test/ELF/Inputs/build-attributes-merged-mixed-2.s @@ -6,10 +6,14 @@ .asciz "GNU" // Name .p2align 3 begin: + .long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND + .long 4 + .long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI and PAC + .long 0 # PAuth ABI property note .long 0xc0000001 // Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH .long 16 // Data size - .quad 49 // PAuth ABI platform - .quad 19 // PAuth ABI version + .quad 49 // PAuth ABI platform + .quad 19 // PAuth ABI version .p2align 3 // Align to 8 byte for 64 bit end: diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-3.s b/lld/test/ELF/Inputs/build-attributes-merged-mixed-3.s similarity index 100% rename from llvm/test/tools/llvm-readobj/ELF/AArch64/Inputs/build-attributes-with-gnu_properties-multifile-3.s rename to lld/test/ELF/Inputs/build-attributes-merged-mixed-3.s diff --git a/lld/test/ELF/aarch64-build-attributes.s b/lld/test/ELF/aarch64-build-attributes.s deleted file mode 100644 index 24e15f94e3d4a..0000000000000 --- a/lld/test/ELF/aarch64-build-attributes.s +++ /dev/null @@ -1,26 +0,0 @@ -// REQUIRES: aarch64 -// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o -// RUN: ld.lld %t.o --shared -o %t.so -// RUN: llvm-readelf --sections %t.so | FileCheck %s -// RUN: ld.lld %t.o -o %t -// RUN: llvm-readelf --sections %t | FileCheck %s -// RUN: ld.lld -r %t.o -o %t2.o -// RUN: llvm-readelf --sections %t2.o | FileCheck %s - -/// File has a Build attributes section. This should not appear in -/// ET_EXEC or ET_SHARED files as there is no requirement for it to -/// do so. FIXME, the ld -r (relocatable link) should output a single -/// merged build attributes section. When full support is added in -/// ld.lld this test should be updated. - -// CHECK-NOT: .ARM.attributes - -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 1 -.aeabi_attribute Tag_Feature_GCS, 1 - -.global _start -.type _start, %function -_start: -ret diff --git a/lld/test/ELF/aarch64-feature-pac-replace.s b/lld/test/ELF/aarch64-feature-pac-replace.s new file mode 100644 index 0000000000000..2937665796773 --- /dev/null +++ b/lld/test/ELF/aarch64-feature-pac-replace.s @@ -0,0 +1,134 @@ +### This file replace .note.gnu.property with aarch64 build attributes in order to confirm +### interoperability. + +# REQUIRES: aarch64 +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-pac1.s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t2.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-pac.s -o %t3.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func2.s -o %tno.o + +## We do not add PAC support when the inputs don't have the .note.gnu.property +## field. + +# RUN: ld.lld %tno.o %t3.o --shared -o %tno.so +# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %tno.so | FileCheck --check-prefix=NOPAC %s +# RUN: llvm-readelf -x .got.plt %tno.so | FileCheck --check-prefix SOGOTPLT %s +# RUN: llvm-readelf --dynamic-table %tno.so | FileCheck --check-prefix NOPACDYN %s + +# NOPAC: Disassembly of section .text: +# NOPAC: 00000000000102b8 : +# NOPAC-NEXT: 102b8: bl 0x102f0 +# NOPAC-NEXT: 102bc: ret +# NOPAC: 00000000000102c0 : +# NOPAC-NEXT: 102c0: ret +# NOPAC: Disassembly of section .plt: +# NOPAC: 00000000000102d0 <.plt>: +# NOPAC-NEXT: 102d0: stp x16, x30, [sp, #-16]! +# NOPAC-NEXT: 102d4: adrp x16, 0x30000 +# NOPAC-NEXT: 102d8: ldr x17, [x16, #960] +# NOPAC-NEXT: 102dc: add x16, x16, #960 +# NOPAC-NEXT: 102e0: br x17 +# NOPAC-NEXT: 102e4: nop +# NOPAC-NEXT: 102e8: nop +# NOPAC-NEXT: 102ec: nop +# NOPAC: 00000000000102f0 : +# NOPAC-NEXT: 102f0: adrp x16, 0x30000 +# NOPAC-NEXT: 102f4: ldr x17, [x16, #968] +# NOPAC-NEXT: 102f8: add x16, x16, #968 +# NOPAC-NEXT: 102fc: br x17 + +# SOGOTPLT: Hex dump of section '.got.plt': +# SOGOTPLT-NEXT: 0x000303b0 00000000 00000000 00000000 00000000 +# SOGOTPLT-NEXT: 0x000303c0 00000000 00000000 d0020100 00000000 + +# NOPACDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) +# NOPACDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT) + + +# RUN: ld.lld %t1.o %t3.o --shared --soname=t.so -o %t.so +# RUN: llvm-readelf -n %t.so | FileCheck --check-prefix PACPROP %s +# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %t.so | FileCheck --check-prefix PACSO %s +# RUN: llvm-readelf -x .got.plt %t.so | FileCheck --check-prefix SOGOTPLT2 %s +# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix PACDYN %s + +# PACPROP: Properties: aarch64 feature: PAC + +# PACSO: Disassembly of section .text: +# PACSO: 0000000000010348 : +# PACSO-NEXT: 10348: bl 0x10380 +# PACSO-NEXT: 1034c: ret +# PACSO: 0000000000010350 : +# PACSO-NEXT: 10350: ret +# PACSO: Disassembly of section .plt: +# PACSO: 0000000000010360 <.plt>: +# PACSO-NEXT: 10360: stp x16, x30, [sp, #-16]! +# PACSO-NEXT: 10364: adrp x16, 0x30000 +# PACSO-NEXT: 10368: ldr x17, [x16, #1120] +# PACSO-NEXT: 1036c: add x16, x16, #1120 +# PACSO-NEXT: 10370: br x17 +# PACSO-NEXT: 10374: nop +# PACSO-NEXT: 10378: nop +# PACSO-NEXT: 1037c: nop +# PACSO: 0000000000010380 : +# PACSO-NEXT: 10380: adrp x16, 0x30000 +# PACSO-NEXT: 10384: ldr x17, [x16, #1128] +# PACSO-NEXT: 10388: add x16, x16, #1128 +# PACSO-NEXT: 1038c: br x17 + +# SOGOTPLT2: Hex dump of section '.got.plt': +# SOGOTPLT2-NEXT: 0x00030450 00000000 00000000 00000000 00000000 +# SOGOTPLT2-NEXT: 0x00030460 00000000 00000000 60030100 00000000 + +# PACDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) +# PACDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT) + + +# RUN: ld.lld %t.o %t2.o -z pac-plt %t.so -o %tpacplt.exe 2>&1 | FileCheck -DFILE=%t2.o --check-prefix WARN %s + +# WARN: warning: [[FILE]]: -z pac-plt: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_PAC property and no valid PAuth core info present for this link job + + +# RUN: llvm-readelf -n %tpacplt.exe | FileCheck --check-prefix=PACPROP %s +# RUN: llvm-readelf --dynamic-table %tpacplt.exe | FileCheck --check-prefix PACDYN2 %s +# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %tpacplt.exe | FileCheck --check-prefix PACPLT %s + +# PACDYN2-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) +# PACDYN2: 0x0000000070000003 (AARCH64_PAC_PLT) + +# PACPLT: Disassembly of section .text: +# PACPLT: 0000000000210388 : +# PACPLT-NEXT: 210388: bl 0x2103c0 +# PACPLT-NEXT: 21038c: ret +# PACPLT: 0000000000210390 : +# PACPLT-NEXT: 210390: ret +# PACPLT: Disassembly of section .plt: +# PACPLT: 00000000002103a0 <.plt>: +# PACPLT-NEXT: 2103a0: stp x16, x30, [sp, #-16]! +# PACPLT-NEXT: 2103a4: adrp x16, 0x230000 +# PACPLT-NEXT: 2103a8: ldr x17, [x16, #1224] +# PACPLT-NEXT: 2103ac: add x16, x16, #1224 +# PACPLT-NEXT: 2103b0: br x17 +# PACPLT-NEXT: 2103b4: nop +# PACPLT-NEXT: 2103b8: nop +# PACPLT-NEXT: 2103bc: nop +# PACPLT: 00000000002103c0 : +# PACPLT-NEXT: 2103c0: adrp x16, 0x230000 +# PACPLT-NEXT: 2103c4: ldr x17, [x16, #1232] +# PACPLT-NEXT: 2103c8: add x16, x16, #1232 +# PACPLT-NEXT: 2103cc: autia1716 +# PACPLT-NEXT: 2103d0: br x17 +# PACPLT-NEXT: 2103d4: nop + + +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 0 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 0 + +.text +.globl _start +.type func1,%function +func1: + bl func2 + ret diff --git a/lld/test/ELF/aarch64-feature-pauth-replace.s b/lld/test/ELF/aarch64-feature-pauth-replace.s new file mode 100644 index 0000000000000..8e93438ab6a06 --- /dev/null +++ b/lld/test/ELF/aarch64-feature-pauth-replace.s @@ -0,0 +1,157 @@ +### This file replace .note.gnu.property with aarch64 build attributes in order to confirm +### interoperability. + +# 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 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 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 + +# 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 + +# 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 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 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 +# 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 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 WARN1 %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 +# WARN1: warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth core info while 'tag1.o' has one +# WARN1-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth core info while 'tag1.o' has one + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-zero.s -o tag-zero.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func2.s -o func2.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o func3.o +# RUN: ld.lld func3.o --shared -o func3.so +# RUN: ld.lld tag1.o func2.o func3.so -z pac-plt --shared -o pacplt-nowarn --fatal-warnings +# RUN: ld.lld tag-zero.o func2.o func3.so -z pac-plt --shared -o pacplt-warn 2>&1 | FileCheck --check-prefix WARN2 %s + +# WARN2: warning: tag-zero.o: -z pac-plt: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_PAC property and no valid PAuth core info present for this link job +# WARN2-NEXT: warning: func2.o: -z pac-plt: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_PAC property and no valid PAuth core info present for this link job + +# RUN: llvm-readelf -d pacplt-nowarn | FileCheck --check-prefix=PACPLTTAG %s +# RUN: llvm-readelf -d pacplt-warn | FileCheck --check-prefix=PACPLTTAG %s + +# PACPLTTAG: 0x0000000070000003 (AARCH64_PAC_PLT) + +# RUN: llvm-objdump -d pacplt-nowarn | FileCheck --check-prefixes=PACPLT,NOHINT -DA=10380 -DB=478 -DC=480 %s +# RUN: llvm-objdump -d pacplt-warn | FileCheck --check-prefixes=PACPLT,HINT -DA=10390 -DB=488 -DC=490 %s + +# PACPLT: Disassembly of section .text: +# PACPLT: : +# PACPLT-NEXT: bl 0x[[A]] +# PACPLT-NEXT: ret +# PACPLT: Disassembly of section .plt: +# PACPLT: <.plt>: +# PACPLT-NEXT: stp x16, x30, [sp, #-0x10]! +# PACPLT-NEXT: adrp x16, 0x30000 +# PACPLT-NEXT: ldr x17, [x16, #0x[[B]]] +# PACPLT-NEXT: add x16, x16, #0x[[B]] +# PACPLT-NEXT: br x17 +# PACPLT-NEXT: nop +# PACPLT-NEXT: nop +# PACPLT-NEXT: nop +# PACPLT: : +# PACPLT-NEXT: adrp x16, 0x30000 +# PACPLT-NEXT: ldr x17, [x16, #0x[[C]]] +# PACPLT-NEXT: add x16, x16, #0x[[C]] +# NOHINT-NEXT: braa x17, x16 +# NOHINT-NEXT: nop +# HINT-NEXT: autia1716 +# HINT-NEXT: br x17 +# PACPLT-NEXT: nop + +# RUN: not ld.lld tag1.o -z pauth-report=u 2>&1 | FileCheck --check-prefix=REPORT-ERR %s +# REPORT-ERR: error: unknown -z pauth-report= value: u{{$}} +# REPORT-EMPTY: + +#--- abi-tag-short.s + +.section ".note.gnu.property", "a" +.long 4 +.long 20 +.long 5 +.asciz "GNU" +.long 0xc0000001 +.long 12 +.quad 2 +.long 31 + +#--- abi-tag-long.s + +.section ".note.gnu.property", "a" +.long 4 +.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 + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 42 +.aeabi_attribute Tag_PAuth_Schema, 1 + +#--- abi-tag2.s + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 42 +.aeabi_attribute Tag_PAuth_Schema, 2 + +#--- abi-tag-zero.s + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 0 +.aeabi_attribute Tag_PAuth_Schema, 0 + +#--- no-info.s + +## 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: diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s b/lld/test/ELF/build-attributes-merged-1.s similarity index 92% rename from llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s rename to lld/test/ELF/build-attributes-merged-1.s index 3f40ce5605fca..1e926a579c0ec 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-to-gnu_properties-1.s +++ b/lld/test/ELF/build-attributes-merged-1.s @@ -1,6 +1,6 @@ # RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-to-gnu_properties-2.s -o %t2.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-to-gnu_properties-3.s -o %t3.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-merged-2.s -o %t2.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-merged-3.s -o %t3.o # RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o # RUN: llvm-readelf -n %t.merged.o | FileCheck %s diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-multifile-1.s b/lld/test/ELF/build-attributes-merged-mixed-1.s similarity index 63% rename from llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-multifile-1.s rename to lld/test/ELF/build-attributes-merged-mixed-1.s index f6843055c2236..78e5e2dd99d55 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-multifile-1.s +++ b/lld/test/ELF/build-attributes-merged-mixed-1.s @@ -1,13 +1,14 @@ # RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-with-gnu_properties-multifile-2.s -o %t2.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-with-gnu_properties-multifile-3.s -o %t3.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-merged-mixed-2.s -o %t2.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-merged-mixed-3.s -o %t3.o # RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o # RUN: llvm-readelf -n %t.merged.o | FileCheck %s # CHECK: Displaying notes found in: .note.gnu.property -# CHECK: Owner Data size Description -# CHECK: GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 (property note) -# CHECK: Properties: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 +# CHECK-NEXT: Owner Data size Description +# CHECK-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +# CHECK-NEXT: Properties: aarch64 feature: BTI, PAC +# CHECK-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 .aeabi_subsection aeabi_pauthabi, required, uleb128 diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-warn.s b/lld/test/ELF/build-attributes-warn.s similarity index 100% rename from llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-with-gnu_properties-warn.s rename to lld/test/ELF/build-attributes-warn.s diff --git a/lld/test/ELF/build-attributes.s b/lld/test/ELF/build-attributes.s new file mode 100644 index 0000000000000..5cf406eacd772 --- /dev/null +++ b/lld/test/ELF/build-attributes.s @@ -0,0 +1,40 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o +// RUN: ld.lld %t.o --shared -o %t.so +// RUN: llvm-readelf --sections %t.so | FileCheck %s +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// RUN: ld.lld %t.o -o %t +// RUN: llvm-readelf --sections %t | FileCheck %s +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// RUN: ld.lld -r %t.o -o %t2.o +// RUN: llvm-readelf --sections %t2.o | FileCheck %s +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE + + +/// The Build attributes section appearing in the output of +/// llvm-mc should not appear in the output of lld, because +/// AArch64 build attributes are being transformed into .gnu.properties. + + +// CHECK: .note.gnu.property +// CHECK-NOT: .ARM.attributes + +// NOTE: Displaying notes found in: .note.gnu.property +// NOTE-NEXT: Owner Data size Description +// NOTE-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +// NOTE-NEXT: Properties: aarch64 feature: BTI, PAC, GCS +// NOTE-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 + + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 1 + +.global _start +.type _start, %function +_start: +ret From 592100f5f57e2999e1b6fbea4360f82e11d7c8c5 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Tue, 1 Apr 2025 16:33:50 +0100 Subject: [PATCH 34/89] change test files names --- ...-attributes-merged-1.s => aarch64-build-attributes-merged-1.s} | 0 ...merged-mixed-1.s => aarch64-build-attributes-merged-mixed-1.s} | 0 .../{build-attributes-warn.s => aarch64-build-attributes-warn.s} | 0 lld/test/ELF/{build-attributes.s => aarch65-build-attributes.s} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename lld/test/ELF/{build-attributes-merged-1.s => aarch64-build-attributes-merged-1.s} (100%) rename lld/test/ELF/{build-attributes-merged-mixed-1.s => aarch64-build-attributes-merged-mixed-1.s} (100%) rename lld/test/ELF/{build-attributes-warn.s => aarch64-build-attributes-warn.s} (100%) rename lld/test/ELF/{build-attributes.s => aarch65-build-attributes.s} (100%) diff --git a/lld/test/ELF/build-attributes-merged-1.s b/lld/test/ELF/aarch64-build-attributes-merged-1.s similarity index 100% rename from lld/test/ELF/build-attributes-merged-1.s rename to lld/test/ELF/aarch64-build-attributes-merged-1.s diff --git a/lld/test/ELF/build-attributes-merged-mixed-1.s b/lld/test/ELF/aarch64-build-attributes-merged-mixed-1.s similarity index 100% rename from lld/test/ELF/build-attributes-merged-mixed-1.s rename to lld/test/ELF/aarch64-build-attributes-merged-mixed-1.s diff --git a/lld/test/ELF/build-attributes-warn.s b/lld/test/ELF/aarch64-build-attributes-warn.s similarity index 100% rename from lld/test/ELF/build-attributes-warn.s rename to lld/test/ELF/aarch64-build-attributes-warn.s diff --git a/lld/test/ELF/build-attributes.s b/lld/test/ELF/aarch65-build-attributes.s similarity index 100% rename from lld/test/ELF/build-attributes.s rename to lld/test/ELF/aarch65-build-attributes.s From fe23b7181da9b2225f495a92d7113c82c1fc37f4 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 2 Apr 2025 15:36:29 +0100 Subject: [PATCH 35/89] remove now unused variables --- lld/ELF/Config.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 7d83336e0d95d..bbaa5badea26f 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -695,10 +695,6 @@ struct Ctx : CommonLinkerContext { llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &); ArrayRef aarch64PauthAbiCoreInfo; - - // AArch64 Build Attributes data - std::optional mergedPauthSubSection; - std::optional mergedFAndBSubSection; }; // The first two elements of versionDefinitions represent VER_NDX_LOCAL and From dceec93dfb0b1b1e87db782f7f2628c16f47cfc7 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 2 Apr 2025 15:36:56 +0100 Subject: [PATCH 36/89] change varibles from std::optional to unsigned --- lld/ELF/InputFiles.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index af449d2c43b86..0b3d49097b13f 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -211,14 +211,14 @@ static void updateSupportedARMFeatures(Ctx &ctx, struct KnownAArch64BuildAttrSubsections { struct PauthSubSection { - std::optional tagPlatform = 0; - std::optional tagSchema = 0; + unsigned tagPlatform = 0; + unsigned tagSchema = 0; bool ignore = 1; } pauth; struct FAndBSubSection { - std::optional tagBTI = 0; - std::optional tagPAC = 0; - std::optional tagGCS = 0; + unsigned tagBTI = 0; + unsigned tagPAC = 0; + unsigned tagGCS = 0; bool ignore = 1; } fAndB; }; @@ -726,16 +726,16 @@ template void ObjFile::parse(bool ignoreComdats) { this->aarch64PauthAbiCoreInfoStorage = std::make_unique>(); uint64_t values[2] = { - static_cast(*subSections.pauth.tagPlatform), - static_cast(*subSections.pauth.tagSchema)}; + static_cast(subSections.pauth.tagPlatform), + static_cast(subSections.pauth.tagSchema)}; std::memcpy(this->aarch64PauthAbiCoreInfoStorage->data(), values, sizeof(values)); this->aarch64PauthAbiCoreInfo = *(this->aarch64PauthAbiCoreInfoStorage); this->andFeatures = 0; - this->andFeatures |= (*subSections.fAndB.tagBTI) << 0; - this->andFeatures |= (*subSections.fAndB.tagPAC) << 1; - this->andFeatures |= (*subSections.fAndB.tagGCS) << 2; + this->andFeatures |= (subSections.fAndB.tagBTI) << 0; + this->andFeatures |= (subSections.fAndB.tagPAC) << 1; + this->andFeatures |= (subSections.fAndB.tagGCS) << 2; } else { Warn(ctx) << &isec << ": object file conatains both `.note.gnu.property` " From de3e43ec3d2f626c1406b22f157449ab4fe0916b Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 2 Apr 2025 15:38:38 +0100 Subject: [PATCH 37/89] remove unused bool --- lld/ELF/InputFiles.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 0b3d49097b13f..db690d5c14074 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -213,13 +213,11 @@ struct KnownAArch64BuildAttrSubsections { struct PauthSubSection { unsigned tagPlatform = 0; unsigned tagSchema = 0; - bool ignore = 1; } pauth; struct FAndBSubSection { unsigned tagBTI = 0; unsigned tagPAC = 0; unsigned tagGCS = 0; - bool ignore = 1; } fAndB; }; From 72e725aeef72797367a4efbf0c8707ca05fe9dc1 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 2 Apr 2025 15:59:46 +0100 Subject: [PATCH 38/89] comments should have capital letters and full stops --- lld/ELF/InputFiles.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index db690d5c14074..69f56add12701 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -604,7 +604,7 @@ template void ObjFile::parse(bool ignoreComdats) { uint64_t size = objSections.size(); sections.resize(size); - // check whether gun properties section present + // Check whether GNU properties section present. bool hasGnuProperties = false; for (size_t i = 0; i != size; ++i) { const Elf_Shdr &sec = objSections[i]; @@ -716,7 +716,7 @@ template void ObjFile::parse(bool ignoreComdats) { InputSection isec(*this, sec, name); Warn(ctx) << &isec << ": " << std::move(e); } else { - // for functions that has to warn/err/report + // For functions that has to warn/err/report. InputSection isec(*this, sec, name); KnownAArch64BuildAttrSubsections subSections = extractBuildAttributesSubsections(ctx, attributes, isec); From 902f9ef39d672a74bd82f2d4c7d6e6f645c67824 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 2 Apr 2025 16:03:27 +0100 Subject: [PATCH 39/89] create InputSection once outside if/else --- lld/ELF/InputFiles.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 69f56add12701..6d13602502e17 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -712,12 +712,11 @@ template void ObjFile::parse(bool ignoreComdats) { StringRef name = check(obj.getSectionName(sec, shstrtab)); ArrayRef contents = check(obj.getSectionContents(sec)); AArch64AttributeParser attributes; + InputSection isec(*this, sec, name); if (Error e = attributes.parse(contents, ELFT::Endianness)) { - InputSection isec(*this, sec, name); Warn(ctx) << &isec << ": " << std::move(e); } else { // For functions that has to warn/err/report. - InputSection isec(*this, sec, name); KnownAArch64BuildAttrSubsections subSections = extractBuildAttributesSubsections(ctx, attributes, isec); if (!hasGnuProperties) { From 2df0fcbfb5da07db181a7d5b2d2a3bad07f0bdf1 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 2 Apr 2025 16:09:23 +0100 Subject: [PATCH 40/89] remove warning when both aarch64 BA and gno properties present + related test file --- lld/ELF/InputFiles.cpp | 5 --- lld/test/ELF/aarch64-build-attributes-warn.s | 36 -------------------- 2 files changed, 41 deletions(-) delete mode 100644 lld/test/ELF/aarch64-build-attributes-warn.s diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 6d13602502e17..5e2189312749f 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -733,11 +733,6 @@ template void ObjFile::parse(bool ignoreComdats) { this->andFeatures |= (subSections.fAndB.tagBTI) << 0; this->andFeatures |= (subSections.fAndB.tagPAC) << 1; this->andFeatures |= (subSections.fAndB.tagGCS) << 2; - } else { - Warn(ctx) << &isec - << ": object file conatains both `.note.gnu.property` " - "and `.ARM.attributes` subsections. `.ARM.attributes` " - "subsection ignored."; } } sections[i] = &InputSection::discarded; diff --git a/lld/test/ELF/aarch64-build-attributes-warn.s b/lld/test/ELF/aarch64-build-attributes-warn.s deleted file mode 100644 index 58c887430c0ca..0000000000000 --- a/lld/test/ELF/aarch64-build-attributes-warn.s +++ /dev/null @@ -1,36 +0,0 @@ -# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t.o -# RUN: ld.lld -r %t.o 2>&1 | FileCheck --check-prefix=WARN %s - -# WARN: (.ARM.attributes): object file conatains both `.note.gnu.property` and `.ARM.attributes` subsections. `.ARM.attributes` subsection ignored. - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 49 -.aeabi_attribute Tag_PAuth_Schema, 19 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 1 -.aeabi_attribute Tag_Feature_GCS, 1 - -.section ".note.gnu.property", "a" - .long 4 // Name length is always 4 ("GNU") - .long end - begin // Data length - .long 5 // Type: NT_GNU_PROPERTY_TYPE_0 - .asciz "GNU" // Name - .p2align 3 -begin: - # PAuth ABI property note - .long 0xc0000001 // Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH - .long 16 // Data size - .quad 0 // PAuth ABI platform - .quad 0 // PAuth ABI version - .p2align 3 // Align to 8 byte for 64 bit -end: -.section ".note.gnu.property", "a" -.long 4 -.long 0x10 -.long 0x5 -.asciz "GNU" -.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND -.long 4 -.long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI and PAC -.long 0 From ecd2c5195936075aa9f58b617732766d59df23a7 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 2 Apr 2025 16:23:23 +0100 Subject: [PATCH 41/89] remove part of tests which are irelevant for testing aarch64 ba --- lld/test/ELF/aarch64-feature-pauth-replace.s | 99 -------------------- 1 file changed, 99 deletions(-) diff --git a/lld/test/ELF/aarch64-feature-pauth-replace.s b/lld/test/ELF/aarch64-feature-pauth-replace.s index 8e93438ab6a06..ed842f3b1cd2f 100644 --- a/lld/test/ELF/aarch64-feature-pauth-replace.s +++ b/lld/test/ELF/aarch64-feature-pauth-replace.s @@ -12,48 +12,6 @@ # 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 - -# 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 - -# 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 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 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 -# 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 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 WARN1 %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 -# WARN1: warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth core info while 'tag1.o' has one -# WARN1-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth core info while 'tag1.o' has one - -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-zero.s -o tag-zero.o -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func2.s -o func2.o -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o func3.o -# RUN: ld.lld func3.o --shared -o func3.so -# RUN: ld.lld tag1.o func2.o func3.so -z pac-plt --shared -o pacplt-nowarn --fatal-warnings -# RUN: ld.lld tag-zero.o func2.o func3.so -z pac-plt --shared -o pacplt-warn 2>&1 | FileCheck --check-prefix WARN2 %s - -# WARN2: warning: tag-zero.o: -z pac-plt: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_PAC property and no valid PAuth core info present for this link job -# WARN2-NEXT: warning: func2.o: -z pac-plt: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_PAC property and no valid PAuth core info present for this link job - # RUN: llvm-readelf -d pacplt-nowarn | FileCheck --check-prefix=PACPLTTAG %s # RUN: llvm-readelf -d pacplt-warn | FileCheck --check-prefix=PACPLTTAG %s @@ -86,50 +44,6 @@ # HINT-NEXT: br x17 # PACPLT-NEXT: nop -# RUN: not ld.lld tag1.o -z pauth-report=u 2>&1 | FileCheck --check-prefix=REPORT-ERR %s -# REPORT-ERR: error: unknown -z pauth-report= value: u{{$}} -# REPORT-EMPTY: - -#--- abi-tag-short.s - -.section ".note.gnu.property", "a" -.long 4 -.long 20 -.long 5 -.asciz "GNU" -.long 0xc0000001 -.long 12 -.quad 2 -.long 31 - -#--- abi-tag-long.s - -.section ".note.gnu.property", "a" -.long 4 -.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 @@ -137,19 +51,6 @@ .aeabi_attribute Tag_PAuth_Platform, 42 .aeabi_attribute Tag_PAuth_Schema, 1 -#--- abi-tag2.s - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 42 -.aeabi_attribute Tag_PAuth_Schema, 2 - -#--- abi-tag-zero.s - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 0 -.aeabi_attribute Tag_PAuth_Schema, 0 - -#--- no-info.s ## define _start to avoid missing entry warning and use --fatal-warnings to assert no diagnostic ## allow multiple definitions of _start for simplicity From d439930b32014556a4acc2acf63704e5cf009d2d Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 2 Apr 2025 16:26:54 +0100 Subject: [PATCH 42/89] fix file name --- .../{aarch65-build-attributes.s => aarch64-build-attributes.s} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lld/test/ELF/{aarch65-build-attributes.s => aarch64-build-attributes.s} (100%) diff --git a/lld/test/ELF/aarch65-build-attributes.s b/lld/test/ELF/aarch64-build-attributes.s similarity index 100% rename from lld/test/ELF/aarch65-build-attributes.s rename to lld/test/ELF/aarch64-build-attributes.s From 22c6478d33cac1d98be4d2109b6c6260f6625e61 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 3 Apr 2025 12:16:16 +0100 Subject: [PATCH 43/89] remove unused func getBuildAttributesSection --- llvm/include/llvm/Support/ELFAttrParserExtended.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/llvm/include/llvm/Support/ELFAttrParserExtended.h b/llvm/include/llvm/Support/ELFAttrParserExtended.h index 6ae43fb0ed75a..68f45fb7f368a 100644 --- a/llvm/include/llvm/Support/ELFAttrParserExtended.h +++ b/llvm/include/llvm/Support/ELFAttrParserExtended.h @@ -38,11 +38,6 @@ class ELFExtendedAttrParser : public ELFAttributeParser { virtual ~ELFExtendedAttrParser() { static_cast(!Cursor.takeError()); } Error parse(ArrayRef Section, llvm::endianness Endian) override; - const SmallVector & - getBuildAttributesSection() const { - return SubSectionVec; - } - std::optional getAttributeValue(unsigned Tag) const override; std::optional getAttributeValue(StringRef BuildAttrSubsectionName, unsigned Tag) const override; From 3321d4690b925927dda58f38cbe9b2d5c9f078b3 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 3 Apr 2025 18:09:20 +0100 Subject: [PATCH 44/89] remove test file for testing errs and warns --- lld/test/ELF/aarch64-feature-pauth-replace.s | 58 -------------------- 1 file changed, 58 deletions(-) delete mode 100644 lld/test/ELF/aarch64-feature-pauth-replace.s diff --git a/lld/test/ELF/aarch64-feature-pauth-replace.s b/lld/test/ELF/aarch64-feature-pauth-replace.s deleted file mode 100644 index ed842f3b1cd2f..0000000000000 --- a/lld/test/ELF/aarch64-feature-pauth-replace.s +++ /dev/null @@ -1,58 +0,0 @@ -### This file replace .note.gnu.property with aarch64 build attributes in order to confirm -### interoperability. - -# 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 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 core info: platform 0x2a (unknown), version 0x1 - -# RUN: llvm-readelf -d pacplt-nowarn | FileCheck --check-prefix=PACPLTTAG %s -# RUN: llvm-readelf -d pacplt-warn | FileCheck --check-prefix=PACPLTTAG %s - -# PACPLTTAG: 0x0000000070000003 (AARCH64_PAC_PLT) - -# RUN: llvm-objdump -d pacplt-nowarn | FileCheck --check-prefixes=PACPLT,NOHINT -DA=10380 -DB=478 -DC=480 %s -# RUN: llvm-objdump -d pacplt-warn | FileCheck --check-prefixes=PACPLT,HINT -DA=10390 -DB=488 -DC=490 %s - -# PACPLT: Disassembly of section .text: -# PACPLT: : -# PACPLT-NEXT: bl 0x[[A]] -# PACPLT-NEXT: ret -# PACPLT: Disassembly of section .plt: -# PACPLT: <.plt>: -# PACPLT-NEXT: stp x16, x30, [sp, #-0x10]! -# PACPLT-NEXT: adrp x16, 0x30000 -# PACPLT-NEXT: ldr x17, [x16, #0x[[B]]] -# PACPLT-NEXT: add x16, x16, #0x[[B]] -# PACPLT-NEXT: br x17 -# PACPLT-NEXT: nop -# PACPLT-NEXT: nop -# PACPLT-NEXT: nop -# PACPLT: : -# PACPLT-NEXT: adrp x16, 0x30000 -# PACPLT-NEXT: ldr x17, [x16, #0x[[C]]] -# PACPLT-NEXT: add x16, x16, #0x[[C]] -# NOHINT-NEXT: braa x17, x16 -# NOHINT-NEXT: nop -# HINT-NEXT: autia1716 -# HINT-NEXT: br x17 -# PACPLT-NEXT: nop - - -#--- abi-tag1.s - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 42 -.aeabi_attribute Tag_PAuth_Schema, 1 - - -## 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: From 17dbb950bb5762bf55e182978863525d3e6b75d5 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 3 Apr 2025 19:05:55 +0100 Subject: [PATCH 45/89] fix endianess --- lld/ELF/InputFiles.cpp | 27 ++++++----- lld/ELF/InputFiles.h | 6 ++- lld/test/ELF/aarch64-build-attributes-be.s | 55 ++++++++++++++++++++++ 3 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 lld/test/ELF/aarch64-build-attributes-be.s diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 5e2189312749f..7bba07c4e4965 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -712,23 +712,26 @@ template void ObjFile::parse(bool ignoreComdats) { StringRef name = check(obj.getSectionName(sec, shstrtab)); ArrayRef contents = check(obj.getSectionContents(sec)); AArch64AttributeParser attributes; + // For functions that has to warn/err/report. InputSection isec(*this, sec, name); if (Error e = attributes.parse(contents, ELFT::Endianness)) { Warn(ctx) << &isec << ": " << std::move(e); } else { - // For functions that has to warn/err/report. - KnownAArch64BuildAttrSubsections subSections = - extractBuildAttributesSubsections(ctx, attributes, isec); if (!hasGnuProperties) { - this->aarch64PauthAbiCoreInfoStorage = - std::make_unique>(); - uint64_t values[2] = { - static_cast(subSections.pauth.tagPlatform), - static_cast(subSections.pauth.tagSchema)}; - std::memcpy(this->aarch64PauthAbiCoreInfoStorage->data(), values, - sizeof(values)); - this->aarch64PauthAbiCoreInfo = - *(this->aarch64PauthAbiCoreInfoStorage); + KnownAArch64BuildAttrSubsections subSections = + extractBuildAttributesSubsections(ctx, attributes, isec); + if (ELFT::Endianness == llvm::endianness::big) { + for (size_t i = 0; i < 8; ++i) { + this->aarch64PauthAbiCoreInfoStorage[i] = static_cast((static_cast(subSections.pauth.tagPlatform) >> (8 * (7 - i))) & 0xFF); + this->aarch64PauthAbiCoreInfoStorage[i + 8] = static_cast((static_cast(subSections.pauth.tagSchema) >> (8 * (7 - i))) & 0xFF); + } + } else { + for (size_t i = 0; i < 8; ++i) { + this->aarch64PauthAbiCoreInfoStorage[i] = static_cast((static_cast(subSections.pauth.tagPlatform) >> (8 * i)) & 0xFF); + this->aarch64PauthAbiCoreInfoStorage[i + 8] = static_cast((static_cast(subSections.pauth.tagSchema) >> (8 * i)) & 0xFF); + } + } + this->aarch64PauthAbiCoreInfo = this->aarch64PauthAbiCoreInfoStorage; this->andFeatures = 0; this->andFeatures |= (subSections.fAndB.tagBTI) << 0; this->andFeatures |= (subSections.fAndB.tagPAC) << 1; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 09e1525394253..ad928bceea018 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -241,8 +241,12 @@ class ELFFileBase : public InputFile { StringRef sourceFile; uint32_t andFeatures = 0; bool hasCommonSyms = false; + struct PauthSubSection { + unsigned tagPlatform = 0; + unsigned tagSchema = 0; + } pauthAbiCoreInfo; ArrayRef aarch64PauthAbiCoreInfo; - std::unique_ptr> aarch64PauthAbiCoreInfoStorage; + std::array aarch64PauthAbiCoreInfoStorage; }; // .o file. diff --git a/lld/test/ELF/aarch64-build-attributes-be.s b/lld/test/ELF/aarch64-build-attributes-be.s new file mode 100644 index 0000000000000..690b2de44ef6d --- /dev/null +++ b/lld/test/ELF/aarch64-build-attributes-be.s @@ -0,0 +1,55 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o +// RUN: ld.lld %t.o --shared -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE + +/// The Build attributes section appearing in the output of +/// llvm-mc should not appear in the output of lld, because +/// AArch64 build attributes are being transformed into .gnu.properties. + +// Test mc -> big endian, lld -> little endian +// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o +// RUN: ld.lld %t.o --shared -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// RUN: ld.lld %t.o -o %t +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// RUN: ld.lld -r %t.o -o %t2.o +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE + +// Test mc -> little endian, lld -> big endian +// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o +// RUN: ld.lld --EB %t.o --shared -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// RUN: ld.lld --EB %t.o -o %t +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// RUN: ld.lld --EB -r %t.o -o %t2.o +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE + +// Test mc -> big endian, lld -> big endian +// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o +// RUN: ld.lld --EB %t.o --shared -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// RUN: ld.lld --EB %t.o -o %t +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// RUN: ld.lld --EB -r %t.o -o %t2.o +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE + +// NOTE: Displaying notes found in: .note.gnu.property +// NOTE-NEXT: Owner Data size Description +// NOTE-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +// NOTE-NEXT: Properties: aarch64 feature: BTI, PAC, GCS +// NOTE-NEXT: AArch64 PAuth ABI core info: platform 0x89abcdef (unknown), version 0x89abcdef + + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 81985529216486895 +.aeabi_attribute Tag_PAuth_Schema, 81985529216486895 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 1 + +.global _start +.type _start, %function +_start: +ret From ed7b5e637ddd2a182b8100da7b80794acde99666 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 3 Apr 2025 19:16:25 +0100 Subject: [PATCH 46/89] format --- lld/ELF/InputFiles.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 7bba07c4e4965..5d9a5ac7b070b 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -719,19 +719,34 @@ template void ObjFile::parse(bool ignoreComdats) { } else { if (!hasGnuProperties) { KnownAArch64BuildAttrSubsections subSections = - extractBuildAttributesSubsections(ctx, attributes, isec); + extractBuildAttributesSubsections(ctx, attributes, isec); if (ELFT::Endianness == llvm::endianness::big) { for (size_t i = 0; i < 8; ++i) { - this->aarch64PauthAbiCoreInfoStorage[i] = static_cast((static_cast(subSections.pauth.tagPlatform) >> (8 * (7 - i))) & 0xFF); - this->aarch64PauthAbiCoreInfoStorage[i + 8] = static_cast((static_cast(subSections.pauth.tagSchema) >> (8 * (7 - i))) & 0xFF); + this->aarch64PauthAbiCoreInfoStorage[i] = static_cast( + (static_cast(subSections.pauth.tagPlatform) >> + (8 * (7 - i))) & + 0xFF); + this->aarch64PauthAbiCoreInfoStorage[i + 8] = + static_cast( + (static_cast(subSections.pauth.tagSchema) >> + (8 * (7 - i))) & + 0xFF); } } else { for (size_t i = 0; i < 8; ++i) { - this->aarch64PauthAbiCoreInfoStorage[i] = static_cast((static_cast(subSections.pauth.tagPlatform) >> (8 * i)) & 0xFF); - this->aarch64PauthAbiCoreInfoStorage[i + 8] = static_cast((static_cast(subSections.pauth.tagSchema) >> (8 * i)) & 0xFF); + this->aarch64PauthAbiCoreInfoStorage[i] = static_cast( + (static_cast(subSections.pauth.tagPlatform) >> + (8 * i)) & + 0xFF); + this->aarch64PauthAbiCoreInfoStorage[i + 8] = + static_cast( + (static_cast(subSections.pauth.tagSchema) >> + (8 * i)) & + 0xFF); } } - this->aarch64PauthAbiCoreInfo = this->aarch64PauthAbiCoreInfoStorage; + this->aarch64PauthAbiCoreInfo = + this->aarch64PauthAbiCoreInfoStorage; this->andFeatures = 0; this->andFeatures |= (subSections.fAndB.tagBTI) << 0; this->andFeatures |= (subSections.fAndB.tagPAC) << 1; From f0eb74d1467f03ec11008ae33417f778d54df0c7 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 3 Apr 2025 20:55:47 +0100 Subject: [PATCH 47/89] restore formatting --- lld/ELF/Config.h | 2 +- lld/ELF/InputFiles.cpp | 3 +-- lld/ELF/InputFiles.h | 2 +- llvm/include/llvm/Support/ELFAttributes.h | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index bbaa5badea26f..7661f2e8f5397 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -132,7 +132,7 @@ enum class SeparateSegmentKind { None, Code, Loadable }; enum class GnuStackKind { None, Exec, NoExec }; // For --lto= -enum LtoKind : uint8_t { UnifiedThin, UnifiedRegular, Default }; +enum LtoKind : uint8_t {UnifiedThin, UnifiedRegular, Default}; // For -z gcs= enum class GcsPolicy { Implicit, Never, Always }; diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 5d9a5ac7b070b..2139f21c1b7ff 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -632,10 +632,9 @@ template void ObjFile::parse(bool ignoreComdats) { .try_emplace(CachedHashStringRef(signature), this) .second; if (keepGroup) { - if (!ctx.arg.resolveGroups) { + if (!ctx.arg.resolveGroups) sections[i] = createInputSection( i, sec, check(obj.getSectionName(sec, shstrtab))); - } } else { // Otherwise, discard group members. for (uint32_t secIndex : entries.slice(1)) { diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index ad928bceea018..aae5f4e498532 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -199,7 +199,7 @@ class ELFFileBase : public InputFile { } MutableArrayRef getMutableGlobalSymbols() { return llvm::MutableArrayRef(symbols.get() + firstGlobal, - numSymbols - firstGlobal); + numSymbols - firstGlobal); } template typename ELFT::ShdrRange getELFShdrs() const { diff --git a/llvm/include/llvm/Support/ELFAttributes.h b/llvm/include/llvm/Support/ELFAttributes.h index f3a304babb0ec..d5b7630f7759c 100644 --- a/llvm/include/llvm/Support/ELFAttributes.h +++ b/llvm/include/llvm/Support/ELFAttributes.h @@ -64,8 +64,7 @@ enum AttrType : unsigned { File = 1, Section = 2, Symbol = 3 }; StringRef attrTypeAsString(unsigned attr, TagNameMap tagNameMap, bool hasTagPrefix = true); -std::optional attrTypeFromString(StringRef tag, - TagNameMap tagNameMap); +std::optional attrTypeFromString(StringRef tag, TagNameMap tagNameMap); // Magic numbers for ELF attributes. enum AttrMagic { Format_Version = 0x41 }; From 6a541b89fcc12527418dc5e2bdcd3a46a61a3292 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 4 Apr 2025 10:01:37 +0100 Subject: [PATCH 48/89] remove unused function arguments --- lld/ELF/InputFiles.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 2139f21c1b7ff..04859bfaec990 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -222,9 +222,7 @@ struct KnownAArch64BuildAttrSubsections { }; static KnownAArch64BuildAttrSubsections -extractBuildAttributesSubsections(Ctx &ctx, - const AArch64AttributeParser &attributes, - const InputSection &isec) { +extractBuildAttributesSubsections(const AArch64AttributeParser &attributes) { KnownAArch64BuildAttrSubsections subSections; subSections.pauth.tagPlatform = @@ -718,7 +716,7 @@ template void ObjFile::parse(bool ignoreComdats) { } else { if (!hasGnuProperties) { KnownAArch64BuildAttrSubsections subSections = - extractBuildAttributesSubsections(ctx, attributes, isec); + extractBuildAttributesSubsections(attributes); if (ELFT::Endianness == llvm::endianness::big) { for (size_t i = 0; i < 8; ++i) { this->aarch64PauthAbiCoreInfoStorage[i] = static_cast( From 4620091ae36a582488186fce3512066358323b47 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 4 Apr 2025 10:03:40 +0100 Subject: [PATCH 49/89] add break to loop when section found --- lld/ELF/InputFiles.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 04859bfaec990..54f79b731f1c4 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -606,8 +606,10 @@ template void ObjFile::parse(bool ignoreComdats) { bool hasGnuProperties = false; for (size_t i = 0; i != size; ++i) { const Elf_Shdr &sec = objSections[i]; - if (check(obj.getSectionName(sec, shstrtab)) == ".note.gnu.property") + if (check(obj.getSectionName(sec, shstrtab)) == ".note.gnu.property") { hasGnuProperties = true; + break; + } } for (size_t i = 0; i != size; ++i) { From c8637a0ee8e60b2a50cee4089645253388ec4cc1 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 4 Apr 2025 11:56:20 +0100 Subject: [PATCH 50/89] refactor by using lambda --- lld/ELF/InputFiles.cpp | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 54f79b731f1c4..206049b092837 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -717,35 +717,15 @@ template void ObjFile::parse(bool ignoreComdats) { Warn(ctx) << &isec << ": " << std::move(e); } else { if (!hasGnuProperties) { - KnownAArch64BuildAttrSubsections subSections = - extractBuildAttributesSubsections(attributes); - if (ELFT::Endianness == llvm::endianness::big) { + KnownAArch64BuildAttrSubsections subSections = extractBuildAttributesSubsections(attributes); + auto serializeUnsigned = [&](unsigned value, size_t offset, bool isBE) { for (size_t i = 0; i < 8; ++i) { - this->aarch64PauthAbiCoreInfoStorage[i] = static_cast( - (static_cast(subSections.pauth.tagPlatform) >> - (8 * (7 - i))) & - 0xFF); - this->aarch64PauthAbiCoreInfoStorage[i + 8] = - static_cast( - (static_cast(subSections.pauth.tagSchema) >> - (8 * (7 - i))) & - 0xFF); - } - } else { - for (size_t i = 0; i < 8; ++i) { - this->aarch64PauthAbiCoreInfoStorage[i] = static_cast( - (static_cast(subSections.pauth.tagPlatform) >> - (8 * i)) & - 0xFF); - this->aarch64PauthAbiCoreInfoStorage[i + 8] = - static_cast( - (static_cast(subSections.pauth.tagSchema) >> - (8 * i)) & - 0xFF); - } - } - this->aarch64PauthAbiCoreInfo = - this->aarch64PauthAbiCoreInfoStorage; + this->aarch64PauthAbiCoreInfoStorage[i + offset] = static_cast((static_cast(value) >> (8 * (isBE ? (7 - i): i))) & 0xFF); }; + }; + serializeUnsigned(subSections.pauth.tagPlatform, 0, ELFT::Endianness == llvm::endianness::big); + serializeUnsigned(subSections.pauth.tagSchema, 8, ELFT::Endianness == llvm::endianness::big); + this->aarch64PauthAbiCoreInfo = this->aarch64PauthAbiCoreInfoStorage; + this->andFeatures = 0; this->andFeatures |= (subSections.fAndB.tagBTI) << 0; this->andFeatures |= (subSections.fAndB.tagPAC) << 1; From 1470bdf2fc239d087cecfc4e5d6384ce577386df Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 4 Apr 2025 12:02:16 +0100 Subject: [PATCH 51/89] format --- lld/ELF/InputFiles.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 206049b092837..a9d9108811c0c 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -717,14 +717,23 @@ template void ObjFile::parse(bool ignoreComdats) { Warn(ctx) << &isec << ": " << std::move(e); } else { if (!hasGnuProperties) { - KnownAArch64BuildAttrSubsections subSections = extractBuildAttributesSubsections(attributes); - auto serializeUnsigned = [&](unsigned value, size_t offset, bool isBE) { + KnownAArch64BuildAttrSubsections subSections = + extractBuildAttributesSubsections(attributes); + auto serializeUnsigned = [&](unsigned value, size_t offset, + bool isBE) { for (size_t i = 0; i < 8; ++i) { - this->aarch64PauthAbiCoreInfoStorage[i + offset] = static_cast((static_cast(value) >> (8 * (isBE ? (7 - i): i))) & 0xFF); }; + this->aarch64PauthAbiCoreInfoStorage[i + offset] = + static_cast((static_cast(value) >> + (8 * (isBE ? (7 - i) : i))) & + 0xFF); + }; }; - serializeUnsigned(subSections.pauth.tagPlatform, 0, ELFT::Endianness == llvm::endianness::big); - serializeUnsigned(subSections.pauth.tagSchema, 8, ELFT::Endianness == llvm::endianness::big); - this->aarch64PauthAbiCoreInfo = this->aarch64PauthAbiCoreInfoStorage; + serializeUnsigned(subSections.pauth.tagPlatform, 0, + ELFT::Endianness == llvm::endianness::big); + serializeUnsigned(subSections.pauth.tagSchema, 8, + ELFT::Endianness == llvm::endianness::big); + this->aarch64PauthAbiCoreInfo = + this->aarch64PauthAbiCoreInfoStorage; this->andFeatures = 0; this->andFeatures |= (subSections.fAndB.tagBTI) << 0; From 98dc05fbd955546ef7a2ec31fee3a34d542b968e Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 4 Apr 2025 12:57:55 +0100 Subject: [PATCH 52/89] remove unused include, s/dispatcher/loader/ --- lld/ELF/Config.h | 1 - lld/ELF/InputFiles.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 7661f2e8f5397..e07c7dd4ca1b6 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -24,7 +24,6 @@ #include "llvm/Support/CodeGen.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Compression.h" -#include "llvm/Support/ELFAttributes.h" #include "llvm/Support/Endian.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/GlobPattern.h" diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index a9d9108811c0c..b0bdccd7b1d6e 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -706,7 +706,7 @@ template void ObjFile::parse(bool ignoreComdats) { // Driver.cpp::readSecurityNotes. This ensures that AArch64 build // attributes are represented in the linked object file as GNU properties, // which are already supported by the Linux kernel and the dynamic - // dispatcher. + // loader. if (sec.sh_type == SHT_AARCH64_ATTRIBUTES) { StringRef name = check(obj.getSectionName(sec, shstrtab)); ArrayRef contents = check(obj.getSectionContents(sec)); From 57d7ff9c1409ec7dedd1f24ecfb89dcbae948b56 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 4 Apr 2025 16:40:45 +0100 Subject: [PATCH 53/89] do not wrtie pauth data when both values are 0 --- lld/ELF/InputFiles.cpp | 31 +++-- .../ELF/Inputs/aarch64-func3-pac-replace.s | 10 ++ lld/test/ELF/Inputs/aarch64-pac1-replace.s | 13 ++ .../ELF/aarch64-feature-pac-replace-all.s | 131 ++++++++++++++++++ ...ce.s => aarch64-feature-pac-replace-one.s} | 74 +++++----- 5 files changed, 206 insertions(+), 53 deletions(-) create mode 100644 lld/test/ELF/Inputs/aarch64-func3-pac-replace.s create mode 100644 lld/test/ELF/Inputs/aarch64-pac1-replace.s create mode 100644 lld/test/ELF/aarch64-feature-pac-replace-all.s rename lld/test/ELF/{aarch64-feature-pac-replace.s => aarch64-feature-pac-replace-one.s} (71%) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index b0bdccd7b1d6e..ccadecc94512e 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -719,22 +719,23 @@ template void ObjFile::parse(bool ignoreComdats) { if (!hasGnuProperties) { KnownAArch64BuildAttrSubsections subSections = extractBuildAttributesSubsections(attributes); - auto serializeUnsigned = [&](unsigned value, size_t offset, - bool isBE) { - for (size_t i = 0; i < 8; ++i) { - this->aarch64PauthAbiCoreInfoStorage[i + offset] = - static_cast((static_cast(value) >> - (8 * (isBE ? (7 - i) : i))) & - 0xFF); + if (subSections.pauth.tagPlatform || subSections.pauth.tagSchema) { + auto serializeUnsigned = [&](unsigned value, size_t offset, + bool isBE) { + for (size_t i = 0; i < 8; ++i) { + this->aarch64PauthAbiCoreInfoStorage[i + offset] = + static_cast((static_cast(value) >> + (8 * (isBE ? (7 - i) : i))) & + 0xFF); + }; }; - }; - serializeUnsigned(subSections.pauth.tagPlatform, 0, - ELFT::Endianness == llvm::endianness::big); - serializeUnsigned(subSections.pauth.tagSchema, 8, - ELFT::Endianness == llvm::endianness::big); - this->aarch64PauthAbiCoreInfo = - this->aarch64PauthAbiCoreInfoStorage; - + serializeUnsigned(subSections.pauth.tagPlatform, 0, + ELFT::Endianness == llvm::endianness::big); + serializeUnsigned(subSections.pauth.tagSchema, 8, + ELFT::Endianness == llvm::endianness::big); + this->aarch64PauthAbiCoreInfo = + this->aarch64PauthAbiCoreInfoStorage; + } this->andFeatures = 0; this->andFeatures |= (subSections.fAndB.tagBTI) << 0; this->andFeatures |= (subSections.fAndB.tagPAC) << 1; diff --git a/lld/test/ELF/Inputs/aarch64-func3-pac-replace.s b/lld/test/ELF/Inputs/aarch64-func3-pac-replace.s new file mode 100644 index 0000000000000..a837a0fe09d92 --- /dev/null +++ b/lld/test/ELF/Inputs/aarch64-func3-pac-replace.s @@ -0,0 +1,10 @@ +// This file replace gnu properties with aarch64 build attributes. + +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_PAC, 1 + +.text +.globl func3 +.type func3,@function +func3: + ret diff --git a/lld/test/ELF/Inputs/aarch64-pac1-replace.s b/lld/test/ELF/Inputs/aarch64-pac1-replace.s new file mode 100644 index 0000000000000..f763f9de2342a --- /dev/null +++ b/lld/test/ELF/Inputs/aarch64-pac1-replace.s @@ -0,0 +1,13 @@ +// This file replace gnu properties with aarch64 build attributes. + +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_PAC, 1 + +.text +.globl func2 +.type func2,@function +func2: + .globl func3 + .type func3, @function + bl func3 + ret diff --git a/lld/test/ELF/aarch64-feature-pac-replace-all.s b/lld/test/ELF/aarch64-feature-pac-replace-all.s new file mode 100644 index 0000000000000..de7a223c91a0a --- /dev/null +++ b/lld/test/ELF/aarch64-feature-pac-replace-all.s @@ -0,0 +1,131 @@ +### This file replace .note.gnu.property with aarch64 build attributes in order to confirm +### interoperability. + +# REQUIRES: aarch64 +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-pac1-replace.s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t2.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-pac-replace.s -o %t3.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func2.s -o %tno.o + +## We do not add PAC support when the inputs don't have the .note.gnu.property +## field. + +# RUN: ld.lld %tno.o %t3.o --shared -o %tno.so +# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %tno.so | FileCheck --check-prefix=NOPAC %s +# RUN: llvm-readelf -x .got.plt %tno.so | FileCheck --check-prefix SOGOTPLT %s +# RUN: llvm-readelf --dynamic-table %tno.so | FileCheck --check-prefix NOPACDYN %s + +# NOPAC: 00000000000102b8 : +# NOPAC-NEXT: 102b8: bl 0x102f0 +# NOPAC-NEXT: ret +# NOPAC: Disassembly of section .plt: +# NOPAC: 00000000000102d0 <.plt>: +# NOPAC-NEXT: 102d0: stp x16, x30, [sp, #-16]! +# NOPAC-NEXT: adrp x16, 0x30000 +# NOPAC-NEXT: ldr x17, [x16, #960] +# NOPAC-NEXT: add x16, x16, #960 +# NOPAC-NEXT: br x17 +# NOPAC-NEXT: nop +# NOPAC-NEXT: nop +# NOPAC-NEXT: nop +# NOPAC: 00000000000102f0 : +# NOPAC-NEXT: 102f0: adrp x16, 0x30000 +# NOPAC-NEXT: ldr x17, [x16, #968] +# NOPAC-NEXT: add x16, x16, #968 +# NOPAC-NEXT: br x17 + +# SOGOTPLT: Hex dump of section '.got.plt': +# SOGOTPLT-NEXT: 0x000303b0 00000000 00000000 00000000 00000000 +# SOGOTPLT-NEXT: 0x000303c0 00000000 00000000 d0020100 00000000 + +# NOPACDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) +# NOPACDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT) + + +# RUN: ld.lld %t1.o %t3.o --shared --soname=t.so -o %t.so +# RUN: llvm-readelf -n %t.so | FileCheck --check-prefix PACPROP %s +# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %t.so | FileCheck --check-prefix PACSO %s +# RUN: llvm-readelf -x .got.plt %t.so | FileCheck --check-prefix SOGOTPLT2 %s +# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix PACDYN %s + +# PACPROP: Properties: aarch64 feature: PAC + +# PACSO: Disassembly of section .text: +# PACSO: 0000000000010348 : +# PACSO-NEXT: 10348: bl 0x10380 +# PACSO-NEXT: 1034c: ret +# PACSO: 0000000000010350 : +# PACSO-NEXT: 10350: ret +# PACSO: Disassembly of section .plt: +# PACSO: 0000000000010360 <.plt>: +# PACSO-NEXT: 10360: stp x16, x30, [sp, #-16]! +# PACSO-NEXT: 10364: adrp x16, 0x30000 +# PACSO-NEXT: 10368: ldr x17, [x16, #1120] +# PACSO-NEXT: 1036c: add x16, x16, #1120 +# PACSO-NEXT: 10370: br x17 +# PACSO-NEXT: 10374: nop +# PACSO-NEXT: 10378: nop +# PACSO-NEXT: 1037c: nop +# PACSO: 0000000000010380 : +# PACSO-NEXT: 10380: adrp x16, 0x30000 +# PACSO-NEXT: 10384: ldr x17, [x16, #1128] +# PACSO-NEXT: 10388: add x16, x16, #1128 +# PACSO-NEXT: 1038c: br x17 + +# SOGOTPLT2: Hex dump of section '.got.plt': +# SOGOTPLT2-NEXT: 0x00030450 00000000 00000000 00000000 00000000 +# SOGOTPLT2-NEXT: 0x00030460 00000000 00000000 60030100 00000000 + +# PACDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) +# PACDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT) + + +# RUN: ld.lld %t.o %t2.o -z pac-plt %t.so -o %tpacplt.exe 2>&1 | FileCheck -DFILE=%t2.o --check-prefix WARN %s + +# WARN: warning: [[FILE]]: -z pac-plt: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_PAC property and no valid PAuth core info present for this link job + + +# RUN: llvm-readelf -n %tpacplt.exe | FileCheck --check-prefix=PACPROP %s +# RUN: llvm-readelf --dynamic-table %tpacplt.exe | FileCheck --check-prefix PACDYN2 %s +# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %tpacplt.exe | FileCheck --check-prefix PACPLT %s + +# PACDYN2-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) +# PACDYN2: 0x0000000070000003 (AARCH64_PAC_PLT) + +# PACPLT: Disassembly of section .text: +# PACPLT: 0000000000210370 : +# PACPLT-NEXT: 210370: bl 0x2103a0 +# PACPLT-NEXT: ret +# PACPLT: 0000000000210378 : +# PACPLT-NEXT: 210378: ret +# PACPLT: Disassembly of section .plt: +# PACPLT: 0000000000210380 <.plt>: +# PACPLT-NEXT: 210380: stp x16, x30, [sp, #-16]! +# PACPLT-NEXT: adrp x16, 0x230000 +# PACPLT-NEXT: ldr x17, [x16, #1192] +# PACPLT-NEXT: add x16, x16, #1192 +# PACPLT-NEXT: br x17 +# PACPLT-NEXT: nop +# PACPLT-NEXT: nop +# PACPLT-NEXT: nop +# PACPLT: 00000000002103a0 : +# PACPLT-NEXT: 2103a0: adrp x16, 0x230000 +# PACPLT-NEXT: ldr x17, [x16, #1200] +# PACPLT-NEXT: add x16, x16, #1200 +# PACPLT-NEXT: autia1716 +# PACPLT-NEXT: br x17 +# PACPLT-NEXT: nop + + +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 0 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 0 + +.text +.globl _start +.type func1,%function +func1: + bl func2 + ret diff --git a/lld/test/ELF/aarch64-feature-pac-replace.s b/lld/test/ELF/aarch64-feature-pac-replace-one.s similarity index 71% rename from lld/test/ELF/aarch64-feature-pac-replace.s rename to lld/test/ELF/aarch64-feature-pac-replace-one.s index 2937665796773..36ac73b1051e3 100644 --- a/lld/test/ELF/aarch64-feature-pac-replace.s +++ b/lld/test/ELF/aarch64-feature-pac-replace-one.s @@ -1,5 +1,6 @@ ### This file replace .note.gnu.property with aarch64 build attributes in order to confirm ### interoperability. +### (Still using gnu properties in the helper files) # REQUIRES: aarch64 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o @@ -16,27 +17,24 @@ # RUN: llvm-readelf -x .got.plt %tno.so | FileCheck --check-prefix SOGOTPLT %s # RUN: llvm-readelf --dynamic-table %tno.so | FileCheck --check-prefix NOPACDYN %s -# NOPAC: Disassembly of section .text: # NOPAC: 00000000000102b8 : -# NOPAC-NEXT: 102b8: bl 0x102f0 -# NOPAC-NEXT: 102bc: ret -# NOPAC: 00000000000102c0 : -# NOPAC-NEXT: 102c0: ret +# NOPAC-NEXT: 102b8: bl 0x102f0 +# NOPAC-NEXT: ret # NOPAC: Disassembly of section .plt: # NOPAC: 00000000000102d0 <.plt>: -# NOPAC-NEXT: 102d0: stp x16, x30, [sp, #-16]! -# NOPAC-NEXT: 102d4: adrp x16, 0x30000 -# NOPAC-NEXT: 102d8: ldr x17, [x16, #960] -# NOPAC-NEXT: 102dc: add x16, x16, #960 -# NOPAC-NEXT: 102e0: br x17 -# NOPAC-NEXT: 102e4: nop -# NOPAC-NEXT: 102e8: nop -# NOPAC-NEXT: 102ec: nop +# NOPAC-NEXT: 102d0: stp x16, x30, [sp, #-16]! +# NOPAC-NEXT: adrp x16, 0x30000 +# NOPAC-NEXT: ldr x17, [x16, #960] +# NOPAC-NEXT: add x16, x16, #960 +# NOPAC-NEXT: br x17 +# NOPAC-NEXT: nop +# NOPAC-NEXT: nop +# NOPAC-NEXT: nop # NOPAC: 00000000000102f0 : -# NOPAC-NEXT: 102f0: adrp x16, 0x30000 -# NOPAC-NEXT: 102f4: ldr x17, [x16, #968] -# NOPAC-NEXT: 102f8: add x16, x16, #968 -# NOPAC-NEXT: 102fc: br x17 +# NOPAC-NEXT: 102f0: adrp x16, 0x30000 +# NOPAC-NEXT: ldr x17, [x16, #968] +# NOPAC-NEXT: add x16, x16, #968 +# NOPAC-NEXT: br x17 # SOGOTPLT: Hex dump of section '.got.plt': # SOGOTPLT-NEXT: 0x000303b0 00000000 00000000 00000000 00000000 @@ -97,28 +95,28 @@ # PACDYN2: 0x0000000070000003 (AARCH64_PAC_PLT) # PACPLT: Disassembly of section .text: -# PACPLT: 0000000000210388 : -# PACPLT-NEXT: 210388: bl 0x2103c0 -# PACPLT-NEXT: 21038c: ret -# PACPLT: 0000000000210390 : -# PACPLT-NEXT: 210390: ret +# PACPLT: 0000000000210370 : +# PACPLT-NEXT: 210370: bl 0x2103a0 +# PACPLT-NEXT: ret +# PACPLT: 0000000000210378 : +# PACPLT-NEXT: 210378: ret # PACPLT: Disassembly of section .plt: -# PACPLT: 00000000002103a0 <.plt>: -# PACPLT-NEXT: 2103a0: stp x16, x30, [sp, #-16]! -# PACPLT-NEXT: 2103a4: adrp x16, 0x230000 -# PACPLT-NEXT: 2103a8: ldr x17, [x16, #1224] -# PACPLT-NEXT: 2103ac: add x16, x16, #1224 -# PACPLT-NEXT: 2103b0: br x17 -# PACPLT-NEXT: 2103b4: nop -# PACPLT-NEXT: 2103b8: nop -# PACPLT-NEXT: 2103bc: nop -# PACPLT: 00000000002103c0 : -# PACPLT-NEXT: 2103c0: adrp x16, 0x230000 -# PACPLT-NEXT: 2103c4: ldr x17, [x16, #1232] -# PACPLT-NEXT: 2103c8: add x16, x16, #1232 -# PACPLT-NEXT: 2103cc: autia1716 -# PACPLT-NEXT: 2103d0: br x17 -# PACPLT-NEXT: 2103d4: nop +# PACPLT: 0000000000210380 <.plt>: +# PACPLT-NEXT: 210380: stp x16, x30, [sp, #-16]! +# PACPLT-NEXT: adrp x16, 0x230000 +# PACPLT-NEXT: ldr x17, [x16, #1192] +# PACPLT-NEXT: add x16, x16, #1192 +# PACPLT-NEXT: br x17 +# PACPLT-NEXT: nop +# PACPLT-NEXT: nop +# PACPLT-NEXT: nop +# PACPLT: 00000000002103a0 : +# PACPLT-NEXT: 2103a0: adrp x16, 0x230000 +# PACPLT-NEXT: ldr x17, [x16, #1200] +# PACPLT-NEXT: add x16, x16, #1200 +# PACPLT-NEXT: autia1716 +# PACPLT-NEXT: br x17 +# PACPLT-NEXT: nop .aeabi_subsection aeabi_feature_and_bits, optional, uleb128 From ddb1b3e2c82d6f11d6310795b963be3137bd972c Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 4 Apr 2025 17:15:15 +0100 Subject: [PATCH 54/89] consolidate test files --- lld/ELF/InputFiles.cpp | 2 + .../ELF/aarch64-feature-pac-replace-all.s | 131 ------------------ ...ce-one.s => aarch64-feature-pac-replace.s} | 15 ++ 3 files changed, 17 insertions(+), 131 deletions(-) delete mode 100644 lld/test/ELF/aarch64-feature-pac-replace-all.s rename lld/test/ELF/{aarch64-feature-pac-replace-one.s => aarch64-feature-pac-replace.s} (80%) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index ccadecc94512e..2cf3ae9bd233f 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -719,6 +719,8 @@ template void ObjFile::parse(bool ignoreComdats) { if (!hasGnuProperties) { KnownAArch64BuildAttrSubsections subSections = extractBuildAttributesSubsections(attributes); + // this condition is important in order not to emit section when + // data does not exists, same as GNU properties. if (subSections.pauth.tagPlatform || subSections.pauth.tagSchema) { auto serializeUnsigned = [&](unsigned value, size_t offset, bool isBE) { diff --git a/lld/test/ELF/aarch64-feature-pac-replace-all.s b/lld/test/ELF/aarch64-feature-pac-replace-all.s deleted file mode 100644 index de7a223c91a0a..0000000000000 --- a/lld/test/ELF/aarch64-feature-pac-replace-all.s +++ /dev/null @@ -1,131 +0,0 @@ -### This file replace .note.gnu.property with aarch64 build attributes in order to confirm -### interoperability. - -# REQUIRES: aarch64 -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-pac1-replace.s -o %t1.o -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t2.o -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-pac-replace.s -o %t3.o -# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func2.s -o %tno.o - -## We do not add PAC support when the inputs don't have the .note.gnu.property -## field. - -# RUN: ld.lld %tno.o %t3.o --shared -o %tno.so -# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %tno.so | FileCheck --check-prefix=NOPAC %s -# RUN: llvm-readelf -x .got.plt %tno.so | FileCheck --check-prefix SOGOTPLT %s -# RUN: llvm-readelf --dynamic-table %tno.so | FileCheck --check-prefix NOPACDYN %s - -# NOPAC: 00000000000102b8 : -# NOPAC-NEXT: 102b8: bl 0x102f0 -# NOPAC-NEXT: ret -# NOPAC: Disassembly of section .plt: -# NOPAC: 00000000000102d0 <.plt>: -# NOPAC-NEXT: 102d0: stp x16, x30, [sp, #-16]! -# NOPAC-NEXT: adrp x16, 0x30000 -# NOPAC-NEXT: ldr x17, [x16, #960] -# NOPAC-NEXT: add x16, x16, #960 -# NOPAC-NEXT: br x17 -# NOPAC-NEXT: nop -# NOPAC-NEXT: nop -# NOPAC-NEXT: nop -# NOPAC: 00000000000102f0 : -# NOPAC-NEXT: 102f0: adrp x16, 0x30000 -# NOPAC-NEXT: ldr x17, [x16, #968] -# NOPAC-NEXT: add x16, x16, #968 -# NOPAC-NEXT: br x17 - -# SOGOTPLT: Hex dump of section '.got.plt': -# SOGOTPLT-NEXT: 0x000303b0 00000000 00000000 00000000 00000000 -# SOGOTPLT-NEXT: 0x000303c0 00000000 00000000 d0020100 00000000 - -# NOPACDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) -# NOPACDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT) - - -# RUN: ld.lld %t1.o %t3.o --shared --soname=t.so -o %t.so -# RUN: llvm-readelf -n %t.so | FileCheck --check-prefix PACPROP %s -# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %t.so | FileCheck --check-prefix PACSO %s -# RUN: llvm-readelf -x .got.plt %t.so | FileCheck --check-prefix SOGOTPLT2 %s -# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix PACDYN %s - -# PACPROP: Properties: aarch64 feature: PAC - -# PACSO: Disassembly of section .text: -# PACSO: 0000000000010348 : -# PACSO-NEXT: 10348: bl 0x10380 -# PACSO-NEXT: 1034c: ret -# PACSO: 0000000000010350 : -# PACSO-NEXT: 10350: ret -# PACSO: Disassembly of section .plt: -# PACSO: 0000000000010360 <.plt>: -# PACSO-NEXT: 10360: stp x16, x30, [sp, #-16]! -# PACSO-NEXT: 10364: adrp x16, 0x30000 -# PACSO-NEXT: 10368: ldr x17, [x16, #1120] -# PACSO-NEXT: 1036c: add x16, x16, #1120 -# PACSO-NEXT: 10370: br x17 -# PACSO-NEXT: 10374: nop -# PACSO-NEXT: 10378: nop -# PACSO-NEXT: 1037c: nop -# PACSO: 0000000000010380 : -# PACSO-NEXT: 10380: adrp x16, 0x30000 -# PACSO-NEXT: 10384: ldr x17, [x16, #1128] -# PACSO-NEXT: 10388: add x16, x16, #1128 -# PACSO-NEXT: 1038c: br x17 - -# SOGOTPLT2: Hex dump of section '.got.plt': -# SOGOTPLT2-NEXT: 0x00030450 00000000 00000000 00000000 00000000 -# SOGOTPLT2-NEXT: 0x00030460 00000000 00000000 60030100 00000000 - -# PACDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) -# PACDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT) - - -# RUN: ld.lld %t.o %t2.o -z pac-plt %t.so -o %tpacplt.exe 2>&1 | FileCheck -DFILE=%t2.o --check-prefix WARN %s - -# WARN: warning: [[FILE]]: -z pac-plt: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_PAC property and no valid PAuth core info present for this link job - - -# RUN: llvm-readelf -n %tpacplt.exe | FileCheck --check-prefix=PACPROP %s -# RUN: llvm-readelf --dynamic-table %tpacplt.exe | FileCheck --check-prefix PACDYN2 %s -# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %tpacplt.exe | FileCheck --check-prefix PACPLT %s - -# PACDYN2-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) -# PACDYN2: 0x0000000070000003 (AARCH64_PAC_PLT) - -# PACPLT: Disassembly of section .text: -# PACPLT: 0000000000210370 : -# PACPLT-NEXT: 210370: bl 0x2103a0 -# PACPLT-NEXT: ret -# PACPLT: 0000000000210378 : -# PACPLT-NEXT: 210378: ret -# PACPLT: Disassembly of section .plt: -# PACPLT: 0000000000210380 <.plt>: -# PACPLT-NEXT: 210380: stp x16, x30, [sp, #-16]! -# PACPLT-NEXT: adrp x16, 0x230000 -# PACPLT-NEXT: ldr x17, [x16, #1192] -# PACPLT-NEXT: add x16, x16, #1192 -# PACPLT-NEXT: br x17 -# PACPLT-NEXT: nop -# PACPLT-NEXT: nop -# PACPLT-NEXT: nop -# PACPLT: 00000000002103a0 : -# PACPLT-NEXT: 2103a0: adrp x16, 0x230000 -# PACPLT-NEXT: ldr x17, [x16, #1200] -# PACPLT-NEXT: add x16, x16, #1200 -# PACPLT-NEXT: autia1716 -# PACPLT-NEXT: br x17 -# PACPLT-NEXT: nop - - -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 0 -.aeabi_attribute Tag_Feature_PAC, 1 -.aeabi_attribute Tag_Feature_GCS, 0 - -.text -.globl _start -.type func1,%function -func1: - bl func2 - ret diff --git a/lld/test/ELF/aarch64-feature-pac-replace-one.s b/lld/test/ELF/aarch64-feature-pac-replace.s similarity index 80% rename from lld/test/ELF/aarch64-feature-pac-replace-one.s rename to lld/test/ELF/aarch64-feature-pac-replace.s index 36ac73b1051e3..866cb62d6bce1 100644 --- a/lld/test/ELF/aarch64-feature-pac-replace-one.s +++ b/lld/test/ELF/aarch64-feature-pac-replace.s @@ -5,17 +5,23 @@ # REQUIRES: aarch64 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-pac1.s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-pac1-replace.s -o %t1-ba.o # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t2.o # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-pac.s -o %t3.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-pac-replace.s -o %t3-ba.o # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func2.s -o %tno.o ## We do not add PAC support when the inputs don't have the .note.gnu.property ## field. # RUN: ld.lld %tno.o %t3.o --shared -o %tno.so +# RUN: ld.lld %tno.o %t3-ba.o --shared -o %tno-ba.so # RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %tno.so | FileCheck --check-prefix=NOPAC %s +# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %tno-ba.so | FileCheck --check-prefix=NOPAC %s # RUN: llvm-readelf -x .got.plt %tno.so | FileCheck --check-prefix SOGOTPLT %s +# RUN: llvm-readelf -x .got.plt %tno-ba.so | FileCheck --check-prefix SOGOTPLT %s # RUN: llvm-readelf --dynamic-table %tno.so | FileCheck --check-prefix NOPACDYN %s +# RUN: llvm-readelf --dynamic-table %tno-ba.so | FileCheck --check-prefix NOPACDYN %s # NOPAC: 00000000000102b8 : # NOPAC-NEXT: 102b8: bl 0x102f0 @@ -45,10 +51,15 @@ # RUN: ld.lld %t1.o %t3.o --shared --soname=t.so -o %t.so +# RUN: ld.lld %t1-ba.o %t3-ba.o --shared --soname=t.so -o %t-ba.so # RUN: llvm-readelf -n %t.so | FileCheck --check-prefix PACPROP %s +# RUN: llvm-readelf -n %t-ba.so | FileCheck --check-prefix PACPROP %s # RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %t.so | FileCheck --check-prefix PACSO %s +# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %t-ba.so | FileCheck --check-prefix PACSO %s # RUN: llvm-readelf -x .got.plt %t.so | FileCheck --check-prefix SOGOTPLT2 %s +# RUN: llvm-readelf -x .got.plt %t-ba.so | FileCheck --check-prefix SOGOTPLT2 %s # RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix PACDYN %s +# RUN: llvm-readelf --dynamic-table %t-ba.so | FileCheck --check-prefix PACDYN %s # PACPROP: Properties: aarch64 feature: PAC @@ -83,13 +94,17 @@ # RUN: ld.lld %t.o %t2.o -z pac-plt %t.so -o %tpacplt.exe 2>&1 | FileCheck -DFILE=%t2.o --check-prefix WARN %s +# RUN: ld.lld %t.o %t2.o -z pac-plt %t-ba.so -o %tpacplt-ba.exe 2>&1 | FileCheck -DFILE=%t2.o --check-prefix WARN %s # WARN: warning: [[FILE]]: -z pac-plt: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_PAC property and no valid PAuth core info present for this link job # RUN: llvm-readelf -n %tpacplt.exe | FileCheck --check-prefix=PACPROP %s +# RUN: llvm-readelf -n %tpacplt-ba.exe | FileCheck --check-prefix=PACPROP %s # RUN: llvm-readelf --dynamic-table %tpacplt.exe | FileCheck --check-prefix PACDYN2 %s +# RUN: llvm-readelf --dynamic-table %tpacplt-ba.exe | FileCheck --check-prefix PACDYN2 %s # RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %tpacplt.exe | FileCheck --check-prefix PACPLT %s +# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+v8.3a --no-show-raw-insn %tpacplt-ba.exe | FileCheck --check-prefix PACPLT %s # PACDYN2-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) # PACDYN2: 0x0000000070000003 (AARCH64_PAC_PLT) From debcd30b8812660845fe6b815fcf87279dc58de8 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Tue, 8 Apr 2025 10:11:31 +0100 Subject: [PATCH 55/89] check gnu properties content --- lld/ELF/InputFiles.cpp | 293 ++++++++++++------ lld/ELF/InputFiles.h | 9 +- lld/test/ELF/aarch64-build-attributes-be.s | 5 - .../ELF/aarch64-build-attributes-both-err.s | 55 ++++ lld/test/ELF/aarch64-build-attributes-both.s | 51 +++ lld/test/ELF/aarch64-build-attributes.s | 5 - 6 files changed, 305 insertions(+), 113 deletions(-) create mode 100644 lld/test/ELF/aarch64-build-attributes-both-err.s create mode 100644 lld/test/ELF/aarch64-build-attributes-both.s diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 2cf3ae9bd233f..203e738484d88 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -586,6 +586,102 @@ uint32_t ObjFile::getSectionIndex(const Elf_Sym &sym) const { this); } +template +static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f, + uint32_t featureAndType, + ArrayRef &desc, const uint8_t *base, + ArrayRef *data = nullptr) { + auto err = [&](const uint8_t *place) -> ELFSyncStream { + auto diag = Err(ctx); + diag << &f << ":(" << ".note.gnu.property+0x" + << Twine::utohexstr(place - base) << "): "; + return diag; + }; + + while (!desc.empty()) { + const uint8_t *place = desc.data(); + if (desc.size() < 8) + return void(err(place) << "program property is too short"); + uint32_t type = read32(desc.data()); + uint32_t size = read32(desc.data() + 4); + desc = desc.slice(8); + if (desc.size() < size) + return void(err(place) << "program property is too short"); + + if (type == featureAndType) { + // We found a FEATURE_1_AND field. There may be more than one of these + // in a .note.gnu.property section, for a relocatable object we + // accumulate the bits set. + if (size < 4) + return void(err(place) << "FEATURE_1_AND entry is too short"); + f.andFeatures |= read32(desc.data()); + } else if (ctx.arg.emachine == EM_AARCH64 && + type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) { + ArrayRef contents = data ? *data : desc; + if (!f.aarch64PauthAbiCoreInfo.empty()) { + return void( + err(contents.data()) + << "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are " + "not supported"); + } else if (size != 16) { + return void(err(contents.data()) + << "GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry " + "is invalid: expected 16 bytes, but got " + << size); + } + f.aarch64PauthAbiCoreInfo = desc; + } + + // Padding is present in the note descriptor, if necessary. + desc = desc.slice(alignTo<(ELFT::Is64Bits ? 8 : 4)>(size)); + } +} +// 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 core info (16 bytes). +template +static gnuPropertiesInfo readGnuProperty(Ctx &ctx, const InputSection &sec, + ObjFile &f) { + using Elf_Nhdr = typename ELFT::Nhdr; + using Elf_Note = typename ELFT::Note; + + ArrayRef data = sec.content(); + auto err = [&](const uint8_t *place) -> ELFSyncStream { + auto diag = Err(ctx); + diag << sec.file << ":(" << sec.name << "+0x" + << Twine::utohexstr(place - sec.content().data()) << "): "; + return diag; + }; + while (!data.empty()) { + // Read one NOTE record. + auto *nhdr = reinterpret_cast(data.data()); + if (data.size() < sizeof(Elf_Nhdr) || + data.size() < nhdr->getSize(sec.addralign)) + return (err(data.data()) << "data is too short", gnuPropertiesInfo{}); + + Elf_Note note(*nhdr); + if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName() != "GNU") { + data = data.slice(nhdr->getSize(sec.addralign)); + continue; + } + + uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64 + ? GNU_PROPERTY_AARCH64_FEATURE_1_AND + : GNU_PROPERTY_X86_FEATURE_1_AND; + + // Read a body of a NOTE record, which consists of type-length-value fields. + ArrayRef desc = note.getDesc(sec.addralign); + const uint8_t *base = sec.content().data(); + parseGnuPropertyNote(ctx, f, featureAndType, desc, base, &data); + + // Go to next NOTE record to look for more FEATURE_1_AND descriptions. + data = data.slice(nhdr->getSize(sec.addralign)); + } + return gnuPropertiesInfo{f.andFeatures, f.aarch64PauthAbiCoreInfo}; +} + template void ObjFile::parse(bool ignoreComdats) { object::ELFFile obj = this->getObj(); // Read a section table. justSymbols is usually false. @@ -602,11 +698,27 @@ template void ObjFile::parse(bool ignoreComdats) { uint64_t size = objSections.size(); sections.resize(size); - // Check whether GNU properties section present. + // Check whether GNU properties section present and store it's data. + // This is done in order to compare the content of GNU properties section with + // aarch64 build attributes section. bool hasGnuProperties = false; + gnuPropertiesInfo gnuPropertiesInformation; for (size_t i = 0; i != size; ++i) { const Elf_Shdr &sec = objSections[i]; if (check(obj.getSectionName(sec, shstrtab)) == ".note.gnu.property") { + if (0 == this->andFeatures && this->aarch64PauthAbiCoreInfo.empty()) { + gnuPropertiesInformation = readGnuProperty( + ctx, + InputSection(*this, sec, check(obj.getSectionName(sec, shstrtab))), + *this); + // Restore state + this->andFeatures = 0; + this->aarch64PauthAbiCoreInfo = {}; + } else { + gnuPropertiesInformation.andFeatures = this->andFeatures; + gnuPropertiesInformation.aarch64PauthAbiCoreInfo = + this->aarch64PauthAbiCoreInfo; + } hasGnuProperties = true; break; } @@ -715,10 +827,86 @@ template void ObjFile::parse(bool ignoreComdats) { InputSection isec(*this, sec, name); if (Error e = attributes.parse(contents, ELFT::Endianness)) { Warn(ctx) << &isec << ": " << std::move(e); + // uint32_t andFeatures = 0; + // std::array aarch64PauthAbiCoreInfoStorage; } else { - if (!hasGnuProperties) { - KnownAArch64BuildAttrSubsections subSections = - extractBuildAttributesSubsections(attributes); + bool writePauth = false; + bool wrtieFeatures = false; + KnownAArch64BuildAttrSubsections subSections = + extractBuildAttributesSubsections(attributes); + if (hasGnuProperties) { + if (!gnuPropertiesInformation.aarch64PauthAbiCoreInfo.empty()) { + // check for mismatch error + auto deserializeArray = [&](size_t offset, bool isBE) { + unsigned value = 0; + for (size_t i = 0; i < 8; ++i) { + value = isBE ? (value << 8) | + gnuPropertiesInformation + .aarch64PauthAbiCoreInfo[i + offset] + : value |= + static_cast( + gnuPropertiesInformation + .aarch64PauthAbiCoreInfo[i + offset]) + << (8 * i); + }; + return value; + }; + unsigned gnuPropPauthPlatform = deserializeArray( + 0, ELFT::Endianness == llvm::endianness::big); + if (subSections.pauth.tagPlatform != gnuPropPauthPlatform) + ErrAlways(ctx) + << &isec + << "Pauth Platform mismatch: file contains both GNU " + "properties and AArch64 build attributes sections\nGNU " + "properties: " + << gnuPropPauthPlatform << "\nAArch64 build attributes: " + << subSections.pauth.tagPlatform; + unsigned gnuPropPauthScheme = deserializeArray( + 8, ELFT::Endianness == llvm::endianness::big); + if (subSections.pauth.tagSchema != gnuPropPauthScheme) + ErrAlways(ctx) + << &isec + << "Pauth Schema mismatch: file contains both GNU " + "properties and AArch64 build attributes sections\nGNU " + "properties: " + << gnuPropPauthScheme << "\nAArch64 build attributes: " + << subSections.pauth.tagSchema; + } else { + writePauth = true; + } + if (subSections.fAndB.tagBTI != + (gnuPropertiesInformation.andFeatures & 0x01)) + ErrAlways(ctx) + << &isec + << "Features BTI mismatch: file contains both GNU " + "properties and AArch64 build attributes sections\nGNU " + "properties: " + << (gnuPropertiesInformation.andFeatures & 0x01) + << "\nAArch64 build attributes: " << subSections.fAndB.tagBTI; + if (subSections.fAndB.tagPAC != + ((gnuPropertiesInformation.andFeatures >> 1) & 0x01)) + ErrAlways(ctx) + << &isec + << "Feature PAC mismatch: file contains both GNU " + "properties and AArch64 build attributes sections\nGNU " + "properties: " + << ((gnuPropertiesInformation.andFeatures >> 1) & 0x01) + << "\nAArch64 build attributes: " << subSections.fAndB.tagBTI; + if (subSections.fAndB.tagGCS != + ((gnuPropertiesInformation.andFeatures >> 2) & 0x01)) + ErrAlways(ctx) + << &isec + << "Feature GCS mismatch: file contains both GNU " + "properties and AArch64 build attributes sections\nGNU " + "properties: " + << ((gnuPropertiesInformation.andFeatures >> 2) & 0x01) + << "\nAArch64 build attributes: " << subSections.fAndB.tagBTI; + } else { + // no GNU properties + writePauth = true; + wrtieFeatures = true; + } + if (writePauth) { // this condition is important in order not to emit section when // data does not exists, same as GNU properties. if (subSections.pauth.tagPlatform || subSections.pauth.tagSchema) { @@ -738,6 +926,8 @@ template void ObjFile::parse(bool ignoreComdats) { this->aarch64PauthAbiCoreInfo = this->aarch64PauthAbiCoreInfoStorage; } + } + if (wrtieFeatures) { this->andFeatures = 0; this->andFeatures |= (subSections.fAndB.tagBTI) << 0; this->andFeatures |= (subSections.fAndB.tagPAC) << 1; @@ -1017,101 +1207,6 @@ void ObjFile::initializeSections(bool ignoreComdats, handleSectionGroup(this->sections, entries); } -template -static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f, - uint32_t featureAndType, - ArrayRef &desc, const uint8_t *base, - ArrayRef *data = nullptr) { - auto err = [&](const uint8_t *place) -> ELFSyncStream { - auto diag = Err(ctx); - diag << &f << ":(" << ".note.gnu.property+0x" - << Twine::utohexstr(place - base) << "): "; - return diag; - }; - - while (!desc.empty()) { - const uint8_t *place = desc.data(); - if (desc.size() < 8) - return void(err(place) << "program property is too short"); - uint32_t type = read32(desc.data()); - uint32_t size = read32(desc.data() + 4); - desc = desc.slice(8); - if (desc.size() < size) - return void(err(place) << "program property is too short"); - - if (type == featureAndType) { - // We found a FEATURE_1_AND field. There may be more than one of these - // in a .note.gnu.property section, for a relocatable object we - // accumulate the bits set. - if (size < 4) - return void(err(place) << "FEATURE_1_AND entry is too short"); - f.andFeatures |= read32(desc.data()); - } else if (ctx.arg.emachine == EM_AARCH64 && - type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) { - ArrayRef contents = data ? *data : desc; - if (!f.aarch64PauthAbiCoreInfo.empty()) { - return void( - err(contents.data()) - << "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are " - "not supported"); - } else if (size != 16) { - return void(err(contents.data()) - << "GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry " - "is invalid: expected 16 bytes, but got " - << size); - } - f.aarch64PauthAbiCoreInfo = desc; - } - - // Padding is present in the note descriptor, if necessary. - desc = desc.slice(alignTo<(ELFT::Is64Bits ? 8 : 4)>(size)); - } -} -// 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 core info (16 bytes). -template -static void readGnuProperty(Ctx &ctx, const InputSection &sec, - ObjFile &f) { - using Elf_Nhdr = typename ELFT::Nhdr; - using Elf_Note = typename ELFT::Note; - - ArrayRef data = sec.content(); - auto err = [&](const uint8_t *place) -> ELFSyncStream { - auto diag = Err(ctx); - diag << sec.file << ":(" << sec.name << "+0x" - << Twine::utohexstr(place - sec.content().data()) << "): "; - return diag; - }; - while (!data.empty()) { - // Read one NOTE record. - auto *nhdr = reinterpret_cast(data.data()); - if (data.size() < sizeof(Elf_Nhdr) || - data.size() < nhdr->getSize(sec.addralign)) - return void(err(data.data()) << "data is too short"); - - Elf_Note note(*nhdr); - if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName() != "GNU") { - data = data.slice(nhdr->getSize(sec.addralign)); - continue; - } - - uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64 - ? GNU_PROPERTY_AARCH64_FEATURE_1_AND - : GNU_PROPERTY_X86_FEATURE_1_AND; - - // Read a body of a NOTE record, which consists of type-length-value fields. - ArrayRef desc = note.getDesc(sec.addralign); - const uint8_t *base = sec.content().data(); - parseGnuPropertyNote(ctx, f, featureAndType, desc, base, &data); - - // Go to next NOTE record to look for more FEATURE_1_AND descriptions. - data = data.slice(nhdr->getSize(sec.addralign)); - } -} - template InputSectionBase *ObjFile::getRelocTarget(uint32_t idx, uint32_t info) { if (info < this->sections.size()) { diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index aae5f4e498532..f9f9b8561c4d5 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -241,14 +241,15 @@ class ELFFileBase : public InputFile { StringRef sourceFile; uint32_t andFeatures = 0; bool hasCommonSyms = false; - struct PauthSubSection { - unsigned tagPlatform = 0; - unsigned tagSchema = 0; - } pauthAbiCoreInfo; ArrayRef aarch64PauthAbiCoreInfo; std::array aarch64PauthAbiCoreInfoStorage; }; +struct gnuPropertiesInfo { + uint32_t andFeatures = 0; + ArrayRef aarch64PauthAbiCoreInfo; +}; + // .o file. template class ObjFile : public ELFFileBase { LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) diff --git a/lld/test/ELF/aarch64-build-attributes-be.s b/lld/test/ELF/aarch64-build-attributes-be.s index 690b2de44ef6d..76a59c0e017d4 100644 --- a/lld/test/ELF/aarch64-build-attributes-be.s +++ b/lld/test/ELF/aarch64-build-attributes-be.s @@ -48,8 +48,3 @@ .aeabi_attribute Tag_Feature_BTI, 1 .aeabi_attribute Tag_Feature_PAC, 1 .aeabi_attribute Tag_Feature_GCS, 1 - -.global _start -.type _start, %function -_start: -ret diff --git a/lld/test/ELF/aarch64-build-attributes-both-err.s b/lld/test/ELF/aarch64-build-attributes-both-err.s new file mode 100644 index 0000000000000..20f99166916dd --- /dev/null +++ b/lld/test/ELF/aarch64-build-attributes-both-err.s @@ -0,0 +1,55 @@ +// REQUIRES: aarch64 + +// Test mc -> little endian, lld -> little endian +// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o +// RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR +// Test mc -> little endian, lld -> big endian +// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o +// RUN: not ld.lld -EB %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR +// Test mc -> big endian, lld -> little endian +// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o +// RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR +// Test mc -> big endian, lld -> big endian +// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o +// RUN: not ld.lld -EB %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR + +// ERR: Pauth Platform mismatch: file contains both GNU properties and AArch64 build attributes sections +// ERR-NEXT: GNU properties: 305419896 +// ERR-NEXT: AArch64 build attributes: 5 +// ERR: Pauth Schema mismatch: file contains both GNU properties and AArch64 build attributes sections +// ERR-NEXT: GNU properties: 2271560481 +// ERR-NEXT: AArch64 build attributes: 5 +// ERR: Features BTI mismatch: file contains both GNU properties and AArch64 build attributes sections +// ERR-NEXT: GNU properties: 0 +// ERR-NEXT: AArch64 build attributes: 1 +// ERR: Feature GCS mismatch: file contains both GNU properties and AArch64 build attributes sections +// ERR-NEXT: GNU properties: 0 +// ERR-NEXT: AArch64 build attributes: 1 + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 5 +.aeabi_attribute Tag_PAuth_Schema, 5 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 1 + +.section ".note.gnu.property", "a" +.long 4 +.long 0x10 +.long 0x5 +.asciz "GNU" +.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND +.long 4 +.long 2 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC +.long 0 + +.section ".note.gnu.property", "a" +.long 4 +.long 24 +.long 5 +.asciz "GNU" +.long 0xc0000001 +.long 16 +.quad 305419896 // platform +.quad 2271560481 // version diff --git a/lld/test/ELF/aarch64-build-attributes-both.s b/lld/test/ELF/aarch64-build-attributes-both.s new file mode 100644 index 0000000000000..abdc1a06ca28e --- /dev/null +++ b/lld/test/ELF/aarch64-build-attributes-both.s @@ -0,0 +1,51 @@ +// REQUIRES: aarch64 + +// Test mc -> little endian, lld -> little endian +// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o +// RUN: ld.lld %t.o -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// Test mc -> little endian, lld -> big endian +// RUN: ld.lld -EB %t.o -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// Test mc -> big endian, lld -> little endian +// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o +// RUN: ld.lld %t.o -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// Test mc -> big endian, lld -> big endian +// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o +// RUN: ld.lld -EB %t.o -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE + + +// NOTE: Displaying notes found in: .note.gnu.property +// NOTE-CHECK: Owner Data size Description +// NOTE-CHECK: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +// NOTE-CHECK: Properties: aarch64 feature: PAC +// NOTE-CHECK: AArch64 PAuth ABI core info: platform 0x12345678 (unknown), version 0x87654321 + + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 305419896 +.aeabi_attribute Tag_PAuth_Schema, 2271560481 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_PAC, 1 + +.section ".note.gnu.property", "a" +.long 4 +.long 0x10 +.long 0x5 +.asciz "GNU" +.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND +.long 4 +.long 2 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC +.long 0 + +.section ".note.gnu.property", "a" +.long 4 +.long 24 +.long 5 +.asciz "GNU" +.long 0xc0000001 +.long 16 +.quad 305419896 // platform +.quad 2271560481 // version diff --git a/lld/test/ELF/aarch64-build-attributes.s b/lld/test/ELF/aarch64-build-attributes.s index 5cf406eacd772..c1064e318ed65 100644 --- a/lld/test/ELF/aarch64-build-attributes.s +++ b/lld/test/ELF/aarch64-build-attributes.s @@ -33,8 +33,3 @@ .aeabi_attribute Tag_Feature_BTI, 1 .aeabi_attribute Tag_Feature_PAC, 1 .aeabi_attribute Tag_Feature_GCS, 1 - -.global _start -.type _start, %function -_start: -ret From deaf7de420b506e17a17b1d3749c4eaeb8ff88e1 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Tue, 8 Apr 2025 14:16:01 +0100 Subject: [PATCH 56/89] add test file when both GNU properties and BA present, but GP has no Pauth while BA do --- .../aarch64-build-attributes-both-noPauth.s | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 lld/test/ELF/aarch64-build-attributes-both-noPauth.s diff --git a/lld/test/ELF/aarch64-build-attributes-both-noPauth.s b/lld/test/ELF/aarch64-build-attributes-both-noPauth.s new file mode 100644 index 0000000000000..55e335945bd0e --- /dev/null +++ b/lld/test/ELF/aarch64-build-attributes-both-noPauth.s @@ -0,0 +1,41 @@ +// REQUIRES: aarch64 + +// Test mc -> little endian, lld -> little endian +// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o +// RUN: ld.lld %t.o -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// Test mc -> little endian, lld -> big endian +// RUN: ld.lld -EB %t.o -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// Test mc -> big endian, lld -> little endian +// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o +// RUN: ld.lld %t.o -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +// Test mc -> big endian, lld -> big endian +// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o +// RUN: ld.lld -EB %t.o -o %t.so +// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE + + +// NOTE: Displaying notes found in: .note.gnu.property +// NOTE-CHECK: Owner Data size Description +// NOTE-CHECK: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +// NOTE-CHECK: Properties: aarch64 feature: PAC +// NOTE-CHECK: AArch64 PAuth ABI core info: platform 0x12345678 (unknown), version 0x87654321 + + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 305419896 +.aeabi_attribute Tag_PAuth_Schema, 2271560481 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_PAC, 1 + +.section ".note.gnu.property", "a" +.long 4 +.long 0x10 +.long 0x5 +.asciz "GNU" +.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND +.long 4 +.long 2 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC +.long 0 From 88359f4b16142f66c8b531bae5ddb8f88f09ee7c Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Tue, 8 Apr 2025 18:42:31 +0100 Subject: [PATCH 57/89] add test file for melformed object file --- .../ELF/aarch64-build-attributes-melformed.s | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 lld/test/ELF/aarch64-build-attributes-melformed.s diff --git a/lld/test/ELF/aarch64-build-attributes-melformed.s b/lld/test/ELF/aarch64-build-attributes-melformed.s new file mode 100644 index 0000000000000..081ac276f920d --- /dev/null +++ b/lld/test/ELF/aarch64-build-attributes-melformed.s @@ -0,0 +1,23 @@ + +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o /dev/null 2>&1 | FileCheck %s + +# CHECK: (.ARM.attributes): invalid Extended Build Attributes subsection size at offset: 3B + + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_NONE + Type: ET_REL + Machine: EM_AARCH64 + Entry: 0x0 + +Sections: + - Name: .ARM.attributes + Type: 0x70000003 # SHT_LOPROC + 3 + AddressAlign: 1 + Offset: 0x40 + Size: 0x41 + Content: "411900000061656162695f7061757468616269000000010102012000000061656162695f666561747572655f616e645f6269747300010000010101020000" \ No newline at end of file From 64a45ed1e29ae1a6b3a00125e1f928df3a23e3bb Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 10 Apr 2025 13:47:02 +0100 Subject: [PATCH 58/89] change struct name --- lld/ELF/InputFiles.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 203e738484d88..e4d5f8ded0039 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -209,7 +209,7 @@ static void updateSupportedARMFeatures(Ctx &ctx, ctx.arg.armHasThumb2ISA |= thumb && *thumb >= ARMBuildAttrs::AllowThumb32; } -struct KnownAArch64BuildAttrSubsections { +struct AArch64BuildAttrSubsections { struct PauthSubSection { unsigned tagPlatform = 0; unsigned tagSchema = 0; @@ -221,10 +221,10 @@ struct KnownAArch64BuildAttrSubsections { } fAndB; }; -static KnownAArch64BuildAttrSubsections +static AArch64BuildAttrSubsections extractBuildAttributesSubsections(const AArch64AttributeParser &attributes) { - KnownAArch64BuildAttrSubsections subSections; + AArch64BuildAttrSubsections subSections; subSections.pauth.tagPlatform = attributes .getAttributeValue("aeabi_pauthabi", @@ -832,7 +832,7 @@ template void ObjFile::parse(bool ignoreComdats) { } else { bool writePauth = false; bool wrtieFeatures = false; - KnownAArch64BuildAttrSubsections subSections = + AArch64BuildAttrSubsections subSections = extractBuildAttributesSubsections(attributes); if (hasGnuProperties) { if (!gnuPropertiesInformation.aarch64PauthAbiCoreInfo.empty()) { From 8873a1591a83ec67b4c1a15a049e96a0d4491a08 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 11 Apr 2025 14:36:54 +0100 Subject: [PATCH 59/89] handle GNU properties and build attributes after loop --- lld/ELF/InputFiles.cpp | 243 ++++++++++++++++++++--------------------- 1 file changed, 117 insertions(+), 126 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index e4d5f8ded0039..1ffdd581fa136 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -682,6 +682,89 @@ static gnuPropertiesInfo readGnuProperty(Ctx &ctx, const InputSection &sec, return gnuPropertiesInfo{f.andFeatures, f.aarch64PauthAbiCoreInfo}; } +template +static void +handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, + bool hasBA, bool hasGP, + const AArch64BuildAttrSubsections &baInfo, + const gnuPropertiesInfo &gpInfo) { + if (hasBA && hasGP) { + if (!gpInfo.aarch64PauthAbiCoreInfo.empty()) { + // check for a mismatch + auto deserializeArray = [&](size_t offset, bool isBE) { + unsigned value = 0; + for (size_t i = 0; i < 8; ++i) { + if (isBE) + value = (value << 8) | gpInfo.aarch64PauthAbiCoreInfo[i + offset]; + else + value |= static_cast( + gpInfo.aarch64PauthAbiCoreInfo[i + offset]) + << (8 * i); + }; + return value; + }; + unsigned gnuPropPauthPlatform = deserializeArray(0, isBE); + if (baInfo.pauth.tagPlatform != gnuPropPauthPlatform) + ErrAlways(ctx) + << tPointer + << "Pauth Platform mismatch: file contains both GNU properties and " + "AArch64 build attributes sections\nGNU properties: " + << gnuPropPauthPlatform + << "\nAArch64 build attributes: " << baInfo.pauth.tagPlatform; + unsigned gnuPropPauthScheme = deserializeArray(8, isBE); + if (baInfo.pauth.tagSchema != gnuPropPauthScheme) + ErrAlways(ctx) + << tPointer + << "Pauth Schema mismatch: file contains both GNU properties and " + "AArch64 build attributes sections\nGNU properties: " + << gnuPropPauthScheme + << "\nAArch64 build attributes: " << baInfo.pauth.tagSchema; + } + if (baInfo.fAndB.tagBTI != (gpInfo.andFeatures & 0x01)) + ErrAlways(ctx) + << tPointer + << "Features BTI mismatch: file contains both GNU properties and " + "AArch64 build attributes sections\nGNU properties: " + << (gpInfo.andFeatures & 0x01) + << "\nAArch64 build attributes: " << baInfo.fAndB.tagBTI; + if (baInfo.fAndB.tagPAC != ((gpInfo.andFeatures >> 1) & 0x01)) + ErrAlways(ctx) + << tPointer + << "Feature PAC mismatch: file contains both GNU properties and " + "AArch64 build attributes sections\nGNU properties: " + << ((gpInfo.andFeatures >> 1) & 0x01) + << "\nAArch64 build attributes: " << baInfo.fAndB.tagPAC; + if (baInfo.fAndB.tagGCS != ((gpInfo.andFeatures >> 2) & 0x01)) + ErrAlways(ctx) + << tPointer + << "Feature GCS mismatch: file contains both GNU properties and " + "AArch64 build attributes sections\nGNU properties: " + << ((gpInfo.andFeatures >> 2) & 0x01) + << "\nAArch64 build attributes: " << baInfo.fAndB.tagGCS; + } + + if (hasBA && !hasGP) { + if (baInfo.pauth.tagPlatform || baInfo.pauth.tagSchema) { + auto serializeUnsigned = [&](unsigned value, size_t offset, bool isBE) { + for (size_t i = 0; i < 8; ++i) { + tPointer->aarch64PauthAbiCoreInfoStorage[i + offset] = + static_cast( + (static_cast(value) >> (8 * (isBE ? (7 - i) : i))) & + 0xFF); + }; + }; + serializeUnsigned(baInfo.pauth.tagPlatform, 0, isBE); + serializeUnsigned(baInfo.pauth.tagSchema, 8, isBE); + tPointer->aarch64PauthAbiCoreInfo = + tPointer->aarch64PauthAbiCoreInfoStorage; + } + tPointer->andFeatures = 0; + tPointer->andFeatures |= (baInfo.fAndB.tagBTI) << 0; + tPointer->andFeatures |= (baInfo.fAndB.tagPAC) << 1; + tPointer->andFeatures |= (baInfo.fAndB.tagGCS) << 2; + } +} + template void ObjFile::parse(bool ignoreComdats) { object::ELFFile obj = this->getObj(); // Read a section table. justSymbols is usually false. @@ -690,7 +773,6 @@ template void ObjFile::parse(bool ignoreComdats) { initializeSymbols(obj); return; } - // Handle dependent libraries and selection of section groups as these are not // done in parallel. ArrayRef objSections = getELFShdrs(); @@ -698,13 +780,20 @@ template void ObjFile::parse(bool ignoreComdats) { uint64_t size = objSections.size(); sections.resize(size); - // Check whether GNU properties section present and store it's data. - // This is done in order to compare the content of GNU properties section with - // aarch64 build attributes section. - bool hasGnuProperties = false; + // For handling AArch64 Build attributes and GNU properties + AArch64BuildAttrSubsections aarch64BAsubSections; gnuPropertiesInfo gnuPropertiesInformation; + bool hasAArch64BuildAttributes = false; + bool hasGNUProperties = false; + for (size_t i = 0; i != size; ++i) { const Elf_Shdr &sec = objSections[i]; + + // Collect GNU properties data. + // GNU properties might be processed in this loop, or only later on (e.g. in + // initializeSections) Therefore there is no guarantee that the GNU + // properties data will be read after this loop end, so it is being + // collected here. if (check(obj.getSectionName(sec, shstrtab)) == ".note.gnu.property") { if (0 == this->andFeatures && this->aarch64PauthAbiCoreInfo.empty()) { gnuPropertiesInformation = readGnuProperty( @@ -719,13 +808,9 @@ template void ObjFile::parse(bool ignoreComdats) { gnuPropertiesInformation.aarch64PauthAbiCoreInfo = this->aarch64PauthAbiCoreInfo; } - hasGnuProperties = true; - break; + hasGNUProperties = true; } - } - for (size_t i = 0; i != size; ++i) { - const Elf_Shdr &sec = objSections[i]; if (LLVM_LIKELY(sec.sh_type == SHT_PROGBITS)) continue; if (LLVM_LIKELY(sec.sh_type == SHT_GROUP)) { @@ -809,130 +894,27 @@ template void ObjFile::parse(bool ignoreComdats) { } break; case EM_AARCH64: { - // The specification states that if a file contains both GNU properties - // and AArch64 build attributes, they can be assumed to be identical. - // Therefore, if a file contains GNU properties, the AArch64 build - // attributes are ignored. If a file does not contain GNU properties, we - // leverage the existing GNU properties mechanism by populating the - // corresponding data structures, which will later be handled by - // Driver.cpp::readSecurityNotes. This ensures that AArch64 build - // attributes are represented in the linked object file as GNU properties, - // which are already supported by the Linux kernel and the dynamic - // loader. + // At this stage AArch64 Build Attributes does not replace GNU Properties. + // When both exists, their values must match. + // When both exists and contain different attributes, they complement each + // other. Curently attributes are represented in the linked object file as + // GNU properties, which are already supported by the Linux kernel and the + // dynamic loader. In the future, when relocatable linking (`-r` flag) is + // performed, a single merged AArch64 Build Attributes section will be + // emitted. + if (sec.sh_type == SHT_AARCH64_ATTRIBUTES) { - StringRef name = check(obj.getSectionName(sec, shstrtab)); ArrayRef contents = check(obj.getSectionContents(sec)); AArch64AttributeParser attributes; - // For functions that has to warn/err/report. + StringRef name = check(obj.getSectionName(sec, shstrtab)); InputSection isec(*this, sec, name); if (Error e = attributes.parse(contents, ELFT::Endianness)) { Warn(ctx) << &isec << ": " << std::move(e); // uint32_t andFeatures = 0; // std::array aarch64PauthAbiCoreInfoStorage; } else { - bool writePauth = false; - bool wrtieFeatures = false; - AArch64BuildAttrSubsections subSections = - extractBuildAttributesSubsections(attributes); - if (hasGnuProperties) { - if (!gnuPropertiesInformation.aarch64PauthAbiCoreInfo.empty()) { - // check for mismatch error - auto deserializeArray = [&](size_t offset, bool isBE) { - unsigned value = 0; - for (size_t i = 0; i < 8; ++i) { - value = isBE ? (value << 8) | - gnuPropertiesInformation - .aarch64PauthAbiCoreInfo[i + offset] - : value |= - static_cast( - gnuPropertiesInformation - .aarch64PauthAbiCoreInfo[i + offset]) - << (8 * i); - }; - return value; - }; - unsigned gnuPropPauthPlatform = deserializeArray( - 0, ELFT::Endianness == llvm::endianness::big); - if (subSections.pauth.tagPlatform != gnuPropPauthPlatform) - ErrAlways(ctx) - << &isec - << "Pauth Platform mismatch: file contains both GNU " - "properties and AArch64 build attributes sections\nGNU " - "properties: " - << gnuPropPauthPlatform << "\nAArch64 build attributes: " - << subSections.pauth.tagPlatform; - unsigned gnuPropPauthScheme = deserializeArray( - 8, ELFT::Endianness == llvm::endianness::big); - if (subSections.pauth.tagSchema != gnuPropPauthScheme) - ErrAlways(ctx) - << &isec - << "Pauth Schema mismatch: file contains both GNU " - "properties and AArch64 build attributes sections\nGNU " - "properties: " - << gnuPropPauthScheme << "\nAArch64 build attributes: " - << subSections.pauth.tagSchema; - } else { - writePauth = true; - } - if (subSections.fAndB.tagBTI != - (gnuPropertiesInformation.andFeatures & 0x01)) - ErrAlways(ctx) - << &isec - << "Features BTI mismatch: file contains both GNU " - "properties and AArch64 build attributes sections\nGNU " - "properties: " - << (gnuPropertiesInformation.andFeatures & 0x01) - << "\nAArch64 build attributes: " << subSections.fAndB.tagBTI; - if (subSections.fAndB.tagPAC != - ((gnuPropertiesInformation.andFeatures >> 1) & 0x01)) - ErrAlways(ctx) - << &isec - << "Feature PAC mismatch: file contains both GNU " - "properties and AArch64 build attributes sections\nGNU " - "properties: " - << ((gnuPropertiesInformation.andFeatures >> 1) & 0x01) - << "\nAArch64 build attributes: " << subSections.fAndB.tagBTI; - if (subSections.fAndB.tagGCS != - ((gnuPropertiesInformation.andFeatures >> 2) & 0x01)) - ErrAlways(ctx) - << &isec - << "Feature GCS mismatch: file contains both GNU " - "properties and AArch64 build attributes sections\nGNU " - "properties: " - << ((gnuPropertiesInformation.andFeatures >> 2) & 0x01) - << "\nAArch64 build attributes: " << subSections.fAndB.tagBTI; - } else { - // no GNU properties - writePauth = true; - wrtieFeatures = true; - } - if (writePauth) { - // this condition is important in order not to emit section when - // data does not exists, same as GNU properties. - if (subSections.pauth.tagPlatform || subSections.pauth.tagSchema) { - auto serializeUnsigned = [&](unsigned value, size_t offset, - bool isBE) { - for (size_t i = 0; i < 8; ++i) { - this->aarch64PauthAbiCoreInfoStorage[i + offset] = - static_cast((static_cast(value) >> - (8 * (isBE ? (7 - i) : i))) & - 0xFF); - }; - }; - serializeUnsigned(subSections.pauth.tagPlatform, 0, - ELFT::Endianness == llvm::endianness::big); - serializeUnsigned(subSections.pauth.tagSchema, 8, - ELFT::Endianness == llvm::endianness::big); - this->aarch64PauthAbiCoreInfo = - this->aarch64PauthAbiCoreInfoStorage; - } - } - if (wrtieFeatures) { - this->andFeatures = 0; - this->andFeatures |= (subSections.fAndB.tagBTI) << 0; - this->andFeatures |= (subSections.fAndB.tagPAC) << 1; - this->andFeatures |= (subSections.fAndB.tagGCS) << 2; - } + aarch64BAsubSections = extractBuildAttributesSubsections(attributes); + hasAArch64BuildAttributes = true; } sections[i] = &InputSection::discarded; } @@ -946,6 +928,15 @@ template void ObjFile::parse(bool ignoreComdats) { } break; } } + + bool isBE = ELFT::Endianness == llvm::endianness::big; + // Handle AArch64 Build Attributes and GNU properties: + // - Err on mismatched values. + // - Store missing values as GNU properties. + handleAArch64BAAndGnuProperties(this, ctx, isBE, hasAArch64BuildAttributes, + hasGNUProperties, aarch64BAsubSections, + gnuPropertiesInformation); + // Read a symbol table. initializeSymbols(obj); } @@ -1947,7 +1938,7 @@ BitcodeFile::BitcodeFile(Ctx &ctx, MemoryBufferRef mb, StringRef archiveName, // ThinLTO assumes that all MemoryBufferRefs given to it have a unique // name. If two archives define two members with the same name, this - // causes a collision which result in only one of the objects being taken + // causes a mismatch which result in only one of the objects being taken // into consideration at LTO time (which very likely causes undefined // symbols later in the link stage). So we append file offset to make // filename unique. From 9e70cbefd8e1a442a919f599908468a77bf950ea Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 11 Apr 2025 14:37:26 +0100 Subject: [PATCH 60/89] delete commented lines --- lld/ELF/InputFiles.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 1ffdd581fa136..9cf667c45c8a0 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -910,8 +910,6 @@ template void ObjFile::parse(bool ignoreComdats) { InputSection isec(*this, sec, name); if (Error e = attributes.parse(contents, ELFT::Endianness)) { Warn(ctx) << &isec << ": " << std::move(e); - // uint32_t andFeatures = 0; - // std::array aarch64PauthAbiCoreInfoStorage; } else { aarch64BAsubSections = extractBuildAttributesSubsections(attributes); hasAArch64BuildAttributes = true; From bbb33fe2aad40f2aff89d3d4ca26eb66cf6fe498 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 11 Apr 2025 15:58:20 +0100 Subject: [PATCH 61/89] only serialize, reduce message size --- lld/ELF/InputFiles.cpp | 87 +++++++------------ .../ELF/aarch64-build-attributes-both-err.s | 14 +-- 2 files changed, 31 insertions(+), 70 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 9cf667c45c8a0..f8b6d5632093c 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -688,73 +688,44 @@ handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, bool hasBA, bool hasGP, const AArch64BuildAttrSubsections &baInfo, const gnuPropertiesInfo &gpInfo) { + + auto serializeUnsigned = [&](unsigned valueLow, unsigned valueHigh, + bool isBE) -> std::array { + std::array arr; + for (size_t i = 0; i < 8; ++i) { + arr[i] = static_cast( + (static_cast(valueLow) >> (8 * (isBE ? (7 - i) : i))) & + 0xFF); + arr[i + 8] = static_cast( + (static_cast(valueHigh) >> (8 * (isBE ? (7 - i) : i))) & + 0xFF); + }; + return arr; + }; + if (hasBA && hasGP) { if (!gpInfo.aarch64PauthAbiCoreInfo.empty()) { - // check for a mismatch - auto deserializeArray = [&](size_t offset, bool isBE) { - unsigned value = 0; - for (size_t i = 0; i < 8; ++i) { - if (isBE) - value = (value << 8) | gpInfo.aarch64PauthAbiCoreInfo[i + offset]; - else - value |= static_cast( - gpInfo.aarch64PauthAbiCoreInfo[i + offset]) - << (8 * i); - }; - return value; - }; - unsigned gnuPropPauthPlatform = deserializeArray(0, isBE); - if (baInfo.pauth.tagPlatform != gnuPropPauthPlatform) - ErrAlways(ctx) - << tPointer - << "Pauth Platform mismatch: file contains both GNU properties and " - "AArch64 build attributes sections\nGNU properties: " - << gnuPropPauthPlatform - << "\nAArch64 build attributes: " << baInfo.pauth.tagPlatform; - unsigned gnuPropPauthScheme = deserializeArray(8, isBE); - if (baInfo.pauth.tagSchema != gnuPropPauthScheme) + auto baPauth = serializeUnsigned(baInfo.pauth.tagPlatform, + baInfo.pauth.tagSchema, isBE); + if (gpInfo.aarch64PauthAbiCoreInfo != ArrayRef(baPauth)) ErrAlways(ctx) << tPointer - << "Pauth Schema mismatch: file contains both GNU properties and " - "AArch64 build attributes sections\nGNU properties: " - << gnuPropPauthScheme - << "\nAArch64 build attributes: " << baInfo.pauth.tagSchema; + << " Pauth Data mismatch: file contains both GNU properties and " + "AArch64 build attributes sections with different Pauth data"; } - if (baInfo.fAndB.tagBTI != (gpInfo.andFeatures & 0x01)) - ErrAlways(ctx) - << tPointer - << "Features BTI mismatch: file contains both GNU properties and " - "AArch64 build attributes sections\nGNU properties: " - << (gpInfo.andFeatures & 0x01) - << "\nAArch64 build attributes: " << baInfo.fAndB.tagBTI; - if (baInfo.fAndB.tagPAC != ((gpInfo.andFeatures >> 1) & 0x01)) - ErrAlways(ctx) - << tPointer - << "Feature PAC mismatch: file contains both GNU properties and " - "AArch64 build attributes sections\nGNU properties: " - << ((gpInfo.andFeatures >> 1) & 0x01) - << "\nAArch64 build attributes: " << baInfo.fAndB.tagPAC; - if (baInfo.fAndB.tagGCS != ((gpInfo.andFeatures >> 2) & 0x01)) - ErrAlways(ctx) - << tPointer - << "Feature GCS mismatch: file contains both GNU properties and " - "AArch64 build attributes sections\nGNU properties: " - << ((gpInfo.andFeatures >> 2) & 0x01) - << "\nAArch64 build attributes: " << baInfo.fAndB.tagGCS; + if (baInfo.fAndB.tagBTI != (gpInfo.andFeatures & 0x01) || + baInfo.fAndB.tagPAC != ((gpInfo.andFeatures >> 1) & 0x01) || + baInfo.fAndB.tagGCS != ((gpInfo.andFeatures >> 2) & 0x01)) + ErrAlways(ctx) << tPointer + << " Features Data mismatch: file contains both GNU " + "properties and AArch64 build attributes sections with " + "different And Features data"; } if (hasBA && !hasGP) { if (baInfo.pauth.tagPlatform || baInfo.pauth.tagSchema) { - auto serializeUnsigned = [&](unsigned value, size_t offset, bool isBE) { - for (size_t i = 0; i < 8; ++i) { - tPointer->aarch64PauthAbiCoreInfoStorage[i + offset] = - static_cast( - (static_cast(value) >> (8 * (isBE ? (7 - i) : i))) & - 0xFF); - }; - }; - serializeUnsigned(baInfo.pauth.tagPlatform, 0, isBE); - serializeUnsigned(baInfo.pauth.tagSchema, 8, isBE); + tPointer->aarch64PauthAbiCoreInfoStorage = serializeUnsigned( + baInfo.pauth.tagPlatform, baInfo.pauth.tagSchema, isBE); tPointer->aarch64PauthAbiCoreInfo = tPointer->aarch64PauthAbiCoreInfoStorage; } diff --git a/lld/test/ELF/aarch64-build-attributes-both-err.s b/lld/test/ELF/aarch64-build-attributes-both-err.s index 20f99166916dd..43671f58a5be1 100644 --- a/lld/test/ELF/aarch64-build-attributes-both-err.s +++ b/lld/test/ELF/aarch64-build-attributes-both-err.s @@ -13,18 +13,8 @@ // RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o // RUN: not ld.lld -EB %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR -// ERR: Pauth Platform mismatch: file contains both GNU properties and AArch64 build attributes sections -// ERR-NEXT: GNU properties: 305419896 -// ERR-NEXT: AArch64 build attributes: 5 -// ERR: Pauth Schema mismatch: file contains both GNU properties and AArch64 build attributes sections -// ERR-NEXT: GNU properties: 2271560481 -// ERR-NEXT: AArch64 build attributes: 5 -// ERR: Features BTI mismatch: file contains both GNU properties and AArch64 build attributes sections -// ERR-NEXT: GNU properties: 0 -// ERR-NEXT: AArch64 build attributes: 1 -// ERR: Feature GCS mismatch: file contains both GNU properties and AArch64 build attributes sections -// ERR-NEXT: GNU properties: 0 -// ERR-NEXT: AArch64 build attributes: 1 +// ERR: Pauth Data mismatch: file contains both GNU properties and AArch64 build attributes sections with different Pauth data +// ERR-NEXT: Features Data mismatch: file contains both GNU properties and AArch64 build attributes sections with different And Features data .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 5 From 711ea6f764c7d319988a7f731bde593d701cae37 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 11 Apr 2025 16:03:55 +0100 Subject: [PATCH 62/89] comments --- lld/ELF/InputFiles.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index f8b6d5632093c..d14924bd5e8a3 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -704,6 +704,7 @@ handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, }; if (hasBA && hasGP) { + // Check for data mismatch if (!gpInfo.aarch64PauthAbiCoreInfo.empty()) { auto baPauth = serializeUnsigned(baInfo.pauth.tagPlatform, baInfo.pauth.tagSchema, isBE); @@ -723,6 +724,9 @@ handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, } if (hasBA && !hasGP) { + // Write missing data + // We can only know when Pauth is missing. + // Unlike AArch64 Build Attributes, GNU properties does not give a way to distinguish between no-value given to value of '0' given. if (baInfo.pauth.tagPlatform || baInfo.pauth.tagSchema) { tPointer->aarch64PauthAbiCoreInfoStorage = serializeUnsigned( baInfo.pauth.tagPlatform, baInfo.pauth.tagSchema, isBE); @@ -763,7 +767,7 @@ template void ObjFile::parse(bool ignoreComdats) { // Collect GNU properties data. // GNU properties might be processed in this loop, or only later on (e.g. in // initializeSections) Therefore there is no guarantee that the GNU - // properties data will be read after this loop end, so it is being + // properties data will be ready after this loop end, so it has to be // collected here. if (check(obj.getSectionName(sec, shstrtab)) == ".note.gnu.property") { if (0 == this->andFeatures && this->aarch64PauthAbiCoreInfo.empty()) { @@ -873,7 +877,6 @@ template void ObjFile::parse(bool ignoreComdats) { // dynamic loader. In the future, when relocatable linking (`-r` flag) is // performed, a single merged AArch64 Build Attributes section will be // emitted. - if (sec.sh_type == SHT_AARCH64_ATTRIBUTES) { ArrayRef contents = check(obj.getSectionContents(sec)); AArch64AttributeParser attributes; From b46b466ac94fded722d703b1fc7c60af077f8940 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 11 Apr 2025 16:11:06 +0100 Subject: [PATCH 63/89] revert unintended change in comment --- lld/ELF/InputFiles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index d14924bd5e8a3..a2465b6f46711 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1910,7 +1910,7 @@ BitcodeFile::BitcodeFile(Ctx &ctx, MemoryBufferRef mb, StringRef archiveName, // ThinLTO assumes that all MemoryBufferRefs given to it have a unique // name. If two archives define two members with the same name, this - // causes a mismatch which result in only one of the objects being taken + // causes a collision which result in only one of the objects being taken // into consideration at LTO time (which very likely causes undefined // symbols later in the link stage). So we append file offset to make // filename unique. From 24f4b80f8f467409ea3d07b645f260f15ee6b237 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Fri, 11 Apr 2025 16:12:52 +0100 Subject: [PATCH 64/89] format --- lld/ELF/InputFiles.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index a2465b6f46711..5a90129515184 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -726,7 +726,8 @@ handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, if (hasBA && !hasGP) { // Write missing data // We can only know when Pauth is missing. - // Unlike AArch64 Build Attributes, GNU properties does not give a way to distinguish between no-value given to value of '0' given. + // Unlike AArch64 Build Attributes, GNU properties does not give a way to + // distinguish between no-value given to value of '0' given. if (baInfo.pauth.tagPlatform || baInfo.pauth.tagSchema) { tPointer->aarch64PauthAbiCoreInfoStorage = serializeUnsigned( baInfo.pauth.tagPlatform, baInfo.pauth.tagSchema, isBE); From 8e277851ee22a9ee1d456dfcd97e82e9148b11d5 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 09:21:23 +0100 Subject: [PATCH 65/89] unsigned -> uint64_t --- lld/ELF/InputFiles.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 5a90129515184..6060797eab7b9 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -211,8 +211,8 @@ static void updateSupportedARMFeatures(Ctx &ctx, struct AArch64BuildAttrSubsections { struct PauthSubSection { - unsigned tagPlatform = 0; - unsigned tagSchema = 0; + uint64_t tagPlatform = 0; + uint64_t tagSchema = 0; } pauth; struct FAndBSubSection { unsigned tagBTI = 0; From da33de6d071150ae682b967470b27ad2d0658bd6 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 09:19:27 +0100 Subject: [PATCH 66/89] change to uint32_t andFeatures = 0; --- lld/ELF/InputFiles.cpp | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 6060797eab7b9..cc6e6c78d45bf 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -214,11 +214,7 @@ struct AArch64BuildAttrSubsections { uint64_t tagPlatform = 0; uint64_t tagSchema = 0; } pauth; - struct FAndBSubSection { - unsigned tagBTI = 0; - unsigned tagPAC = 0; - unsigned tagGCS = 0; - } fAndB; + uint32_t andFeatures = 0; }; static AArch64BuildAttrSubsections @@ -235,21 +231,23 @@ extractBuildAttributesSubsections(const AArch64AttributeParser &attributes) { .getAttributeValue("aeabi_pauthabi", llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA) .value_or(0); - subSections.fAndB.tagBTI = + subSections.andFeatures |= attributes .getAttributeValue("aeabi_feature_and_bits", llvm::AArch64BuildAttributes::TAG_FEATURE_BTI) .value_or(0); - subSections.fAndB.tagPAC = - attributes - .getAttributeValue("aeabi_feature_and_bits", - llvm::AArch64BuildAttributes::TAG_FEATURE_PAC) - .value_or(0); - subSections.fAndB.tagGCS = - attributes - .getAttributeValue("aeabi_feature_and_bits", - llvm::AArch64BuildAttributes::TAG_FEATURE_GCS) - .value_or(0); + subSections.andFeatures |= + (attributes + .getAttributeValue("aeabi_feature_and_bits", + llvm::AArch64BuildAttributes::TAG_FEATURE_PAC) + .value_or(0)) + << 1; + subSections.andFeatures |= + (attributes + .getAttributeValue("aeabi_feature_and_bits", + llvm::AArch64BuildAttributes::TAG_FEATURE_GCS) + .value_or(0)) + << 2; return subSections; } @@ -714,9 +712,7 @@ handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, << " Pauth Data mismatch: file contains both GNU properties and " "AArch64 build attributes sections with different Pauth data"; } - if (baInfo.fAndB.tagBTI != (gpInfo.andFeatures & 0x01) || - baInfo.fAndB.tagPAC != ((gpInfo.andFeatures >> 1) & 0x01) || - baInfo.fAndB.tagGCS != ((gpInfo.andFeatures >> 2) & 0x01)) + if (baInfo.andFeatures != gpInfo.andFeatures) ErrAlways(ctx) << tPointer << " Features Data mismatch: file contains both GNU " "properties and AArch64 build attributes sections with " @@ -734,10 +730,7 @@ handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, tPointer->aarch64PauthAbiCoreInfo = tPointer->aarch64PauthAbiCoreInfoStorage; } - tPointer->andFeatures = 0; - tPointer->andFeatures |= (baInfo.fAndB.tagBTI) << 0; - tPointer->andFeatures |= (baInfo.fAndB.tagPAC) << 1; - tPointer->andFeatures |= (baInfo.fAndB.tagGCS) << 2; + tPointer->andFeatures = baInfo.andFeatures; } } From 5cb1940a80ee3c856ae3a662873792b1e30b0d49 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 09:43:02 +0100 Subject: [PATCH 67/89] use lambda for getting attributes values --- lld/ELF/InputFiles.cpp | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index cc6e6c78d45bf..710160bd7d3c3 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -221,33 +221,24 @@ static AArch64BuildAttrSubsections extractBuildAttributesSubsections(const AArch64AttributeParser &attributes) { AArch64BuildAttrSubsections subSections; + auto getPauthValue = [&](unsigned tag) -> unsigned { + return attributes.getAttributeValue("aeabi_pauthabi", tag).value_or(0); + }; subSections.pauth.tagPlatform = - attributes - .getAttributeValue("aeabi_pauthabi", - llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM) - .value_or(0); + getPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM); subSections.pauth.tagSchema = - attributes - .getAttributeValue("aeabi_pauthabi", - llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA) - .value_or(0); + getPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA); + + auto getFeatureValue = [&](unsigned tag) -> unsigned { + return attributes.getAttributeValue("aeabi_feature_and_bits", tag) + .value_or(0); + }; subSections.andFeatures |= - attributes - .getAttributeValue("aeabi_feature_and_bits", - llvm::AArch64BuildAttributes::TAG_FEATURE_BTI) - .value_or(0); + getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_BTI); subSections.andFeatures |= - (attributes - .getAttributeValue("aeabi_feature_and_bits", - llvm::AArch64BuildAttributes::TAG_FEATURE_PAC) - .value_or(0)) - << 1; + getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_PAC) << 1; subSections.andFeatures |= - (attributes - .getAttributeValue("aeabi_feature_and_bits", - llvm::AArch64BuildAttributes::TAG_FEATURE_GCS) - .value_or(0)) - << 2; + getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_GCS) << 2; return subSections; } From 572e5f45b007a802c58908256615b7d500d4cc2b Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 10:34:22 +0100 Subject: [PATCH 68/89] move reading .note.gnu.property to the parse loop --- lld/ELF/InputFiles.cpp | 43 ++++++++++++------------------------------ 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 710160bd7d3c3..6387147be3101 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -749,26 +749,20 @@ template void ObjFile::parse(bool ignoreComdats) { for (size_t i = 0; i != size; ++i) { const Elf_Shdr &sec = objSections[i]; - // Collect GNU properties data. - // GNU properties might be processed in this loop, or only later on (e.g. in - // initializeSections) Therefore there is no guarantee that the GNU - // properties data will be ready after this loop end, so it has to be - // collected here. + // Object files that use processor features such as Intel Control-Flow + // Enforcement (CET) or AArch64 Branch Target Identification BTI, use a + // .note.gnu.property section containing a bitfield of feature bits like the + // GNU_PROPERTY_X86_FEATURE_1_IBT flag. Read a bitmap containing the flag. if (check(obj.getSectionName(sec, shstrtab)) == ".note.gnu.property") { - if (0 == this->andFeatures && this->aarch64PauthAbiCoreInfo.empty()) { - gnuPropertiesInformation = readGnuProperty( - ctx, - InputSection(*this, sec, check(obj.getSectionName(sec, shstrtab))), - *this); - // Restore state - this->andFeatures = 0; - this->aarch64PauthAbiCoreInfo = {}; - } else { - gnuPropertiesInformation.andFeatures = this->andFeatures; - gnuPropertiesInformation.aarch64PauthAbiCoreInfo = - this->aarch64PauthAbiCoreInfo; - } + gnuPropertiesInformation = readGnuProperty( + ctx, + InputSection(*this, sec, check(obj.getSectionName(sec, shstrtab))), + *this); hasGNUProperties = true; + // Since we merge bitmaps from multiple object files to create a new + // .note.gnu.property containing a single AND'ed bitmap, we discard an + // input file's .note.gnu.property section. + sections[i] = &InputSection::discarded; } if (LLVM_LIKELY(sec.sh_type == SHT_PROGBITS)) @@ -1207,19 +1201,6 @@ InputSectionBase *ObjFile::createInputSection(uint32_t idx, return &InputSection::discarded; } - // Object files that use processor features such as Intel Control-Flow - // Enforcement (CET) or AArch64 Branch Target Identification BTI, use a - // .note.gnu.property section containing a bitfield of feature bits like the - // GNU_PROPERTY_X86_FEATURE_1_IBT flag. Read a bitmap containing the flag. - // - // Since we merge bitmaps from multiple object files to create a new - // .note.gnu.property containing a single AND'ed bitmap, we discard an input - // file's .note.gnu.property section. - if (name == ".note.gnu.property") { - readGnuProperty(ctx, 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 From 31214b8a4e2b5ca9afc37e3187972f2caff05e3c Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 11:04:11 +0100 Subject: [PATCH 69/89] use split-file for testing --- .../ELF/Inputs/aarch64-func3-pac-replace.s | 2 +- .../ELF/Inputs/build-attributes-merged-2.s | 8 --- .../ELF/Inputs/build-attributes-merged-3.s | 8 --- .../Inputs/build-attributes-merged-mixed-2.s | 19 ------- .../Inputs/build-attributes-merged-mixed-3.s | 10 ---- .../ELF/aarch64-build-attributes-merged-1.s | 20 ------- .../aarch64-build-attributes-merged-mixed-1.s | 20 ------- .../aarch64-build-attributes-merged-mixed.s | 53 +++++++++++++++++++ .../ELF/aarch64-build-attributes-merged.s | 42 +++++++++++++++ 9 files changed, 96 insertions(+), 86 deletions(-) delete mode 100644 lld/test/ELF/Inputs/build-attributes-merged-2.s delete mode 100644 lld/test/ELF/Inputs/build-attributes-merged-3.s delete mode 100644 lld/test/ELF/Inputs/build-attributes-merged-mixed-2.s delete mode 100644 lld/test/ELF/Inputs/build-attributes-merged-mixed-3.s delete mode 100644 lld/test/ELF/aarch64-build-attributes-merged-1.s delete mode 100644 lld/test/ELF/aarch64-build-attributes-merged-mixed-1.s create mode 100644 lld/test/ELF/aarch64-build-attributes-merged-mixed.s create mode 100644 lld/test/ELF/aarch64-build-attributes-merged.s diff --git a/lld/test/ELF/Inputs/aarch64-func3-pac-replace.s b/lld/test/ELF/Inputs/aarch64-func3-pac-replace.s index a837a0fe09d92..b6133844d07f7 100644 --- a/lld/test/ELF/Inputs/aarch64-func3-pac-replace.s +++ b/lld/test/ELF/Inputs/aarch64-func3-pac-replace.s @@ -1,4 +1,4 @@ -// This file replace gnu properties with aarch64 build attributes. +// Declare file properties exclusively with aarch64 build attributes. .aeabi_subsection aeabi_feature_and_bits, optional, uleb128 .aeabi_attribute Tag_Feature_PAC, 1 diff --git a/lld/test/ELF/Inputs/build-attributes-merged-2.s b/lld/test/ELF/Inputs/build-attributes-merged-2.s deleted file mode 100644 index 8210b5fba596d..0000000000000 --- a/lld/test/ELF/Inputs/build-attributes-merged-2.s +++ /dev/null @@ -1,8 +0,0 @@ - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 49 -.aeabi_attribute Tag_PAuth_Schema, 19 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 0 -.aeabi_attribute Tag_Feature_GCS, 1 diff --git a/lld/test/ELF/Inputs/build-attributes-merged-3.s b/lld/test/ELF/Inputs/build-attributes-merged-3.s deleted file mode 100644 index 4f09184aa7a08..0000000000000 --- a/lld/test/ELF/Inputs/build-attributes-merged-3.s +++ /dev/null @@ -1,8 +0,0 @@ - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 49 -.aeabi_attribute Tag_PAuth_Schema, 19 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 1 -.aeabi_attribute Tag_Feature_GCS, 0 diff --git a/lld/test/ELF/Inputs/build-attributes-merged-mixed-2.s b/lld/test/ELF/Inputs/build-attributes-merged-mixed-2.s deleted file mode 100644 index da1e5dbc0b450..0000000000000 --- a/lld/test/ELF/Inputs/build-attributes-merged-mixed-2.s +++ /dev/null @@ -1,19 +0,0 @@ - -.section ".note.gnu.property", "a" - .long 4 // Name length is always 4 ("GNU") - .long end - begin // Data length - .long 5 // Type: NT_GNU_PROPERTY_TYPE_0 - .asciz "GNU" // Name - .p2align 3 -begin: - .long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND - .long 4 - .long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI and PAC - .long 0 - # PAuth ABI property note - .long 0xc0000001 // Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH - .long 16 // Data size - .quad 49 // PAuth ABI platform - .quad 19 // PAuth ABI version - .p2align 3 // Align to 8 byte for 64 bit -end: diff --git a/lld/test/ELF/Inputs/build-attributes-merged-mixed-3.s b/lld/test/ELF/Inputs/build-attributes-merged-mixed-3.s deleted file mode 100644 index 22fd19c2c953c..0000000000000 --- a/lld/test/ELF/Inputs/build-attributes-merged-mixed-3.s +++ /dev/null @@ -1,10 +0,0 @@ - -.section ".note.gnu.property", "a" -.long 4 -.long 0x10 -.long 0x5 -.asciz "GNU" -.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND -.long 4 -.long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI and PAC -.long 0 diff --git a/lld/test/ELF/aarch64-build-attributes-merged-1.s b/lld/test/ELF/aarch64-build-attributes-merged-1.s deleted file mode 100644 index 1e926a579c0ec..0000000000000 --- a/lld/test/ELF/aarch64-build-attributes-merged-1.s +++ /dev/null @@ -1,20 +0,0 @@ -# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-merged-2.s -o %t2.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-merged-3.s -o %t3.o -# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o -# RUN: llvm-readelf -n %t.merged.o | FileCheck %s - -# CHECK: Displaying notes found in: .note.gnu.property -# CHECK-NEXT: Owner Data size Description -# CHECK-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) -# CHECK-NEXT: Properties: aarch64 feature: BTI -# CHECK-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 - - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 49 -.aeabi_attribute Tag_PAuth_Schema, 19 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 1 -.aeabi_attribute Tag_Feature_GCS, 1 diff --git a/lld/test/ELF/aarch64-build-attributes-merged-mixed-1.s b/lld/test/ELF/aarch64-build-attributes-merged-mixed-1.s deleted file mode 100644 index 78e5e2dd99d55..0000000000000 --- a/lld/test/ELF/aarch64-build-attributes-merged-mixed-1.s +++ /dev/null @@ -1,20 +0,0 @@ -# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-merged-mixed-2.s -o %t2.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj %p/Inputs/build-attributes-merged-mixed-3.s -o %t3.o -# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o -# RUN: llvm-readelf -n %t.merged.o | FileCheck %s - -# CHECK: Displaying notes found in: .note.gnu.property -# CHECK-NEXT: Owner Data size Description -# CHECK-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) -# CHECK-NEXT: Properties: aarch64 feature: BTI, PAC -# CHECK-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 - - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 49 -.aeabi_attribute Tag_PAuth_Schema, 19 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 1 -.aeabi_attribute Tag_Feature_GCS, 1 diff --git a/lld/test/ELF/aarch64-build-attributes-merged-mixed.s b/lld/test/ELF/aarch64-build-attributes-merged-mixed.s new file mode 100644 index 0000000000000..55185f9413cfd --- /dev/null +++ b/lld/test/ELF/aarch64-build-attributes-merged-mixed.s @@ -0,0 +1,53 @@ +# RUN: rm -rf %t && split-file %s %t && cd %t + +# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-mixed-2.s -o %t2.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-mixed-3.s -o %t3.o +# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o +# RUN: llvm-readelf -n %t.merged.o | FileCheck %s + +# CHECK: Displaying notes found in: .note.gnu.property +# CHECK-NEXT: Owner Data size Description +# CHECK-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +# CHECK-NEXT: Properties: aarch64 feature: BTI, PAC +# CHECK-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 + + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 1 + +#--- merged-mixed-2.s +.section ".note.gnu.property", "a" + .long 4 // Name length is always 4 ("GNU") + .long end - begin // Data length + .long 5 // Type: NT_GNU_PROPERTY_TYPE_0 + .asciz "GNU" // Name + .p2align 3 +begin: + .long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND + .long 4 + .long 7 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI, PAC and GCS + .long 0 + # PAuth ABI property note + .long 0xc0000001 // Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH + .long 16 // Data size + .quad 49 // PAuth ABI platform + .quad 19 // PAuth ABI version + .p2align 3 // Align to 8 byte for 64 bit +end: + +#--- merged-mixed-3.s +.section ".note.gnu.property", "a" +.long 4 +.long 0x10 +.long 0x5 +.asciz "GNU" +.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND +.long 4 +.long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI and PAC +.long 0 diff --git a/lld/test/ELF/aarch64-build-attributes-merged.s b/lld/test/ELF/aarch64-build-attributes-merged.s new file mode 100644 index 0000000000000..daf3ef2e0081d --- /dev/null +++ b/lld/test/ELF/aarch64-build-attributes-merged.s @@ -0,0 +1,42 @@ +# RUN: rm -rf %t && split-file %s %t && cd %t + +# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-2.s -o %t2.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-3.s -o %t3.o +# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o +# RUN: llvm-readelf -n %t.merged.o | FileCheck %s + +# CHECK: Displaying notes found in: .note.gnu.property +# CHECK-NEXT: Owner Data size Description +# CHECK-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +# CHECK-NEXT: Properties: aarch64 feature: BTI +# CHECK-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 + + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 1 + + +#--- merged-2.s +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 0 +.aeabi_attribute Tag_Feature_GCS, 1 + + +#--- merged-3.s +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 0 \ No newline at end of file From 7d2d7956b646716782dcd635edbff31d59766ead Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 11:39:19 +0100 Subject: [PATCH 70/89] move AArch64 related code to AArch64.h --- lld/ELF/Arch/AArch64.cpp | 27 +++++++++++++++++++++++++++ lld/ELF/Arch/AArch64.h | 22 ++++++++++++++++++++++ lld/ELF/InputFiles.cpp | 34 +--------------------------------- 3 files changed, 50 insertions(+), 33 deletions(-) create mode 100644 lld/ELF/Arch/AArch64.h diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 9538dd4a70bae..7775b8b2be391 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "AArch64.h" #include "InputFiles.h" #include "OutputSections.h" #include "Symbols.h" @@ -1259,3 +1260,29 @@ void elf::setAArch64TargetInfo(Ctx &ctx) { else ctx.target.reset(new AArch64(ctx)); } + +AArch64BuildAttrSubsections +extractBuildAttributesSubsections(const llvm::AArch64AttributeParser &attributes) { + + AArch64BuildAttrSubsections subSections; + auto getPauthValue = [&](unsigned tag) -> unsigned { + return attributes.getAttributeValue("aeabi_pauthabi", tag).value_or(0); + }; + subSections.pauth.tagPlatform = + getPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM); + subSections.pauth.tagSchema = + getPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA); + + auto getFeatureValue = [&](unsigned tag) -> unsigned { + return attributes.getAttributeValue("aeabi_feature_and_bits", tag) + .value_or(0); + }; + subSections.andFeatures |= + getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_BTI); + subSections.andFeatures |= + getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_PAC) << 1; + subSections.andFeatures |= + getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_GCS) << 2; + + return subSections; +} diff --git a/lld/ELF/Arch/AArch64.h b/lld/ELF/Arch/AArch64.h new file mode 100644 index 0000000000000..703dfd9857257 --- /dev/null +++ b/lld/ELF/Arch/AArch64.h @@ -0,0 +1,22 @@ +//===- AARch64.h ---------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#include +#include "llvm/Support/AArch64AttributeParser.h" +#include "llvm/Support/AArch64BuildAttributes.h" + +struct AArch64BuildAttrSubsections { + struct PauthSubSection { + uint64_t tagPlatform = 0; + uint64_t tagSchema = 0; + } pauth; + uint32_t andFeatures = 0; +}; + +AArch64BuildAttrSubsections +extractBuildAttributesSubsections(const llvm::AArch64AttributeParser&); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 6387147be3101..afe8a49bd65df 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "Arch/AArch64.h" #include "InputFiles.h" #include "Config.h" #include "DWARF.h" @@ -209,39 +210,6 @@ static void updateSupportedARMFeatures(Ctx &ctx, ctx.arg.armHasThumb2ISA |= thumb && *thumb >= ARMBuildAttrs::AllowThumb32; } -struct AArch64BuildAttrSubsections { - struct PauthSubSection { - uint64_t tagPlatform = 0; - uint64_t tagSchema = 0; - } pauth; - uint32_t andFeatures = 0; -}; - -static AArch64BuildAttrSubsections -extractBuildAttributesSubsections(const AArch64AttributeParser &attributes) { - - AArch64BuildAttrSubsections subSections; - auto getPauthValue = [&](unsigned tag) -> unsigned { - return attributes.getAttributeValue("aeabi_pauthabi", tag).value_or(0); - }; - subSections.pauth.tagPlatform = - getPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM); - subSections.pauth.tagSchema = - getPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA); - - auto getFeatureValue = [&](unsigned tag) -> unsigned { - return attributes.getAttributeValue("aeabi_feature_and_bits", tag) - .value_or(0); - }; - subSections.andFeatures |= - getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_BTI); - subSections.andFeatures |= - getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_PAC) << 1; - subSections.andFeatures |= - getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_GCS) << 2; - - return subSections; -} InputFile::InputFile(Ctx &ctx, Kind k, MemoryBufferRef m) : ctx(ctx), mb(m), groupId(ctx.driver.nextGroupId), fileKind(k) { From b2803a32598a40aaa5b2b43a3f4ba7b9a236337b Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 11:39:52 +0100 Subject: [PATCH 71/89] restore white space --- lld/ELF/InputFiles.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index afe8a49bd65df..5f21bbc36614b 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -701,6 +701,7 @@ template void ObjFile::parse(bool ignoreComdats) { initializeSymbols(obj); return; } + // Handle dependent libraries and selection of section groups as these are not // done in parallel. ArrayRef objSections = getELFShdrs(); From cb49f850d99fa0f9c780fd44b6f5a28a5f4bb257 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 11:43:25 +0100 Subject: [PATCH 72/89] remove {} and fix typo in comments --- lld/ELF/InputFiles.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 5f21bbc36614b..892a514d21cc5 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -816,14 +816,14 @@ template void ObjFile::parse(bool ignoreComdats) { } } break; - case EM_AARCH64: { + case EM_AARCH64: // At this stage AArch64 Build Attributes does not replace GNU Properties. // When both exists, their values must match. // When both exists and contain different attributes, they complement each - // other. Curently attributes are represented in the linked object file as - // GNU properties, which are already supported by the Linux kernel and the - // dynamic loader. In the future, when relocatable linking (`-r` flag) is - // performed, a single merged AArch64 Build Attributes section will be + // other. Currently attributes are represented in the linked object file + // as GNU properties, which are already supported by the Linux kernel and + // the dynamic loader. In the future, when relocatable linking (`-r` flag) + // is performed, a single merged AArch64 Build Attributes section will be // emitted. if (sec.sh_type == SHT_AARCH64_ATTRIBUTES) { ArrayRef contents = check(obj.getSectionContents(sec)); @@ -840,12 +840,12 @@ template void ObjFile::parse(bool ignoreComdats) { } // Producing a static binary with MTE globals is not currently supported, // remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as they're unused - // medatada, and we don't want them to end up in the output file for + // metadata, and we don't want them to end up in the output file for // static executables. if (sec.sh_type == SHT_AARCH64_MEMTAG_GLOBALS_STATIC && !canHaveMemtagGlobals(ctx)) sections[i] = &InputSection::discarded; - } break; + break; } } From dd89ea1fa57c85f0581b5633dcfb22def41f7c05 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 12:00:31 +0100 Subject: [PATCH 73/89] format --- lld/ELF/Arch/AArch64.cpp | 5 +++-- lld/ELF/Arch/AArch64.h | 5 ++--- lld/ELF/InputFiles.cpp | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 7775b8b2be391..090baf8649f73 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -14,6 +14,7 @@ #include "Target.h" #include "lld/Common/ErrorHandler.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/Support/AArch64BuildAttributes.h" #include "llvm/Support/Endian.h" using namespace llvm; @@ -1261,8 +1262,8 @@ void elf::setAArch64TargetInfo(Ctx &ctx) { ctx.target.reset(new AArch64(ctx)); } -AArch64BuildAttrSubsections -extractBuildAttributesSubsections(const llvm::AArch64AttributeParser &attributes) { +AArch64BuildAttrSubsections extractBuildAttributesSubsections( + const llvm::AArch64AttributeParser &attributes) { AArch64BuildAttrSubsections subSections; auto getPauthValue = [&](unsigned tag) -> unsigned { diff --git a/lld/ELF/Arch/AArch64.h b/lld/ELF/Arch/AArch64.h index 703dfd9857257..3a122dc481967 100644 --- a/lld/ELF/Arch/AArch64.h +++ b/lld/ELF/Arch/AArch64.h @@ -6,9 +6,8 @@ // //===---------------------------------------------------------------------===// -#include #include "llvm/Support/AArch64AttributeParser.h" -#include "llvm/Support/AArch64BuildAttributes.h" +#include struct AArch64BuildAttrSubsections { struct PauthSubSection { @@ -19,4 +18,4 @@ struct AArch64BuildAttrSubsections { }; AArch64BuildAttrSubsections -extractBuildAttributesSubsections(const llvm::AArch64AttributeParser&); +extractBuildAttributesSubsections(const llvm::AArch64AttributeParser &); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 892a514d21cc5..9f03d31e13f6e 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "Arch/AArch64.h" #include "InputFiles.h" +#include "Arch/AArch64.h" #include "Config.h" #include "DWARF.h" #include "Driver.h" @@ -24,7 +24,6 @@ #include "llvm/LTO/LTO.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Support/AArch64AttributeParser.h" -#include "llvm/Support/AArch64BuildAttributes.h" #include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/Endian.h" From 93f21f22a95648cac8c90e94f7bffdb6e9adf567 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 12:06:38 +0100 Subject: [PATCH 74/89] remove empty line --- lld/ELF/InputFiles.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 9f03d31e13f6e..3f5da08cf7307 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -209,7 +209,6 @@ static void updateSupportedARMFeatures(Ctx &ctx, ctx.arg.armHasThumb2ISA |= thumb && *thumb >= ARMBuildAttrs::AllowThumb32; } - InputFile::InputFile(Ctx &ctx, Kind k, MemoryBufferRef m) : ctx(ctx), mb(m), groupId(ctx.driver.nextGroupId), fileKind(k) { // All files within the same --{start,end}-group get the same group ID. From e40609abf2ae5c97a84c2bf6cd3f95ef60ac887a Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Mon, 14 Apr 2025 16:39:56 +0100 Subject: [PATCH 75/89] revert std::string to StringRef, change already been merged --- llvm/include/llvm/Support/ELFAttributes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/Support/ELFAttributes.h b/llvm/include/llvm/Support/ELFAttributes.h index d5b7630f7759c..3abdb27ffe0f1 100644 --- a/llvm/include/llvm/Support/ELFAttributes.h +++ b/llvm/include/llvm/Support/ELFAttributes.h @@ -38,7 +38,7 @@ struct BuildAttributeItem { }; struct BuildAttributeSubSection { - std::string Name; + StringRef Name; unsigned IsOptional; unsigned ParameterType; SmallVector Content; From 3f5b14cf6a351ac32ccf82c1d083228a81b558b2 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Tue, 15 Apr 2025 13:01:57 +0100 Subject: [PATCH 76/89] typo and format --- lld/ELF/Arch/AArch64.h | 2 +- lld/ELF/InputFiles.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lld/ELF/Arch/AArch64.h b/lld/ELF/Arch/AArch64.h index 3a122dc481967..2c259e741d076 100644 --- a/lld/ELF/Arch/AArch64.h +++ b/lld/ELF/Arch/AArch64.h @@ -1,4 +1,4 @@ -//===- AARch64.h ---------------------------------------------------------===// +//===- AArch64.h ---------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 3f5da08cf7307..dd2ce4aeb3657 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -591,6 +591,7 @@ static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f, desc = desc.slice(alignTo<(ELFT::Is64Bits ? 8 : 4)>(size)); } } + // 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 From 5013203c2af1d813f1b215d1f29ce09c80a358f9 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 16 Apr 2025 10:34:22 +0100 Subject: [PATCH 77/89] move AArch64 specific code to llvm/include/llvm/Support/AArch64AttributeParser.h --- lld/ELF/Arch/AArch64.cpp | 27 ------------------- lld/ELF/Arch/AArch64.h | 21 --------------- lld/ELF/InputFiles.cpp | 13 +++++---- .../llvm/Support/AArch64AttributeParser.h | 11 ++++++++ llvm/lib/Support/AArch64AttributeParser.cpp | 27 +++++++++++++++++++ 5 files changed, 44 insertions(+), 55 deletions(-) delete mode 100644 lld/ELF/Arch/AArch64.h diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 090baf8649f73..ef861982b3557 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "AArch64.h" #include "InputFiles.h" #include "OutputSections.h" #include "Symbols.h" @@ -1261,29 +1260,3 @@ void elf::setAArch64TargetInfo(Ctx &ctx) { else ctx.target.reset(new AArch64(ctx)); } - -AArch64BuildAttrSubsections extractBuildAttributesSubsections( - const llvm::AArch64AttributeParser &attributes) { - - AArch64BuildAttrSubsections subSections; - auto getPauthValue = [&](unsigned tag) -> unsigned { - return attributes.getAttributeValue("aeabi_pauthabi", tag).value_or(0); - }; - subSections.pauth.tagPlatform = - getPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM); - subSections.pauth.tagSchema = - getPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA); - - auto getFeatureValue = [&](unsigned tag) -> unsigned { - return attributes.getAttributeValue("aeabi_feature_and_bits", tag) - .value_or(0); - }; - subSections.andFeatures |= - getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_BTI); - subSections.andFeatures |= - getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_PAC) << 1; - subSections.andFeatures |= - getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_GCS) << 2; - - return subSections; -} diff --git a/lld/ELF/Arch/AArch64.h b/lld/ELF/Arch/AArch64.h deleted file mode 100644 index 2c259e741d076..0000000000000 --- a/lld/ELF/Arch/AArch64.h +++ /dev/null @@ -1,21 +0,0 @@ -//===- AArch64.h ---------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===---------------------------------------------------------------------===// - -#include "llvm/Support/AArch64AttributeParser.h" -#include - -struct AArch64BuildAttrSubsections { - struct PauthSubSection { - uint64_t tagPlatform = 0; - uint64_t tagSchema = 0; - } pauth; - uint32_t andFeatures = 0; -}; - -AArch64BuildAttrSubsections -extractBuildAttributesSubsections(const llvm::AArch64AttributeParser &); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index dd2ce4aeb3657..56669a5cb5f98 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "InputFiles.h" -#include "Arch/AArch64.h" #include "Config.h" #include "DWARF.h" #include "Driver.h" @@ -662,15 +661,15 @@ handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, if (hasBA && hasGP) { // Check for data mismatch if (!gpInfo.aarch64PauthAbiCoreInfo.empty()) { - auto baPauth = serializeUnsigned(baInfo.pauth.tagPlatform, - baInfo.pauth.tagSchema, isBE); + auto baPauth = serializeUnsigned(baInfo.Pauth.TagPlatform, + baInfo.Pauth.TagSchema, isBE); if (gpInfo.aarch64PauthAbiCoreInfo != ArrayRef(baPauth)) ErrAlways(ctx) << tPointer << " Pauth Data mismatch: file contains both GNU properties and " "AArch64 build attributes sections with different Pauth data"; } - if (baInfo.andFeatures != gpInfo.andFeatures) + if (baInfo.AndFeatures != gpInfo.andFeatures) ErrAlways(ctx) << tPointer << " Features Data mismatch: file contains both GNU " "properties and AArch64 build attributes sections with " @@ -682,13 +681,13 @@ handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, // We can only know when Pauth is missing. // Unlike AArch64 Build Attributes, GNU properties does not give a way to // distinguish between no-value given to value of '0' given. - if (baInfo.pauth.tagPlatform || baInfo.pauth.tagSchema) { + if (baInfo.Pauth.TagPlatform || baInfo.Pauth.TagSchema) { tPointer->aarch64PauthAbiCoreInfoStorage = serializeUnsigned( - baInfo.pauth.tagPlatform, baInfo.pauth.tagSchema, isBE); + baInfo.Pauth.TagPlatform, baInfo.Pauth.TagSchema, isBE); tPointer->aarch64PauthAbiCoreInfo = tPointer->aarch64PauthAbiCoreInfoStorage; } - tPointer->andFeatures = baInfo.andFeatures; + tPointer->andFeatures = baInfo.AndFeatures; } } diff --git a/llvm/include/llvm/Support/AArch64AttributeParser.h b/llvm/include/llvm/Support/AArch64AttributeParser.h index 823ae180a5c5a..dbdcba8de4e7f 100644 --- a/llvm/include/llvm/Support/AArch64AttributeParser.h +++ b/llvm/include/llvm/Support/AArch64AttributeParser.h @@ -24,6 +24,17 @@ class AArch64AttributeParser : public ELFExtendedAttrParser { : ELFExtendedAttrParser(nullptr, returnTagsNamesMap()) {} }; +// Used for extracting AArch64 Build Attributes +struct AArch64BuildAttrSubsections { + struct PauthSubSection { + uint64_t TagPlatform = 0; + uint64_t TagSchema = 0; + } Pauth; + uint32_t AndFeatures = 0; +}; + +AArch64BuildAttrSubsections +extractBuildAttributesSubsections(const llvm::AArch64AttributeParser &); } // namespace llvm #endif // LLVM_SUPPORT_AARCH64ATTRIBUTEPARSER_H diff --git a/llvm/lib/Support/AArch64AttributeParser.cpp b/llvm/lib/Support/AArch64AttributeParser.cpp index c675ef2a3b3df..18c10f72c153a 100644 --- a/llvm/lib/Support/AArch64AttributeParser.cpp +++ b/llvm/lib/Support/AArch64AttributeParser.cpp @@ -8,6 +8,7 @@ //===---------------------------------------------------------------------===// #include "llvm/Support/AArch64AttributeParser.h" +#include "llvm/Support/AArch64BuildAttributes.h" std::vector & llvm::AArch64AttributeParser::returnTagsNamesMap() { @@ -19,3 +20,29 @@ llvm::AArch64AttributeParser::returnTagsNamesMap() { {"aeabi_feature_and_bits", 2, "Tag_Feature_GCS"}}; return TagsNamesMap; } + +llvm::AArch64BuildAttrSubsections llvm::extractBuildAttributesSubsections( + const llvm::AArch64AttributeParser &Attributes) { + + llvm::AArch64BuildAttrSubsections SubSections; + auto getPauthValue = [&Attributes](unsigned Tag) { + return Attributes.getAttributeValue("aeabi_pauthabi", Tag).value_or(0); + }; + SubSections.Pauth.TagPlatform = + getPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM); + SubSections.Pauth.TagSchema = + getPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA); + + auto getFeatureValue = [&Attributes](unsigned Tag) { + return Attributes.getAttributeValue("aeabi_feature_and_bits", Tag) + .value_or(0); + }; + SubSections.AndFeatures |= + getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_BTI); + SubSections.AndFeatures |= + getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_PAC) << 1; + SubSections.AndFeatures |= + getFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_GCS) << 2; + + return SubSections; +} From 973878140e109a0ae96a5d54a313439886eacebc Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 16 Apr 2025 10:40:05 +0100 Subject: [PATCH 78/89] add check before executing handleAArch64BAAndGnuProperties --- lld/ELF/InputFiles.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 56669a5cb5f98..42e8221b578eb 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -847,13 +847,15 @@ template void ObjFile::parse(bool ignoreComdats) { } } - bool isBE = ELFT::Endianness == llvm::endianness::big; - // Handle AArch64 Build Attributes and GNU properties: - // - Err on mismatched values. - // - Store missing values as GNU properties. - handleAArch64BAAndGnuProperties(this, ctx, isBE, hasAArch64BuildAttributes, - hasGNUProperties, aarch64BAsubSections, - gnuPropertiesInformation); + if (hasAArch64BuildAttributes) { + bool isBE = ELFT::Endianness == llvm::endianness::big; + // Handle AArch64 Build Attributes and GNU properties: + // - Err on mismatched values. + // - Store missing values as GNU properties. + handleAArch64BAAndGnuProperties(this, ctx, isBE, hasAArch64BuildAttributes, + hasGNUProperties, aarch64BAsubSections, + gnuPropertiesInformation); + } // Read a symbol table. initializeSymbols(obj); From 45f7246ccb6f999438867544016ef0bab4b4d961 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 16 Apr 2025 10:41:47 +0100 Subject: [PATCH 79/89] fix typo in file name --- ...ttributes-melformed.s => aarch64-build-attributes-malformed.s} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lld/test/ELF/{aarch64-build-attributes-melformed.s => aarch64-build-attributes-malformed.s} (100%) diff --git a/lld/test/ELF/aarch64-build-attributes-melformed.s b/lld/test/ELF/aarch64-build-attributes-malformed.s similarity index 100% rename from lld/test/ELF/aarch64-build-attributes-melformed.s rename to lld/test/ELF/aarch64-build-attributes-malformed.s From d802fccee737364db5c46e887d5701595cf1cfcc Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 16 Apr 2025 11:17:17 +0100 Subject: [PATCH 80/89] remove redundant tests, consolidate some tests files --- lld/test/ELF/aarch64-build-attributes-be.s | 4 +- .../aarch64-build-attributes-both-noPauth.s | 41 ------------ lld/test/ELF/aarch64-build-attributes-both.s | 51 --------------- ...h-err.s => aarch64-build-attributes-err.s} | 10 --- .../ELF/aarch64-build-attributes-malformed.s | 2 +- .../aarch64-build-attributes-merged-mixed.s | 53 ---------------- .../ELF/aarch64-build-attributes-merged.s | 42 ------------- lld/test/ELF/aarch64-build-attributes-mixed.s | 62 +++++++++++++++++++ lld/test/ELF/aarch64-build-attributes.s | 57 ++++++++++------- 9 files changed, 100 insertions(+), 222 deletions(-) delete mode 100644 lld/test/ELF/aarch64-build-attributes-both-noPauth.s delete mode 100644 lld/test/ELF/aarch64-build-attributes-both.s rename lld/test/ELF/{aarch64-build-attributes-both-err.s => aarch64-build-attributes-err.s} (64%) delete mode 100644 lld/test/ELF/aarch64-build-attributes-merged-mixed.s delete mode 100644 lld/test/ELF/aarch64-build-attributes-merged.s create mode 100644 lld/test/ELF/aarch64-build-attributes-mixed.s diff --git a/lld/test/ELF/aarch64-build-attributes-be.s b/lld/test/ELF/aarch64-build-attributes-be.s index 76a59c0e017d4..427f9bd0ae3e8 100644 --- a/lld/test/ELF/aarch64-build-attributes-be.s +++ b/lld/test/ELF/aarch64-build-attributes-be.s @@ -3,8 +3,8 @@ // RUN: ld.lld %t.o --shared -o %t.so // RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -/// The Build attributes section appearing in the output of -/// llvm-mc should not appear in the output of lld, because +/// The Build attributes section appearing in the output of +/// llvm-mc should not appear in the output of lld, because /// AArch64 build attributes are being transformed into .gnu.properties. // Test mc -> big endian, lld -> little endian diff --git a/lld/test/ELF/aarch64-build-attributes-both-noPauth.s b/lld/test/ELF/aarch64-build-attributes-both-noPauth.s deleted file mode 100644 index 55e335945bd0e..0000000000000 --- a/lld/test/ELF/aarch64-build-attributes-both-noPauth.s +++ /dev/null @@ -1,41 +0,0 @@ -// REQUIRES: aarch64 - -// Test mc -> little endian, lld -> little endian -// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o -// RUN: ld.lld %t.o -o %t.so -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -// Test mc -> little endian, lld -> big endian -// RUN: ld.lld -EB %t.o -o %t.so -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -// Test mc -> big endian, lld -> little endian -// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o -// RUN: ld.lld %t.o -o %t.so -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -// Test mc -> big endian, lld -> big endian -// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o -// RUN: ld.lld -EB %t.o -o %t.so -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE - - -// NOTE: Displaying notes found in: .note.gnu.property -// NOTE-CHECK: Owner Data size Description -// NOTE-CHECK: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) -// NOTE-CHECK: Properties: aarch64 feature: PAC -// NOTE-CHECK: AArch64 PAuth ABI core info: platform 0x12345678 (unknown), version 0x87654321 - - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 305419896 -.aeabi_attribute Tag_PAuth_Schema, 2271560481 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_PAC, 1 - -.section ".note.gnu.property", "a" -.long 4 -.long 0x10 -.long 0x5 -.asciz "GNU" -.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND -.long 4 -.long 2 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC -.long 0 diff --git a/lld/test/ELF/aarch64-build-attributes-both.s b/lld/test/ELF/aarch64-build-attributes-both.s deleted file mode 100644 index abdc1a06ca28e..0000000000000 --- a/lld/test/ELF/aarch64-build-attributes-both.s +++ /dev/null @@ -1,51 +0,0 @@ -// REQUIRES: aarch64 - -// Test mc -> little endian, lld -> little endian -// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o -// RUN: ld.lld %t.o -o %t.so -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -// Test mc -> little endian, lld -> big endian -// RUN: ld.lld -EB %t.o -o %t.so -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -// Test mc -> big endian, lld -> little endian -// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o -// RUN: ld.lld %t.o -o %t.so -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -// Test mc -> big endian, lld -> big endian -// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o -// RUN: ld.lld -EB %t.o -o %t.so -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE - - -// NOTE: Displaying notes found in: .note.gnu.property -// NOTE-CHECK: Owner Data size Description -// NOTE-CHECK: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) -// NOTE-CHECK: Properties: aarch64 feature: PAC -// NOTE-CHECK: AArch64 PAuth ABI core info: platform 0x12345678 (unknown), version 0x87654321 - - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 305419896 -.aeabi_attribute Tag_PAuth_Schema, 2271560481 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_PAC, 1 - -.section ".note.gnu.property", "a" -.long 4 -.long 0x10 -.long 0x5 -.asciz "GNU" -.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND -.long 4 -.long 2 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC -.long 0 - -.section ".note.gnu.property", "a" -.long 4 -.long 24 -.long 5 -.asciz "GNU" -.long 0xc0000001 -.long 16 -.quad 305419896 // platform -.quad 2271560481 // version diff --git a/lld/test/ELF/aarch64-build-attributes-both-err.s b/lld/test/ELF/aarch64-build-attributes-err.s similarity index 64% rename from lld/test/ELF/aarch64-build-attributes-both-err.s rename to lld/test/ELF/aarch64-build-attributes-err.s index 43671f58a5be1..965f13673eb5c 100644 --- a/lld/test/ELF/aarch64-build-attributes-both-err.s +++ b/lld/test/ELF/aarch64-build-attributes-err.s @@ -1,17 +1,7 @@ // REQUIRES: aarch64 -// Test mc -> little endian, lld -> little endian // RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o // RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR -// Test mc -> little endian, lld -> big endian -// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o -// RUN: not ld.lld -EB %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR -// Test mc -> big endian, lld -> little endian -// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o -// RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR -// Test mc -> big endian, lld -> big endian -// RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o -// RUN: not ld.lld -EB %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR // ERR: Pauth Data mismatch: file contains both GNU properties and AArch64 build attributes sections with different Pauth data // ERR-NEXT: Features Data mismatch: file contains both GNU properties and AArch64 build attributes sections with different And Features data diff --git a/lld/test/ELF/aarch64-build-attributes-malformed.s b/lld/test/ELF/aarch64-build-attributes-malformed.s index 081ac276f920d..e82f577467c6a 100644 --- a/lld/test/ELF/aarch64-build-attributes-malformed.s +++ b/lld/test/ELF/aarch64-build-attributes-malformed.s @@ -20,4 +20,4 @@ Sections: AddressAlign: 1 Offset: 0x40 Size: 0x41 - Content: "411900000061656162695f7061757468616269000000010102012000000061656162695f666561747572655f616e645f6269747300010000010101020000" \ No newline at end of file + Content: "411900000061656162695f7061757468616269000000010102012000000061656162695f666561747572655f616e645f6269747300010000010101020000" diff --git a/lld/test/ELF/aarch64-build-attributes-merged-mixed.s b/lld/test/ELF/aarch64-build-attributes-merged-mixed.s deleted file mode 100644 index 55185f9413cfd..0000000000000 --- a/lld/test/ELF/aarch64-build-attributes-merged-mixed.s +++ /dev/null @@ -1,53 +0,0 @@ -# RUN: rm -rf %t && split-file %s %t && cd %t - -# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-mixed-2.s -o %t2.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-mixed-3.s -o %t3.o -# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o -# RUN: llvm-readelf -n %t.merged.o | FileCheck %s - -# CHECK: Displaying notes found in: .note.gnu.property -# CHECK-NEXT: Owner Data size Description -# CHECK-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) -# CHECK-NEXT: Properties: aarch64 feature: BTI, PAC -# CHECK-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 - - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 49 -.aeabi_attribute Tag_PAuth_Schema, 19 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 1 -.aeabi_attribute Tag_Feature_GCS, 1 - -#--- merged-mixed-2.s -.section ".note.gnu.property", "a" - .long 4 // Name length is always 4 ("GNU") - .long end - begin // Data length - .long 5 // Type: NT_GNU_PROPERTY_TYPE_0 - .asciz "GNU" // Name - .p2align 3 -begin: - .long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND - .long 4 - .long 7 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI, PAC and GCS - .long 0 - # PAuth ABI property note - .long 0xc0000001 // Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH - .long 16 // Data size - .quad 49 // PAuth ABI platform - .quad 19 // PAuth ABI version - .p2align 3 // Align to 8 byte for 64 bit -end: - -#--- merged-mixed-3.s -.section ".note.gnu.property", "a" -.long 4 -.long 0x10 -.long 0x5 -.asciz "GNU" -.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND -.long 4 -.long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI and PAC -.long 0 diff --git a/lld/test/ELF/aarch64-build-attributes-merged.s b/lld/test/ELF/aarch64-build-attributes-merged.s deleted file mode 100644 index daf3ef2e0081d..0000000000000 --- a/lld/test/ELF/aarch64-build-attributes-merged.s +++ /dev/null @@ -1,42 +0,0 @@ -# RUN: rm -rf %t && split-file %s %t && cd %t - -# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-2.s -o %t2.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-3.s -o %t3.o -# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o -# RUN: llvm-readelf -n %t.merged.o | FileCheck %s - -# CHECK: Displaying notes found in: .note.gnu.property -# CHECK-NEXT: Owner Data size Description -# CHECK-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) -# CHECK-NEXT: Properties: aarch64 feature: BTI -# CHECK-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 - - -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 49 -.aeabi_attribute Tag_PAuth_Schema, 19 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 1 -.aeabi_attribute Tag_Feature_GCS, 1 - - -#--- merged-2.s -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 49 -.aeabi_attribute Tag_PAuth_Schema, 19 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 0 -.aeabi_attribute Tag_Feature_GCS, 1 - - -#--- merged-3.s -.aeabi_subsection aeabi_pauthabi, required, uleb128 -.aeabi_attribute Tag_PAuth_Platform, 49 -.aeabi_attribute Tag_PAuth_Schema, 19 -.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 -.aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 1 -.aeabi_attribute Tag_Feature_GCS, 0 \ No newline at end of file diff --git a/lld/test/ELF/aarch64-build-attributes-mixed.s b/lld/test/ELF/aarch64-build-attributes-mixed.s new file mode 100644 index 0000000000000..2eec339c13793 --- /dev/null +++ b/lld/test/ELF/aarch64-build-attributes-mixed.s @@ -0,0 +1,62 @@ +# RUN: rm -rf %t && split-file %s %t && cd %t + +# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t11.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-mixed-2.s -o %t12.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-mixed-3.s -o %t13.o +# RUN: ld.lld -r %t11.o %t12.o %t13.o -o %t.merged1.o +# RUN: llvm-readelf -n %t.merged1.o | FileCheck %s --check-prefix=NOTE-MIXED + +# NOTE-MIXED: Displaying notes found in: .note.gnu.property +# NOTE-MIXED-NEXT: Owner Data size Description +# NOTE-MIXED-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +# NOTE-MIXED-NEXT: Properties: aarch64 feature: BTI, PAC +# NOTE-MIXED-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 + +# The Build attributes section appearing in the output of +# llvm-mc should not appear in the output of lld, because +# AArch64 build attributes are being transformed into .gnu.properties. + +# CHECK: .note.gnu.property +# CHECK-NOT: .ARM.attributes + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 1 + + +#--- merged-mixed-2.s +.section ".note.gnu.property", "a" + .long 4 // Name length is always 4 ("GNU") + .long end - begin // Data length + .long 5 // Type: NT_GNU_PROPERTY_TYPE_0 + .asciz "GNU" // Name + .p2align 3 +begin: + .long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND + .long 4 + .long 7 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI, PAC and GCS + .long 0 + # PAuth ABI property note + .long 0xc0000001 // Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH + .long 16 // Data size + .quad 49 // PAuth ABI platform + .quad 19 // PAuth ABI version + .p2align 3 // Align to 8 byte for 64 bit +end: + +#--- merged-mixed-3.s +.section .note.gnu.property, "a" + .align 4 + .long 4 // namesz + .long 0x10 // descsz + .long 5 // type (NT_GNU_PROPERTY_TYPE_0) + .asciz "GNU" // name (null-terminated) + .align 4 + .long 0xc0000000 // pr_type (GNU_PROPERTY_AARCH64_FEATURE_1_AND) + .long 4 // pr_datasz + .long 7 // pr_data: BTI (1), PAC (2), GCS (4) = 0b111 = 7 + .long 0 // padding or next property diff --git a/lld/test/ELF/aarch64-build-attributes.s b/lld/test/ELF/aarch64-build-attributes.s index c1064e318ed65..9e402046b728a 100644 --- a/lld/test/ELF/aarch64-build-attributes.s +++ b/lld/test/ELF/aarch64-build-attributes.s @@ -1,35 +1,48 @@ -// REQUIRES: aarch64 -// RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o -// RUN: ld.lld %t.o --shared -o %t.so -// RUN: llvm-readelf --sections %t.so | FileCheck %s -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -// RUN: ld.lld %t.o -o %t -// RUN: llvm-readelf --sections %t | FileCheck %s -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -// RUN: ld.lld -r %t.o -o %t2.o -// RUN: llvm-readelf --sections %t2.o | FileCheck %s -// RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-2.s -o %t2.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-3.s -o %t3.o +# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o +# RUN: llvm-readelf -n %t.merged.o | FileCheck %s --check-prefix=NOTE -/// The Build attributes section appearing in the output of -/// llvm-mc should not appear in the output of lld, because -/// AArch64 build attributes are being transformed into .gnu.properties. +# NOTE: Displaying notes found in: .note.gnu.property +# NOTE-NEXT: Owner Data size Description +# NOTE-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +# NOTE-NEXT: Properties: aarch64 feature: BTI +# NOTE-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 +# The Build attributes section appearing in the output of +# llvm-mc should not appear in the output of lld, because +# AArch64 build attributes are being transformed into .gnu.properties. -// CHECK: .note.gnu.property -// CHECK-NOT: .ARM.attributes +# CHECK: .note.gnu.property +# CHECK-NOT: .ARM.attributes -// NOTE: Displaying notes found in: .note.gnu.property -// NOTE-NEXT: Owner Data size Description -// NOTE-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) -// NOTE-NEXT: Properties: aarch64 feature: BTI, PAC, GCS -// NOTE-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 1 +#--- merged-2.s .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 49 .aeabi_attribute Tag_PAuth_Schema, 19 .aeabi_subsection aeabi_feature_and_bits, optional, uleb128 .aeabi_attribute Tag_Feature_BTI, 1 -.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_PAC, 0 .aeabi_attribute Tag_Feature_GCS, 1 + + +#--- merged-3.s +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 49 +.aeabi_attribute Tag_PAuth_Schema, 19 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +.aeabi_attribute Tag_Feature_PAC, 1 +.aeabi_attribute Tag_Feature_GCS, 0 From ae1a032594ea066072ac5698ec80d583fd95520b Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 16 Apr 2025 11:28:08 +0100 Subject: [PATCH 81/89] move functions back to original location in file, add forward declaration instead --- lld/ELF/InputFiles.cpp | 199 +++++++++++++++++++++-------------------- 1 file changed, 104 insertions(+), 95 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 42e8221b578eb..b7d4cd36668c9 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -540,102 +540,14 @@ uint32_t ObjFile::getSectionIndex(const Elf_Sym &sym) const { this); } +// Forward declarations: template -static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f, - uint32_t featureAndType, - ArrayRef &desc, const uint8_t *base, - ArrayRef *data = nullptr) { - auto err = [&](const uint8_t *place) -> ELFSyncStream { - auto diag = Err(ctx); - diag << &f << ":(" << ".note.gnu.property+0x" - << Twine::utohexstr(place - base) << "): "; - return diag; - }; - - while (!desc.empty()) { - const uint8_t *place = desc.data(); - if (desc.size() < 8) - return void(err(place) << "program property is too short"); - uint32_t type = read32(desc.data()); - uint32_t size = read32(desc.data() + 4); - desc = desc.slice(8); - if (desc.size() < size) - return void(err(place) << "program property is too short"); - - if (type == featureAndType) { - // We found a FEATURE_1_AND field. There may be more than one of these - // in a .note.gnu.property section, for a relocatable object we - // accumulate the bits set. - if (size < 4) - return void(err(place) << "FEATURE_1_AND entry is too short"); - f.andFeatures |= read32(desc.data()); - } else if (ctx.arg.emachine == EM_AARCH64 && - type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) { - ArrayRef contents = data ? *data : desc; - if (!f.aarch64PauthAbiCoreInfo.empty()) { - return void( - err(contents.data()) - << "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are " - "not supported"); - } else if (size != 16) { - return void(err(contents.data()) - << "GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry " - "is invalid: expected 16 bytes, but got " - << size); - } - f.aarch64PauthAbiCoreInfo = desc; - } - - // Padding is present in the note descriptor, if necessary. - desc = desc.slice(alignTo<(ELFT::Is64Bits ? 8 : 4)>(size)); - } -} - -// 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 core info (16 bytes). -template -static gnuPropertiesInfo readGnuProperty(Ctx &ctx, const InputSection &sec, - ObjFile &f) { - using Elf_Nhdr = typename ELFT::Nhdr; - using Elf_Note = typename ELFT::Note; - - ArrayRef data = sec.content(); - auto err = [&](const uint8_t *place) -> ELFSyncStream { - auto diag = Err(ctx); - diag << sec.file << ":(" << sec.name << "+0x" - << Twine::utohexstr(place - sec.content().data()) << "): "; - return diag; - }; - while (!data.empty()) { - // Read one NOTE record. - auto *nhdr = reinterpret_cast(data.data()); - if (data.size() < sizeof(Elf_Nhdr) || - data.size() < nhdr->getSize(sec.addralign)) - return (err(data.data()) << "data is too short", gnuPropertiesInfo{}); - - Elf_Note note(*nhdr); - if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName() != "GNU") { - data = data.slice(nhdr->getSize(sec.addralign)); - continue; - } - - uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64 - ? GNU_PROPERTY_AARCH64_FEATURE_1_AND - : GNU_PROPERTY_X86_FEATURE_1_AND; - - // Read a body of a NOTE record, which consists of type-length-value fields. - ArrayRef desc = note.getDesc(sec.addralign); - const uint8_t *base = sec.content().data(); - parseGnuPropertyNote(ctx, f, featureAndType, desc, base, &data); - - // Go to next NOTE record to look for more FEATURE_1_AND descriptions. - data = data.slice(nhdr->getSize(sec.addralign)); - } - return gnuPropertiesInfo{f.andFeatures, f.aarch64PauthAbiCoreInfo}; -} +static void parseGnuPropertyNote(Ctx &, ELFFileBase &, uint32_t, + ArrayRef &, const uint8_t *, + ArrayRef * = nullptr); +template +static gnuPropertiesInfo readGnuProperty(Ctx &, const InputSection &, + ObjFile &); template static void @@ -1526,6 +1438,103 @@ std::vector SharedFile::parseVerneed(const ELFFile &obj, return verneeds; } +template +static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f, + uint32_t featureAndType, + ArrayRef &desc, const uint8_t *base, + ArrayRef *data) { + auto err = [&](const uint8_t *place) -> ELFSyncStream { + auto diag = Err(ctx); + diag << &f << ":(" << ".note.gnu.property+0x" + << Twine::utohexstr(place - base) << "): "; + return diag; + }; + + while (!desc.empty()) { + const uint8_t *place = desc.data(); + if (desc.size() < 8) + return void(err(place) << "program property is too short"); + uint32_t type = read32(desc.data()); + uint32_t size = read32(desc.data() + 4); + desc = desc.slice(8); + if (desc.size() < size) + return void(err(place) << "program property is too short"); + + if (type == featureAndType) { + // We found a FEATURE_1_AND field. There may be more than one of these + // in a .note.gnu.property section, for a relocatable object we + // accumulate the bits set. + if (size < 4) + return void(err(place) << "FEATURE_1_AND entry is too short"); + f.andFeatures |= read32(desc.data()); + } else if (ctx.arg.emachine == EM_AARCH64 && + type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) { + ArrayRef contents = data ? *data : desc; + if (!f.aarch64PauthAbiCoreInfo.empty()) { + return void( + err(contents.data()) + << "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are " + "not supported"); + } else if (size != 16) { + return void(err(contents.data()) + << "GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry " + "is invalid: expected 16 bytes, but got " + << size); + } + f.aarch64PauthAbiCoreInfo = desc; + } + + // Padding is present in the note descriptor, if necessary. + desc = desc.slice(alignTo<(ELFT::Is64Bits ? 8 : 4)>(size)); + } +} + +// 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 core info (16 bytes). +template +static gnuPropertiesInfo readGnuProperty(Ctx &ctx, const InputSection &sec, + ObjFile &f) { + using Elf_Nhdr = typename ELFT::Nhdr; + using Elf_Note = typename ELFT::Note; + + ArrayRef data = sec.content(); + auto err = [&](const uint8_t *place) -> ELFSyncStream { + auto diag = Err(ctx); + diag << sec.file << ":(" << sec.name << "+0x" + << Twine::utohexstr(place - sec.content().data()) << "): "; + return diag; + }; + while (!data.empty()) { + // Read one NOTE record. + auto *nhdr = reinterpret_cast(data.data()); + if (data.size() < sizeof(Elf_Nhdr) || + data.size() < nhdr->getSize(sec.addralign)) + return (err(data.data()) << "data is too short", gnuPropertiesInfo{}); + + Elf_Note note(*nhdr); + if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName() != "GNU") { + data = data.slice(nhdr->getSize(sec.addralign)); + continue; + } + + uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64 + ? GNU_PROPERTY_AARCH64_FEATURE_1_AND + : GNU_PROPERTY_X86_FEATURE_1_AND; + + // Read a body of a NOTE record, which consists of type-length-value fields. + ArrayRef desc = note.getDesc(sec.addralign); + const uint8_t *base = sec.content().data(); + parseGnuPropertyNote(ctx, f, featureAndType, desc, base, &data); + + // Go to next NOTE record to look for more FEATURE_1_AND descriptions. + data = data.slice(nhdr->getSize(sec.addralign)); + } + return gnuPropertiesInfo{f.andFeatures, f.aarch64PauthAbiCoreInfo}; +} + // Parse PT_GNU_PROPERTY segments in DSO. The process is similar to // readGnuProperty, but we don't have the InputSection information. template From b5c882e0e104999ed1350713017d7da70e287bbf Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 16 Apr 2025 12:08:36 +0100 Subject: [PATCH 82/89] remove dead code --- llvm/include/llvm/Support/ELFAttributes.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/llvm/include/llvm/Support/ELFAttributes.h b/llvm/include/llvm/Support/ELFAttributes.h index 3abdb27ffe0f1..1d7cd4c315be1 100644 --- a/llvm/include/llvm/Support/ELFAttributes.h +++ b/llvm/include/llvm/Support/ELFAttributes.h @@ -42,11 +42,6 @@ struct BuildAttributeSubSection { unsigned IsOptional; unsigned ParameterType; SmallVector Content; - BuildAttributeSubSection() {}; - BuildAttributeSubSection(const std::string &N, unsigned Opt, unsigned Type, - SmallVector &&Content) - : Name(N), IsOptional(Opt), ParameterType(Type), - Content(std::move(Content)) {} }; // Tag to string: ELF extended build attribute section From 54fe2759dbb91d6068689770a1156b3eeecf521e Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 16 Apr 2025 12:15:22 +0100 Subject: [PATCH 83/89] move code back to prev lcation --- lld/ELF/InputFiles.cpp | 194 ++++++++++++++++++++--------------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index b7d4cd36668c9..2e760f7baf81d 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1030,6 +1030,103 @@ void ObjFile::initializeSections(bool ignoreComdats, handleSectionGroup(this->sections, entries); } +template +static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f, + uint32_t featureAndType, + ArrayRef &desc, const uint8_t *base, + ArrayRef *data) { + auto err = [&](const uint8_t *place) -> ELFSyncStream { + auto diag = Err(ctx); + diag << &f << ":(" << ".note.gnu.property+0x" + << Twine::utohexstr(place - base) << "): "; + return diag; + }; + + while (!desc.empty()) { + const uint8_t *place = desc.data(); + if (desc.size() < 8) + return void(err(place) << "program property is too short"); + uint32_t type = read32(desc.data()); + uint32_t size = read32(desc.data() + 4); + desc = desc.slice(8); + if (desc.size() < size) + return void(err(place) << "program property is too short"); + + if (type == featureAndType) { + // We found a FEATURE_1_AND field. There may be more than one of these + // in a .note.gnu.property section, for a relocatable object we + // accumulate the bits set. + if (size < 4) + return void(err(place) << "FEATURE_1_AND entry is too short"); + f.andFeatures |= read32(desc.data()); + } else if (ctx.arg.emachine == EM_AARCH64 && + type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) { + ArrayRef contents = data ? *data : desc; + if (!f.aarch64PauthAbiCoreInfo.empty()) { + return void( + err(contents.data()) + << "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are " + "not supported"); + } else if (size != 16) { + return void(err(contents.data()) + << "GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry " + "is invalid: expected 16 bytes, but got " + << size); + } + f.aarch64PauthAbiCoreInfo = desc; + } + + // Padding is present in the note descriptor, if necessary. + desc = desc.slice(alignTo<(ELFT::Is64Bits ? 8 : 4)>(size)); + } +} + +// 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 core info (16 bytes). +template +static gnuPropertiesInfo readGnuProperty(Ctx &ctx, const InputSection &sec, + ObjFile &f) { + using Elf_Nhdr = typename ELFT::Nhdr; + using Elf_Note = typename ELFT::Note; + + ArrayRef data = sec.content(); + auto err = [&](const uint8_t *place) -> ELFSyncStream { + auto diag = Err(ctx); + diag << sec.file << ":(" << sec.name << "+0x" + << Twine::utohexstr(place - sec.content().data()) << "): "; + return diag; + }; + while (!data.empty()) { + // Read one NOTE record. + auto *nhdr = reinterpret_cast(data.data()); + if (data.size() < sizeof(Elf_Nhdr) || + data.size() < nhdr->getSize(sec.addralign)) + return (err(data.data()) << "data is too short", gnuPropertiesInfo{}); + + Elf_Note note(*nhdr); + if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName() != "GNU") { + data = data.slice(nhdr->getSize(sec.addralign)); + continue; + } + + uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64 + ? GNU_PROPERTY_AARCH64_FEATURE_1_AND + : GNU_PROPERTY_X86_FEATURE_1_AND; + + // Read a body of a NOTE record, which consists of type-length-value fields. + ArrayRef desc = note.getDesc(sec.addralign); + const uint8_t *base = sec.content().data(); + parseGnuPropertyNote(ctx, f, featureAndType, desc, base, &data); + + // Go to next NOTE record to look for more FEATURE_1_AND descriptions. + data = data.slice(nhdr->getSize(sec.addralign)); + } + return gnuPropertiesInfo{f.andFeatures, f.aarch64PauthAbiCoreInfo}; +} + template InputSectionBase *ObjFile::getRelocTarget(uint32_t idx, uint32_t info) { if (info < this->sections.size()) { @@ -1438,103 +1535,6 @@ std::vector SharedFile::parseVerneed(const ELFFile &obj, return verneeds; } -template -static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f, - uint32_t featureAndType, - ArrayRef &desc, const uint8_t *base, - ArrayRef *data) { - auto err = [&](const uint8_t *place) -> ELFSyncStream { - auto diag = Err(ctx); - diag << &f << ":(" << ".note.gnu.property+0x" - << Twine::utohexstr(place - base) << "): "; - return diag; - }; - - while (!desc.empty()) { - const uint8_t *place = desc.data(); - if (desc.size() < 8) - return void(err(place) << "program property is too short"); - uint32_t type = read32(desc.data()); - uint32_t size = read32(desc.data() + 4); - desc = desc.slice(8); - if (desc.size() < size) - return void(err(place) << "program property is too short"); - - if (type == featureAndType) { - // We found a FEATURE_1_AND field. There may be more than one of these - // in a .note.gnu.property section, for a relocatable object we - // accumulate the bits set. - if (size < 4) - return void(err(place) << "FEATURE_1_AND entry is too short"); - f.andFeatures |= read32(desc.data()); - } else if (ctx.arg.emachine == EM_AARCH64 && - type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) { - ArrayRef contents = data ? *data : desc; - if (!f.aarch64PauthAbiCoreInfo.empty()) { - return void( - err(contents.data()) - << "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are " - "not supported"); - } else if (size != 16) { - return void(err(contents.data()) - << "GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry " - "is invalid: expected 16 bytes, but got " - << size); - } - f.aarch64PauthAbiCoreInfo = desc; - } - - // Padding is present in the note descriptor, if necessary. - desc = desc.slice(alignTo<(ELFT::Is64Bits ? 8 : 4)>(size)); - } -} - -// 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 core info (16 bytes). -template -static gnuPropertiesInfo readGnuProperty(Ctx &ctx, const InputSection &sec, - ObjFile &f) { - using Elf_Nhdr = typename ELFT::Nhdr; - using Elf_Note = typename ELFT::Note; - - ArrayRef data = sec.content(); - auto err = [&](const uint8_t *place) -> ELFSyncStream { - auto diag = Err(ctx); - diag << sec.file << ":(" << sec.name << "+0x" - << Twine::utohexstr(place - sec.content().data()) << "): "; - return diag; - }; - while (!data.empty()) { - // Read one NOTE record. - auto *nhdr = reinterpret_cast(data.data()); - if (data.size() < sizeof(Elf_Nhdr) || - data.size() < nhdr->getSize(sec.addralign)) - return (err(data.data()) << "data is too short", gnuPropertiesInfo{}); - - Elf_Note note(*nhdr); - if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName() != "GNU") { - data = data.slice(nhdr->getSize(sec.addralign)); - continue; - } - - uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64 - ? GNU_PROPERTY_AARCH64_FEATURE_1_AND - : GNU_PROPERTY_X86_FEATURE_1_AND; - - // Read a body of a NOTE record, which consists of type-length-value fields. - ArrayRef desc = note.getDesc(sec.addralign); - const uint8_t *base = sec.content().data(); - parseGnuPropertyNote(ctx, f, featureAndType, desc, base, &data); - - // Go to next NOTE record to look for more FEATURE_1_AND descriptions. - data = data.slice(nhdr->getSize(sec.addralign)); - } - return gnuPropertiesInfo{f.andFeatures, f.aarch64PauthAbiCoreInfo}; -} - // Parse PT_GNU_PROPERTY segments in DSO. The process is similar to // readGnuProperty, but we don't have the InputSection information. template From afca83d6a5a7f66bf75fa46f41286f840d14c42a Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Wed, 16 Apr 2025 12:57:47 +0100 Subject: [PATCH 84/89] remove unnecessery include --- lld/ELF/Arch/AArch64.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index ef861982b3557..9538dd4a70bae 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -13,7 +13,6 @@ #include "Target.h" #include "lld/Common/ErrorHandler.h" #include "llvm/BinaryFormat/ELF.h" -#include "llvm/Support/AArch64BuildAttributes.h" #include "llvm/Support/Endian.h" using namespace llvm; From 20760a9f7f0e275f6c5a5cd95baf4fc9dcc7a625 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 17 Apr 2025 14:36:33 +0100 Subject: [PATCH 85/89] change test file from using yaml to using .section notations --- .../ELF/aarch64-build-attributes-malformed.s | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/lld/test/ELF/aarch64-build-attributes-malformed.s b/lld/test/ELF/aarch64-build-attributes-malformed.s index e82f577467c6a..208da0c224179 100644 --- a/lld/test/ELF/aarch64-build-attributes-malformed.s +++ b/lld/test/ELF/aarch64-build-attributes-malformed.s @@ -1,23 +1,16 @@ - -# RUN: yaml2obj %s -o %t.o +# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t.o # RUN: ld.lld %t.o /dev/null 2>&1 | FileCheck %s -# CHECK: (.ARM.attributes): invalid Extended Build Attributes subsection size at offset: 3B - - ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - OSABI: ELFOSABI_NONE - Type: ET_REL - Machine: EM_AARCH64 - Entry: 0x0 +# CHECK: (.ARM.attributes): invalid Extended Build Attributes subsection size at offset: 39 -Sections: - - Name: .ARM.attributes - Type: 0x70000003 # SHT_LOPROC + 3 - AddressAlign: 1 - Offset: 0x40 - Size: 0x41 - Content: "411900000061656162695f7061757468616269000000010102012000000061656162695f666561747572655f616e645f6269747300010000010101020000" +.section .ARM.attributes,"",%0x70000003 +.byte 0x41 // Tag 'A' (format version) +.long 0x00000019 // Subsection length +.asciz "aeabi_pauthabi" // Subsection name +.byte 0x00, 0x00 // Optionality and Type +.byte 0x01, 0x01, 0x02, 0x01 // PAuth_Platform and PAuth_Schema +.long 0x00000023 // Subsection length +.asciz "aeabi_feature_and_bits" // Subsection name +.byte 0x01, 0x00 // Optionality and Type +.byte 0x00, 0x01, 0x01, 0x01, 0x02, 0x01 // BTI, PAC, GCS +.byte 0x00, 0x00 // This is the malformation, data is too long. From 8b1e00226776b0b05fbe150a5fc995fbd2ca1e3c Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 17 Apr 2025 14:43:04 +0100 Subject: [PATCH 86/89] change ErrAlways to Err --- lld/ELF/InputFiles.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 2e760f7baf81d..b75bbd13e9dde 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -576,16 +576,16 @@ handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, auto baPauth = serializeUnsigned(baInfo.Pauth.TagPlatform, baInfo.Pauth.TagSchema, isBE); if (gpInfo.aarch64PauthAbiCoreInfo != ArrayRef(baPauth)) - ErrAlways(ctx) + Err(ctx) << tPointer << " Pauth Data mismatch: file contains both GNU properties and " "AArch64 build attributes sections with different Pauth data"; } if (baInfo.AndFeatures != gpInfo.andFeatures) - ErrAlways(ctx) << tPointer - << " Features Data mismatch: file contains both GNU " - "properties and AArch64 build attributes sections with " - "different And Features data"; + Err(ctx) << tPointer + << " Features Data mismatch: file contains both GNU " + "properties and AArch64 build attributes sections with " + "different And Features data"; } if (hasBA && !hasGP) { From 37a3aecf02546b7e62cec8fc8c9bb07dd59422be Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Thu, 17 Apr 2025 14:51:36 +0100 Subject: [PATCH 87/89] change test files comments to follow lld convention --- lld/test/ELF/aarch64-build-attributes-be.s | 6 +-- lld/test/ELF/aarch64-build-attributes-mixed.s | 38 +++++++++---------- lld/test/ELF/aarch64-build-attributes.s | 36 +++++++++--------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/lld/test/ELF/aarch64-build-attributes-be.s b/lld/test/ELF/aarch64-build-attributes-be.s index 427f9bd0ae3e8..985e19348cf66 100644 --- a/lld/test/ELF/aarch64-build-attributes-be.s +++ b/lld/test/ELF/aarch64-build-attributes-be.s @@ -7,7 +7,7 @@ /// llvm-mc should not appear in the output of lld, because /// AArch64 build attributes are being transformed into .gnu.properties. -// Test mc -> big endian, lld -> little endian +/// Test mc -> big endian, lld -> little endian // RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o // RUN: ld.lld %t.o --shared -o %t.so // RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE @@ -16,7 +16,7 @@ // RUN: ld.lld -r %t.o -o %t2.o // RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -// Test mc -> little endian, lld -> big endian +/// Test mc -> little endian, lld -> big endian // RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o // RUN: ld.lld --EB %t.o --shared -o %t.so // RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE @@ -25,7 +25,7 @@ // RUN: ld.lld --EB -r %t.o -o %t2.o // RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE -// Test mc -> big endian, lld -> big endian +/// Test mc -> big endian, lld -> big endian // RUN: llvm-mc -triple=aarch64_be %s -filetype=obj -o %t.o // RUN: ld.lld --EB %t.o --shared -o %t.so // RUN: llvm-readelf -n %t.so | FileCheck %s --check-prefix=NOTE diff --git a/lld/test/ELF/aarch64-build-attributes-mixed.s b/lld/test/ELF/aarch64-build-attributes-mixed.s index 2eec339c13793..729aebcef8d75 100644 --- a/lld/test/ELF/aarch64-build-attributes-mixed.s +++ b/lld/test/ELF/aarch64-build-attributes-mixed.s @@ -1,23 +1,23 @@ -# RUN: rm -rf %t && split-file %s %t && cd %t +// RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t11.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-mixed-2.s -o %t12.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-mixed-3.s -o %t13.o -# RUN: ld.lld -r %t11.o %t12.o %t13.o -o %t.merged1.o -# RUN: llvm-readelf -n %t.merged1.o | FileCheck %s --check-prefix=NOTE-MIXED +// RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t11.o +// RUN: llvm-mc -triple=aarch64 -filetype=obj merged-mixed-2.s -o %t12.o +// RUN: llvm-mc -triple=aarch64 -filetype=obj merged-mixed-3.s -o %t13.o +// RUN: ld.lld -r %t11.o %t12.o %t13.o -o %t.merged1.o +// RUN: llvm-readelf -n %t.merged1.o | FileCheck %s --check-prefix=NOTE-MIXED -# NOTE-MIXED: Displaying notes found in: .note.gnu.property -# NOTE-MIXED-NEXT: Owner Data size Description -# NOTE-MIXED-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) -# NOTE-MIXED-NEXT: Properties: aarch64 feature: BTI, PAC -# NOTE-MIXED-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 +// NOTE-MIXED: Displaying notes found in: .note.gnu.property +// NOTE-MIXED-NEXT: Owner Data size Description +// NOTE-MIXED-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +// NOTE-MIXED-NEXT: Properties: aarch64 feature: BTI, PAC +// NOTE-MIXED-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 -# The Build attributes section appearing in the output of -# llvm-mc should not appear in the output of lld, because -# AArch64 build attributes are being transformed into .gnu.properties. +/// The Build attributes section appearing in the output of +/// llvm-mc should not appear in the output of lld, because +/// AArch64 build attributes are being transformed into .gnu.properties. -# CHECK: .note.gnu.property -# CHECK-NOT: .ARM.attributes +// CHECK: .note.gnu.property +// CHECK-NOT: .ARM.attributes .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 49 @@ -28,7 +28,7 @@ .aeabi_attribute Tag_Feature_GCS, 1 -#--- merged-mixed-2.s +//--- merged-mixed-2.s .section ".note.gnu.property", "a" .long 4 // Name length is always 4 ("GNU") .long end - begin // Data length @@ -40,7 +40,7 @@ begin: .long 4 .long 7 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI, PAC and GCS .long 0 - # PAuth ABI property note + // PAuth ABI property note .long 0xc0000001 // Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH .long 16 // Data size .quad 49 // PAuth ABI platform @@ -48,7 +48,7 @@ begin: .p2align 3 // Align to 8 byte for 64 bit end: -#--- merged-mixed-3.s +//--- merged-mixed-3.s .section .note.gnu.property, "a" .align 4 .long 4 // namesz diff --git a/lld/test/ELF/aarch64-build-attributes.s b/lld/test/ELF/aarch64-build-attributes.s index 9e402046b728a..55dbadd470279 100644 --- a/lld/test/ELF/aarch64-build-attributes.s +++ b/lld/test/ELF/aarch64-build-attributes.s @@ -1,23 +1,23 @@ -# RUN: rm -rf %t && split-file %s %t && cd %t +// RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-2.s -o %t2.o -# RUN: llvm-mc -triple=aarch64 -filetype=obj merged-3.s -o %t3.o -# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o -# RUN: llvm-readelf -n %t.merged.o | FileCheck %s --check-prefix=NOTE +// RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o %t1.o +// RUN: llvm-mc -triple=aarch64 -filetype=obj merged-2.s -o %t2.o +// RUN: llvm-mc -triple=aarch64 -filetype=obj merged-3.s -o %t3.o +// RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t.merged.o +// RUN: llvm-readelf -n %t.merged.o | FileCheck %s --check-prefix=NOTE -# NOTE: Displaying notes found in: .note.gnu.property -# NOTE-NEXT: Owner Data size Description -# NOTE-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) -# NOTE-NEXT: Properties: aarch64 feature: BTI -# NOTE-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 +// NOTE: Displaying notes found in: .note.gnu.property +// NOTE-NEXT: Owner Data size Description +// NOTE-NEXT: GNU 0x00000028 NT_GNU_PROPERTY_TYPE_0 (property note) +// NOTE-NEXT: Properties: aarch64 feature: BTI +// NOTE-NEXT: AArch64 PAuth ABI core info: platform 0x31 (unknown), version 0x13 -# The Build attributes section appearing in the output of -# llvm-mc should not appear in the output of lld, because -# AArch64 build attributes are being transformed into .gnu.properties. +/// The Build attributes section appearing in the output of +/// llvm-mc should not appear in the output of lld, because +/// AArch64 build attributes are being transformed into .gnu.properties. -# CHECK: .note.gnu.property -# CHECK-NOT: .ARM.attributes +// CHECK: .note.gnu.property +// CHECK-NOT: .ARM.attributes .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 49 @@ -28,7 +28,7 @@ .aeabi_attribute Tag_Feature_GCS, 1 -#--- merged-2.s +//--- merged-2.s .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 49 .aeabi_attribute Tag_PAuth_Schema, 19 @@ -38,7 +38,7 @@ .aeabi_attribute Tag_Feature_GCS, 1 -#--- merged-3.s +//--- merged-3.s .aeabi_subsection aeabi_pauthabi, required, uleb128 .aeabi_attribute Tag_PAuth_Platform, 49 .aeabi_attribute Tag_PAuth_Schema, 19 From da6ddb22f166a0ab3c9614d10d1cc7b83dbdd2e8 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Tue, 22 Apr 2025 11:05:25 +0100 Subject: [PATCH 88/89] remove unneeded default ctor --- llvm/include/llvm/Support/ELFAttributes.h | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/include/llvm/Support/ELFAttributes.h b/llvm/include/llvm/Support/ELFAttributes.h index 1d7cd4c315be1..0e123f0c1a6ff 100644 --- a/llvm/include/llvm/Support/ELFAttributes.h +++ b/llvm/include/llvm/Support/ELFAttributes.h @@ -32,7 +32,6 @@ struct BuildAttributeItem { unsigned Tag; unsigned IntValue; std::string StringValue; - BuildAttributeItem() {}; BuildAttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV) : Type(Ty), Tag(Tg), IntValue(IV), StringValue(std::move(SV)) {} }; From b3e62eccbe0015dee1da8b43d4ad616fcfce9414 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Tue, 22 Apr 2025 17:52:10 +0100 Subject: [PATCH 89/89] arrange forward declarations --- lld/ELF/InputFiles.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index b75bbd13e9dde..2412e63048c7d 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -540,15 +540,6 @@ uint32_t ObjFile::getSectionIndex(const Elf_Sym &sym) const { this); } -// Forward declarations: -template -static void parseGnuPropertyNote(Ctx &, ELFFileBase &, uint32_t, - ArrayRef &, const uint8_t *, - ArrayRef * = nullptr); -template -static gnuPropertiesInfo readGnuProperty(Ctx &, const InputSection &, - ObjFile &); - template static void handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, @@ -603,6 +594,11 @@ handleAArch64BAAndGnuProperties(const ELFT &tPointer, Ctx &ctx, bool isBE, } } +// Forward declaration: +template +static gnuPropertiesInfo readGnuProperty(Ctx &, const InputSection &, + ObjFile &); + template void ObjFile::parse(bool ignoreComdats) { object::ELFFile obj = this->getObj(); // Read a section table. justSymbols is usually false. @@ -1034,7 +1030,7 @@ template static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f, uint32_t featureAndType, ArrayRef &desc, const uint8_t *base, - ArrayRef *data) { + ArrayRef *data = nullptr) { auto err = [&](const uint8_t *place) -> ELFSyncStream { auto diag = Err(ctx); diag << &f << ":(" << ".note.gnu.property+0x"