Skip to content

Commit a10af46

Browse files
committed
[LLVM][Clang][AArch64] Implement AArch64 build attributes
- Added support for AArch64-specific build attributes. - Print AArch64 build attributes to assembly. - Emit AArch64 build attributes to ELF. Specification: https://github.com/ARM-software/abi-aa/blob/654a64cbac041fc3bff617800998d40b5068f592/buildattr64/buildattr64.rst#aeabi-feature-and-bits-subsection
1 parent 5d38a34 commit a10af46

File tree

11 files changed

+472
-98
lines changed

11 files changed

+472
-98
lines changed

llvm/include/llvm/BinaryFormat/ELF.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,8 @@ enum : unsigned {
11501150
SHT_ARM_ATTRIBUTES = 0x70000003U,
11511151
SHT_ARM_DEBUGOVERLAY = 0x70000004U,
11521152
SHT_ARM_OVERLAYSECTION = 0x70000005U,
1153+
// Support for AArch64 build attributes
1154+
SHT_AARCH64_ATTRIBUTES = 0x70000003U,
11531155
// Special aarch64-specific section for MTE support, as described in:
11541156
// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#section-types
11551157
SHT_AARCH64_AUTH_RELR = 0x70000004U,

llvm/include/llvm/MC/MCELFStreamer.h

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_MC_MCELFSTREAMER_H
1111

1212
#include "llvm/ADT/SmallVector.h"
13+
#include "llvm/ADT/StringRef.h"
1314
#include "llvm/MC/MCDirectives.h"
1415
#include "llvm/MC/MCObjectStreamer.h"
1516

@@ -107,25 +108,41 @@ class MCELFStreamer : public MCObjectStreamer {
107108
std::string StringValue;
108109
};
109110

111+
/// ELF object attributes subsection support
112+
struct AttributeSubSection {
113+
// [<uint32: subsection-length> NTBS: vendor-name <bytes: vendor-data>]*
114+
StringRef Vendor;
115+
// <uint8: optional> <uint8: parameter type> <attribute>*
116+
unsigned IsMandatory; // SubsectionMandatory::REQUIRED (0), SubsectionMandatory::OPTIONAL (1)
117+
unsigned ParameterType; // SubsectionType::ULEB128 (0), SubsectionType::NTBS (1)
118+
SmallVector<AttributeItem, 64> Content;
119+
};
120+
110121
// Attributes that are added and managed entirely by target.
111122
SmallVector<AttributeItem, 64> Contents;
112123
void setAttributeItem(unsigned Attribute, unsigned Value,
113-
bool OverwriteExisting);
124+
bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes);
114125
void setAttributeItem(unsigned Attribute, StringRef Value,
115-
bool OverwriteExisting);
126+
bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes);
116127
void setAttributeItems(unsigned Attribute, unsigned IntValue,
117-
StringRef StringValue, bool OverwriteExisting);
128+
StringRef StringValue, bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes);
118129
void emitAttributesSection(StringRef Vendor, const Twine &Section,
119130
unsigned Type, MCSection *&AttributeSection) {
120131
createAttributesSection(Vendor, Section, Type, AttributeSection, Contents);
121132
}
133+
void emitAttributesSection(MCSection *&AttributeSection,
134+
const Twine &Section, unsigned Type, SmallVector<AttributeSubSection, 64> &SubSectionVec) {
135+
createAttributesSection(AttributeSection, Section, Type, SubSectionVec);
136+
}
122137

123138
private:
124-
AttributeItem *getAttributeItem(unsigned Attribute);
125-
size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec);
139+
AttributeItem *getAttributeItem(unsigned Attribute, SmallVector<AttributeItem, 64> &Attributes);
140+
size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) const;
126141
void createAttributesSection(StringRef Vendor, const Twine &Section,
127142
unsigned Type, MCSection *&AttributeSection,
128143
SmallVector<AttributeItem, 64> &AttrsVec);
144+
void createAttributesSection(MCSection *&AttributeSection, const Twine & Section,
145+
unsigned Type, SmallVector<AttributeSubSection, 64> &SubSectionVec);
129146

130147
// GNU attributes that will get emitted at the end of the asm file.
131148
SmallVector<AttributeItem, 64> GNUAttributes;

llvm/include/llvm/Support/ARMBuildAttributes.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,58 @@
2121
#include "llvm/Support/ELFAttributes.h"
2222

2323
namespace llvm {
24+
class StringRef;
25+
2426
namespace ARMBuildAttrs {
2527

2628
const TagNameMap &getARMAttributeTags();
2729

30+
/// AArch64 build attributes vendors (=subsection name)
31+
enum Vendor : unsigned {
32+
AEBI_FEATURE_AND_BITS = 0,
33+
AEBI_PAUTHABI = 1
34+
};
35+
36+
inline StringRef vendorToStr(unsigned Vendor) {
37+
switch(Vendor) {
38+
default:
39+
llvm_unreachable("unknown AArch64 vendor name");
40+
return "";
41+
case AEBI_FEATURE_AND_BITS:
42+
return "aeabi-feature-and-bits";
43+
case AEBI_PAUTHABI:
44+
return "aeabi-pauthabi";
45+
}
46+
}
47+
48+
enum SubsectionMandatory : unsigned {
49+
OPTIONAL = 0,
50+
REQUIRED = 1
51+
};
52+
53+
enum SubsectionType : unsigned {
54+
ULEB128 = 0,
55+
NTBS = 1
56+
};
57+
58+
enum FeatureAndBitsTags : unsigned {
59+
Tag_PAuth_Platform = 1,
60+
Tag_PAuth_Schema = 2
61+
};
62+
63+
enum PauthabiTags : unsigned {
64+
Tag_Feature_BTI = 0,
65+
Tag_Feature_PAC = 1,
66+
Tag_Feature_GCS = 2
67+
};
68+
69+
enum PauthabiTagsFlag : unsigned {
70+
Feature_BTI_Flag = 1 << 0,
71+
Feature_PAC_Flag = 1 << 1,
72+
Feature_GCS_Flag = 1 << 2
73+
};
74+
/// ---
75+
2876
enum SpecialAttr {
2977
// This is for the .cpu asm attr. It translates into one or more
3078
// AttrType (below) entries in the .ARM.attributes section in the ELF.
@@ -88,6 +136,21 @@ enum AttrType : unsigned {
88136
MPextension_use_old = 70 // recoded to MPextension_use (ABI r2.08)
89137
};
90138

139+
enum AVAttr {
140+
AV_cpp_exceptions = 6,
141+
AV_eba = 16
142+
};
143+
144+
StringRef AttrTypeAsString(StringRef Vendor, unsigned Attr, bool HasTagPrefix = true);
145+
StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true);
146+
StringRef AttrTypeAsString(AVAttr Attr, bool HasTagPrefix = true);
147+
int AttrTypeFromString(StringRef Vendor, StringRef Tag);
148+
149+
// Magic numbers for .ARM.attributes
150+
enum AttrMagic {
151+
Format_Version = 0x41
152+
};
153+
91154
// Legal Values for CPU_arch, (=6), uleb128
92155
enum CPUArch {
93156
Pre_v4 = 0,

llvm/lib/MC/MCELFStreamer.cpp

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -636,9 +636,9 @@ void MCELFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
636636
}
637637

638638
void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
639-
bool OverwriteExisting) {
639+
bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
640640
// Look for existing attribute item
641-
if (AttributeItem *Item = getAttributeItem(Attribute)) {
641+
if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
642642
if (!OverwriteExisting)
643643
return;
644644
Item->Type = AttributeItem::NumericAttribute;
@@ -653,9 +653,9 @@ void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
653653
}
654654

655655
void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
656-
bool OverwriteExisting) {
656+
bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
657657
// Look for existing attribute item
658-
if (AttributeItem *Item = getAttributeItem(Attribute)) {
658+
if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
659659
if (!OverwriteExisting)
660660
return;
661661
Item->Type = AttributeItem::TextAttribute;
@@ -671,9 +671,9 @@ void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
671671

672672
void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
673673
StringRef StringValue,
674-
bool OverwriteExisting) {
674+
bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
675675
// Look for existing attribute item
676-
if (AttributeItem *Item = getAttributeItem(Attribute)) {
676+
if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
677677
if (!OverwriteExisting)
678678
return;
679679
Item->Type = AttributeItem::NumericAndTextAttributes;
@@ -689,15 +689,15 @@ void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
689689
}
690690

691691
MCELFStreamer::AttributeItem *
692-
MCELFStreamer::getAttributeItem(unsigned Attribute) {
693-
for (AttributeItem &Item : Contents)
692+
MCELFStreamer::getAttributeItem(unsigned Attribute, SmallVector<AttributeItem, 64> &Attributes) {
693+
for (AttributeItem &Item : Attributes)
694694
if (Item.Tag == Attribute)
695695
return &Item;
696696
return nullptr;
697697
}
698698

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

786+
void MCELFStreamer::createAttributesSection(MCSection *&AttributeSection,
787+
const Twine &Section, unsigned Type, SmallVector<AttributeSubSection, 64> &SubSectionVec) {
788+
// <format-version: 'A'>
789+
// [ <uint32: subsection-length> NTBS: vendor-name
790+
// <bytes: vendor-data>
791+
// ]*
792+
// vendor-data expends to:
793+
// <uint8: optional> <uint8: parameter type> <attribute>*
794+
if (SubSectionVec.size() == 0) {
795+
return;
796+
}
797+
798+
// Switch section to AttributeSection or get/create the section.
799+
if (AttributeSection) {
800+
switchSection(AttributeSection);
801+
} else {
802+
AttributeSection = getContext().getELFSection(Section, Type, 0);
803+
switchSection(AttributeSection);
804+
805+
// Format version
806+
emitInt8(0x41);
807+
}
808+
809+
for (AttributeSubSection &SubSection : SubSectionVec) {
810+
// subsection-length + vendor-name + '\0'
811+
const size_t VendorHeaderSize = 4 + SubSection.Vendor.size() + 1;
812+
// optional + parameter-type
813+
const size_t VendorParameters = 1 + 1;
814+
const size_t ContentsSize = calculateContentSize(SubSection.Content);
815+
816+
emitInt32(VendorHeaderSize + VendorParameters + ContentsSize);
817+
emitBytes(SubSection.Vendor);
818+
emitInt8(SubSection.IsMandatory);
819+
emitInt8(SubSection.ParameterType);
820+
821+
for (AttributeItem &Item : SubSection.Content) {
822+
emitULEB128IntValue(Item.Tag);
823+
switch (Item.Type) {
824+
default:
825+
llvm_unreachable("Invalid attribute type");
826+
case AttributeItem::NumericAttribute:
827+
emitULEB128IntValue(Item.IntValue);
828+
break;
829+
case AttributeItem::TextAttribute:
830+
emitBytes(Item.StringValue);
831+
emitInt8(0); // '\0'
832+
break;
833+
case AttributeItem::NumericAndTextAttributes:
834+
emitULEB128IntValue(Item.IntValue);
835+
emitBytes(Item.StringValue);
836+
emitInt8(0); // '\0'
837+
break;
838+
}
839+
}
840+
}
841+
SubSectionVec.clear();
842+
}
843+
786844
MCStreamer *llvm::createELFStreamer(MCContext &Context,
787845
std::unique_ptr<MCAsmBackend> &&MAB,
788846
std::unique_ptr<MCObjectWriter> &&OW,

llvm/lib/Support/ARMBuildAttrs.cpp

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "llvm/ADT/StringRef.h"
910
#include "llvm/Support/ARMBuildAttributes.h"
1011

1112
using namespace llvm;
1213

13-
static const TagNameItem tagData[] = {
14+
namespace {
15+
const TagNameItem ARMAttributeTags[] = {
1416
{ARMBuildAttrs::File, "Tag_File"},
1517
{ARMBuildAttrs::Section, "Tag_Section"},
1618
{ARMBuildAttrs::Symbol, "Tag_Symbol"},
@@ -67,7 +69,56 @@ static const TagNameItem tagData[] = {
6769
{ARMBuildAttrs::ABI_align_preserved, "Tag_ABI_align8_preserved"},
6870
};
6971

70-
constexpr TagNameMap ARMAttributeTags{tagData};
71-
const TagNameMap &llvm::ARMBuildAttrs::getARMAttributeTags() {
72-
return ARMAttributeTags;
72+
const TagNameItem AVAttributeTags[] = {
73+
{ ARMBuildAttrs::AV_cpp_exceptions, "Tag_AV_cpp_exceptions" },
74+
{ ARMBuildAttrs::AV_eba, "Tag_AV_eba" },
75+
};
76+
77+
template<typename T, size_t N> int FromString(T (&Table)[N], StringRef Tag) {
78+
bool HasTagPrefix = Tag.starts_with("Tag_");
79+
for (unsigned TI = 0; TI < N; ++TI)
80+
if (Table[TI].tagName.drop_front(HasTagPrefix ? 0 : 4) == Tag)
81+
return Table[TI].attr;
82+
return -1;
83+
}
84+
85+
template<typename T, size_t N, typename A>
86+
StringRef AsString(T (&Table)[N], A Attr, bool HasTagPrefix) {
87+
for (unsigned TI = 0; TI < N; ++TI)
88+
if (Table[TI].attr == Attr)
89+
return Table[TI].tagName.drop_front(HasTagPrefix ? 0 : 4);
90+
return StringRef();
91+
}
92+
}
93+
94+
namespace llvm {
95+
namespace ARMBuildAttrs {
96+
StringRef AttrTypeAsString(StringRef Vendor, unsigned Attr, bool HasTagPrefix) {
97+
if (Vendor.equals_insensitive("aeabi") || Vendor.equals_insensitive("eabi"))
98+
return AsString(ARMAttributeTags, static_cast<AttrType>(Attr),
99+
HasTagPrefix);
100+
else if (Vendor.equals_insensitive("arm"))
101+
return AsString(AVAttributeTags, static_cast<AVAttr>(Attr), HasTagPrefix);
102+
return StringRef();
103+
}
104+
105+
StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix) {
106+
return AsString(ARMAttributeTags, static_cast<AttrType>(Attr), HasTagPrefix);
107+
}
108+
109+
StringRef AttrTypeAsString(AVAttr Attr, bool HasTagPrefix) {
110+
return AsString(AVAttributeTags, static_cast<AVAttr>(Attr), HasTagPrefix);
111+
}
112+
113+
int AttrTypeFromString(StringRef Vendor, StringRef Tag) {
114+
if (Vendor.equals_insensitive("aeabi") || Vendor.equals_insensitive("eabi"))
115+
return FromString(ARMAttributeTags, Tag);
116+
else if (Vendor.equals_insensitive("arm"))
117+
return FromString(AVAttributeTags, Tag);
118+
return -1;
119+
}
120+
121+
static constexpr TagNameMap tagNameMap(ARMAttributeTags);
122+
const TagNameMap &getARMAttributeTags() { return tagNameMap; }
123+
}
73124
}

0 commit comments

Comments
 (0)