[llvm] [ELFYAML] Introduce `CustomRawContent` (PR #115707)
NAKAMURA Takumi via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 14 05:14:41 PST 2024
https://github.com/chapuni updated https://github.com/llvm/llvm-project/pull/115707
>From b8eb9d3761e4c9dccdd3a990d7f81ca5e3fb0bfd Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 11 Nov 2024 19:04:40 +0900
Subject: [PATCH 1/7] [ELFYAML] Introduce `CustomRawContent`
---
llvm/include/llvm/ObjectYAML/ELFYAML.h | 70 +++++++++++++++++++++++++-
llvm/include/llvm/Support/YAMLTraits.h | 17 +++++++
llvm/lib/ObjectYAML/ELFEmitter.cpp | 16 +++++-
llvm/lib/ObjectYAML/ELFYAML.cpp | 24 ++++++++-
llvm/lib/Support/YAMLTraits.cpp | 8 +++
llvm/tools/obj2yaml/elf2yaml.cpp | 63 +++++++++++++++++++++++
llvm/tools/yaml2obj/yaml2obj.cpp | 16 ++++++
7 files changed, 211 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 8f045d6383623b..ee8ca11aa2ee62 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -211,6 +211,7 @@ struct Chunk {
Dynamic,
Group,
RawContent,
+ CustomRawContent,
Relocation,
Relr,
NoBits,
@@ -388,7 +389,7 @@ struct DynamicSection : Section {
struct RawContentSection : Section {
std::optional<llvm::yaml::Hex64> Info;
- RawContentSection() : Section(ChunkKind::RawContent) {}
+ RawContentSection(ChunkKind Kind = ChunkKind::RawContent) : Section(Kind) {}
static bool classof(const Chunk *S) {
return S->Kind == ChunkKind::RawContent;
@@ -398,6 +399,29 @@ struct RawContentSection : Section {
std::optional<std::vector<uint8_t>> ContentBuf;
};
+/// Abstract base class for non-blob contents.
+struct CustomRawContentSection : RawContentSection {
+ CustomRawContentSection() : RawContentSection(ChunkKind::CustomRawContent) {
+ // Type assumes PROGBITS.
+ Type = ELF::SHT_PROGBITS;
+ Flags = ELF::SHF_GNU_RETAIN;
+ AddressAlign = 1;
+ }
+
+ /// Apply mappings.
+ virtual void sectionMapping(yaml::IO &IO) = 0;
+
+ /// Decode Content and store to members.
+ virtual Error decode(const ArrayRef<uint8_t> Content, bool isLE) = 0;
+
+ /// Encode members and returns Content.
+ virtual std::string encode() const = 0;
+
+ static bool classof(const Chunk *S) {
+ return S->Kind == ChunkKind::CustomRawContent;
+ }
+};
+
struct NoBitsSection : Section {
NoBitsSection() : Section(ChunkKind::NoBits) {}
@@ -757,6 +781,50 @@ struct Object {
bool shouldAllocateFileSpace(ArrayRef<ProgramHeader> Phdrs,
const NoBitsSection &S);
+/// ELFYAML::Opt -- Abstract base class for ELFYAML to provide
+/// the interface for handling CustomRawConetentSection.
+///
+/// Users in ELFYAML should obtain the pointer with
+/// dyn_cast<ELFYAML::Opt> if IO::Opt is the instance from yaml::Opt.
+///
+/// if (auto *Opt = dyn_cast<ELFYAML::Opt>(IO.Opt))
+///
+/// Derivered classes should not modify OptClassID to ensue that
+/// dyn_cast<ELFYAML::Opt> can find this interface.
+class Opt : public yaml::Opt {
+public:
+ Opt() {
+ OptClassID = &ID;
+ ELFOptClassID = &ID;
+ }
+ ~Opt();
+
+ /// Create an empty new object of CustomRawContentSection.
+ /// Its contents will be filled later.
+ /// This is called:
+ /// - Before preMapping for elf2yaml.
+ /// - After preMapping for yaml2elf.
+ virtual std::unique_ptr<CustomRawContentSection>
+ makeCustomRawContentSection(StringRef Name) const = 0;
+
+ /// Called before mapping sections for prettyprinting yaml.
+ virtual void preMapping(const ELFYAML::Object &Object, bool IsOutputting) = 0;
+
+ /// Called after mapping sections to gather members for the file format.
+ virtual void postMapping(const ELFYAML::Object &Object,
+ bool IsOutputting) = 0;
+
+ /// Tell IO::Opt to be this and derivered classes.
+ static bool classof(const yaml::Opt *Obj) { return (Obj->OptClassID == &ID); }
+
+ /// This will be not needed unless the pointer to ELFYAML::Opt would
+ /// be cast further.
+ static bool classof(const Opt *Obj) { return (Obj->ELFOptClassID == &ID); }
+ const char *ELFOptClassID;
+
+private:
+ static const char ID;
+};
} // end namespace ELFYAML
} // end namespace llvm
diff --git a/llvm/include/llvm/Support/YAMLTraits.h b/llvm/include/llvm/Support/YAMLTraits.h
index 1d04783753d5cd..1f1e06a9e37735 100644
--- a/llvm/include/llvm/Support/YAMLTraits.h
+++ b/llvm/include/llvm/Support/YAMLTraits.h
@@ -39,6 +39,18 @@ class VersionTuple;
namespace yaml {
+/// The base class of options.
+class Opt {
+public:
+ virtual ~Opt();
+
+ static bool classof(const Opt *Obj) { return (Obj->OptClassID == &ID); }
+ const char *OptClassID = &ID;
+
+private:
+ static const char ID;
+};
+
enum class NodeKind : uint8_t {
Scalar,
Map,
@@ -964,6 +976,11 @@ class IO {
private:
void *Ctxt;
+ Opt DefaultOpt;
+
+public:
+ /// This may be overwritten in derivered classes.
+ Opt *Opt = &DefaultOpt;
};
namespace detail {
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index fc234581a45a70..09a540b0485176 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -251,6 +251,9 @@ template <class ELFT> class ELFState {
void writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::NoBitsSection &Section,
ContiguousBlobAccumulator &CBA);
+ void writeSectionContent(Elf_Shdr &SHeader,
+ const ELFYAML::CustomRawContentSection &Section,
+ ContiguousBlobAccumulator &CBA);
void writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::RawContentSection &Section,
ContiguousBlobAccumulator &CBA);
@@ -859,7 +862,9 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
if (!isa<ELFYAML::NoBitsSection>(Sec) && (Sec->Content || Sec->Size))
SHeader.sh_size = writeContent(CBA, Sec->Content, Sec->Size);
- if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
+ if (auto S = dyn_cast<ELFYAML::CustomRawContentSection>(Sec)) {
+ writeSectionContent(SHeader, *S, CBA);
+ } else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
writeSectionContent(SHeader, *S, CBA);
} else if (auto S = dyn_cast<ELFYAML::SymtabShndxSection>(Sec)) {
writeSectionContent(SHeader, *S, CBA);
@@ -1264,6 +1269,15 @@ void ELFState<ELFT>::writeSectionContent(
SHeader.sh_info = *Section.Info;
}
+template <class ELFT>
+void ELFState<ELFT>::writeSectionContent(
+ Elf_Shdr &SHeader, const ELFYAML::CustomRawContentSection &Section,
+ ContiguousBlobAccumulator &CBA) {
+ std::string Storage = Section.encode();
+ SHeader.sh_size = Storage.size();
+ CBA.write(Storage.data(), Storage.size());
+}
+
static bool isMips64EL(const ELFYAML::Object &Obj) {
return Obj.getMachine() == llvm::ELF::EM_MIPS &&
Obj.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) &&
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 89ffc383a4a6ec..7d06c2c32e23b8 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -29,6 +29,9 @@ namespace llvm {
ELFYAML::Chunk::~Chunk() = default;
+ELFYAML::Opt::~Opt() = default;
+const char ELFYAML::Opt::ID = 'E';
+
namespace ELFYAML {
ELF_ELFOSABI Object::getOSAbi() const { return Header.OSABI; }
@@ -1582,6 +1585,19 @@ static bool isInteger(StringRef Val) {
void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
IO &IO, std::unique_ptr<ELFYAML::Chunk> &Section) {
+ if (!IO.outputting()) {
+ /// Prepare CustomRawContentSection by Name for ELFEmitter.
+ if (auto *Opt = dyn_cast<ELFYAML::Opt>(IO.Opt)) {
+ StringRef Name;
+ IO.mapOptional("Name", Name);
+ if (auto S = Opt->makeCustomRawContentSection(Name)) {
+ S->sectionMapping(IO);
+ Section = std::move(S);
+ return;
+ }
+ }
+ }
+
ELFYAML::ELF_SHT Type;
StringRef TypeStr;
if (IO.outputting()) {
@@ -1731,7 +1747,9 @@ void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
Section = std::make_unique<ELFYAML::RawContentSection>();
}
- if (auto S = dyn_cast<ELFYAML::RawContentSection>(Section.get()))
+ if (auto S = dyn_cast<ELFYAML::CustomRawContentSection>(Section.get()))
+ S->sectionMapping(IO);
+ else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Section.get()))
sectionMapping(IO, *S);
else
sectionMapping(IO, *cast<ELFYAML::StackSizesSection>(Section.get()));
@@ -1981,6 +1999,8 @@ void MappingTraits<ELFYAML::ARMIndexTableEntry>::mapping(
void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
assert(!IO.getContext() && "The IO context is initialized already");
IO.setContext(&Object);
+ if (auto *Opt = dyn_cast<ELFYAML::Opt>(IO.Opt))
+ Opt->preMapping(Object, IO.outputting());
IO.mapTag("!ELF", true);
IO.mapRequired("FileHeader", Object.Header);
IO.mapOptional("ProgramHeaders", Object.ProgramHeaders);
@@ -1994,6 +2014,8 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
Object.DWARF->Is64BitAddrSize =
Object.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
}
+ if (auto *Opt = dyn_cast<ELFYAML::Opt>(IO.Opt))
+ Opt->postMapping(Object, IO.outputting());
IO.setContext(nullptr);
}
diff --git a/llvm/lib/Support/YAMLTraits.cpp b/llvm/lib/Support/YAMLTraits.cpp
index 56b557646100b1..4c5d8d5a138aa4 100644
--- a/llvm/lib/Support/YAMLTraits.cpp
+++ b/llvm/lib/Support/YAMLTraits.cpp
@@ -31,6 +31,14 @@
using namespace llvm;
using namespace yaml;
+//===----------------------------------------------------------------------===//
+// Opt
+//===----------------------------------------------------------------------===//
+
+Opt::~Opt() = default;
+
+const char Opt::ID = '@';
+
//===----------------------------------------------------------------------===//
// IO
//===----------------------------------------------------------------------===//
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index 9b4644bde36c0b..3b3fc0f9e8b3c1 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -22,6 +22,19 @@
using namespace llvm;
namespace {
+class DumperOpt : public ELFYAML::Opt {
+public:
+ std::unique_ptr<ELFYAML::CustomRawContentSection>
+ makeCustomRawContentSection(StringRef Name) const override {
+ return nullptr;
+ }
+ void preMapping(const ELFYAML::Object &Object, bool IsOutputting) override {
+ // Do nothing.
+ }
+ void postMapping(const ELFYAML::Object &Object, bool IsOutputting) override {
+ // Do nothing.
+ }
+};
template <class ELFT>
class ELFDumper {
@@ -80,6 +93,8 @@ class ELFDumper {
Expected<ELFYAML::RelrSection *> dumpRelrSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::RawContentSection *>
dumpContentSection(const Elf_Shdr *Shdr);
+ Expected<ELFYAML::CustomRawContentSection *>
+ dumpCustomRawContentSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::SymtabShndxSection *>
dumpSymtabShndxSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr);
@@ -104,6 +119,8 @@ class ELFDumper {
std::optional<DWARFYAML::Data> DWARF);
public:
+ DumperOpt Opt;
+
ELFDumper(const object::ELFFile<ELFT> &O, std::unique_ptr<DWARFContext> DCtx);
Expected<ELFYAML::Object *> dump();
};
@@ -657,6 +674,18 @@ ELFDumper<ELFT>::dumpSections() {
if (!NameOrErr)
return NameOrErr.takeError();
+ if (auto ResultOrErr = dumpCustomRawContentSection(&Sec)) {
+ auto *Ptr = *ResultOrErr;
+ if (Ptr) {
+ if (Error E = Add(Ptr))
+ return E;
+ continue;
+ } else {
+ // Do nothing -- nullptr
+ }
+ } else
+ return ResultOrErr.takeError();
+
if (ELFYAML::StackSizesSection::nameMatches(*NameOrErr)) {
if (Error E = Add(dumpStackSizesSection(&Sec)))
return std::move(E);
@@ -1654,6 +1683,39 @@ ELFDumper<ELFT>::dumpMipsABIFlags(const Elf_Shdr *Shdr) {
return S.release();
}
+template <class ELFT>
+Expected<ELFYAML::CustomRawContentSection *>
+ELFDumper<ELFT>::dumpCustomRawContentSection(const Elf_Shdr *Shdr) {
+ Expected<StringRef> NameOrErr = getUniquedSectionName(*Shdr);
+ if (Error E = NameOrErr.takeError())
+ return nullptr;
+ auto Name = std::move(*NameOrErr);
+
+ auto S = Opt.makeCustomRawContentSection(Name);
+ if (!S)
+ return nullptr;
+
+ if (Error E = dumpCommonSection(Shdr, *S))
+ return std::move(E);
+
+ unsigned SecIndex = Shdr - &Sections[0];
+ if (SecIndex == 0 && Shdr->sh_type == ELF::SHT_NULL)
+ return nullptr;
+
+ auto ContentOrErr = Obj.getSectionContents(*Shdr);
+ if (!ContentOrErr)
+ return ContentOrErr.takeError();
+
+ ArrayRef<uint8_t> Content = *ContentOrErr;
+ if (Content.empty())
+ return nullptr;
+
+ S->Content = yaml::BinaryRef(Content);
+ if (Error E = S->decode(Content, Obj.isLE()))
+ return E;
+ return S.release();
+}
+
template <class ELFT>
static Error elf2yaml(raw_ostream &Out, const object::ELFFile<ELFT> &Obj,
std::unique_ptr<DWARFContext> DWARFCtx) {
@@ -1664,6 +1726,7 @@ static Error elf2yaml(raw_ostream &Out, const object::ELFFile<ELFT> &Obj,
std::unique_ptr<ELFYAML::Object> YAML(YAMLOrErr.get());
yaml::Output Yout(Out);
+ Yout.Opt = &Dumper.Opt;
Yout << *YAML;
return Error::success();
diff --git a/llvm/tools/yaml2obj/yaml2obj.cpp b/llvm/tools/yaml2obj/yaml2obj.cpp
index 4a060e1aad427f..3d356dc7a006fc 100644
--- a/llvm/tools/yaml2obj/yaml2obj.cpp
+++ b/llvm/tools/yaml2obj/yaml2obj.cpp
@@ -58,6 +58,20 @@ static cl::opt<uint64_t> MaxSize(
cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
cl::value_desc("filename"), cl::init("-"),
cl::Prefix, cl::cat(Cat));
+
+class EmitterOpt : public ELFYAML::Opt {
+public:
+ std::unique_ptr<ELFYAML::CustomRawContentSection>
+ makeCustomRawContentSection(StringRef Name) const override {
+ return nullptr;
+ }
+ void preMapping(const ELFYAML::Object &Object, bool IsOutputting) override {
+ // Do nothing.
+ }
+ void postMapping(const ELFYAML::Object &Object, bool IsOutputting) override {
+ // Do nothing.
+ }
+};
} // namespace
static std::optional<std::string> preprocess(StringRef Buf,
@@ -142,7 +156,9 @@ int main(int argc, char **argv) {
if (PreprocessOnly) {
Out->os() << Buffer;
} else {
+ EmitterOpt Opt;
yaml::Input YIn(*Buffer);
+ YIn.Opt = &Opt;
if (!convertYAML(YIn, Out->os(), ErrHandler, DocNum,
MaxSize == 0 ? UINT64_MAX : MaxSize))
>From 94b13aa2e89ed269e6b996cf906d199d011863be Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 12 Nov 2024 23:48:52 +0900
Subject: [PATCH 2/7] Make CustomRaw more generic
---
llvm/include/llvm/ObjectYAML/ELFYAML.h | 7 +------
llvm/lib/ObjectYAML/ELFYAML.cpp | 6 ++++--
llvm/tools/obj2yaml/elf2yaml.cpp | 1 -
3 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index ee8ca11aa2ee62..0723c23a9beff1 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -401,12 +401,7 @@ struct RawContentSection : Section {
/// Abstract base class for non-blob contents.
struct CustomRawContentSection : RawContentSection {
- CustomRawContentSection() : RawContentSection(ChunkKind::CustomRawContent) {
- // Type assumes PROGBITS.
- Type = ELF::SHT_PROGBITS;
- Flags = ELF::SHF_GNU_RETAIN;
- AddressAlign = 1;
- }
+ CustomRawContentSection() : RawContentSection(ChunkKind::CustomRawContent) {}
/// Apply mappings.
virtual void sectionMapping(yaml::IO &IO) = 0;
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 7d06c2c32e23b8..aff2d5e18ce89f 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -1591,6 +1591,7 @@ void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
StringRef Name;
IO.mapOptional("Name", Name);
if (auto S = Opt->makeCustomRawContentSection(Name)) {
+ commonSectionMapping(IO, *S);
S->sectionMapping(IO);
Section = std::move(S);
return;
@@ -1747,9 +1748,10 @@ void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
Section = std::make_unique<ELFYAML::RawContentSection>();
}
- if (auto S = dyn_cast<ELFYAML::CustomRawContentSection>(Section.get()))
+ if (auto S = dyn_cast<ELFYAML::CustomRawContentSection>(Section.get())) {
+ commonSectionMapping(IO, *S);
S->sectionMapping(IO);
- else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Section.get()))
+ } else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Section.get()))
sectionMapping(IO, *S);
else
sectionMapping(IO, *cast<ELFYAML::StackSizesSection>(Section.get()));
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index 3b3fc0f9e8b3c1..7ef5db512b6bc9 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -1710,7 +1710,6 @@ ELFDumper<ELFT>::dumpCustomRawContentSection(const Elf_Shdr *Shdr) {
if (Content.empty())
return nullptr;
- S->Content = yaml::BinaryRef(Content);
if (Error E = S->decode(Content, Obj.isLE()))
return E;
return S.release();
>From eedb1bfb63d077a9c1dc333fe3bda32d6ff7359a Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 12 Nov 2024 23:49:34 +0900
Subject: [PATCH 3/7] Emit Content as the fallback
---
llvm/lib/ObjectYAML/ELFEmitter.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 09a540b0485176..1c7297bf5f09f6 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -1273,6 +1273,13 @@ template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
Elf_Shdr &SHeader, const ELFYAML::CustomRawContentSection &Section,
ContiguousBlobAccumulator &CBA) {
+ if (Section.Info)
+ SHeader.sh_info = *Section.Info;
+
+ // If Section has Content, emit it w/o encoding other fields.
+ if (Section.Content)
+ return;
+
std::string Storage = Section.encode();
SHeader.sh_size = Storage.size();
CBA.write(Storage.data(), Storage.size());
>From 4b47bb25feb84116315173293beecd8086220911 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 12 Nov 2024 23:50:38 +0900
Subject: [PATCH 4/7] Make CustomRawContentSection sibling and independet from
RawContentSection
---
llvm/include/llvm/ObjectYAML/ELFYAML.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 0723c23a9beff1..30d83fcf1a1581 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -389,7 +389,7 @@ struct DynamicSection : Section {
struct RawContentSection : Section {
std::optional<llvm::yaml::Hex64> Info;
- RawContentSection(ChunkKind Kind = ChunkKind::RawContent) : Section(Kind) {}
+ RawContentSection() : Section(ChunkKind::RawContent) {}
static bool classof(const Chunk *S) {
return S->Kind == ChunkKind::RawContent;
@@ -400,8 +400,10 @@ struct RawContentSection : Section {
};
/// Abstract base class for non-blob contents.
-struct CustomRawContentSection : RawContentSection {
- CustomRawContentSection() : RawContentSection(ChunkKind::CustomRawContent) {}
+struct CustomRawContentSection : Section {
+ std::optional<llvm::yaml::Hex64> Info;
+
+ CustomRawContentSection() : Section(ChunkKind::CustomRawContent) {}
/// Apply mappings.
virtual void sectionMapping(yaml::IO &IO) = 0;
>From 6f449538308c796295e78931bc0e27cd6b979122 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 14 Nov 2024 21:50:01 +0900
Subject: [PATCH 5/7] Move yaml::Opt to yaml::IO::OptBase [-fpermissive]
---
llvm/include/llvm/ObjectYAML/ELFYAML.h | 14 +++++++-----
llvm/include/llvm/Support/YAMLTraits.h | 31 ++++++++++++++------------
llvm/lib/Support/YAMLTraits.cpp | 6 ++---
3 files changed, 28 insertions(+), 23 deletions(-)
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 30d83fcf1a1581..983d9fe9c33206 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -788,11 +788,11 @@ bool shouldAllocateFileSpace(ArrayRef<ProgramHeader> Phdrs,
///
/// Derivered classes should not modify OptClassID to ensue that
/// dyn_cast<ELFYAML::Opt> can find this interface.
-class Opt : public yaml::Opt {
+class Opt : public yaml::IO::OptBase {
public:
Opt() {
+ OptBaseClassID = &ID;
OptClassID = &ID;
- ELFOptClassID = &ID;
}
~Opt();
@@ -811,13 +811,15 @@ class Opt : public yaml::Opt {
virtual void postMapping(const ELFYAML::Object &Object,
bool IsOutputting) = 0;
- /// Tell IO::Opt to be this and derivered classes.
- static bool classof(const yaml::Opt *Obj) { return (Obj->OptClassID == &ID); }
+ /// Tell IO::OptBase to be this and derivered classes.
+ static bool classof(const yaml::IO::OptBase *Obj) {
+ return (Obj->OptBaseClassID == &ID);
+ }
/// This will be not needed unless the pointer to ELFYAML::Opt would
/// be cast further.
- static bool classof(const Opt *Obj) { return (Obj->ELFOptClassID == &ID); }
- const char *ELFOptClassID;
+ static bool classof(const Opt *Obj) { return (Obj->OptClassID == &ID); }
+ const char *OptClassID;
private:
static const char ID;
diff --git a/llvm/include/llvm/Support/YAMLTraits.h b/llvm/include/llvm/Support/YAMLTraits.h
index 1f1e06a9e37735..2b16dd21c56b6d 100644
--- a/llvm/include/llvm/Support/YAMLTraits.h
+++ b/llvm/include/llvm/Support/YAMLTraits.h
@@ -39,18 +39,6 @@ class VersionTuple;
namespace yaml {
-/// The base class of options.
-class Opt {
-public:
- virtual ~Opt();
-
- static bool classof(const Opt *Obj) { return (Obj->OptClassID == &ID); }
- const char *OptClassID = &ID;
-
-private:
- static const char ID;
-};
-
enum class NodeKind : uint8_t {
Scalar,
Map,
@@ -974,13 +962,28 @@ class IO {
}
}
+public:
+ /// The base class of options.
+ class OptBase {
+ public:
+ virtual ~OptBase();
+
+ static bool classof(const OptBase *Obj) {
+ return (Obj->OptBaseClassID == &ID);
+ }
+ const char *OptBaseClassID = &ID;
+
+ private:
+ static const char ID;
+ };
+
private:
void *Ctxt;
- Opt DefaultOpt;
+ OptBase DefaultOpt;
public:
/// This may be overwritten in derivered classes.
- Opt *Opt = &DefaultOpt;
+ OptBase *Opt = &DefaultOpt;
};
namespace detail {
diff --git a/llvm/lib/Support/YAMLTraits.cpp b/llvm/lib/Support/YAMLTraits.cpp
index 4c5d8d5a138aa4..4b1c4b368d2394 100644
--- a/llvm/lib/Support/YAMLTraits.cpp
+++ b/llvm/lib/Support/YAMLTraits.cpp
@@ -32,12 +32,12 @@ using namespace llvm;
using namespace yaml;
//===----------------------------------------------------------------------===//
-// Opt
+// IO::OptBase
//===----------------------------------------------------------------------===//
-Opt::~Opt() = default;
+IO::OptBase::~OptBase() = default;
-const char Opt::ID = '@';
+const char IO::OptBase::ID = '@';
//===----------------------------------------------------------------------===//
// IO
>From 9f7a0c4524bd95f39ddde9c254920ba7dd13510a Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 14 Nov 2024 22:10:06 +0900
Subject: [PATCH 6/7] Make ELFYAML::Opt non-abstract
---
llvm/include/llvm/ObjectYAML/ELFYAML.h | 12 ++++++------
llvm/lib/ObjectYAML/ELFYAML.cpp | 13 +++++++++++++
llvm/tools/obj2yaml/elf2yaml.cpp | 14 +-------------
llvm/tools/yaml2obj/yaml2obj.cpp | 14 +-------------
4 files changed, 21 insertions(+), 32 deletions(-)
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 983d9fe9c33206..59af9ac8851c05 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -778,8 +778,8 @@ struct Object {
bool shouldAllocateFileSpace(ArrayRef<ProgramHeader> Phdrs,
const NoBitsSection &S);
-/// ELFYAML::Opt -- Abstract base class for ELFYAML to provide
-/// the interface for handling CustomRawConetentSection.
+/// ELFYAML::Opt -- Null base class for ELFYAML to provide the
+/// interface for handling CustomRawConetentSection.
///
/// Users in ELFYAML should obtain the pointer with
/// dyn_cast<ELFYAML::Opt> if IO::Opt is the instance from yaml::Opt.
@@ -801,15 +801,15 @@ class Opt : public yaml::IO::OptBase {
/// This is called:
/// - Before preMapping for elf2yaml.
/// - After preMapping for yaml2elf.
+ /// Returns nullptr to delegate default actions.
virtual std::unique_ptr<CustomRawContentSection>
- makeCustomRawContentSection(StringRef Name) const = 0;
+ makeCustomRawContentSection(StringRef Name) const;
/// Called before mapping sections for prettyprinting yaml.
- virtual void preMapping(const ELFYAML::Object &Object, bool IsOutputting) = 0;
+ virtual void preMapping(const ELFYAML::Object &Object, bool IsOutputting);
/// Called after mapping sections to gather members for the file format.
- virtual void postMapping(const ELFYAML::Object &Object,
- bool IsOutputting) = 0;
+ virtual void postMapping(const ELFYAML::Object &Object, bool IsOutputting);
/// Tell IO::OptBase to be this and derivered classes.
static bool classof(const yaml::IO::OptBase *Obj) {
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index aff2d5e18ce89f..83ee88e57d66be 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -32,6 +32,19 @@ ELFYAML::Chunk::~Chunk() = default;
ELFYAML::Opt::~Opt() = default;
const char ELFYAML::Opt::ID = 'E';
+std::unique_ptr<ELFYAML::CustomRawContentSection>
+ELFYAML::Opt::makeCustomRawContentSection(StringRef Name) const {
+ return nullptr;
+}
+
+/// Called before mapping sections for prettyprinting yaml.
+void ELFYAML::Opt::preMapping(const ELFYAML::Object &Object,
+ bool IsOutputting) {}
+
+/// Called after mapping sections to gather members for the file format.
+void ELFYAML::Opt::postMapping(const ELFYAML::Object &Object,
+ bool IsOutputting) {}
+
namespace ELFYAML {
ELF_ELFOSABI Object::getOSAbi() const { return Header.OSABI; }
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index 7ef5db512b6bc9..d3fbe9c2d17c19 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -22,19 +22,7 @@
using namespace llvm;
namespace {
-class DumperOpt : public ELFYAML::Opt {
-public:
- std::unique_ptr<ELFYAML::CustomRawContentSection>
- makeCustomRawContentSection(StringRef Name) const override {
- return nullptr;
- }
- void preMapping(const ELFYAML::Object &Object, bool IsOutputting) override {
- // Do nothing.
- }
- void postMapping(const ELFYAML::Object &Object, bool IsOutputting) override {
- // Do nothing.
- }
-};
+struct DumperOpt : public ELFYAML::Opt {};
template <class ELFT>
class ELFDumper {
diff --git a/llvm/tools/yaml2obj/yaml2obj.cpp b/llvm/tools/yaml2obj/yaml2obj.cpp
index 3d356dc7a006fc..b899b8d7cdf2cf 100644
--- a/llvm/tools/yaml2obj/yaml2obj.cpp
+++ b/llvm/tools/yaml2obj/yaml2obj.cpp
@@ -59,19 +59,7 @@ cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
cl::value_desc("filename"), cl::init("-"),
cl::Prefix, cl::cat(Cat));
-class EmitterOpt : public ELFYAML::Opt {
-public:
- std::unique_ptr<ELFYAML::CustomRawContentSection>
- makeCustomRawContentSection(StringRef Name) const override {
- return nullptr;
- }
- void preMapping(const ELFYAML::Object &Object, bool IsOutputting) override {
- // Do nothing.
- }
- void postMapping(const ELFYAML::Object &Object, bool IsOutputting) override {
- // Do nothing.
- }
-};
+struct EmitterOpt : public ELFYAML::Opt {};
} // namespace
static std::optional<std::string> preprocess(StringRef Buf,
>From 67df0dc3bac0462137d34bc2cdb315634a2dae97 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 14 Nov 2024 22:11:07 +0900
Subject: [PATCH 7/7] s/CustomRawContentSection/CustomSection/
---
llvm/include/llvm/ObjectYAML/ELFYAML.h | 14 +++++++-------
llvm/lib/ObjectYAML/ELFEmitter.cpp | 10 +++++-----
llvm/lib/ObjectYAML/ELFYAML.cpp | 10 +++++-----
llvm/tools/obj2yaml/elf2yaml.cpp | 11 +++++------
4 files changed, 22 insertions(+), 23 deletions(-)
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 59af9ac8851c05..38497c813c0fae 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -211,7 +211,7 @@ struct Chunk {
Dynamic,
Group,
RawContent,
- CustomRawContent,
+ CustomContent,
Relocation,
Relr,
NoBits,
@@ -400,10 +400,10 @@ struct RawContentSection : Section {
};
/// Abstract base class for non-blob contents.
-struct CustomRawContentSection : Section {
+struct CustomSection : Section {
std::optional<llvm::yaml::Hex64> Info;
- CustomRawContentSection() : Section(ChunkKind::CustomRawContent) {}
+ CustomSection() : Section(ChunkKind::CustomContent) {}
/// Apply mappings.
virtual void sectionMapping(yaml::IO &IO) = 0;
@@ -415,7 +415,7 @@ struct CustomRawContentSection : Section {
virtual std::string encode() const = 0;
static bool classof(const Chunk *S) {
- return S->Kind == ChunkKind::CustomRawContent;
+ return S->Kind == ChunkKind::CustomContent;
}
};
@@ -796,14 +796,14 @@ class Opt : public yaml::IO::OptBase {
}
~Opt();
- /// Create an empty new object of CustomRawContentSection.
+ /// Create an empty new object of CustomSection.
/// Its contents will be filled later.
/// This is called:
/// - Before preMapping for elf2yaml.
/// - After preMapping for yaml2elf.
/// Returns nullptr to delegate default actions.
- virtual std::unique_ptr<CustomRawContentSection>
- makeCustomRawContentSection(StringRef Name) const;
+ virtual std::unique_ptr<CustomSection>
+ makeCustomSection(StringRef Name) const;
/// Called before mapping sections for prettyprinting yaml.
virtual void preMapping(const ELFYAML::Object &Object, bool IsOutputting);
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 1c7297bf5f09f6..f70f9e56014038 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -252,7 +252,7 @@ template <class ELFT> class ELFState {
const ELFYAML::NoBitsSection &Section,
ContiguousBlobAccumulator &CBA);
void writeSectionContent(Elf_Shdr &SHeader,
- const ELFYAML::CustomRawContentSection &Section,
+ const ELFYAML::CustomSection &Section,
ContiguousBlobAccumulator &CBA);
void writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::RawContentSection &Section,
@@ -862,7 +862,7 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
if (!isa<ELFYAML::NoBitsSection>(Sec) && (Sec->Content || Sec->Size))
SHeader.sh_size = writeContent(CBA, Sec->Content, Sec->Size);
- if (auto S = dyn_cast<ELFYAML::CustomRawContentSection>(Sec)) {
+ if (auto S = dyn_cast<ELFYAML::CustomSection>(Sec)) {
writeSectionContent(SHeader, *S, CBA);
} else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
writeSectionContent(SHeader, *S, CBA);
@@ -1270,9 +1270,9 @@ void ELFState<ELFT>::writeSectionContent(
}
template <class ELFT>
-void ELFState<ELFT>::writeSectionContent(
- Elf_Shdr &SHeader, const ELFYAML::CustomRawContentSection &Section,
- ContiguousBlobAccumulator &CBA) {
+void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
+ const ELFYAML::CustomSection &Section,
+ ContiguousBlobAccumulator &CBA) {
if (Section.Info)
SHeader.sh_info = *Section.Info;
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 83ee88e57d66be..3f73637929cadc 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -32,8 +32,8 @@ ELFYAML::Chunk::~Chunk() = default;
ELFYAML::Opt::~Opt() = default;
const char ELFYAML::Opt::ID = 'E';
-std::unique_ptr<ELFYAML::CustomRawContentSection>
-ELFYAML::Opt::makeCustomRawContentSection(StringRef Name) const {
+std::unique_ptr<ELFYAML::CustomSection>
+ELFYAML::Opt::makeCustomSection(StringRef Name) const {
return nullptr;
}
@@ -1599,11 +1599,11 @@ static bool isInteger(StringRef Val) {
void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
IO &IO, std::unique_ptr<ELFYAML::Chunk> &Section) {
if (!IO.outputting()) {
- /// Prepare CustomRawContentSection by Name for ELFEmitter.
+ /// Prepare CustomSection by Name for ELFEmitter.
if (auto *Opt = dyn_cast<ELFYAML::Opt>(IO.Opt)) {
StringRef Name;
IO.mapOptional("Name", Name);
- if (auto S = Opt->makeCustomRawContentSection(Name)) {
+ if (auto S = Opt->makeCustomSection(Name)) {
commonSectionMapping(IO, *S);
S->sectionMapping(IO);
Section = std::move(S);
@@ -1761,7 +1761,7 @@ void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
Section = std::make_unique<ELFYAML::RawContentSection>();
}
- if (auto S = dyn_cast<ELFYAML::CustomRawContentSection>(Section.get())) {
+ if (auto S = dyn_cast<ELFYAML::CustomSection>(Section.get())) {
commonSectionMapping(IO, *S);
S->sectionMapping(IO);
} else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Section.get()))
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index d3fbe9c2d17c19..8567de489a0bfd 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -81,8 +81,7 @@ class ELFDumper {
Expected<ELFYAML::RelrSection *> dumpRelrSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::RawContentSection *>
dumpContentSection(const Elf_Shdr *Shdr);
- Expected<ELFYAML::CustomRawContentSection *>
- dumpCustomRawContentSection(const Elf_Shdr *Shdr);
+ Expected<ELFYAML::CustomSection *> dumpCustomSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::SymtabShndxSection *>
dumpSymtabShndxSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr);
@@ -662,7 +661,7 @@ ELFDumper<ELFT>::dumpSections() {
if (!NameOrErr)
return NameOrErr.takeError();
- if (auto ResultOrErr = dumpCustomRawContentSection(&Sec)) {
+ if (auto ResultOrErr = dumpCustomSection(&Sec)) {
auto *Ptr = *ResultOrErr;
if (Ptr) {
if (Error E = Add(Ptr))
@@ -1672,14 +1671,14 @@ ELFDumper<ELFT>::dumpMipsABIFlags(const Elf_Shdr *Shdr) {
}
template <class ELFT>
-Expected<ELFYAML::CustomRawContentSection *>
-ELFDumper<ELFT>::dumpCustomRawContentSection(const Elf_Shdr *Shdr) {
+Expected<ELFYAML::CustomSection *>
+ELFDumper<ELFT>::dumpCustomSection(const Elf_Shdr *Shdr) {
Expected<StringRef> NameOrErr = getUniquedSectionName(*Shdr);
if (Error E = NameOrErr.takeError())
return nullptr;
auto Name = std::move(*NameOrErr);
- auto S = Opt.makeCustomRawContentSection(Name);
+ auto S = Opt.makeCustomSection(Name);
if (!S)
return nullptr;
More information about the llvm-commits
mailing list