Skip to content

[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

Merged
merged 1 commit into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/include/llvm/BinaryFormat/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
25 changes: 23 additions & 2 deletions llvm/include/llvm/MC/MCELFStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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.
Expand All @@ -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;
Expand Down
75 changes: 75 additions & 0 deletions llvm/include/llvm/Support/AArch64BuildAttributes.h
Original file line number Diff line number Diff line change
@@ -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
65 changes: 63 additions & 2 deletions llvm/lib/MC/MCELFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down
117 changes: 117 additions & 0 deletions llvm/lib/Support/AArch64BuildAttributes.cpp
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions llvm/lib/Support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ add_llvm_component_library(LLVMSupport
APInt.cpp
APSInt.cpp
ARMBuildAttrs.cpp
AArch64BuildAttributes.cpp
ARMAttributeParser.cpp
ARMWinEH.cpp
Allocator.cpp
Expand Down
Loading
Loading