Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 @@ -1150,6 +1150,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
37 changes: 32 additions & 5 deletions llvm/include/llvm/MC/MCELFStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLVM_MC_MCELFSTREAMER_H

#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCObjectStreamer.h"

Expand Down Expand Up @@ -107,25 +108,51 @@ class MCELFStreamer : public MCObjectStreamer {
std::string StringValue;
};

/// ELF object attributes subsection support
struct AttributeSubSection {
// [<uint32: subsection-length> NTBS: vendor-name <bytes: vendor-data>]*
StringRef Vendor;
// <uint8: optional> <uint8: parameter type> <attribute>*
unsigned IsMandatory; // SubsectionMandatory::REQUIRED (0),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have added enums for these in ARMBuildAttributes.h, should they be used here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is a good idea.
Changing the relevant locations.

// SubsectionMandatory::OPTIONAL (1)
unsigned
ParameterType; // SubsectionType::ULEB128 (0), SubsectionType::NTBS (1)
SmallVector<AttributeItem, 64> Content;
};

// Attributes that are added and managed entirely by target.
SmallVector<AttributeItem, 64> Contents;
void setAttributeItem(unsigned Attribute, unsigned Value,
bool OverwriteExisting);
bool OverwriteExisting,
SmallVector<AttributeItem, 64> &Attributes);
void setAttributeItem(unsigned Attribute, StringRef Value,
bool OverwriteExisting);
bool OverwriteExisting,
SmallVector<AttributeItem, 64> &Attributes);
void setAttributeItems(unsigned Attribute, unsigned IntValue,
StringRef StringValue, bool OverwriteExisting);
StringRef StringValue, bool OverwriteExisting,
SmallVector<AttributeItem, 64> &Attributes);
void emitAttributesSection(StringRef Vendor, const Twine &Section,
unsigned Type, MCSection *&AttributeSection) {
createAttributesSection(Vendor, Section, Type, AttributeSection, Contents);
}
void
emitAttributesSection(MCSection *&AttributeSection, const Twine &Section,
unsigned Type,
SmallVector<AttributeSubSection, 64> &SubSectionVec) {
createAttributesSection(AttributeSection, Section, Type, SubSectionVec);
}

private:
AttributeItem *getAttributeItem(unsigned Attribute);
size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec);
AttributeItem *getAttributeItem(unsigned Attribute,
SmallVector<AttributeItem, 64> &Attributes);
size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) const;
void createAttributesSection(StringRef Vendor, const Twine &Section,
unsigned Type, MCSection *&AttributeSection,
SmallVector<AttributeItem, 64> &AttrsVec);
void
createAttributesSection(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
50 changes: 50 additions & 0 deletions llvm/include/llvm/Support/ARMBuildAttributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,49 @@
#include "llvm/Support/ELFAttributes.h"

namespace llvm {
class StringRef;

namespace ARMBuildAttrs {

const TagNameMap &getARMAttributeTags();

/// AArch64 build attributes vendors (=subsection name)
enum Vendor : unsigned { AEBI_FEATURE_AND_BITS = 0, AEBI_PAUTHABI = 1 };
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/AEBI/AEABI/


inline StringRef vendorToStr(unsigned Vendor) {
switch (Vendor) {
default:
llvm_unreachable("unknown AArch64 vendor name");
return "";
case AEBI_FEATURE_AND_BITS:
return "aeabi-feature-and-bits";
case AEBI_PAUTHABI:
return "aeabi-pauthabi";
}
}

enum SubsectionMandatory : unsigned { OPTIONAL = 0, REQUIRED = 1 };

enum SubsectionType : unsigned { ULEB128 = 0, NTBS = 1 };

enum FeatureAndBitsTags : unsigned {
Tag_PAuth_Platform = 1,
Tag_PAuth_Schema = 2
};

enum PauthabiTags : unsigned {
Tag_Feature_BTI = 0,
Tag_Feature_PAC = 1,
Tag_Feature_GCS = 2
};

enum PauthabiTagsFlag : unsigned {
Feature_BTI_Flag = 1 << 0,
Feature_PAC_Flag = 1 << 1,
Feature_GCS_Flag = 1 << 2
};
/// ---

enum SpecialAttr {
// This is for the .cpu asm attr. It translates into one or more
// AttrType (below) entries in the .ARM.attributes section in the ELF.
Expand Down Expand Up @@ -88,6 +127,17 @@ enum AttrType : unsigned {
MPextension_use_old = 70 // recoded to MPextension_use (ABI r2.08)
};

enum AVAttr { AV_cpp_exceptions = 6, AV_eba = 16 };

StringRef AttrTypeAsString(StringRef Vendor, unsigned Attr,
bool HasTagPrefix = true);
StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true);
StringRef AttrTypeAsString(AVAttr Attr, bool HasTagPrefix = true);
int AttrTypeFromString(StringRef Vendor, StringRef Tag);

// Magic numbers for .ARM.attributes
enum AttrMagic { Format_Version = 0x41 };

// Legal Values for CPU_arch, (=6), uleb128
enum CPUArch {
Pre_v4 = 0,
Expand Down
90 changes: 76 additions & 14 deletions llvm/lib/MC/MCELFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,10 +635,11 @@ void MCELFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
llvm_unreachable("ELF doesn't support this directive");
}

void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
bool OverwriteExisting) {
void MCELFStreamer::setAttributeItem(
unsigned Attribute, unsigned Value, bool OverwriteExisting,
SmallVector<AttributeItem, 64> &Attributes) {
// Look for existing attribute item
if (AttributeItem *Item = getAttributeItem(Attribute)) {
if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
if (!OverwriteExisting)
return;
Item->Type = AttributeItem::NumericAttribute;
Expand All @@ -652,10 +653,11 @@ void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
Contents.push_back(Item);
}

void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
bool OverwriteExisting) {
void MCELFStreamer::setAttributeItem(
unsigned Attribute, StringRef Value, bool OverwriteExisting,
SmallVector<AttributeItem, 64> &Attributes) {
// Look for existing attribute item
if (AttributeItem *Item = getAttributeItem(Attribute)) {
if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
if (!OverwriteExisting)
return;
Item->Type = AttributeItem::TextAttribute;
Expand All @@ -669,11 +671,11 @@ void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
Contents.push_back(Item);
}

void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
StringRef StringValue,
bool OverwriteExisting) {
void MCELFStreamer::setAttributeItems(
unsigned Attribute, unsigned IntValue, StringRef StringValue,
bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
// Look for existing attribute item
if (AttributeItem *Item = getAttributeItem(Attribute)) {
if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
if (!OverwriteExisting)
return;
Item->Type = AttributeItem::NumericAndTextAttributes;
Expand All @@ -689,15 +691,16 @@ void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
}

MCELFStreamer::AttributeItem *
MCELFStreamer::getAttributeItem(unsigned Attribute) {
for (AttributeItem &Item : Contents)
MCELFStreamer::getAttributeItem(unsigned Attribute,
SmallVector<AttributeItem, 64> &Attributes) {
for (AttributeItem &Item : Attributes)
if (Item.Tag == Attribute)
return &Item;
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 +786,65 @@ void MCELFStreamer::createAttributesSection(
AttrsVec.clear();
}

void MCELFStreamer::createAttributesSection(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I've understood correctly, AArch64 uses a slightly different format to AArch32, RISC-V and Hexagon, so the function names should probably make this clear, instead of using overloading to select between the two formats.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it has to be the functions names, or could it be explained in comments?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a different name would be better, since the behaviour is different in a way which isn't really related to the argument types.

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 (SubSectionVec.size() == 0) {
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.Vendor.size() + 1;
// optional + parameter-type
const size_t VendorParameters = 1 + 1;
const size_t ContentsSize = calculateContentSize(SubSection.Content);

emitInt32(VendorHeaderSize + VendorParameters + ContentsSize);
emitBytes(SubSection.Vendor);
emitInt8(SubSection.IsMandatory);
emitInt8(SubSection.ParameterType);

for (AttributeItem &Item : SubSection.Content) {
emitULEB128IntValue(Item.Tag);
switch (Item.Type) {
default:
llvm_unreachable("Invalid attribute type");
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
59 changes: 55 additions & 4 deletions llvm/lib/Support/ARMBuildAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ARMBuildAttributes.h"

using namespace llvm;

static const TagNameItem tagData[] = {
namespace {
const TagNameItem ARMAttributeTags[] = {
{ARMBuildAttrs::File, "Tag_File"},
{ARMBuildAttrs::Section, "Tag_Section"},
{ARMBuildAttrs::Symbol, "Tag_Symbol"},
Expand Down Expand Up @@ -67,7 +69,56 @@ static const TagNameItem tagData[] = {
{ARMBuildAttrs::ABI_align_preserved, "Tag_ABI_align8_preserved"},
};

constexpr TagNameMap ARMAttributeTags{tagData};
const TagNameMap &llvm::ARMBuildAttrs::getARMAttributeTags() {
return ARMAttributeTags;
const TagNameItem AVAttributeTags[] = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are downstream changes we have to work with armlink, and shouldn't be included here.

{ARMBuildAttrs::AV_cpp_exceptions, "Tag_AV_cpp_exceptions"},
{ARMBuildAttrs::AV_eba, "Tag_AV_eba"},
};

template <typename T, size_t N> int FromString(T (&Table)[N], StringRef Tag) {
bool HasTagPrefix = Tag.starts_with("Tag_");
for (unsigned TI = 0; TI < N; ++TI)
if (Table[TI].tagName.drop_front(HasTagPrefix ? 0 : 4) == Tag)
return Table[TI].attr;
return -1;
}

template <typename T, size_t N, typename A>
StringRef AsString(T (&Table)[N], A Attr, bool HasTagPrefix) {
for (unsigned TI = 0; TI < N; ++TI)
if (Table[TI].attr == Attr)
return Table[TI].tagName.drop_front(HasTagPrefix ? 0 : 4);
return StringRef();
}
} // namespace

namespace llvm {
namespace ARMBuildAttrs {
StringRef AttrTypeAsString(StringRef Vendor, unsigned Attr, bool HasTagPrefix) {
if (Vendor.equals_insensitive("aeabi") || Vendor.equals_insensitive("eabi"))
return AsString(ARMAttributeTags, static_cast<AttrType>(Attr),
HasTagPrefix);
else if (Vendor.equals_insensitive("arm"))
return AsString(AVAttributeTags, static_cast<AVAttr>(Attr), HasTagPrefix);
return StringRef();
}

StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix) {
return AsString(ARMAttributeTags, static_cast<AttrType>(Attr), HasTagPrefix);
}

StringRef AttrTypeAsString(AVAttr Attr, bool HasTagPrefix) {
return AsString(AVAttributeTags, static_cast<AVAttr>(Attr), HasTagPrefix);
}

int AttrTypeFromString(StringRef Vendor, StringRef Tag) {
if (Vendor.equals_insensitive("aeabi") || Vendor.equals_insensitive("eabi"))
return FromString(ARMAttributeTags, Tag);
else if (Vendor.equals_insensitive("arm"))
return FromString(AVAttributeTags, Tag);
return -1;
}

static constexpr TagNameMap tagNameMap(ARMAttributeTags);
const TagNameMap &getARMAttributeTags() { return tagNameMap; }
} // namespace ARMBuildAttrs
} // namespace llvm
Loading
Loading