Skip to content

[readobj][Arm][AArch64] Refactor Build Attributes parsing under ELFAtributeParser and add support for AArch64 Build Attributes #128727

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 18 commits into from
Mar 10, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
12 changes: 6 additions & 6 deletions lld/ELF/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@ mergeAttributesSection(Ctx &ctx,
switch (RISCVAttrs::AttrType(tag.attr)) {
// Integer attributes.
case RISCVAttrs::STACK_ALIGN:
if (auto i = parser.getAttributeValue(tag.attr)) {
if (auto i = parser.getAttributeValue("", tag.attr)) {
auto r = merged.intAttr.try_emplace(tag.attr, *i);
if (r.second) {
firstStackAlign = sec;
Expand All @@ -1188,13 +1188,13 @@ mergeAttributesSection(Ctx &ctx,
}
continue;
case RISCVAttrs::UNALIGNED_ACCESS:
if (auto i = parser.getAttributeValue(tag.attr))
if (auto i = parser.getAttributeValue("", tag.attr))
merged.intAttr[tag.attr] |= *i;
continue;

// String attributes.
case RISCVAttrs::ARCH:
if (auto s = parser.getAttributeString(tag.attr)) {
if (auto s = parser.getAttributeString("", tag.attr)) {
hasArch = true;
mergeArch(ctx, exts, xlen, sec, *s);
}
Expand All @@ -1207,7 +1207,7 @@ mergeAttributesSection(Ctx &ctx,
break;

case RISCVAttrs::AttrType::ATOMIC_ABI:
if (auto i = parser.getAttributeValue(tag.attr)) {
if (auto i = parser.getAttributeValue("", tag.attr)) {
auto r = merged.intAttr.try_emplace(tag.attr, *i);
if (r.second)
firstAtomicAbi = sec;
Expand All @@ -1225,12 +1225,12 @@ mergeAttributesSection(Ctx &ctx,
// TODO Adjust after resolution to
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/352
if (tag.attr % 2 == 0) {
if (auto i = parser.getAttributeValue(tag.attr)) {
if (auto i = parser.getAttributeValue("", tag.attr)) {
auto r = merged.intAttr.try_emplace(tag.attr, *i);
if (!r.second && r.first->second != *i)
r.first->second = 0;
}
} else if (auto s = parser.getAttributeString(tag.attr)) {
} else if (auto s = parser.getAttributeString("", tag.attr)) {
auto r = merged.strAttr.try_emplace(tag.attr, *s);
if (!r.second && r.first->second != *s)
r.first->second = {};
Expand Down
10 changes: 5 additions & 5 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ static ELFKind getELFKind(Ctx &ctx, MemoryBufferRef mb, StringRef archiveName) {
static void updateARMVFPArgs(Ctx &ctx, const ARMAttributeParser &attributes,
const InputFile *f) {
std::optional<unsigned> attr =
attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args);
attributes.getAttributeValue("", ARMBuildAttrs::ABI_VFP_args);
if (!attr)
// If an ABI tag isn't present then it is implicitly given the value of 0
// which maps to ARMBuildAttrs::BaseAAPCS. However many assembler files,
Expand Down Expand Up @@ -155,7 +155,7 @@ static void updateARMVFPArgs(Ctx &ctx, const ARMAttributeParser &attributes,
static void updateSupportedARMFeatures(Ctx &ctx,
const ARMAttributeParser &attributes) {
std::optional<unsigned> attr =
attributes.getAttributeValue(ARMBuildAttrs::CPU_arch);
attributes.getAttributeValue("", ARMBuildAttrs::CPU_arch);
if (!attr)
return;
auto arch = *attr;
Expand Down Expand Up @@ -189,7 +189,7 @@ static void updateSupportedARMFeatures(Ctx &ctx,

// Only ARMv8-M or later architectures have CMSE support.
std::optional<unsigned> profile =
attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile);
attributes.getAttributeValue("", ARMBuildAttrs::CPU_arch_profile);
if (!profile)
return;
if (arch >= ARMBuildAttrs::CPUArch::v8_M_Base &&
Expand All @@ -200,9 +200,9 @@ static void updateSupportedARMFeatures(Ctx &ctx,
// For now, let's limit it to ones where ARM isn't available and we know have
// Thumb2.
std::optional<unsigned> armISA =
attributes.getAttributeValue(ARMBuildAttrs::ARM_ISA_use);
attributes.getAttributeValue("", ARMBuildAttrs::ARM_ISA_use);
std::optional<unsigned> thumb =
attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use);
attributes.getAttributeValue("", ARMBuildAttrs::THUMB_ISA_use);
ctx.arg.armHasArmISA |= armISA && *armISA >= ARMBuildAttrs::Allowed;
ctx.arg.armHasThumb2ISA |= thumb && *thumb >= ARMBuildAttrs::AllowThumb32;
}
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/Object/ELFObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,9 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
case ELF::EM_ARM:
Type = ELF::SHT_ARM_ATTRIBUTES;
break;
case ELF::EM_AARCH64:
Type = ELF::SHT_AARCH64_ATTRIBUTES;
break;
case ELF::EM_RISCV:
Type = ELF::SHT_RISCV_ATTRIBUTES;
break;
Expand Down
29 changes: 29 additions & 0 deletions llvm/include/llvm/Support/AArch64AttributeParser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//=== - AArch64AttributeParser.h-AArch64 Attribute Information Printer - ===//
//
// 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
//
//===--------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_AARCH64ATTRIBUTEPARSER_H
#define LLVM_SUPPORT_AARCH64ATTRIBUTEPARSER_H

#include "llvm/Support/ELFAttrParserExtended.h"
#include "llvm/Support/ELFAttributes.h"

namespace llvm {

class AArch64AttributeParser : public ELFExtendedAttrParser {
static const std::vector<SubsectionAndTagToTagName> returnTagsNamesMap();

public:
AArch64AttributeParser(ScopedPrinter *Sw)
: ELFExtendedAttrParser(Sw, returnTagsNamesMap()) {}
AArch64AttributeParser()
: ELFExtendedAttrParser(nullptr, returnTagsNamesMap()) {}
};

} // namespace llvm

#endif // LLVM_SUPPORT_AARCH64ATTRIBUTEPARSER_H
4 changes: 2 additions & 2 deletions llvm/include/llvm/Support/AArch64BuildAttributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

namespace llvm {

namespace AArch64BuildAttrs {
namespace AArch64BuildAttributes {

/// AArch64 build attributes vendors IDs (a.k.a subsection name)
enum VendorID : unsigned {
Expand Down Expand Up @@ -69,7 +69,7 @@ enum FeatureAndBitsFlag : unsigned {
Feature_PAC_Flag = 1 << 1,
Feature_GCS_Flag = 1 << 2
};
} // namespace AArch64BuildAttrs
} // namespace AArch64BuildAttributes
} // namespace llvm

#endif // LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H
9 changes: 5 additions & 4 deletions llvm/include/llvm/Support/ARMAttributeParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
#define LLVM_SUPPORT_ARMATTRIBUTEPARSER_H

#include "ARMBuildAttributes.h"
#include "ELFAttributeParser.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ELFAttrParserCompact.h"
#include "llvm/Support/Error.h"

namespace llvm {

class ScopedPrinter;

class ARMAttributeParser : public ELFAttributeParser {
class ARMAttributeParser : public ELFCompactAttrParser {
struct DisplayHandler {
ARMBuildAttrs::AttrType attribute;
Error (ARMAttributeParser::*routine)(ARMBuildAttrs::AttrType);
Expand Down Expand Up @@ -74,9 +74,10 @@ class ARMAttributeParser : public ELFAttributeParser {

public:
ARMAttributeParser(ScopedPrinter *sw)
: ELFAttributeParser(sw, ARMBuildAttrs::getARMAttributeTags(), "aeabi") {}
: ELFCompactAttrParser(sw, ARMBuildAttrs::getARMAttributeTags(),
"aeabi") {}
ARMAttributeParser()
: ELFAttributeParser(ARMBuildAttrs::getARMAttributeTags(), "aeabi") {}
: ELFCompactAttrParser(ARMBuildAttrs::getARMAttributeTags(), "aeabi") {}
};
}

Expand Down
8 changes: 4 additions & 4 deletions llvm/include/llvm/Support/CSKYAttributeParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
#define LLVM_SUPPORT_CSKYATTRIBUTEPARSER_H

#include "llvm/Support/CSKYAttributes.h"
#include "llvm/Support/ELFAttributeParser.h"
#include "llvm/Support/ELFAttrParserCompact.h"

namespace llvm {
class CSKYAttributeParser : public ELFAttributeParser {
class CSKYAttributeParser : public ELFCompactAttrParser {
struct DisplayHandler {
CSKYAttrs::AttrType attribute;
Error (CSKYAttributeParser::*routine)(unsigned);
Expand All @@ -33,9 +33,9 @@ class CSKYAttributeParser : public ELFAttributeParser {

public:
CSKYAttributeParser(ScopedPrinter *sw)
: ELFAttributeParser(sw, CSKYAttrs::getCSKYAttributeTags(), "csky") {}
: ELFCompactAttrParser(sw, CSKYAttrs::getCSKYAttributeTags(), "csky") {}
CSKYAttributeParser()
: ELFAttributeParser(CSKYAttrs::getCSKYAttributeTags(), "csky") {}
: ELFCompactAttrParser(CSKYAttrs::getCSKYAttributeTags(), "csky") {}
};

} // namespace llvm
Expand Down
82 changes: 82 additions & 0 deletions llvm/include/llvm/Support/ELFAttrParserCompact.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//===- ELF AttributeParser.h - ELF Attribute Parser -------------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_ELFCOMPACTATTRPARSER_H
#define LLVM_SUPPORT_ELFCOMPACTATTRPARSER_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/ELFAttributeParser.h"
#include "llvm/Support/ELFAttributes.h"
#include "llvm/Support/Error.h"

#include <optional>
#include <unordered_map>

namespace llvm {
class StringRef;
class ScopedPrinter;

class ELFCompactAttrParser : public ELFAttributeParser {
StringRef vendor;
std::unordered_map<unsigned, unsigned> attributes;
std::unordered_map<unsigned, StringRef> attributesStr;

virtual Error handler(uint64_t tag, bool &handled) = 0;

protected:
ScopedPrinter *sw;
TagNameMap tagToStringMap;
DataExtractor de{ArrayRef<uint8_t>{}, true, 0};
DataExtractor::Cursor cursor{0};

void printAttribute(unsigned tag, unsigned value, StringRef valueDesc);

Error parseStringAttribute(const char *name, unsigned tag,
ArrayRef<const char *> strings);
Error parseAttributeList(uint32_t length);
void parseIndexList(SmallVectorImpl<uint8_t> &indexList);
Error parseSubsection(uint32_t length);

void setAttributeString(unsigned tag, StringRef value) {
attributesStr.emplace(tag, value);
}

public:
virtual ~ELFCompactAttrParser() { static_cast<void>(!cursor.takeError()); }
Error integerAttribute(unsigned tag);
Error stringAttribute(unsigned tag);

ELFCompactAttrParser(ScopedPrinter *sw, TagNameMap tagNameMap,
StringRef vendor)
: vendor(vendor), sw(sw), tagToStringMap(tagNameMap) {}
ELFCompactAttrParser(TagNameMap tagNameMap, StringRef vendor)
: vendor(vendor), sw(nullptr), tagToStringMap(tagNameMap) {}

Error parse(ArrayRef<uint8_t> section, llvm::endianness endian) override;

std::optional<unsigned>
getAttributeValue(StringRef buildAttributeSubsectionName,
unsigned tag) const override {
auto I = attributes.find(tag);
if (I == attributes.end())
return std::nullopt;
return I->second;
}
std::optional<StringRef>
getAttributeString(StringRef buildAttributeSubsectionName,
unsigned tag) const override {
auto I = attributesStr.find(tag);
if (I == attributesStr.end())
return std::nullopt;
return I->second;
}
};

} // namespace llvm
#endif // LLVM_SUPPORT_ELFCOMPACTATTRPARSER_H
51 changes: 51 additions & 0 deletions llvm/include/llvm/Support/ELFAttrParserExtended.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//===- ELF AttributeParser.h - ELF Attribute Parser -------------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_ELFEXTENDEDATTRPARSER_H
#define LLVM_SUPPORT_ELFEXTENDEDATTRPARSER_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/ELFAttributeParser.h"
#include "llvm/Support/ELFAttributes.h"
#include "llvm/Support/Error.h"
#include <optional>
#include <vector>

namespace llvm {
class StringRef;
class ScopedPrinter;

class ELFExtendedAttrParser : public ELFAttributeParser {
protected:
ScopedPrinter *Sw;
DataExtractor De{ArrayRef<uint8_t>{}, true, 0};
DataExtractor::Cursor Cursor{0};

// Data structure for holding Extended ELF Build Attribute subsection
SmallVector<BuildAttributeSubSection, 64> SubSectionVec;
// Maps SubsectionName + Tag to tags names. Required for printing comments.
const std::vector<SubsectionAndTagToTagName> TagsNamesMap;
StringRef getTagName(const StringRef &s, const unsigned i);

public:
Error parse(ArrayRef<uint8_t> Section, llvm::endianness Endian) override;

std::optional<unsigned> getAttributeValue(StringRef BuildAttrSubsectionName,
unsigned Tag) const override;
std::optional<StringRef> getAttributeString(StringRef BuildAttrSubsectionName,
unsigned Tag) const override;

ELFExtendedAttrParser(ScopedPrinter *Sw,
std::vector<SubsectionAndTagToTagName> TagsNamesMap)
: Sw(Sw), TagsNamesMap(TagsNamesMap) {}
ELFExtendedAttrParser(std::vector<SubsectionAndTagToTagName> TagsNamesMap)
: Sw(nullptr), TagsNamesMap(TagsNamesMap) {}
};
} // namespace llvm
#endif // LLVM_SUPPORT_ELFEXTENDEDATTRPARSER_H
Loading
Loading