Skip to content

Commit 79046bc

Browse files
sivan-shanigithub-actions[bot]
authored andcommitted
Automerge: [LLVM][Clang][AArch64] Implement AArch64 build attributes (#118771)
- Added support for AArch64-specific build attributes. - Print AArch64 build attributes to assembly. - Parse AArch64 build attributes from assembly. - Emit AArch64 build attributes to ELF. Specification: ARM-software/abi-aa#230
2 parents 3922cbe + d7fb4a2 commit 79046bc

28 files changed

+1438
-22
lines changed

llvm/include/llvm/BinaryFormat/ELF.h

+2
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,8 @@ enum : unsigned {
11581158
SHT_ARM_ATTRIBUTES = 0x70000003U,
11591159
SHT_ARM_DEBUGOVERLAY = 0x70000004U,
11601160
SHT_ARM_OVERLAYSECTION = 0x70000005U,
1161+
// Support for AArch64 build attributes
1162+
SHT_AARCH64_ATTRIBUTES = 0x70000003U,
11611163
// Special aarch64-specific section for MTE support, as described in:
11621164
// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#section-types
11631165
SHT_AARCH64_AUTH_RELR = 0x70000004U,

llvm/include/llvm/MC/MCELFStreamer.h

+23-2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class MCELFStreamer : public MCObjectStreamer {
9696
// This structure holds all attributes, accounting for their string /
9797
// numeric value, so we can later emit them in declaration order, keeping
9898
// all in the same vector.
99-
enum {
99+
enum Types {
100100
HiddenAttribute = 0,
101101
NumericAttribute,
102102
TextAttribute,
@@ -105,6 +105,17 @@ class MCELFStreamer : public MCObjectStreamer {
105105
unsigned Tag;
106106
unsigned IntValue;
107107
std::string StringValue;
108+
AttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV)
109+
: Type(Ty), Tag(Tg), IntValue(IV), StringValue(SV) {}
110+
};
111+
112+
/// ELF object attributes subsection support
113+
struct AttributeSubSection {
114+
bool IsActive;
115+
StringRef VendorName;
116+
unsigned IsOptional;
117+
unsigned ParameterType;
118+
SmallVector<AttributeItem, 64> Content;
108119
};
109120

110121
// Attributes that are added and managed entirely by target.
@@ -119,13 +130,23 @@ class MCELFStreamer : public MCObjectStreamer {
119130
unsigned Type, MCSection *&AttributeSection) {
120131
createAttributesSection(Vendor, Section, Type, AttributeSection, Contents);
121132
}
133+
void
134+
emitAttributesSection(MCSection *&AttributeSection, const Twine &Section,
135+
unsigned Type,
136+
SmallVector<AttributeSubSection, 64> &SubSectionVec) {
137+
createAttributesWithSubsection(AttributeSection, Section, Type,
138+
SubSectionVec);
139+
}
122140

123141
private:
124142
AttributeItem *getAttributeItem(unsigned Attribute);
125-
size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec);
143+
size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) const;
126144
void createAttributesSection(StringRef Vendor, const Twine &Section,
127145
unsigned Type, MCSection *&AttributeSection,
128146
SmallVector<AttributeItem, 64> &AttrsVec);
147+
void createAttributesWithSubsection(
148+
MCSection *&AttributeSection, const Twine &Section, unsigned Type,
149+
SmallVector<AttributeSubSection, 64> &SubSectionVec);
129150

130151
// GNU attributes that will get emitted at the end of the asm file.
131152
SmallVector<AttributeItem, 64> GNUAttributes;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//===-- AArch64BuildAttributes.h - AARch64 Build Attributes -----*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains enumerations and support routines for AArch64 build
10+
// attributes as defined in Build Attributes for the AArch64 document.
11+
//
12+
// Build Attributes for the Arm® 64-bit Architecture (AArch64) 2024Q1
13+
//
14+
// https://github.com/ARM-software/abi-aa/pull/230
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
19+
#define LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
20+
21+
#include "llvm/ADT/StringRef.h"
22+
23+
namespace llvm {
24+
25+
namespace AArch64BuildAttributes {
26+
27+
/// AArch64 build attributes vendors IDs (a.k.a subsection name)
28+
enum VendorID : unsigned {
29+
AEABI_FEATURE_AND_BITS = 0,
30+
AEABI_PAUTHABI = 1,
31+
VENDOR_UNKNOWN = 404 // Treated as a private subsection name
32+
};
33+
StringRef getVendorName(unsigned const Vendor);
34+
VendorID getVendorID(StringRef const Vendor);
35+
36+
enum SubsectionOptional : unsigned {
37+
REQUIRED = 0,
38+
OPTIONAL = 1,
39+
OPTIONAL_NOT_FOUND = 404
40+
};
41+
StringRef getOptionalStr(unsigned Optional);
42+
SubsectionOptional getOptionalID(StringRef Optional);
43+
StringRef getSubsectionOptionalUnknownError();
44+
45+
enum SubsectionType : unsigned { ULEB128 = 0, NTBS = 1, TYPE_NOT_FOUND = 404 };
46+
StringRef getTypeStr(unsigned Type);
47+
SubsectionType getTypeID(StringRef Type);
48+
StringRef getSubsectionTypeUnknownError();
49+
50+
enum PauthABITags : unsigned {
51+
TAG_PAUTH_PLATFORM = 1,
52+
TAG_PAUTH_SCHEMA = 2,
53+
PAUTHABI_TAG_NOT_FOUND = 404
54+
};
55+
StringRef getPauthABITagsStr(unsigned PauthABITag);
56+
PauthABITags getPauthABITagsID(StringRef PauthABITag);
57+
58+
enum FeatureAndBitsTags : unsigned {
59+
TAG_FEATURE_BTI = 0,
60+
TAG_FEATURE_PAC = 1,
61+
TAG_FEATURE_GCS = 2,
62+
FEATURE_AND_BITS_TAG_NOT_FOUND = 404
63+
};
64+
StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag);
65+
FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag);
66+
67+
enum FeatureAndBitsFlag : unsigned {
68+
Feature_BTI_Flag = 1 << 0,
69+
Feature_PAC_Flag = 1 << 1,
70+
Feature_GCS_Flag = 1 << 2
71+
};
72+
} // namespace AArch64BuildAttributes
73+
} // namespace llvm
74+
75+
#endif // LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H

llvm/lib/MC/MCELFStreamer.cpp

+63-2
Original file line numberDiff line numberDiff line change
@@ -696,8 +696,8 @@ MCELFStreamer::getAttributeItem(unsigned Attribute) {
696696
return nullptr;
697697
}
698698

699-
size_t
700-
MCELFStreamer::calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) {
699+
size_t MCELFStreamer::calculateContentSize(
700+
SmallVector<AttributeItem, 64> &AttrsVec) const {
701701
size_t Result = 0;
702702
for (const AttributeItem &Item : AttrsVec) {
703703
switch (Item.Type) {
@@ -783,6 +783,67 @@ void MCELFStreamer::createAttributesSection(
783783
AttrsVec.clear();
784784
}
785785

786+
void MCELFStreamer::createAttributesWithSubsection(
787+
MCSection *&AttributeSection, const Twine &Section, unsigned Type,
788+
SmallVector<AttributeSubSection, 64> &SubSectionVec) {
789+
// <format-version: 'A'>
790+
// [ <uint32: subsection-length> NTBS: vendor-name
791+
// <bytes: vendor-data>
792+
// ]*
793+
// vendor-data expends to:
794+
// <uint8: optional> <uint8: parameter type> <attribute>*
795+
if (0 == SubSectionVec.size()) {
796+
return;
797+
}
798+
799+
// Switch section to AttributeSection or get/create the section.
800+
if (AttributeSection) {
801+
switchSection(AttributeSection);
802+
} else {
803+
AttributeSection = getContext().getELFSection(Section, Type, 0);
804+
switchSection(AttributeSection);
805+
806+
// Format version
807+
emitInt8(0x41);
808+
}
809+
810+
for (AttributeSubSection &SubSection : SubSectionVec) {
811+
// subsection-length + vendor-name + '\0'
812+
const size_t VendorHeaderSize = 4 + SubSection.VendorName.size() + 1;
813+
// optional + parameter-type
814+
const size_t VendorParameters = 1 + 1;
815+
const size_t ContentsSize = calculateContentSize(SubSection.Content);
816+
817+
emitInt32(VendorHeaderSize + VendorParameters + ContentsSize);
818+
emitBytes(SubSection.VendorName);
819+
emitInt8(0); // '\0'
820+
emitInt8(SubSection.IsOptional);
821+
emitInt8(SubSection.ParameterType);
822+
823+
for (AttributeItem &Item : SubSection.Content) {
824+
emitULEB128IntValue(Item.Tag);
825+
switch (Item.Type) {
826+
default:
827+
assert(0 && "Invalid attribute type");
828+
break;
829+
case AttributeItem::NumericAttribute:
830+
emitULEB128IntValue(Item.IntValue);
831+
break;
832+
case AttributeItem::TextAttribute:
833+
emitBytes(Item.StringValue);
834+
emitInt8(0); // '\0'
835+
break;
836+
case AttributeItem::NumericAndTextAttributes:
837+
emitULEB128IntValue(Item.IntValue);
838+
emitBytes(Item.StringValue);
839+
emitInt8(0); // '\0'
840+
break;
841+
}
842+
}
843+
}
844+
SubSectionVec.clear();
845+
}
846+
786847
MCStreamer *llvm::createELFStreamer(MCContext &Context,
787848
std::unique_ptr<MCAsmBackend> &&MAB,
788849
std::unique_ptr<MCObjectWriter> &&OW,
+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//===-- AArch64BuildAttributes.cpp - AArch64 Build Attributes -------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Support/AArch64BuildAttributes.h"
10+
#include "llvm/ADT/StringSwitch.h"
11+
12+
namespace llvm {
13+
namespace AArch64BuildAttributes {
14+
15+
StringRef getVendorName(unsigned Vendor) {
16+
switch (Vendor) {
17+
case AEABI_FEATURE_AND_BITS:
18+
return "aeabi_feature_and_bits";
19+
case AEABI_PAUTHABI:
20+
return "aeabi_pauthabi";
21+
case VENDOR_UNKNOWN:
22+
return "";
23+
default:
24+
assert(0 && "Vendor name error");
25+
return "";
26+
}
27+
}
28+
VendorID getVendorID(StringRef Vendor) {
29+
return StringSwitch<VendorID>(Vendor)
30+
.Case("aeabi_feature_and_bits", AEABI_FEATURE_AND_BITS)
31+
.Case("aeabi_pauthabi", AEABI_PAUTHABI)
32+
.Default(VENDOR_UNKNOWN);
33+
}
34+
35+
StringRef getOptionalStr(unsigned Optional) {
36+
switch (Optional) {
37+
case REQUIRED:
38+
return "required";
39+
case OPTIONAL:
40+
return "optional";
41+
case OPTIONAL_NOT_FOUND:
42+
default:
43+
return "";
44+
}
45+
}
46+
SubsectionOptional getOptionalID(StringRef Optional) {
47+
return StringSwitch<SubsectionOptional>(Optional)
48+
.Case("required", REQUIRED)
49+
.Case("optional", OPTIONAL)
50+
.Default(OPTIONAL_NOT_FOUND);
51+
}
52+
StringRef getSubsectionOptionalUnknownError() {
53+
return "unknown AArch64 build attributes optionality, expected "
54+
"required|optional";
55+
}
56+
57+
StringRef getTypeStr(unsigned Type) {
58+
switch (Type) {
59+
case ULEB128:
60+
return "uleb128";
61+
case NTBS:
62+
return "ntbs";
63+
case TYPE_NOT_FOUND:
64+
default:
65+
return "";
66+
}
67+
}
68+
SubsectionType getTypeID(StringRef Type) {
69+
return StringSwitch<SubsectionType>(Type)
70+
.Cases("uleb128", "ULEB128", ULEB128)
71+
.Cases("ntbs", "NTBS", NTBS)
72+
.Default(TYPE_NOT_FOUND);
73+
}
74+
StringRef getSubsectionTypeUnknownError() {
75+
return "unknown AArch64 build attributes type, expected uleb128|ntbs";
76+
}
77+
78+
StringRef getPauthABITagsStr(unsigned PauthABITag) {
79+
switch (PauthABITag) {
80+
case TAG_PAUTH_PLATFORM:
81+
return "Tag_PAuth_Platform";
82+
case TAG_PAUTH_SCHEMA:
83+
return "Tag_PAuth_Schema";
84+
case PAUTHABI_TAG_NOT_FOUND:
85+
default:
86+
return "";
87+
}
88+
}
89+
PauthABITags getPauthABITagsID(StringRef PauthABITag) {
90+
return StringSwitch<PauthABITags>(PauthABITag)
91+
.Case("Tag_PAuth_Platform", TAG_PAUTH_PLATFORM)
92+
.Case("Tag_PAuth_Schema", TAG_PAUTH_SCHEMA)
93+
.Default(PAUTHABI_TAG_NOT_FOUND);
94+
}
95+
96+
StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag) {
97+
switch (FeatureAndBitsTag) {
98+
case TAG_FEATURE_BTI:
99+
return "Tag_Feature_BTI";
100+
case TAG_FEATURE_PAC:
101+
return "Tag_Feature_PAC";
102+
case TAG_FEATURE_GCS:
103+
return "Tag_Feature_GCS";
104+
case FEATURE_AND_BITS_TAG_NOT_FOUND:
105+
default:
106+
return "";
107+
}
108+
}
109+
FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag) {
110+
return StringSwitch<FeatureAndBitsTags>(FeatureAndBitsTag)
111+
.Case("Tag_Feature_BTI", TAG_FEATURE_BTI)
112+
.Case("Tag_Feature_PAC", TAG_FEATURE_PAC)
113+
.Case("Tag_Feature_GCS", TAG_FEATURE_GCS)
114+
.Default(FEATURE_AND_BITS_TAG_NOT_FOUND);
115+
}
116+
} // namespace AArch64BuildAttributes
117+
} // namespace llvm

llvm/lib/Support/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ add_llvm_component_library(LLVMSupport
144144
APInt.cpp
145145
APSInt.cpp
146146
ARMBuildAttrs.cpp
147+
AArch64BuildAttributes.cpp
147148
ARMAttributeParser.cpp
148149
ARMWinEH.cpp
149150
Allocator.cpp

0 commit comments

Comments
 (0)