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 all commits
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
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 std::vector<SubsectionAndTagToTagName> &returnTagsNamesMap();

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

} // namespace llvm

#endif // LLVM_SUPPORT_AARCH64ATTRIBUTEPARSER_H
6 changes: 3 additions & 3 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
#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
92 changes: 92 additions & 0 deletions llvm/include/llvm/Support/ELFAttrParserCompact.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//===- 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(unsigned tag) const override {
auto I = attributes.find(tag);
if (I == attributes.end())
return std::nullopt;
return I->second;
}
std::optional<unsigned>
getAttributeValue(StringRef buildAttributeSubsectionName,
unsigned tag) const override {
assert("" == buildAttributeSubsectionName &&
"buildAttributeSubsectionName must be an empty string");
return getAttributeValue(tag);
}
std::optional<StringRef> getAttributeString(unsigned tag) const override {
auto I = attributesStr.find(tag);
if (I == attributesStr.end())
return std::nullopt;
return I->second;
}
std::optional<StringRef>
getAttributeString(StringRef buildAttributeSubsectionName,
unsigned tag) const override {
assert("" == buildAttributeSubsectionName &&
"buildAttributeSubsectionName must be an empty string");
return getAttributeString(tag);
}
};

} // namespace llvm
#endif // LLVM_SUPPORT_ELFCOMPACTATTRPARSER_H
56 changes: 56 additions & 0 deletions llvm/include/llvm/Support/ELFAttrParserExtended.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//===- 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, 8> SubSectionVec;
// Maps SubsectionName + Tag to tags names. Required for printing comments.
const std::vector<SubsectionAndTagToTagName> TagsNamesMap;
StringRef getTagName(const StringRef &BuildAttrSubsectionName,
const unsigned Tag);

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

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

ELFExtendedAttrParser(
ScopedPrinter *Sw,
const std::vector<SubsectionAndTagToTagName> TagsNamesMap)
: Sw(Sw), TagsNamesMap(TagsNamesMap) {}
ELFExtendedAttrParser(
const std::vector<SubsectionAndTagToTagName> TagsNamesMap)
: Sw(nullptr), TagsNamesMap(TagsNamesMap) {}
};
} // namespace llvm
#endif // LLVM_SUPPORT_ELFEXTENDEDATTRPARSER_H
71 changes: 18 additions & 53 deletions llvm/include/llvm/Support/ELFAttributeParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,69 +9,34 @@
#ifndef LLVM_SUPPORT_ELFATTRIBUTEPARSER_H
#define LLVM_SUPPORT_ELFATTRIBUTEPARSER_H

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

#include <optional>
#include <unordered_map>

namespace llvm {
class StringRef;
class ScopedPrinter;

class 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 ~ELFAttributeParser() { static_cast<void>(!cursor.takeError()); }
Error integerAttribute(unsigned tag);
Error stringAttribute(unsigned tag);

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

ELFAttributeParser(TagNameMap tagNameMap, StringRef vendor)
: vendor(vendor), sw(nullptr), tagToStringMap(tagNameMap) {}

Error parse(ArrayRef<uint8_t> section, llvm::endianness endian);
virtual ~ELFAttributeParser() {}

std::optional<unsigned> getAttributeValue(unsigned tag) const {
auto I = attributes.find(tag);
if (I == attributes.end())
return std::nullopt;
return I->second;
virtual Error parse(ArrayRef<uint8_t> Section, llvm::endianness Endian) {
return llvm::Error::success();
}
virtual std::optional<unsigned>
getAttributeValue(StringRef BuildAttrSubsectionName, unsigned Tag) const {
return std::nullopt;
}
virtual std::optional<unsigned> getAttributeValue(unsigned Tag) const {
return std::nullopt;
}
virtual std::optional<StringRef>
getAttributeString(StringRef BuildAttrSubsectionName, unsigned Tag) const {
return std::nullopt;
}
std::optional<StringRef> getAttributeString(unsigned tag) const {
auto I = attributesStr.find(tag);
if (I == attributesStr.end())
return std::nullopt;
return I->second;
virtual std::optional<StringRef> getAttributeString(unsigned Tag) const {
return std::nullopt;
}
};

} // namespace llvm
#endif
#endif // LLVM_SUPPORT_ELFATTRIBUTEPARSER_H
29 changes: 29 additions & 0 deletions llvm/include/llvm/Support/ELFAttributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,42 @@

namespace llvm {

// Tag to string: ELF compact build attribute section
struct TagNameItem {
unsigned attr;
StringRef tagName;
};

using TagNameMap = ArrayRef<TagNameItem>;

// Build Attribute storage for ELF extended attribute section
struct BuildAttributeItem {
enum Types : uint8_t {
NumericAttribute = 0,
TextAttribute,
} Type;
unsigned Tag;
unsigned IntValue;
std::string StringValue;
BuildAttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV)
: Type(Ty), Tag(Tg), IntValue(IV), StringValue(std::move(SV)) {}
};
struct BuildAttributeSubSection {
StringRef Name;
unsigned IsOptional;
unsigned ParameterType;
SmallVector<BuildAttributeItem, 64> Content;
};

// Tag to string: ELF extended build attribute section
struct SubsectionAndTagToTagName {
StringRef SubsectionName;
unsigned Tag;
StringRef TagName;
SubsectionAndTagToTagName(StringRef SN, unsigned Tg, StringRef TN)
: SubsectionName(SN), Tag(Tg), TagName(TN) {}
};

namespace ELFAttrs {

enum AttrType : unsigned { File = 1, Section = 2, Symbol = 3 };
Expand Down
Loading