-
Notifications
You must be signed in to change notification settings - Fork 13.2k
[LLVM][Clang][AArch64] Implement AArch64 build attributes #123990
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Added support for AArch64-specific build attributes. - Print AArch64 build attributes to assembly. - Emit AArch64 build attributes to ELF. Specification: ARM-software/abi-aa#230
@llvm/pr-subscribers-backend-aarch64 @llvm/pr-subscribers-llvm-binary-utilities Author: SivanShani-Arm (sivan-shani) Changes
Specification: ARM-software/abi-aa#230 Patch is 73.06 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/123990.diff 28 Files Affected:
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 1bc69f791bd84c..48ae0db80f43ee 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1158,6 +1158,8 @@ enum : unsigned {
SHT_ARM_ATTRIBUTES = 0x70000003U,
SHT_ARM_DEBUGOVERLAY = 0x70000004U,
SHT_ARM_OVERLAYSECTION = 0x70000005U,
+ // Support for AArch64 build attributes
+ SHT_AARCH64_ATTRIBUTES = 0x70000003U,
// Special aarch64-specific section for MTE support, as described in:
// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#section-types
SHT_AARCH64_AUTH_RELR = 0x70000004U,
diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index 94d14088d0f5d2..5a1cdd9e96cad4 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -96,7 +96,7 @@ class MCELFStreamer : public MCObjectStreamer {
// This structure holds all attributes, accounting for their string /
// numeric value, so we can later emit them in declaration order, keeping
// all in the same vector.
- enum {
+ enum Types {
HiddenAttribute = 0,
NumericAttribute,
TextAttribute,
@@ -105,6 +105,17 @@ class MCELFStreamer : public MCObjectStreamer {
unsigned Tag;
unsigned IntValue;
std::string StringValue;
+ AttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV)
+ : Type(Ty), Tag(Tg), IntValue(IV), StringValue(SV) {}
+ };
+
+ /// ELF object attributes subsection support
+ struct AttributeSubSection {
+ bool IsActive;
+ StringRef VendorName;
+ unsigned IsOptional;
+ unsigned ParameterType;
+ SmallVector<AttributeItem, 64> Content;
};
// Attributes that are added and managed entirely by target.
@@ -119,13 +130,23 @@ class MCELFStreamer : public MCObjectStreamer {
unsigned Type, MCSection *&AttributeSection) {
createAttributesSection(Vendor, Section, Type, AttributeSection, Contents);
}
+ void
+ emitAttributesSection(MCSection *&AttributeSection, const Twine &Section,
+ unsigned Type,
+ SmallVector<AttributeSubSection, 64> &SubSectionVec) {
+ createAttributesWithSubsection(AttributeSection, Section, Type,
+ SubSectionVec);
+ }
private:
AttributeItem *getAttributeItem(unsigned Attribute);
- size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec);
+ size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) const;
void createAttributesSection(StringRef Vendor, const Twine &Section,
unsigned Type, MCSection *&AttributeSection,
SmallVector<AttributeItem, 64> &AttrsVec);
+ void createAttributesWithSubsection(
+ MCSection *&AttributeSection, const Twine &Section, unsigned Type,
+ SmallVector<AttributeSubSection, 64> &SubSectionVec);
// GNU attributes that will get emitted at the end of the asm file.
SmallVector<AttributeItem, 64> GNUAttributes;
diff --git a/llvm/include/llvm/Support/AArch64BuildAttributes.h b/llvm/include/llvm/Support/AArch64BuildAttributes.h
new file mode 100644
index 00000000000000..ea293b72f9bb11
--- /dev/null
+++ b/llvm/include/llvm/Support/AArch64BuildAttributes.h
@@ -0,0 +1,75 @@
+//===-- AArch64BuildAttributes.h - AARch64 Build Attributes -----*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains enumerations and support routines for AArch64 build
+// attributes as defined in Build Attributes for the AArch64 document.
+//
+// Build Attributes for the Arm® 64-bit Architecture (AArch64) 2024Q1
+//
+// https://github.com/ARM-software/abi-aa/pull/230
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
+#define LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+namespace AArch64BuildAttributes {
+
+/// AArch64 build attributes vendors IDs (a.k.a subsection name)
+enum VendorID : unsigned {
+ AEABI_FEATURE_AND_BITS = 0,
+ AEABI_PAUTHABI = 1,
+ VENDOR_UNKNOWN = 404 // Treated as a private subsection name
+};
+StringRef getVendorName(unsigned const Vendor);
+VendorID getVendorID(StringRef const Vendor);
+
+enum SubsectionOptional : unsigned {
+ REQUIRED = 0,
+ OPTIONAL = 1,
+ OPTIONAL_NOT_FOUND = 404
+};
+StringRef getOptionalStr(unsigned Optional);
+SubsectionOptional getOptionalID(StringRef Optional);
+StringRef getSubsectionOptionalUnknownError();
+
+enum SubsectionType : unsigned { ULEB128 = 0, NTBS = 1, TYPE_NOT_FOUND = 404 };
+StringRef getTypeStr(unsigned Type);
+SubsectionType getTypeID(StringRef Type);
+StringRef getSubsectionTypeUnknownError();
+
+enum PauthABITags : unsigned {
+ TAG_PAUTH_PLATFORM = 1,
+ TAG_PAUTH_SCHEMA = 2,
+ PAUTHABI_TAG_NOT_FOUND = 404
+};
+StringRef getPauthABITagsStr(unsigned PauthABITag);
+PauthABITags getPauthABITagsID(StringRef PauthABITag);
+
+enum FeatureAndBitsTags : unsigned {
+ TAG_FEATURE_BTI = 0,
+ TAG_FEATURE_PAC = 1,
+ TAG_FEATURE_GCS = 2,
+ FEATURE_AND_BITS_TAG_NOT_FOUND = 404
+};
+StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag);
+FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag);
+
+enum FeatureAndBitsFlag : unsigned {
+ Feature_BTI_Flag = 1 << 0,
+ Feature_PAC_Flag = 1 << 1,
+ Feature_GCS_Flag = 1 << 2
+};
+} // namespace AArch64BuildAttributes
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
\ No newline at end of file
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 64ab2b2ab58f5b..282c82198507d7 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -696,8 +696,8 @@ MCELFStreamer::getAttributeItem(unsigned Attribute) {
return nullptr;
}
-size_t
-MCELFStreamer::calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) {
+size_t MCELFStreamer::calculateContentSize(
+ SmallVector<AttributeItem, 64> &AttrsVec) const {
size_t Result = 0;
for (const AttributeItem &Item : AttrsVec) {
switch (Item.Type) {
@@ -783,6 +783,67 @@ void MCELFStreamer::createAttributesSection(
AttrsVec.clear();
}
+void MCELFStreamer::createAttributesWithSubsection(
+ MCSection *&AttributeSection, const Twine &Section, unsigned Type,
+ SmallVector<AttributeSubSection, 64> &SubSectionVec) {
+ // <format-version: 'A'>
+ // [ <uint32: subsection-length> NTBS: vendor-name
+ // <bytes: vendor-data>
+ // ]*
+ // vendor-data expends to:
+ // <uint8: optional> <uint8: parameter type> <attribute>*
+ if (0 == SubSectionVec.size()) {
+ return;
+ }
+
+ // Switch section to AttributeSection or get/create the section.
+ if (AttributeSection) {
+ switchSection(AttributeSection);
+ } else {
+ AttributeSection = getContext().getELFSection(Section, Type, 0);
+ switchSection(AttributeSection);
+
+ // Format version
+ emitInt8(0x41);
+ }
+
+ for (AttributeSubSection &SubSection : SubSectionVec) {
+ // subsection-length + vendor-name + '\0'
+ const size_t VendorHeaderSize = 4 + SubSection.VendorName.size() + 1;
+ // optional + parameter-type
+ const size_t VendorParameters = 1 + 1;
+ const size_t ContentsSize = calculateContentSize(SubSection.Content);
+
+ emitInt32(VendorHeaderSize + VendorParameters + ContentsSize);
+ emitBytes(SubSection.VendorName);
+ emitInt8(0); // '\0'
+ emitInt8(SubSection.IsOptional);
+ emitInt8(SubSection.ParameterType);
+
+ for (AttributeItem &Item : SubSection.Content) {
+ emitULEB128IntValue(Item.Tag);
+ switch (Item.Type) {
+ default:
+ assert(0 && "Invalid attribute type");
+ break;
+ case AttributeItem::NumericAttribute:
+ emitULEB128IntValue(Item.IntValue);
+ break;
+ case AttributeItem::TextAttribute:
+ emitBytes(Item.StringValue);
+ emitInt8(0); // '\0'
+ break;
+ case AttributeItem::NumericAndTextAttributes:
+ emitULEB128IntValue(Item.IntValue);
+ emitBytes(Item.StringValue);
+ emitInt8(0); // '\0'
+ break;
+ }
+ }
+ }
+ SubSectionVec.clear();
+}
+
MCStreamer *llvm::createELFStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> &&MAB,
std::unique_ptr<MCObjectWriter> &&OW,
diff --git a/llvm/lib/Support/AArch64BuildAttributes.cpp b/llvm/lib/Support/AArch64BuildAttributes.cpp
new file mode 100644
index 00000000000000..ada34eb3f927d1
--- /dev/null
+++ b/llvm/lib/Support/AArch64BuildAttributes.cpp
@@ -0,0 +1,117 @@
+//===-- AArch64BuildAttributes.cpp - AArch64 Build Attributes -------------===//
+//
+// 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/AArch64BuildAttributes.h"
+#include "llvm/ADT/StringSwitch.h"
+
+namespace llvm {
+namespace AArch64BuildAttributes {
+
+StringRef getVendorName(unsigned Vendor) {
+ switch (Vendor) {
+ case AEABI_FEATURE_AND_BITS:
+ return "aeabi_feature_and_bits";
+ case AEABI_PAUTHABI:
+ return "aeabi_pauthabi";
+ case VENDOR_UNKNOWN:
+ return "";
+ default:
+ assert(0 && "Vendor name error");
+ return "";
+ }
+}
+VendorID getVendorID(StringRef Vendor) {
+ return StringSwitch<VendorID>(Vendor)
+ .Case("aeabi_feature_and_bits", AEABI_FEATURE_AND_BITS)
+ .Case("aeabi_pauthabi", AEABI_PAUTHABI)
+ .Default(VENDOR_UNKNOWN);
+}
+
+StringRef getOptionalStr(unsigned Optional) {
+ switch (Optional) {
+ case REQUIRED:
+ return "required";
+ case OPTIONAL:
+ return "optional";
+ case OPTIONAL_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+SubsectionOptional getOptionalID(StringRef Optional) {
+ return StringSwitch<SubsectionOptional>(Optional)
+ .Case("required", REQUIRED)
+ .Case("optional", OPTIONAL)
+ .Default(OPTIONAL_NOT_FOUND);
+}
+StringRef getSubsectionOptionalUnknownError() {
+ return "unknown AArch64 build attributes optionality, expected "
+ "required|optional";
+}
+
+StringRef getTypeStr(unsigned Type) {
+ switch (Type) {
+ case ULEB128:
+ return "uleb128";
+ case NTBS:
+ return "ntbs";
+ case TYPE_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+SubsectionType getTypeID(StringRef Type) {
+ return StringSwitch<SubsectionType>(Type)
+ .Cases("uleb128", "ULEB128", ULEB128)
+ .Cases("ntbs", "NTBS", NTBS)
+ .Default(TYPE_NOT_FOUND);
+}
+StringRef getSubsectionTypeUnknownError() {
+ return "unknown AArch64 build attributes type, expected uleb128|ntbs";
+}
+
+StringRef getPauthABITagsStr(unsigned PauthABITag) {
+ switch (PauthABITag) {
+ case TAG_PAUTH_PLATFORM:
+ return "Tag_PAuth_Platform";
+ case TAG_PAUTH_SCHEMA:
+ return "Tag_PAuth_Schema";
+ case PAUTHABI_TAG_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+PauthABITags getPauthABITagsID(StringRef PauthABITag) {
+ return StringSwitch<PauthABITags>(PauthABITag)
+ .Case("Tag_PAuth_Platform", TAG_PAUTH_PLATFORM)
+ .Case("Tag_PAuth_Schema", TAG_PAUTH_SCHEMA)
+ .Default(PAUTHABI_TAG_NOT_FOUND);
+}
+
+StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag) {
+ switch (FeatureAndBitsTag) {
+ case TAG_FEATURE_BTI:
+ return "Tag_Feature_BTI";
+ case TAG_FEATURE_PAC:
+ return "Tag_Feature_PAC";
+ case TAG_FEATURE_GCS:
+ return "Tag_Feature_GCS";
+ case FEATURE_AND_BITS_TAG_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag) {
+ return StringSwitch<FeatureAndBitsTags>(FeatureAndBitsTag)
+ .Case("Tag_Feature_BTI", TAG_FEATURE_BTI)
+ .Case("Tag_Feature_PAC", TAG_FEATURE_PAC)
+ .Case("Tag_Feature_GCS", TAG_FEATURE_GCS)
+ .Default(FEATURE_AND_BITS_TAG_NOT_FOUND);
+}
+} // namespace AArch64BuildAttributes
+} // namespace llvm
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 2ecaea4b02bf61..122240c27b1fcd 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -144,6 +144,7 @@ add_llvm_component_library(LLVMSupport
APInt.cpp
APSInt.cpp
ARMBuildAttrs.cpp
+ AArch64BuildAttributes.cpp
ARMAttributeParser.cpp
ARMWinEH.cpp
Allocator.cpp
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 27e65d60122fd7..8d8520c68232be 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -208,6 +208,10 @@ class AArch64AsmPrinter : public AsmPrinter {
/// pseudo instructions.
bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
+ // Emit Build Attributes
+ void emitAttributes(unsigned Flags, uint64_t PAuthABIPlatform,
+ uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
+
void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
void EmitToStreamer(const MCInst &Inst) {
EmitToStreamer(*OutStreamer, Inst);
@@ -345,36 +349,53 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
if (!TT.isOSBinFormatELF())
return;
- // Assemble feature flags that may require creation of a note section.
- unsigned Flags = 0;
+ // For emitting build attributes and .note.gnu.property section
+ auto *TS =
+ static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
+ // Assemble feature flags that may require creation of build attributes and a
+ // note section.
+ unsigned BAFlags = 0;
+ unsigned GNUFlags = 0;
if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("branch-target-enforcement")))
- if (!BTE->isZero())
- Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+ M.getModuleFlag("branch-target-enforcement"))) {
+ if (!BTE->isZero()) {
+ BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
+ GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+ }
+ }
if (const auto *GCS = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("guarded-control-stack")))
- if (!GCS->isZero())
- Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
+ M.getModuleFlag("guarded-control-stack"))) {
+ if (!GCS->isZero()) {
+ BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
+ GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
+ }
+ }
if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("sign-return-address")))
- if (!Sign->isZero())
- Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+ M.getModuleFlag("sign-return-address"))) {
+ if (!Sign->isZero()) {
+ BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
+ GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+ }
+ }
uint64_t PAuthABIPlatform = -1;
if (const auto *PAP = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("aarch64-elf-pauthabi-platform")))
+ M.getModuleFlag("aarch64-elf-pauthabi-platform"))) {
PAuthABIPlatform = PAP->getZExtValue();
+ }
+
uint64_t PAuthABIVersion = -1;
if (const auto *PAV = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("aarch64-elf-pauthabi-version")))
+ M.getModuleFlag("aarch64-elf-pauthabi-version"))) {
PAuthABIVersion = PAV->getZExtValue();
+ }
+ // Emit AArch64 Build Attributes
+ emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
// Emit a .note.gnu.property section with the flags.
- auto *TS =
- static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
- TS->emitNoteSection(Flags, PAuthABIPlatform, PAuthABIVersion);
+ TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
}
void AArch64AsmPrinter::emitFunctionHeaderComment() {
@@ -447,6 +468,58 @@ void AArch64AsmPrinter::emitSled(const MachineInstr &MI, SledKind Kind) {
recordSled(CurSled, MI, Kind, 2);
}
+void AArch64AsmPrinter::emitAttributes(unsigned Flags,
+ uint64_t PAuthABIPlatform,
+ uint64_t PAuthABIVersion,
+ AArch64TargetStreamer *TS) {
+
+ PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
+ PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
+
+ if (PAuthABIPlatform || PAuthABIVersion) {
+ TS->emitAtributesSubsection(
+ AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_PAUTHABI),
+ AArch64BuildAttributes::SubsectionOptional::REQUIRED,
+ AArch64BuildAttributes::SubsectionType::ULEB128);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_PAUTHABI),
+ AArch64BuildAttributes::TAG_PAUTH_PLATFORM,
+ PAuthABIPlatform, "", false);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_PAUTHABI),
+ AArch64BuildAttributes::TAG_PAUTH_SCHEMA, PAuthABIVersion,
+ "", false);
+ }
+
+ unsigned BTIValue =
+ (Flags & AArch64BuildAttributes::Feature_BTI_Flag) ? 1 : 0;
+ unsigned PACValue =
+ (Flags & AArch64BuildAttributes::Feature_PAC_Flag) ? 1 : 0;
+ unsigned GCSValue =
+ (Flags & AArch64BuildAttributes::Feature_GCS_Flag) ? 1 : 0;
+
+ if (BTIValue || PACValue || GCSValue) {
+ TS->emitAtributesSubsection(
+ AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
+ AArch64BuildAttributes::SubsectionType::ULEB128);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::TAG_FEATURE_BTI, BTIValue, "",
+ false);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::TAG_FEATURE_PAC, PACValue, "",
+ false);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::TAG_FEATURE_GCS, GCSValue, "",
+ false);
+ }
+}
+
// Emit the following code for Intrinsic::{xray_customevent,xray_typedevent}
// (built-in functions __xray_customevent/__xray_typedevent).
//
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 92f9f7309f8ec0..d3eda48f3276e9 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -42,7 +42,7 @@
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Support/Casting.h"
+#include "llvm/Support/AArch64BuildAttributes.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -228,6 +228,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
bool parseDirectiveSEHPACSignLR(SMLoc L);
bool parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired, bool Writeback);
+ bool parseDirectiveAeabiSubSectionHeader(SMLoc L);
+ bool parseDirectiveAeabiAArch64Attr(SMLoc L);
bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
SmallVectorImpl<SMLoc> &Loc);
@@ -6992,6 +6994,7 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
const MCContext::Environment Format = getContext().g...
[truncated]
|
@llvm/pr-subscribers-llvm-support Author: SivanShani-Arm (sivan-shani) Changes
Specification: ARM-software/abi-aa#230 Patch is 73.06 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/123990.diff 28 Files Affected:
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 1bc69f791bd84c..48ae0db80f43ee 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1158,6 +1158,8 @@ enum : unsigned {
SHT_ARM_ATTRIBUTES = 0x70000003U,
SHT_ARM_DEBUGOVERLAY = 0x70000004U,
SHT_ARM_OVERLAYSECTION = 0x70000005U,
+ // Support for AArch64 build attributes
+ SHT_AARCH64_ATTRIBUTES = 0x70000003U,
// Special aarch64-specific section for MTE support, as described in:
// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#section-types
SHT_AARCH64_AUTH_RELR = 0x70000004U,
diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index 94d14088d0f5d2..5a1cdd9e96cad4 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -96,7 +96,7 @@ class MCELFStreamer : public MCObjectStreamer {
// This structure holds all attributes, accounting for their string /
// numeric value, so we can later emit them in declaration order, keeping
// all in the same vector.
- enum {
+ enum Types {
HiddenAttribute = 0,
NumericAttribute,
TextAttribute,
@@ -105,6 +105,17 @@ class MCELFStreamer : public MCObjectStreamer {
unsigned Tag;
unsigned IntValue;
std::string StringValue;
+ AttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV)
+ : Type(Ty), Tag(Tg), IntValue(IV), StringValue(SV) {}
+ };
+
+ /// ELF object attributes subsection support
+ struct AttributeSubSection {
+ bool IsActive;
+ StringRef VendorName;
+ unsigned IsOptional;
+ unsigned ParameterType;
+ SmallVector<AttributeItem, 64> Content;
};
// Attributes that are added and managed entirely by target.
@@ -119,13 +130,23 @@ class MCELFStreamer : public MCObjectStreamer {
unsigned Type, MCSection *&AttributeSection) {
createAttributesSection(Vendor, Section, Type, AttributeSection, Contents);
}
+ void
+ emitAttributesSection(MCSection *&AttributeSection, const Twine &Section,
+ unsigned Type,
+ SmallVector<AttributeSubSection, 64> &SubSectionVec) {
+ createAttributesWithSubsection(AttributeSection, Section, Type,
+ SubSectionVec);
+ }
private:
AttributeItem *getAttributeItem(unsigned Attribute);
- size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec);
+ size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) const;
void createAttributesSection(StringRef Vendor, const Twine &Section,
unsigned Type, MCSection *&AttributeSection,
SmallVector<AttributeItem, 64> &AttrsVec);
+ void createAttributesWithSubsection(
+ MCSection *&AttributeSection, const Twine &Section, unsigned Type,
+ SmallVector<AttributeSubSection, 64> &SubSectionVec);
// GNU attributes that will get emitted at the end of the asm file.
SmallVector<AttributeItem, 64> GNUAttributes;
diff --git a/llvm/include/llvm/Support/AArch64BuildAttributes.h b/llvm/include/llvm/Support/AArch64BuildAttributes.h
new file mode 100644
index 00000000000000..ea293b72f9bb11
--- /dev/null
+++ b/llvm/include/llvm/Support/AArch64BuildAttributes.h
@@ -0,0 +1,75 @@
+//===-- AArch64BuildAttributes.h - AARch64 Build Attributes -----*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains enumerations and support routines for AArch64 build
+// attributes as defined in Build Attributes for the AArch64 document.
+//
+// Build Attributes for the Arm® 64-bit Architecture (AArch64) 2024Q1
+//
+// https://github.com/ARM-software/abi-aa/pull/230
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
+#define LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+namespace AArch64BuildAttributes {
+
+/// AArch64 build attributes vendors IDs (a.k.a subsection name)
+enum VendorID : unsigned {
+ AEABI_FEATURE_AND_BITS = 0,
+ AEABI_PAUTHABI = 1,
+ VENDOR_UNKNOWN = 404 // Treated as a private subsection name
+};
+StringRef getVendorName(unsigned const Vendor);
+VendorID getVendorID(StringRef const Vendor);
+
+enum SubsectionOptional : unsigned {
+ REQUIRED = 0,
+ OPTIONAL = 1,
+ OPTIONAL_NOT_FOUND = 404
+};
+StringRef getOptionalStr(unsigned Optional);
+SubsectionOptional getOptionalID(StringRef Optional);
+StringRef getSubsectionOptionalUnknownError();
+
+enum SubsectionType : unsigned { ULEB128 = 0, NTBS = 1, TYPE_NOT_FOUND = 404 };
+StringRef getTypeStr(unsigned Type);
+SubsectionType getTypeID(StringRef Type);
+StringRef getSubsectionTypeUnknownError();
+
+enum PauthABITags : unsigned {
+ TAG_PAUTH_PLATFORM = 1,
+ TAG_PAUTH_SCHEMA = 2,
+ PAUTHABI_TAG_NOT_FOUND = 404
+};
+StringRef getPauthABITagsStr(unsigned PauthABITag);
+PauthABITags getPauthABITagsID(StringRef PauthABITag);
+
+enum FeatureAndBitsTags : unsigned {
+ TAG_FEATURE_BTI = 0,
+ TAG_FEATURE_PAC = 1,
+ TAG_FEATURE_GCS = 2,
+ FEATURE_AND_BITS_TAG_NOT_FOUND = 404
+};
+StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag);
+FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag);
+
+enum FeatureAndBitsFlag : unsigned {
+ Feature_BTI_Flag = 1 << 0,
+ Feature_PAC_Flag = 1 << 1,
+ Feature_GCS_Flag = 1 << 2
+};
+} // namespace AArch64BuildAttributes
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
\ No newline at end of file
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 64ab2b2ab58f5b..282c82198507d7 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -696,8 +696,8 @@ MCELFStreamer::getAttributeItem(unsigned Attribute) {
return nullptr;
}
-size_t
-MCELFStreamer::calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) {
+size_t MCELFStreamer::calculateContentSize(
+ SmallVector<AttributeItem, 64> &AttrsVec) const {
size_t Result = 0;
for (const AttributeItem &Item : AttrsVec) {
switch (Item.Type) {
@@ -783,6 +783,67 @@ void MCELFStreamer::createAttributesSection(
AttrsVec.clear();
}
+void MCELFStreamer::createAttributesWithSubsection(
+ MCSection *&AttributeSection, const Twine &Section, unsigned Type,
+ SmallVector<AttributeSubSection, 64> &SubSectionVec) {
+ // <format-version: 'A'>
+ // [ <uint32: subsection-length> NTBS: vendor-name
+ // <bytes: vendor-data>
+ // ]*
+ // vendor-data expends to:
+ // <uint8: optional> <uint8: parameter type> <attribute>*
+ if (0 == SubSectionVec.size()) {
+ return;
+ }
+
+ // Switch section to AttributeSection or get/create the section.
+ if (AttributeSection) {
+ switchSection(AttributeSection);
+ } else {
+ AttributeSection = getContext().getELFSection(Section, Type, 0);
+ switchSection(AttributeSection);
+
+ // Format version
+ emitInt8(0x41);
+ }
+
+ for (AttributeSubSection &SubSection : SubSectionVec) {
+ // subsection-length + vendor-name + '\0'
+ const size_t VendorHeaderSize = 4 + SubSection.VendorName.size() + 1;
+ // optional + parameter-type
+ const size_t VendorParameters = 1 + 1;
+ const size_t ContentsSize = calculateContentSize(SubSection.Content);
+
+ emitInt32(VendorHeaderSize + VendorParameters + ContentsSize);
+ emitBytes(SubSection.VendorName);
+ emitInt8(0); // '\0'
+ emitInt8(SubSection.IsOptional);
+ emitInt8(SubSection.ParameterType);
+
+ for (AttributeItem &Item : SubSection.Content) {
+ emitULEB128IntValue(Item.Tag);
+ switch (Item.Type) {
+ default:
+ assert(0 && "Invalid attribute type");
+ break;
+ case AttributeItem::NumericAttribute:
+ emitULEB128IntValue(Item.IntValue);
+ break;
+ case AttributeItem::TextAttribute:
+ emitBytes(Item.StringValue);
+ emitInt8(0); // '\0'
+ break;
+ case AttributeItem::NumericAndTextAttributes:
+ emitULEB128IntValue(Item.IntValue);
+ emitBytes(Item.StringValue);
+ emitInt8(0); // '\0'
+ break;
+ }
+ }
+ }
+ SubSectionVec.clear();
+}
+
MCStreamer *llvm::createELFStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> &&MAB,
std::unique_ptr<MCObjectWriter> &&OW,
diff --git a/llvm/lib/Support/AArch64BuildAttributes.cpp b/llvm/lib/Support/AArch64BuildAttributes.cpp
new file mode 100644
index 00000000000000..ada34eb3f927d1
--- /dev/null
+++ b/llvm/lib/Support/AArch64BuildAttributes.cpp
@@ -0,0 +1,117 @@
+//===-- AArch64BuildAttributes.cpp - AArch64 Build Attributes -------------===//
+//
+// 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/AArch64BuildAttributes.h"
+#include "llvm/ADT/StringSwitch.h"
+
+namespace llvm {
+namespace AArch64BuildAttributes {
+
+StringRef getVendorName(unsigned Vendor) {
+ switch (Vendor) {
+ case AEABI_FEATURE_AND_BITS:
+ return "aeabi_feature_and_bits";
+ case AEABI_PAUTHABI:
+ return "aeabi_pauthabi";
+ case VENDOR_UNKNOWN:
+ return "";
+ default:
+ assert(0 && "Vendor name error");
+ return "";
+ }
+}
+VendorID getVendorID(StringRef Vendor) {
+ return StringSwitch<VendorID>(Vendor)
+ .Case("aeabi_feature_and_bits", AEABI_FEATURE_AND_BITS)
+ .Case("aeabi_pauthabi", AEABI_PAUTHABI)
+ .Default(VENDOR_UNKNOWN);
+}
+
+StringRef getOptionalStr(unsigned Optional) {
+ switch (Optional) {
+ case REQUIRED:
+ return "required";
+ case OPTIONAL:
+ return "optional";
+ case OPTIONAL_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+SubsectionOptional getOptionalID(StringRef Optional) {
+ return StringSwitch<SubsectionOptional>(Optional)
+ .Case("required", REQUIRED)
+ .Case("optional", OPTIONAL)
+ .Default(OPTIONAL_NOT_FOUND);
+}
+StringRef getSubsectionOptionalUnknownError() {
+ return "unknown AArch64 build attributes optionality, expected "
+ "required|optional";
+}
+
+StringRef getTypeStr(unsigned Type) {
+ switch (Type) {
+ case ULEB128:
+ return "uleb128";
+ case NTBS:
+ return "ntbs";
+ case TYPE_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+SubsectionType getTypeID(StringRef Type) {
+ return StringSwitch<SubsectionType>(Type)
+ .Cases("uleb128", "ULEB128", ULEB128)
+ .Cases("ntbs", "NTBS", NTBS)
+ .Default(TYPE_NOT_FOUND);
+}
+StringRef getSubsectionTypeUnknownError() {
+ return "unknown AArch64 build attributes type, expected uleb128|ntbs";
+}
+
+StringRef getPauthABITagsStr(unsigned PauthABITag) {
+ switch (PauthABITag) {
+ case TAG_PAUTH_PLATFORM:
+ return "Tag_PAuth_Platform";
+ case TAG_PAUTH_SCHEMA:
+ return "Tag_PAuth_Schema";
+ case PAUTHABI_TAG_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+PauthABITags getPauthABITagsID(StringRef PauthABITag) {
+ return StringSwitch<PauthABITags>(PauthABITag)
+ .Case("Tag_PAuth_Platform", TAG_PAUTH_PLATFORM)
+ .Case("Tag_PAuth_Schema", TAG_PAUTH_SCHEMA)
+ .Default(PAUTHABI_TAG_NOT_FOUND);
+}
+
+StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag) {
+ switch (FeatureAndBitsTag) {
+ case TAG_FEATURE_BTI:
+ return "Tag_Feature_BTI";
+ case TAG_FEATURE_PAC:
+ return "Tag_Feature_PAC";
+ case TAG_FEATURE_GCS:
+ return "Tag_Feature_GCS";
+ case FEATURE_AND_BITS_TAG_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag) {
+ return StringSwitch<FeatureAndBitsTags>(FeatureAndBitsTag)
+ .Case("Tag_Feature_BTI", TAG_FEATURE_BTI)
+ .Case("Tag_Feature_PAC", TAG_FEATURE_PAC)
+ .Case("Tag_Feature_GCS", TAG_FEATURE_GCS)
+ .Default(FEATURE_AND_BITS_TAG_NOT_FOUND);
+}
+} // namespace AArch64BuildAttributes
+} // namespace llvm
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 2ecaea4b02bf61..122240c27b1fcd 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -144,6 +144,7 @@ add_llvm_component_library(LLVMSupport
APInt.cpp
APSInt.cpp
ARMBuildAttrs.cpp
+ AArch64BuildAttributes.cpp
ARMAttributeParser.cpp
ARMWinEH.cpp
Allocator.cpp
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 27e65d60122fd7..8d8520c68232be 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -208,6 +208,10 @@ class AArch64AsmPrinter : public AsmPrinter {
/// pseudo instructions.
bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
+ // Emit Build Attributes
+ void emitAttributes(unsigned Flags, uint64_t PAuthABIPlatform,
+ uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
+
void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
void EmitToStreamer(const MCInst &Inst) {
EmitToStreamer(*OutStreamer, Inst);
@@ -345,36 +349,53 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
if (!TT.isOSBinFormatELF())
return;
- // Assemble feature flags that may require creation of a note section.
- unsigned Flags = 0;
+ // For emitting build attributes and .note.gnu.property section
+ auto *TS =
+ static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
+ // Assemble feature flags that may require creation of build attributes and a
+ // note section.
+ unsigned BAFlags = 0;
+ unsigned GNUFlags = 0;
if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("branch-target-enforcement")))
- if (!BTE->isZero())
- Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+ M.getModuleFlag("branch-target-enforcement"))) {
+ if (!BTE->isZero()) {
+ BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
+ GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+ }
+ }
if (const auto *GCS = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("guarded-control-stack")))
- if (!GCS->isZero())
- Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
+ M.getModuleFlag("guarded-control-stack"))) {
+ if (!GCS->isZero()) {
+ BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
+ GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
+ }
+ }
if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("sign-return-address")))
- if (!Sign->isZero())
- Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+ M.getModuleFlag("sign-return-address"))) {
+ if (!Sign->isZero()) {
+ BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
+ GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+ }
+ }
uint64_t PAuthABIPlatform = -1;
if (const auto *PAP = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("aarch64-elf-pauthabi-platform")))
+ M.getModuleFlag("aarch64-elf-pauthabi-platform"))) {
PAuthABIPlatform = PAP->getZExtValue();
+ }
+
uint64_t PAuthABIVersion = -1;
if (const auto *PAV = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("aarch64-elf-pauthabi-version")))
+ M.getModuleFlag("aarch64-elf-pauthabi-version"))) {
PAuthABIVersion = PAV->getZExtValue();
+ }
+ // Emit AArch64 Build Attributes
+ emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
// Emit a .note.gnu.property section with the flags.
- auto *TS =
- static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
- TS->emitNoteSection(Flags, PAuthABIPlatform, PAuthABIVersion);
+ TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
}
void AArch64AsmPrinter::emitFunctionHeaderComment() {
@@ -447,6 +468,58 @@ void AArch64AsmPrinter::emitSled(const MachineInstr &MI, SledKind Kind) {
recordSled(CurSled, MI, Kind, 2);
}
+void AArch64AsmPrinter::emitAttributes(unsigned Flags,
+ uint64_t PAuthABIPlatform,
+ uint64_t PAuthABIVersion,
+ AArch64TargetStreamer *TS) {
+
+ PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
+ PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
+
+ if (PAuthABIPlatform || PAuthABIVersion) {
+ TS->emitAtributesSubsection(
+ AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_PAUTHABI),
+ AArch64BuildAttributes::SubsectionOptional::REQUIRED,
+ AArch64BuildAttributes::SubsectionType::ULEB128);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_PAUTHABI),
+ AArch64BuildAttributes::TAG_PAUTH_PLATFORM,
+ PAuthABIPlatform, "", false);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_PAUTHABI),
+ AArch64BuildAttributes::TAG_PAUTH_SCHEMA, PAuthABIVersion,
+ "", false);
+ }
+
+ unsigned BTIValue =
+ (Flags & AArch64BuildAttributes::Feature_BTI_Flag) ? 1 : 0;
+ unsigned PACValue =
+ (Flags & AArch64BuildAttributes::Feature_PAC_Flag) ? 1 : 0;
+ unsigned GCSValue =
+ (Flags & AArch64BuildAttributes::Feature_GCS_Flag) ? 1 : 0;
+
+ if (BTIValue || PACValue || GCSValue) {
+ TS->emitAtributesSubsection(
+ AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
+ AArch64BuildAttributes::SubsectionType::ULEB128);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::TAG_FEATURE_BTI, BTIValue, "",
+ false);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::TAG_FEATURE_PAC, PACValue, "",
+ false);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::TAG_FEATURE_GCS, GCSValue, "",
+ false);
+ }
+}
+
// Emit the following code for Intrinsic::{xray_customevent,xray_typedevent}
// (built-in functions __xray_customevent/__xray_typedevent).
//
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 92f9f7309f8ec0..d3eda48f3276e9 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -42,7 +42,7 @@
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Support/Casting.h"
+#include "llvm/Support/AArch64BuildAttributes.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -228,6 +228,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
bool parseDirectiveSEHPACSignLR(SMLoc L);
bool parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired, bool Writeback);
+ bool parseDirectiveAeabiSubSectionHeader(SMLoc L);
+ bool parseDirectiveAeabiAArch64Attr(SMLoc L);
bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
SmallVectorImpl<SMLoc> &Loc);
@@ -6992,6 +6994,7 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
const MCContext::Environment Format = getContext().g...
[truncated]
|
@llvm/pr-subscribers-mc Author: SivanShani-Arm (sivan-shani) Changes
Specification: ARM-software/abi-aa#230 Patch is 73.06 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/123990.diff 28 Files Affected:
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 1bc69f791bd84c..48ae0db80f43ee 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1158,6 +1158,8 @@ enum : unsigned {
SHT_ARM_ATTRIBUTES = 0x70000003U,
SHT_ARM_DEBUGOVERLAY = 0x70000004U,
SHT_ARM_OVERLAYSECTION = 0x70000005U,
+ // Support for AArch64 build attributes
+ SHT_AARCH64_ATTRIBUTES = 0x70000003U,
// Special aarch64-specific section for MTE support, as described in:
// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#section-types
SHT_AARCH64_AUTH_RELR = 0x70000004U,
diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index 94d14088d0f5d2..5a1cdd9e96cad4 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -96,7 +96,7 @@ class MCELFStreamer : public MCObjectStreamer {
// This structure holds all attributes, accounting for their string /
// numeric value, so we can later emit them in declaration order, keeping
// all in the same vector.
- enum {
+ enum Types {
HiddenAttribute = 0,
NumericAttribute,
TextAttribute,
@@ -105,6 +105,17 @@ class MCELFStreamer : public MCObjectStreamer {
unsigned Tag;
unsigned IntValue;
std::string StringValue;
+ AttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV)
+ : Type(Ty), Tag(Tg), IntValue(IV), StringValue(SV) {}
+ };
+
+ /// ELF object attributes subsection support
+ struct AttributeSubSection {
+ bool IsActive;
+ StringRef VendorName;
+ unsigned IsOptional;
+ unsigned ParameterType;
+ SmallVector<AttributeItem, 64> Content;
};
// Attributes that are added and managed entirely by target.
@@ -119,13 +130,23 @@ class MCELFStreamer : public MCObjectStreamer {
unsigned Type, MCSection *&AttributeSection) {
createAttributesSection(Vendor, Section, Type, AttributeSection, Contents);
}
+ void
+ emitAttributesSection(MCSection *&AttributeSection, const Twine &Section,
+ unsigned Type,
+ SmallVector<AttributeSubSection, 64> &SubSectionVec) {
+ createAttributesWithSubsection(AttributeSection, Section, Type,
+ SubSectionVec);
+ }
private:
AttributeItem *getAttributeItem(unsigned Attribute);
- size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec);
+ size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) const;
void createAttributesSection(StringRef Vendor, const Twine &Section,
unsigned Type, MCSection *&AttributeSection,
SmallVector<AttributeItem, 64> &AttrsVec);
+ void createAttributesWithSubsection(
+ MCSection *&AttributeSection, const Twine &Section, unsigned Type,
+ SmallVector<AttributeSubSection, 64> &SubSectionVec);
// GNU attributes that will get emitted at the end of the asm file.
SmallVector<AttributeItem, 64> GNUAttributes;
diff --git a/llvm/include/llvm/Support/AArch64BuildAttributes.h b/llvm/include/llvm/Support/AArch64BuildAttributes.h
new file mode 100644
index 00000000000000..ea293b72f9bb11
--- /dev/null
+++ b/llvm/include/llvm/Support/AArch64BuildAttributes.h
@@ -0,0 +1,75 @@
+//===-- AArch64BuildAttributes.h - AARch64 Build Attributes -----*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains enumerations and support routines for AArch64 build
+// attributes as defined in Build Attributes for the AArch64 document.
+//
+// Build Attributes for the Arm® 64-bit Architecture (AArch64) 2024Q1
+//
+// https://github.com/ARM-software/abi-aa/pull/230
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
+#define LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+namespace AArch64BuildAttributes {
+
+/// AArch64 build attributes vendors IDs (a.k.a subsection name)
+enum VendorID : unsigned {
+ AEABI_FEATURE_AND_BITS = 0,
+ AEABI_PAUTHABI = 1,
+ VENDOR_UNKNOWN = 404 // Treated as a private subsection name
+};
+StringRef getVendorName(unsigned const Vendor);
+VendorID getVendorID(StringRef const Vendor);
+
+enum SubsectionOptional : unsigned {
+ REQUIRED = 0,
+ OPTIONAL = 1,
+ OPTIONAL_NOT_FOUND = 404
+};
+StringRef getOptionalStr(unsigned Optional);
+SubsectionOptional getOptionalID(StringRef Optional);
+StringRef getSubsectionOptionalUnknownError();
+
+enum SubsectionType : unsigned { ULEB128 = 0, NTBS = 1, TYPE_NOT_FOUND = 404 };
+StringRef getTypeStr(unsigned Type);
+SubsectionType getTypeID(StringRef Type);
+StringRef getSubsectionTypeUnknownError();
+
+enum PauthABITags : unsigned {
+ TAG_PAUTH_PLATFORM = 1,
+ TAG_PAUTH_SCHEMA = 2,
+ PAUTHABI_TAG_NOT_FOUND = 404
+};
+StringRef getPauthABITagsStr(unsigned PauthABITag);
+PauthABITags getPauthABITagsID(StringRef PauthABITag);
+
+enum FeatureAndBitsTags : unsigned {
+ TAG_FEATURE_BTI = 0,
+ TAG_FEATURE_PAC = 1,
+ TAG_FEATURE_GCS = 2,
+ FEATURE_AND_BITS_TAG_NOT_FOUND = 404
+};
+StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag);
+FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag);
+
+enum FeatureAndBitsFlag : unsigned {
+ Feature_BTI_Flag = 1 << 0,
+ Feature_PAC_Flag = 1 << 1,
+ Feature_GCS_Flag = 1 << 2
+};
+} // namespace AArch64BuildAttributes
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
\ No newline at end of file
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 64ab2b2ab58f5b..282c82198507d7 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -696,8 +696,8 @@ MCELFStreamer::getAttributeItem(unsigned Attribute) {
return nullptr;
}
-size_t
-MCELFStreamer::calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) {
+size_t MCELFStreamer::calculateContentSize(
+ SmallVector<AttributeItem, 64> &AttrsVec) const {
size_t Result = 0;
for (const AttributeItem &Item : AttrsVec) {
switch (Item.Type) {
@@ -783,6 +783,67 @@ void MCELFStreamer::createAttributesSection(
AttrsVec.clear();
}
+void MCELFStreamer::createAttributesWithSubsection(
+ MCSection *&AttributeSection, const Twine &Section, unsigned Type,
+ SmallVector<AttributeSubSection, 64> &SubSectionVec) {
+ // <format-version: 'A'>
+ // [ <uint32: subsection-length> NTBS: vendor-name
+ // <bytes: vendor-data>
+ // ]*
+ // vendor-data expends to:
+ // <uint8: optional> <uint8: parameter type> <attribute>*
+ if (0 == SubSectionVec.size()) {
+ return;
+ }
+
+ // Switch section to AttributeSection or get/create the section.
+ if (AttributeSection) {
+ switchSection(AttributeSection);
+ } else {
+ AttributeSection = getContext().getELFSection(Section, Type, 0);
+ switchSection(AttributeSection);
+
+ // Format version
+ emitInt8(0x41);
+ }
+
+ for (AttributeSubSection &SubSection : SubSectionVec) {
+ // subsection-length + vendor-name + '\0'
+ const size_t VendorHeaderSize = 4 + SubSection.VendorName.size() + 1;
+ // optional + parameter-type
+ const size_t VendorParameters = 1 + 1;
+ const size_t ContentsSize = calculateContentSize(SubSection.Content);
+
+ emitInt32(VendorHeaderSize + VendorParameters + ContentsSize);
+ emitBytes(SubSection.VendorName);
+ emitInt8(0); // '\0'
+ emitInt8(SubSection.IsOptional);
+ emitInt8(SubSection.ParameterType);
+
+ for (AttributeItem &Item : SubSection.Content) {
+ emitULEB128IntValue(Item.Tag);
+ switch (Item.Type) {
+ default:
+ assert(0 && "Invalid attribute type");
+ break;
+ case AttributeItem::NumericAttribute:
+ emitULEB128IntValue(Item.IntValue);
+ break;
+ case AttributeItem::TextAttribute:
+ emitBytes(Item.StringValue);
+ emitInt8(0); // '\0'
+ break;
+ case AttributeItem::NumericAndTextAttributes:
+ emitULEB128IntValue(Item.IntValue);
+ emitBytes(Item.StringValue);
+ emitInt8(0); // '\0'
+ break;
+ }
+ }
+ }
+ SubSectionVec.clear();
+}
+
MCStreamer *llvm::createELFStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> &&MAB,
std::unique_ptr<MCObjectWriter> &&OW,
diff --git a/llvm/lib/Support/AArch64BuildAttributes.cpp b/llvm/lib/Support/AArch64BuildAttributes.cpp
new file mode 100644
index 00000000000000..ada34eb3f927d1
--- /dev/null
+++ b/llvm/lib/Support/AArch64BuildAttributes.cpp
@@ -0,0 +1,117 @@
+//===-- AArch64BuildAttributes.cpp - AArch64 Build Attributes -------------===//
+//
+// 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/AArch64BuildAttributes.h"
+#include "llvm/ADT/StringSwitch.h"
+
+namespace llvm {
+namespace AArch64BuildAttributes {
+
+StringRef getVendorName(unsigned Vendor) {
+ switch (Vendor) {
+ case AEABI_FEATURE_AND_BITS:
+ return "aeabi_feature_and_bits";
+ case AEABI_PAUTHABI:
+ return "aeabi_pauthabi";
+ case VENDOR_UNKNOWN:
+ return "";
+ default:
+ assert(0 && "Vendor name error");
+ return "";
+ }
+}
+VendorID getVendorID(StringRef Vendor) {
+ return StringSwitch<VendorID>(Vendor)
+ .Case("aeabi_feature_and_bits", AEABI_FEATURE_AND_BITS)
+ .Case("aeabi_pauthabi", AEABI_PAUTHABI)
+ .Default(VENDOR_UNKNOWN);
+}
+
+StringRef getOptionalStr(unsigned Optional) {
+ switch (Optional) {
+ case REQUIRED:
+ return "required";
+ case OPTIONAL:
+ return "optional";
+ case OPTIONAL_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+SubsectionOptional getOptionalID(StringRef Optional) {
+ return StringSwitch<SubsectionOptional>(Optional)
+ .Case("required", REQUIRED)
+ .Case("optional", OPTIONAL)
+ .Default(OPTIONAL_NOT_FOUND);
+}
+StringRef getSubsectionOptionalUnknownError() {
+ return "unknown AArch64 build attributes optionality, expected "
+ "required|optional";
+}
+
+StringRef getTypeStr(unsigned Type) {
+ switch (Type) {
+ case ULEB128:
+ return "uleb128";
+ case NTBS:
+ return "ntbs";
+ case TYPE_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+SubsectionType getTypeID(StringRef Type) {
+ return StringSwitch<SubsectionType>(Type)
+ .Cases("uleb128", "ULEB128", ULEB128)
+ .Cases("ntbs", "NTBS", NTBS)
+ .Default(TYPE_NOT_FOUND);
+}
+StringRef getSubsectionTypeUnknownError() {
+ return "unknown AArch64 build attributes type, expected uleb128|ntbs";
+}
+
+StringRef getPauthABITagsStr(unsigned PauthABITag) {
+ switch (PauthABITag) {
+ case TAG_PAUTH_PLATFORM:
+ return "Tag_PAuth_Platform";
+ case TAG_PAUTH_SCHEMA:
+ return "Tag_PAuth_Schema";
+ case PAUTHABI_TAG_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+PauthABITags getPauthABITagsID(StringRef PauthABITag) {
+ return StringSwitch<PauthABITags>(PauthABITag)
+ .Case("Tag_PAuth_Platform", TAG_PAUTH_PLATFORM)
+ .Case("Tag_PAuth_Schema", TAG_PAUTH_SCHEMA)
+ .Default(PAUTHABI_TAG_NOT_FOUND);
+}
+
+StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag) {
+ switch (FeatureAndBitsTag) {
+ case TAG_FEATURE_BTI:
+ return "Tag_Feature_BTI";
+ case TAG_FEATURE_PAC:
+ return "Tag_Feature_PAC";
+ case TAG_FEATURE_GCS:
+ return "Tag_Feature_GCS";
+ case FEATURE_AND_BITS_TAG_NOT_FOUND:
+ default:
+ return "";
+ }
+}
+FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag) {
+ return StringSwitch<FeatureAndBitsTags>(FeatureAndBitsTag)
+ .Case("Tag_Feature_BTI", TAG_FEATURE_BTI)
+ .Case("Tag_Feature_PAC", TAG_FEATURE_PAC)
+ .Case("Tag_Feature_GCS", TAG_FEATURE_GCS)
+ .Default(FEATURE_AND_BITS_TAG_NOT_FOUND);
+}
+} // namespace AArch64BuildAttributes
+} // namespace llvm
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 2ecaea4b02bf61..122240c27b1fcd 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -144,6 +144,7 @@ add_llvm_component_library(LLVMSupport
APInt.cpp
APSInt.cpp
ARMBuildAttrs.cpp
+ AArch64BuildAttributes.cpp
ARMAttributeParser.cpp
ARMWinEH.cpp
Allocator.cpp
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 27e65d60122fd7..8d8520c68232be 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -208,6 +208,10 @@ class AArch64AsmPrinter : public AsmPrinter {
/// pseudo instructions.
bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
+ // Emit Build Attributes
+ void emitAttributes(unsigned Flags, uint64_t PAuthABIPlatform,
+ uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
+
void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
void EmitToStreamer(const MCInst &Inst) {
EmitToStreamer(*OutStreamer, Inst);
@@ -345,36 +349,53 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
if (!TT.isOSBinFormatELF())
return;
- // Assemble feature flags that may require creation of a note section.
- unsigned Flags = 0;
+ // For emitting build attributes and .note.gnu.property section
+ auto *TS =
+ static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
+ // Assemble feature flags that may require creation of build attributes and a
+ // note section.
+ unsigned BAFlags = 0;
+ unsigned GNUFlags = 0;
if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("branch-target-enforcement")))
- if (!BTE->isZero())
- Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+ M.getModuleFlag("branch-target-enforcement"))) {
+ if (!BTE->isZero()) {
+ BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
+ GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+ }
+ }
if (const auto *GCS = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("guarded-control-stack")))
- if (!GCS->isZero())
- Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
+ M.getModuleFlag("guarded-control-stack"))) {
+ if (!GCS->isZero()) {
+ BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
+ GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
+ }
+ }
if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("sign-return-address")))
- if (!Sign->isZero())
- Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+ M.getModuleFlag("sign-return-address"))) {
+ if (!Sign->isZero()) {
+ BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
+ GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+ }
+ }
uint64_t PAuthABIPlatform = -1;
if (const auto *PAP = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("aarch64-elf-pauthabi-platform")))
+ M.getModuleFlag("aarch64-elf-pauthabi-platform"))) {
PAuthABIPlatform = PAP->getZExtValue();
+ }
+
uint64_t PAuthABIVersion = -1;
if (const auto *PAV = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("aarch64-elf-pauthabi-version")))
+ M.getModuleFlag("aarch64-elf-pauthabi-version"))) {
PAuthABIVersion = PAV->getZExtValue();
+ }
+ // Emit AArch64 Build Attributes
+ emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
// Emit a .note.gnu.property section with the flags.
- auto *TS =
- static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
- TS->emitNoteSection(Flags, PAuthABIPlatform, PAuthABIVersion);
+ TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
}
void AArch64AsmPrinter::emitFunctionHeaderComment() {
@@ -447,6 +468,58 @@ void AArch64AsmPrinter::emitSled(const MachineInstr &MI, SledKind Kind) {
recordSled(CurSled, MI, Kind, 2);
}
+void AArch64AsmPrinter::emitAttributes(unsigned Flags,
+ uint64_t PAuthABIPlatform,
+ uint64_t PAuthABIVersion,
+ AArch64TargetStreamer *TS) {
+
+ PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
+ PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
+
+ if (PAuthABIPlatform || PAuthABIVersion) {
+ TS->emitAtributesSubsection(
+ AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_PAUTHABI),
+ AArch64BuildAttributes::SubsectionOptional::REQUIRED,
+ AArch64BuildAttributes::SubsectionType::ULEB128);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_PAUTHABI),
+ AArch64BuildAttributes::TAG_PAUTH_PLATFORM,
+ PAuthABIPlatform, "", false);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_PAUTHABI),
+ AArch64BuildAttributes::TAG_PAUTH_SCHEMA, PAuthABIVersion,
+ "", false);
+ }
+
+ unsigned BTIValue =
+ (Flags & AArch64BuildAttributes::Feature_BTI_Flag) ? 1 : 0;
+ unsigned PACValue =
+ (Flags & AArch64BuildAttributes::Feature_PAC_Flag) ? 1 : 0;
+ unsigned GCSValue =
+ (Flags & AArch64BuildAttributes::Feature_GCS_Flag) ? 1 : 0;
+
+ if (BTIValue || PACValue || GCSValue) {
+ TS->emitAtributesSubsection(
+ AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
+ AArch64BuildAttributes::SubsectionType::ULEB128);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::TAG_FEATURE_BTI, BTIValue, "",
+ false);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::TAG_FEATURE_PAC, PACValue, "",
+ false);
+ TS->emitAttribute(AArch64BuildAttributes::getVendorName(
+ AArch64BuildAttributes::AEABI_FEATURE_AND_BITS),
+ AArch64BuildAttributes::TAG_FEATURE_GCS, GCSValue, "",
+ false);
+ }
+}
+
// Emit the following code for Intrinsic::{xray_customevent,xray_typedevent}
// (built-in functions __xray_customevent/__xray_typedevent).
//
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 92f9f7309f8ec0..d3eda48f3276e9 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -42,7 +42,7 @@
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Support/Casting.h"
+#include "llvm/Support/AArch64BuildAttributes.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -228,6 +228,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
bool parseDirectiveSEHPACSignLR(SMLoc L);
bool parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired, bool Writeback);
+ bool parseDirectiveAeabiSubSectionHeader(SMLoc L);
+ bool parseDirectiveAeabiAArch64Attr(SMLoc L);
bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
SmallVectorImpl<SMLoc> &Loc);
@@ -6992,6 +6994,7 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
const MCContext::Environment Format = getContext().g...
[truncated]
|
Patch was previously reverted due to failing tests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. FWIW, check-llvm
is happy on my end.
@@ -33,6 +33,7 @@ static_library("Support") { | |||
"Windows", | |||
] | |||
sources = [ | |||
"AArch64BuildAttributes.cpp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(fyi, there's no need to update .gn files. They're updated automatically by a bot based on changes to cmake files. if you do update them, please add trailing commas and add files just once instead of twice like here. i fixed this in 92b839e)
We're seeing significant binary size increase in Chromium after this. I haven't dug into the change yet, but is that something to be expected? |
Specifically it seems like the From looking briefly at the linked spec, it sounds like the attributes are supposed to go in the relocatable object files, not that they should be linked into the executables. @smithp35 in case I'm not getting this right. |
The sections are not supposed to end up in linked executables. Follow-up to llvm#123990
It should be like the Arm 32-bit case. The linker should merge all of the input sections and then it is the implementation's choice whether to output a single merged attributes section, or not (GNU ld preferred to output the section). I think the problem here is that no LLD support has been added (yet) to deal with the attributes sections, so as you say they are just being accumulated. A way of fixing this temporarily would be to submit a temporary patch for LLD to delete them, or to make the output in llvm conditional until LLD support is added. |
I've posted #125838 to discard .ARM.attributes sections in LLD. This will be the right thing to do for all but relocatable links so it can be built upon by @sivan-shani , who is working on full support in LLD right now. |
Just to double check: do we know the status of GNU ld support for this, or could users of that also run into the binary size issue we hit? |
To the best of my knowledge no AArch64 build attributes code was up-streamed yet. |
Then it seems like this change breaks users of GNU ld who care about binary size? Perhaps we should revert this until a proper fix is found. |
GNU ld support is being worked on by one of our GNU team at the moment, I don't think they have published any patches yet. It is aiming for GCC 15 and the next binutills release. If you can give me some time, I'll take the idea of using SHF_EXCLUDE to the GNU team to see if that will cause any problems. I think that flag is fairly recent so I'd like to check what binutils support it. |
Repeating a comment on the LLD patch just in case its useful in this context. FWIW I've just checked GNU ld. It already has some code for SHT_AARCH64_ATTRIBUTES as the section name has been reserved since the initial AArch64 ABI. This will remove (I've tested it) the SHT_AARCH64_ATTRIBUTES section from the output so we don't need to worry about GNU ld. |
Useful practices:
|
For re-lands, what I like to do is make use of the fact that PRs can contain multiple commits, so I can include the original commit as it was, then the follow-up commit which shows what I fixed. Example: #122734 |
Specification: ARM-software/abi-aa#230