Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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
65 changes: 65 additions & 0 deletions llvm/include/llvm/ObjectYAML/ELFYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ struct Chunk {
Dynamic,
Group,
RawContent,
CustomRawContent,
Relocation,
Relr,
NoBits,
Expand Down Expand Up @@ -398,6 +399,26 @@ struct RawContentSection : Section {
std::optional<std::vector<uint8_t>> ContentBuf;
};

/// Abstract base class for non-blob contents.
struct CustomRawContentSection : Section {
std::optional<llvm::yaml::Hex64> Info;

CustomRawContentSection() : Section(ChunkKind::CustomRawContent) {}

/// 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) {}

Expand Down Expand Up @@ -757,6 +778,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 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why does your new class type need a completely different approach to e.g. HashSection or NoteSection?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Excuse me, I haven't understood your suggestion. Let me take more time.

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

Expand Down
17 changes: 17 additions & 0 deletions llvm/include/llvm/Support/YAMLTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -964,6 +976,11 @@ class IO {

private:
void *Ctxt;
Opt DefaultOpt;

public:
/// This may be overwritten in derivered classes.
Opt *Opt = &DefaultOpt;
};

namespace detail {
Expand Down
23 changes: 22 additions & 1 deletion llvm/lib/ObjectYAML/ELFEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1264,6 +1269,22 @@ 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) {
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());
}

static bool isMips64EL(const ELFYAML::Object &Obj) {
return Obj.getMachine() == llvm::ELF::EM_MIPS &&
Obj.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) &&
Expand Down
26 changes: 25 additions & 1 deletion llvm/lib/ObjectYAML/ELFYAML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand Down Expand Up @@ -1582,6 +1585,20 @@ 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)) {
commonSectionMapping(IO, *S);
S->sectionMapping(IO);
Section = std::move(S);
return;
}
}
}

ELFYAML::ELF_SHT Type;
StringRef TypeStr;
if (IO.outputting()) {
Expand Down Expand Up @@ -1731,7 +1748,10 @@ 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())) {
commonSectionMapping(IO, *S);
S->sectionMapping(IO);
} else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Section.get()))
sectionMapping(IO, *S);
else
sectionMapping(IO, *cast<ELFYAML::StackSizesSection>(Section.get()));
Expand Down Expand Up @@ -1981,6 +2001,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);
Expand All @@ -1994,6 +2016,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);
}

Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Support/YAMLTraits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@
using namespace llvm;
using namespace yaml;

//===----------------------------------------------------------------------===//
// Opt
//===----------------------------------------------------------------------===//

Opt::~Opt() = default;

const char Opt::ID = '@';

//===----------------------------------------------------------------------===//
// IO
//===----------------------------------------------------------------------===//
Expand Down
62 changes: 62 additions & 0 deletions llvm/tools/obj2yaml/elf2yaml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -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();
};
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1654,6 +1683,38 @@ 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;

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) {
Expand All @@ -1664,6 +1725,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();
Expand Down
16 changes: 16 additions & 0 deletions llvm/tools/yaml2obj/yaml2obj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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))
Expand Down
Loading