1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[yaml2obj] - Add a way to describe the custom data that is not part of an output section.

Currently there is no way to describe the data that is not a part of an output section.
It can be a data used to align sections or to fill the gaps with something,
or another kind of custom data. In this patch I suggest a way to describe it. It looks like that:

```
Sections:
  - Type:    CustomFiller
    Pattern: "CCDD"
    Size:    4
  - Name:    .bar
    Type:    SHT_PROGBITS
    Content: "FF"
```

I.e. I've added a kind of synthetic section with a synthetic type "CustomFiller".
In the code it is called a "SyntheticFiller", which is "a synthetic section which
might be used to write the custom data around regular output sections. It does
not present in the sections header table, but it might affect the output file size and
program headers produced. Think about it as about piece of data."

`SyntheticFiller` currently has a `Pattern` field and a `Size` field + an optional `Name`.
When written, `Size` of bytes in the output will be filled with a `Pattern`.
It is possible to reference a named filler it by name from the program headers description,
just like any other normal section.

Differential revision: https://reviews.llvm.org/D69709
This commit is contained in:
Georgii Rymar 2019-11-01 15:24:58 +03:00
parent 407077ed2f
commit 6f39af85a4
9 changed files with 584 additions and 153 deletions

View File

@ -130,8 +130,8 @@ struct NoteEntry {
llvm::yaml::Hex32 Type;
};
struct Section {
enum class SectionKind {
struct Chunk {
enum class ChunkKind {
Dynamic,
Group,
RawContent,
@ -146,10 +146,18 @@ struct Section {
SymtabShndxSection,
Symver,
MipsABIFlags,
Addrsig
Addrsig,
Fill
};
SectionKind Kind;
ChunkKind Kind;
StringRef Name;
Chunk(ChunkKind K) : Kind(K) {}
virtual ~Chunk();
};
struct Section : public Chunk {
ELF_SHT Type;
Optional<ELF_SHF> Flags;
llvm::yaml::Hex64 Address;
@ -161,9 +169,10 @@ struct Section {
// When they are, this flag is used to signal about that.
bool IsImplicit;
Section(SectionKind Kind, bool IsImplicit = false)
: Kind(Kind), IsImplicit(IsImplicit) {}
virtual ~Section();
Section(ChunkKind Kind, bool IsImplicit = false)
: Chunk(Kind), IsImplicit(IsImplicit) {}
static bool classof(const Chunk *S) { return S->Kind != ChunkKind::Fill; }
// The following members are used to override section fields which is
// useful for creating invalid objects.
@ -181,15 +190,32 @@ struct Section {
Optional<llvm::yaml::Hex64> ShSize;
};
// Fill is a block of data which is placed outside of sections. It is
// not present in the sections header table, but it might affect the output file
// size and program headers produced.
struct Fill : Chunk {
Optional<yaml::BinaryRef> Pattern;
llvm::yaml::Hex64 Size;
// We have to remember the offset of the fill, because it does not have
// a corresponding section header, unlike a section. We might need this
// information when writing the output.
uint64_t ShOffset;
Fill() : Chunk(ChunkKind::Fill) {}
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Fill; }
};
struct StackSizesSection : Section {
Optional<yaml::BinaryRef> Content;
Optional<llvm::yaml::Hex64> Size;
Optional<std::vector<StackSizeEntry>> Entries;
StackSizesSection() : Section(SectionKind::StackSizes) {}
StackSizesSection() : Section(ChunkKind::StackSizes) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::StackSizes;
static bool classof(const Chunk *S) {
return S->Kind == ChunkKind::StackSizes;
}
static bool nameMatches(StringRef Name) {
@ -201,11 +227,9 @@ struct DynamicSection : Section {
std::vector<DynamicEntry> Entries;
Optional<yaml::BinaryRef> Content;
DynamicSection() : Section(SectionKind::Dynamic) {}
DynamicSection() : Section(ChunkKind::Dynamic) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::Dynamic;
}
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Dynamic; }
};
struct RawContentSection : Section {
@ -213,21 +237,19 @@ struct RawContentSection : Section {
Optional<llvm::yaml::Hex64> Size;
Optional<llvm::yaml::Hex64> Info;
RawContentSection() : Section(SectionKind::RawContent) {}
RawContentSection() : Section(ChunkKind::RawContent) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::RawContent;
static bool classof(const Chunk *S) {
return S->Kind == ChunkKind::RawContent;
}
};
struct NoBitsSection : Section {
llvm::yaml::Hex64 Size;
NoBitsSection() : Section(SectionKind::NoBits) {}
NoBitsSection() : Section(ChunkKind::NoBits) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::NoBits;
}
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::NoBits; }
};
struct NoteSection : Section {
@ -235,8 +257,9 @@ struct NoteSection : Section {
Optional<llvm::yaml::Hex64> Size;
Optional<std::vector<ELFYAML::NoteEntry>> Notes;
NoteSection() : Section(SectionKind::Note) {}
static bool classof(const Section *S) { return S->Kind == SectionKind::Note; }
NoteSection() : Section(ChunkKind::Note) {}
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Note; }
};
struct HashSection : Section {
@ -245,9 +268,9 @@ struct HashSection : Section {
Optional<std::vector<uint32_t>> Bucket;
Optional<std::vector<uint32_t>> Chain;
HashSection() : Section(SectionKind::Hash) {}
HashSection() : Section(ChunkKind::Hash) {}
static bool classof(const Section *S) { return S->Kind == SectionKind::Hash; }
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Hash; }
};
struct GnuHashHeader {
@ -278,9 +301,9 @@ struct GnuHashSection : Section {
Optional<std::vector<llvm::yaml::Hex32>> HashBuckets;
Optional<std::vector<llvm::yaml::Hex32>> HashValues;
GnuHashSection() : Section(SectionKind::GnuHash) {}
GnuHashSection() : Section(ChunkKind::GnuHash) {}
static bool classof(const Section *S) { return S->Kind == SectionKind::GnuHash; }
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::GnuHash; }
};
struct VernauxEntry {
@ -300,10 +323,10 @@ struct VerneedSection : Section {
std::vector<VerneedEntry> VerneedV;
llvm::yaml::Hex64 Info;
VerneedSection() : Section(SectionKind::Verneed) {}
VerneedSection() : Section(ChunkKind::Verneed) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::Verneed;
static bool classof(const Chunk *S) {
return S->Kind == ChunkKind::Verneed;
}
};
@ -321,20 +344,17 @@ struct AddrsigSection : Section {
Optional<llvm::yaml::Hex64> Size;
Optional<std::vector<AddrsigSymbol>> Symbols;
AddrsigSection() : Section(SectionKind::Addrsig) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::Addrsig;
}
AddrsigSection() : Section(ChunkKind::Addrsig) {}
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Addrsig; }
};
struct SymverSection : Section {
std::vector<uint16_t> Entries;
SymverSection() : Section(SectionKind::Symver) {}
SymverSection() : Section(ChunkKind::Symver) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::Symver;
}
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Symver; }
};
struct VerdefEntry {
@ -349,11 +369,9 @@ struct VerdefSection : Section {
std::vector<VerdefEntry> Entries;
llvm::yaml::Hex64 Info;
VerdefSection() : Section(SectionKind::Verdef) {}
VerdefSection() : Section(ChunkKind::Verdef) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::Verdef;
}
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Verdef; }
};
struct Group : Section {
@ -362,11 +380,9 @@ struct Group : Section {
std::vector<SectionOrType> Members;
Optional<StringRef> Signature; /* Info */
Group() : Section(SectionKind::Group) {}
Group() : Section(ChunkKind::Group) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::Group;
}
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Group; }
};
struct Relocation {
@ -380,20 +396,20 @@ struct RelocationSection : Section {
std::vector<Relocation> Relocations;
StringRef RelocatableSec; /* Info */
RelocationSection() : Section(SectionKind::Relocation) {}
RelocationSection() : Section(ChunkKind::Relocation) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::Relocation;
static bool classof(const Chunk *S) {
return S->Kind == ChunkKind::Relocation;
}
};
struct SymtabShndxSection : Section {
std::vector<uint32_t> Entries;
SymtabShndxSection() : Section(SectionKind::SymtabShndxSection) {}
SymtabShndxSection() : Section(ChunkKind::SymtabShndxSection) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::SymtabShndxSection;
static bool classof(const Chunk *S) {
return S->Kind == ChunkKind::SymtabShndxSection;
}
};
@ -411,23 +427,35 @@ struct MipsABIFlags : Section {
MIPS_AFL_FLAGS1 Flags1;
llvm::yaml::Hex32 Flags2;
MipsABIFlags() : Section(SectionKind::MipsABIFlags) {}
MipsABIFlags() : Section(ChunkKind::MipsABIFlags) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::MipsABIFlags;
static bool classof(const Chunk *S) {
return S->Kind == ChunkKind::MipsABIFlags;
}
};
struct Object {
FileHeader Header;
std::vector<ProgramHeader> ProgramHeaders;
std::vector<std::unique_ptr<Section>> Sections;
// An object might contain output section descriptions as well as
// custom data that does not belong to any section.
std::vector<std::unique_ptr<Chunk>> Chunks;
// Although in reality the symbols reside in a section, it is a lot
// cleaner and nicer if we read them from the YAML as a separate
// top-level key, which automatically ensures that invariants like there
// being a single SHT_SYMTAB section are upheld.
Optional<std::vector<Symbol>> Symbols;
std::vector<Symbol> DynamicSymbols;
std::vector<Section *> getSections() {
std::vector<Section *> Ret;
for (const std::unique_ptr<Chunk> &Sec : Chunks)
if (auto S = dyn_cast<ELFYAML::Section>(Sec.get()))
Ret.push_back(S);
return Ret;
}
};
} // end namespace ELFYAML
@ -438,7 +466,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::NoteEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>)
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Chunk>)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerdefEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VernauxEntry)
@ -607,10 +635,9 @@ template <> struct MappingTraits<ELFYAML::Relocation> {
static void mapping(IO &IO, ELFYAML::Relocation &Rel);
};
template <>
struct MappingTraits<std::unique_ptr<ELFYAML::Section>> {
static void mapping(IO &IO, std::unique_ptr<ELFYAML::Section> &Section);
static StringRef validate(IO &io, std::unique_ptr<ELFYAML::Section> &Section);
template <> struct MappingTraits<std::unique_ptr<ELFYAML::Chunk>> {
static void mapping(IO &IO, std::unique_ptr<ELFYAML::Chunk> &C);
static StringRef validate(IO &io, std::unique_ptr<ELFYAML::Chunk> &C);
};
template <>

View File

@ -85,7 +85,8 @@ public:
/// Write the contents (regardless of whether it is binary or a
/// hex string) as binary to the given raw_ostream.
void writeAsBinary(raw_ostream &OS) const;
/// N can be used to specify the maximum number of bytes.
void writeAsBinary(raw_ostream &OS, uint64_t N = UINT64_MAX) const;
/// Write the contents (regardless of whether it is binary or a
/// hex string) as hex to the given raw_ostream.

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/StringTableBuilder.h"
@ -88,6 +89,15 @@ public:
unsigned size() const { return Map.size(); }
};
namespace {
struct Fragment {
uint64_t Offset;
uint64_t Size;
uint32_t Type;
uint64_t AddrAlign;
};
}; // namespace
/// "Single point of truth" for the ELF file construction.
/// TODO: This class still has a ways to go before it is truly a "single
/// point of truth".
@ -142,6 +152,11 @@ template <class ELFT> class ELFState {
ELFYAML::Section *YAMLSec);
void setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
std::vector<Elf_Shdr> &SHeaders);
std::vector<Fragment>
getPhdrFragments(const ELFYAML::ProgramHeader &Phdr,
ArrayRef<typename ELFT::Shdr> SHeaders);
void finalizeStrings();
void writeELFHeader(ContiguousBlobAccumulator &CBA, raw_ostream &OS);
void writeSectionContent(Elf_Shdr &SHeader,
@ -186,6 +201,8 @@ template <class ELFT> class ELFState {
const ELFYAML::GnuHashSection &Section,
ContiguousBlobAccumulator &CBA);
void writeFill(ELFYAML::Fill &Fill, ContiguousBlobAccumulator &CBA);
ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);
public:
@ -207,17 +224,18 @@ template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }
template <class ELFT>
ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
: Doc(D), ErrHandler(EH) {
std::vector<ELFYAML::Section *> Sections = Doc.getSections();
StringSet<> DocSections;
for (std::unique_ptr<ELFYAML::Section> &D : Doc.Sections)
if (!D->Name.empty())
DocSections.insert(D->Name);
for (const ELFYAML::Section *Sec : Sections)
if (!Sec->Name.empty())
DocSections.insert(Sec->Name);
// Insert SHT_NULL section implicitly when it is not defined in YAML.
if (Doc.Sections.empty() || Doc.Sections.front()->Type != ELF::SHT_NULL)
Doc.Sections.insert(
Doc.Sections.begin(),
if (Sections.empty() || Sections.front()->Type != ELF::SHT_NULL)
Doc.Chunks.insert(
Doc.Chunks.begin(),
std::make_unique<ELFYAML::Section>(
ELFYAML::Section::SectionKind::RawContent, /*IsImplicit=*/true));
ELFYAML::Chunk::ChunkKind::RawContent, /*IsImplicit=*/true));
std::vector<StringRef> ImplicitSections;
if (Doc.Symbols)
@ -233,10 +251,10 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
if (DocSections.count(SecName))
continue;
std::unique_ptr<ELFYAML::Section> Sec = std::make_unique<ELFYAML::Section>(
ELFYAML::Section::SectionKind::RawContent, true /*IsImplicit*/);
std::unique_ptr<ELFYAML::Chunk> Sec = std::make_unique<ELFYAML::Section>(
ELFYAML::Chunk::ChunkKind::RawContent, true /*IsImplicit*/);
Sec->Name = SecName;
Doc.Sections.push_back(std::move(Sec));
Doc.Chunks.push_back(std::move(Sec));
}
}
@ -274,7 +292,7 @@ void ELFState<ELFT>::writeELFHeader(ContiguousBlobAccumulator &CBA, raw_ostream
Header.e_shoff =
Doc.Header.SHOff ? typename ELFT::uint(*Doc.Header.SHOff) : SHOff;
Header.e_shnum =
Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : Doc.Sections.size();
Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : Doc.getSections().size();
Header.e_shstrndx = Doc.Header.SHStrNdx ? (uint16_t)*Doc.Header.SHStrNdx
: SN2I.get(".shstrtab");
@ -371,18 +389,25 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
ContiguousBlobAccumulator &CBA) {
// Ensure SHN_UNDEF entry is present. An all-zero section header is a
// valid SHN_UNDEF entry since SHT_NULL == 0.
SHeaders.resize(Doc.Sections.size());
SHeaders.resize(Doc.getSections().size());
for (size_t I = 0; I < Doc.Sections.size(); ++I) {
ELFYAML::Section *Sec = Doc.Sections[I].get();
if (I == 0 && Sec->IsImplicit)
size_t SecNdx = -1;
for (const std::unique_ptr<ELFYAML::Chunk> &D : Doc.Chunks) {
if (auto S = dyn_cast<ELFYAML::Fill>(D.get())) {
writeFill(*S, CBA);
continue;
}
++SecNdx;
ELFYAML::Section *Sec = cast<ELFYAML::Section>(D.get());
if (SecNdx == 0 && Sec->IsImplicit)
continue;
// We have a few sections like string or symbol tables that are usually
// added implicitly to the end. However, if they are explicitly specified
// in the YAML, we need to write them here. This ensures the file offset
// remains correct.
Elf_Shdr &SHeader = SHeaders[I];
Elf_Shdr &SHeader = SHeaders[SecNdx];
if (initImplicitHeader(CBA, SHeader, Sec->Name,
Sec->IsImplicit ? nullptr : Sec))
continue;
@ -401,7 +426,7 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
if (!Sec->Link.empty())
SHeader.sh_link = toSectionIndex(Sec->Link, Sec->Name);
if (I == 0) {
if (SecNdx == 0) {
if (auto RawSec = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
// We do not write any content for special SHN_UNDEF section.
if (RawSec->Size)
@ -640,23 +665,44 @@ template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) {
HasError = true;
}
template <class ELFT>
std::vector<Fragment>
ELFState<ELFT>::getPhdrFragments(const ELFYAML::ProgramHeader &Phdr,
ArrayRef<typename ELFT::Shdr> SHeaders) {
DenseMap<StringRef, ELFYAML::Fill *> NameToFill;
for (const std::unique_ptr<ELFYAML::Chunk> &D : Doc.Chunks)
if (auto S = dyn_cast<ELFYAML::Fill>(D.get()))
NameToFill[S->Name] = S;
std::vector<Fragment> Ret;
for (const ELFYAML::SectionName &SecName : Phdr.Sections) {
unsigned Index;
if (SN2I.lookup(SecName.Section, Index)) {
const typename ELFT::Shdr &H = SHeaders[Index];
Ret.push_back({H.sh_offset, H.sh_size, H.sh_type, H.sh_addralign});
continue;
}
if (ELFYAML::Fill *Fill = NameToFill.lookup(SecName.Section)) {
Ret.push_back({Fill->ShOffset, Fill->Size, llvm::ELF::SHT_PROGBITS,
/*ShAddrAlign=*/1});
continue;
}
reportError("unknown section or fill referenced: '" + SecName.Section +
"' by program header");
}
return Ret;
}
template <class ELFT>
void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
std::vector<Elf_Shdr> &SHeaders) {
uint32_t PhdrIdx = 0;
for (auto &YamlPhdr : Doc.ProgramHeaders) {
Elf_Phdr &PHeader = PHeaders[PhdrIdx++];
std::vector<Elf_Shdr *> Sections;
for (const ELFYAML::SectionName &SecName : YamlPhdr.Sections) {
unsigned Index;
if (!SN2I.lookup(SecName.Section, Index)) {
reportError("unknown section referenced: '" + SecName.Section +
"' by program header");
continue;
}
Sections.push_back(&SHeaders[Index]);
}
std::vector<Fragment> Fragments = getPhdrFragments(YamlPhdr, SHeaders);
if (YamlPhdr.Offset) {
PHeader.p_offset = *YamlPhdr.Offset;
@ -667,19 +713,19 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
PHeader.p_offset = 0;
// Find the minimum offset for the program header.
for (Elf_Shdr *SHeader : Sections)
PHeader.p_offset = std::min(PHeader.p_offset, SHeader->sh_offset);
for (const Fragment &F : Fragments)
PHeader.p_offset = std::min((uint64_t)PHeader.p_offset, F.Offset);
}
// Find the maximum offset of the end of a section in order to set p_filesz
// and p_memsz. When setting p_filesz, trailing SHT_NOBITS sections are not
// counted.
uint64_t FileOffset = PHeader.p_offset, MemOffset = PHeader.p_offset;
for (Elf_Shdr *SHeader : Sections) {
uint64_t End = SHeader->sh_offset + SHeader->sh_size;
for (const Fragment &F : Fragments) {
uint64_t End = F.Offset + F.Size;
MemOffset = std::max(MemOffset, End);
if (SHeader->sh_type != llvm::ELF::SHT_NOBITS)
if (F.Type != llvm::ELF::SHT_NOBITS)
FileOffset = std::max(FileOffset, End);
}
@ -696,8 +742,8 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
// sections so that by default the segment has a valid and sensible
// alignment.
PHeader.p_align = 1;
for (Elf_Shdr *SHeader : Sections)
PHeader.p_align = std::max(PHeader.p_align, SHeader->sh_addralign);
for (const Fragment &F : Fragments)
PHeader.p_align = std::max((uint64_t)PHeader.p_align, F.AddrAlign);
}
}
}
@ -1160,16 +1206,45 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
Section.HashValues->size() * 4;
}
template <class ELFT>
void ELFState<ELFT>::writeFill(ELFYAML::Fill &Fill,
ContiguousBlobAccumulator &CBA) {
raw_ostream &OS = CBA.getOSAndAlignedOffset(Fill.ShOffset, /*Align=*/1);
size_t PatternSize = Fill.Pattern ? Fill.Pattern->binary_size() : 0;
if (!PatternSize) {
OS.write_zeros(Fill.Size);
return;
}
// Fill the content with the specified pattern.
uint64_t Written = 0;
for (; Written + PatternSize <= Fill.Size; Written += PatternSize)
Fill.Pattern->writeAsBinary(OS);
Fill.Pattern->writeAsBinary(OS, Fill.Size - Written);
}
template <class ELFT> void ELFState<ELFT>::buildSectionIndex() {
for (unsigned I = 0, E = Doc.Sections.size(); I != E; ++I) {
StringRef Name = Doc.Sections[I]->Name;
if (Name.empty())
size_t SecNdx = -1;
StringSet<> Seen;
for (size_t I = 0; I < Doc.Chunks.size(); ++I) {
const std::unique_ptr<ELFYAML::Chunk> &C = Doc.Chunks[I];
bool IsSection = isa<ELFYAML::Section>(C.get());
if (IsSection)
++SecNdx;
if (C->Name.empty())
continue;
DotShStrtab.add(ELFYAML::dropUniqueSuffix(Name));
if (!SN2I.addName(Name, I))
reportError("repeated section name: '" + Name +
"' at YAML section number " + Twine(I));
if (!Seen.insert(C->Name).second)
reportError("repeated section/fill name: '" + C->Name +
"' at YAML section/fill number " + Twine(I));
if (!IsSection || HasError)
continue;
if (!SN2I.addName(C->Name, SecNdx))
llvm_unreachable("buildSectionIndex() failed");
DotShStrtab.add(ELFYAML::dropUniqueSuffix(C->Name));
}
DotShStrtab.finalize();
@ -1202,14 +1277,14 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
// SHT_GNU_verdef and SHT_GNU_verneed sections might also
// add strings to .dynstr section.
for (const std::unique_ptr<ELFYAML::Section> &Sec : Doc.Sections) {
if (auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Sec.get())) {
for (const ELFYAML::Chunk *Sec : Doc.getSections()) {
if (auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Sec)) {
for (const ELFYAML::VerneedEntry &VE : VerNeed->VerneedV) {
DotDynstr.add(VE.File);
for (const ELFYAML::VernauxEntry &Aux : VE.AuxV)
DotDynstr.add(Aux.Name);
}
} else if (auto VerDef = dyn_cast<ELFYAML::VerdefSection>(Sec.get())) {
} else if (auto VerDef = dyn_cast<ELFYAML::VerdefSection>(Sec)) {
for (const ELFYAML::VerdefEntry &E : VerDef->Entries)
for (StringRef Name : E.VerNames)
DotDynstr.add(Name);
@ -1230,6 +1305,9 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
State.finalizeStrings();
State.buildSectionIndex();
if (State.HasError)
return false;
State.buildSymbolIndexes();
std::vector<Elf_Phdr> PHeaders;

View File

@ -24,7 +24,7 @@
namespace llvm {
ELFYAML::Section::~Section() = default;
ELFYAML::Chunk::~Chunk() = default;
namespace yaml {
@ -1094,6 +1094,12 @@ static void sectionMapping(IO &IO, ELFYAML::AddrsigSection &Section) {
IO.mapOptional("Symbols", Section.Symbols);
}
static void fillMapping(IO &IO, ELFYAML::Fill &Fill) {
IO.mapOptional("Name", Fill.Name, StringRef());
IO.mapOptional("Pattern", Fill.Pattern);
IO.mapRequired("Size", Fill.Size);
}
void MappingTraits<ELFYAML::SectionOrType>::mapping(
IO &IO, ELFYAML::SectionOrType &sectionOrType) {
IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType);
@ -1124,15 +1130,27 @@ static void sectionMapping(IO &IO, ELFYAML::MipsABIFlags &Section) {
IO.mapOptional("Flags2", Section.Flags2, Hex32(0));
}
void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping(
IO &IO, std::unique_ptr<ELFYAML::Section> &Section) {
ELFYAML::ELF_SHT sectionType;
if (IO.outputting())
sectionType = Section->Type;
else
IO.mapRequired("Type", sectionType);
void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
IO &IO, std::unique_ptr<ELFYAML::Chunk> &Section) {
ELFYAML::ELF_SHT Type;
if (IO.outputting()) {
Type = cast<ELFYAML::Section>(Section.get())->Type;
} else {
// When the Type string does not have a "SHT_" prefix, we know it is not a
// description of a regular ELF output section. Currently, we have one
// special type named "Fill". See comments for Fill.
StringRef StrType;
IO.mapRequired("Type", StrType);
if (StrType == "Fill") {
Section.reset(new ELFYAML::Fill());
fillMapping(IO, *cast<ELFYAML::Fill>(Section.get()));
return;
}
switch (sectionType) {
IO.mapRequired("Type", Type);
}
switch (Type) {
case ELF::SHT_DYNAMIC:
if (!IO.outputting())
Section.reset(new ELFYAML::DynamicSection());
@ -1218,17 +1236,17 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping(
}
}
StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate(
IO &io, std::unique_ptr<ELFYAML::Section> &Section) {
StringRef MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::validate(
IO &io, std::unique_ptr<ELFYAML::Chunk> &C) {
if (const auto *RawSection =
dyn_cast<ELFYAML::RawContentSection>(Section.get())) {
dyn_cast<ELFYAML::RawContentSection>(C.get())) {
if (RawSection->Size && RawSection->Content &&
(uint64_t)(*RawSection->Size) < RawSection->Content->binary_size())
return "Section size must be greater than or equal to the content size";
return {};
}
if (const auto *SS = dyn_cast<ELFYAML::StackSizesSection>(Section.get())) {
if (const auto *SS = dyn_cast<ELFYAML::StackSizesSection>(C.get())) {
if (!SS->Entries && !SS->Content && !SS->Size)
return ".stack_sizes: one of Content, Entries and Size must be specified";
@ -1248,7 +1266,7 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate(
return {};
}
if (const auto *HS = dyn_cast<ELFYAML::HashSection>(Section.get())) {
if (const auto *HS = dyn_cast<ELFYAML::HashSection>(C.get())) {
if (!HS->Content && !HS->Bucket && !HS->Chain && !HS->Size)
return "one of \"Content\", \"Size\", \"Bucket\" or \"Chain\" must be "
"specified";
@ -1271,7 +1289,7 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate(
return {};
}
if (const auto *Sec = dyn_cast<ELFYAML::AddrsigSection>(Section.get())) {
if (const auto *Sec = dyn_cast<ELFYAML::AddrsigSection>(C.get())) {
if (!Sec->Symbols && !Sec->Content && !Sec->Size)
return "one of \"Content\", \"Size\" or \"Symbols\" must be specified";
@ -1296,7 +1314,7 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate(
return {};
}
if (const auto *NS = dyn_cast<ELFYAML::NoteSection>(Section.get())) {
if (const auto *NS = dyn_cast<ELFYAML::NoteSection>(C.get())) {
if (!NS->Content && !NS->Size && !NS->Notes)
return "one of \"Content\", \"Size\" or \"Notes\" must be "
"specified";
@ -1314,7 +1332,7 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate(
return {};
}
if (const auto *Sec = dyn_cast<ELFYAML::GnuHashSection>(Section.get())) {
if (const auto *Sec = dyn_cast<ELFYAML::GnuHashSection>(C.get())) {
if (!Sec->Content && !Sec->Header && !Sec->BloomFilter &&
!Sec->HashBuckets && !Sec->HashValues)
return "either \"Content\" or \"Header\", \"BloomFilter\", "
@ -1337,6 +1355,14 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate(
return {};
}
if (const auto *F = dyn_cast<ELFYAML::Fill>(C.get())) {
if (!F->Pattern)
return {};
if (F->Pattern->binary_size() != 0 && !F->Size)
return "\"Size\" can't be 0 when \"Pattern\" is not empty";
return {};
}
return {};
}
@ -1455,7 +1481,7 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
IO.mapTag("!ELF", true);
IO.mapRequired("FileHeader", Object.Header);
IO.mapOptional("ProgramHeaders", Object.ProgramHeaders);
IO.mapOptional("Sections", Object.Sections);
IO.mapOptional("Sections", Object.Chunks);
IO.mapOptional("Symbols", Object.Symbols);
IO.mapOptional("DynamicSymbols", Object.DynamicSymbols);
IO.setContext(nullptr);

View File

@ -37,15 +37,16 @@ StringRef yaml::ScalarTraits<yaml::BinaryRef>::input(StringRef Scalar, void *,
return {};
}
void yaml::BinaryRef::writeAsBinary(raw_ostream &OS) const {
void yaml::BinaryRef::writeAsBinary(raw_ostream &OS, uint64_t N) const {
if (!DataIsHexString) {
OS.write((const char *)Data.data(), Data.size());
OS.write((const char *)Data.data(), std::min(N, Data.size()));
return;
}
for (unsigned I = 0, N = Data.size(); I != N; I += 2) {
uint8_t Byte = llvm::hexDigitValue(Data[I]);
for (uint64_t I = 0, E = std::min(N, Data.size() / 2); I != E; ++I) {
uint8_t Byte = llvm::hexDigitValue(Data[I * 2]);
Byte <<= 4;
Byte |= llvm::hexDigitValue(Data[I + 1]);
Byte |= llvm::hexDigitValue(Data[I * 2 + 1]);
OS.write(Byte);
}
}

View File

@ -0,0 +1,298 @@
## Here we check that we are able to define sections with a type of "Fill".
## Fills are custom pieces of data that can be placed anywhere just like normal
## output sections, but they are not real output sections and you'll never see them in
## the section headers.
## Check we can create named and unnamed fills and use "Pattern" and "Size" fields
## to describe the data emitted.
## Check the data emitted and how it affects regular sections offsets.
## Check that the "Name" field is optional for fills.
## Check that "Size" can be greater than or equal to the pattern data size.
# RUN: yaml2obj --docnum=1 %s -o %t1
# RUN: llvm-readelf --sections --headers %t1 | FileCheck %s --check-prefix=BASIC
# BASIC: Number of section headers: 5
# BASIC: Section Headers:
# BASIC-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# BASIC-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
# BASIC-NEXT: [ 1] .foo PROGBITS 0000000000000000 000043 000002 00 0 0 0
# BASIC-NEXT: [ 2] .bar PROGBITS 0000000000000000 000049 000001 00 0 0 0
# BASIC-NEXT: [ 3] .strtab STRTAB 0000000000000000 00004b 000001 00 0 0 1
# BASIC-NEXT: [ 4] .shstrtab STRTAB 0000000000000000 00004c 00001d 00 0 0 1
## The fill we dump starts at (offset of .foo - 3), which is (0x43 - 3) = 0x40.
# RUN: od -t x1 -v -j 0x40 -N 11 %t1 | FileCheck %s --ignore-case --check-prefix=DATA
# DATA: aa bb aa 11 22 cc dd cc dd ff ee
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Type: Fill
Pattern: "AABB"
Size: 0x3
- Name: .foo
Type: SHT_PROGBITS
Content: "1122"
- Type: Fill
Name: unusedName
Pattern: "CCDD"
Size: 4
- Name: .bar
Type: SHT_PROGBITS
Content: "FF"
- Type: Fill
Pattern: "EE"
Size: 1
## Check we can have no explicit regular sections in the YAML description, and can
## describe the content with the use of fills only.
## Check that "Size" can be less than the pattern data size.
# RUN: yaml2obj --docnum=2 %s -o %t2
# RUN: llvm-readelf --sections --headers %t2 | FileCheck %s --check-prefix=NOSECTIONS
## The fill we dump starts at (offset of .strtab - 3 - 2), which is (0x45 - 5) = 0x40.
# RUN: od -t x1 -v -j 0x40 -N 6 %t2 | FileCheck %s --ignore-case --check-prefix=NOSECTIONS-DATA
# NOSECTIONS: Number of section headers: 3
# NOSECTIONS: Section Headers:
# NOSECTIONS-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# NOSECTIONS-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
# NOSECTIONS-NEXT: [ 1] .strtab STRTAB 0000000000000000 000045 000001 00 0 0 1
# NOSECTIONS-NEXT: [ 2] .shstrtab STRTAB 0000000000000000 000046 000013 00 0 0 1
## .strtab that follows fills starts at 0x46 and always has a null character at the begining.
# NOSECTIONS-DATA: aa bb cc dd ee 00
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Type: Fill
Pattern: "AABBCCFF"
Size: 0x3
- Type: Fill
Pattern: "DDEEFF"
Size: 0x2
## Check we can use named fills when describing program headers.
## Check that fills consume the file size and therefore affect the p_filesz fields of segments.
## Check that the fill does not affect the p_align field of the segment.
# RUN: yaml2obj --docnum=3 %s -o %t3
# RUN: llvm-readelf --sections --program-headers %t3 | FileCheck %s --check-prefix=PHDR
# PHDR: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# PHDR: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
# PHDR: [ 1] .bar PROGBITS 0000000000000100 0000c0 000005 00 0 0 2
# PHDR: [ 2] .strtab STRTAB 0000000000000000 00010a 000001 00 0 0 1
# PHDR: [ 3] .shstrtab STRTAB 0000000000000000 00010b 000018 00 0 0 1
# PHDR: Program Headers:
# PHDR: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
# PHDR: LOAD 0x0000b0 0x0000000000000100 0x0000000000000100 0x00005a 0x00005a 0x2
# PHDR: GNU_RELRO 0x0000c5 0x0000000000000105 0x0000000000000105 0x000045 0x000045 0x1
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Type: Fill
Name: fill1
Pattern: ""
Size: 0x10
- Name: .bar
Type: SHT_PROGBITS
Size: 0x5
Address: 0x100
AddressAlign: 2
- Type: Fill
Name: fill2
Pattern: ""
Size: 0x45
ProgramHeaders:
- Type: PT_LOAD
VAddr: 0x100
PAddr: 0x100
Sections:
- Section: fill1
- Section: .bar
- Section: fill2
- Type: PT_GNU_RELRO
VAddr: 0x105
PAddr: 0x105
Sections:
- Section: fill2
## Check that the "Pattern" field is not mandatory.
# RUN: yaml2obj --docnum=4 2>&1 -o %t4 %s
# RUN: llvm-readelf --sections %t4 | FileCheck %s --check-prefix=NOPATTERN
## The fill we dump starts at (offset of .strtab - 1 - 3 - 1), which is (0x45 - 5) = 0x40.
# RUN: od -t x1 -v -j 0x40 -N 5 %t4 | FileCheck %s --ignore-case --check-prefix=NOPATTERN-DATA
# NOPATTERN: [Nr] Name Type Address Off
# NOPATTERN: [ 1] .strtab STRTAB 0000000000000000 000045
# NOPATTERN-DATA: aa 00 00 00 bb
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Type: Fill
Size: 0x1
Pattern: "AA"
- Type: Fill
Size: 0x3
- Type: Fill
Size: 0x1
Pattern: "BB"
## Check that the "Size" field is mandatory.
# RUN: not yaml2obj --docnum=5 2>&1 %s | FileCheck %s --check-prefix=NOSIZE
## NOSIZE: error: missing required key 'Size'
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Type: Fill
Pattern: "00"
## Check that fills are not allowed to have duplicate names.
# RUN: not yaml2obj --docnum=6 2>&1 %s | FileCheck %s --check-prefix=UNIQUE-NAME
# UNIQUE-NAME: error: repeated section/fill name: 'foo' at YAML section/fill number 2
# UNIQUE-NAME: error: repeated section/fill name: 'foo' at YAML section/fill number 3
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Type: Fill
Name: foo
Pattern: "00"
Size: 1
- Type: Fill
Name: foo
Pattern: "00"
Size: 1
- Name: foo
Type: SHT_PROGBITS
## Check that "Pattern" can be empty, when "Size" is zero.
# RUN: yaml2obj --docnum=7 2>&1 %s -o %t7
# RUN: llvm-readelf --sections %t7 | FileCheck %s --check-prefix=NOOP
# NOOP: [Nr] Name Type Address Off
# NOOP: [ 1] begin PROGBITS 0000000000000000 000040
# NOOP: [ 2] end PROGBITS 0000000000000000 000041
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: begin
Type: SHT_PROGBITS
Size: 1
- Type: Fill
Pattern: ""
Size: 0
- Name: end
Type: SHT_PROGBITS
Size: 1
## Check that we can have an empty "Pattern", but have non-zero "Size".
## In this case we emit Size number of zeroes to the output.
# RUN: yaml2obj --docnum=8 2>&1 -o %t8 %s
# RUN: llvm-readelf --sections %t8 | FileCheck %s --check-prefix=EMPTY-PATTERN
## The fill we dump starts at (offset of .strtab - 1 - 3 - 1), which is (0x45 - 5) = 0x40.
# RUN: od -t x1 -v -j 0x40 -N 5 %t8 | FileCheck %s --ignore-case --check-prefix=EMPTY-PATTERN-DATA
# EMPTY-PATTERN: Section Headers:
# EMPTY-PATTERN-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# EMPTY-PATTERN-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
# EMPTY-PATTERN-NEXT: [ 1] .strtab STRTAB 0000000000000000 000045 000001 00 0 0 1
# EMPTY-PATTERN-DATA: aa 00 00 00 bb
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Type: Fill
Pattern: "AA"
Size: 0x1
- Type: Fill
Size: 3
Pattern: ""
- Type: Fill
Pattern: "BB"
Size: 0x1
## Check that "Size" can't be 0, when "Pattern" is not empty.
# RUN: not yaml2obj --docnum=9 2>&1 %s | FileCheck %s --check-prefix=ZERO-SIZE-ERR
# ZERO-SIZE-ERR: error: "Size" can't be 0 when "Pattern" is not empty
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Type: Fill
Pattern: "00"
Size: 0
## Check we report an error when a program header references
## an unknown section or fill and have at least one Fill defined.
# RUN: not yaml2obj --docnum=10 2>&1 %s | FileCheck %s --check-prefix=UNKNOWN-ERR
# UNKNOWN-ERR: error: unknown section or fill referenced: 'fill' by program header
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Type: Fill
Pattern: ""
Size: 0
ProgramHeaders:
- Type: PT_LOAD
Sections:
- Section: fill

View File

@ -29,8 +29,8 @@ Sections:
## sections with equal names and suffixes.
# RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --check-prefix=CASE2
# CASE2: error: repeated section name: '.foo [1]' at YAML section number 2
# CASE2: error: repeated section name: '.foo [1]' at YAML section number 3
# CASE2: error: repeated section/fill name: '.foo [1]' at YAML section/fill number 2
# CASE2: error: repeated section/fill name: '.foo [1]' at YAML section/fill number 3
--- !ELF
FileHeader:
@ -51,7 +51,7 @@ Sections:
## names are equal.
# RUN: not yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --check-prefix=CASE3
# CASE3: error: repeated section name: '.foo' at YAML section number 2
# CASE3: error: repeated section/fill name: '.foo' at YAML section/fill number 2
--- !ELF
FileHeader:

View File

@ -81,8 +81,8 @@ ProgramHeaders:
## Check we do not allow referencing sections that do not exist.
# RUN: not yaml2obj --docnum=2 %s -o %t 2>&1 | FileCheck %s --check-prefix=ERR
# ERR: error: unknown section referenced: '.foo' by program header
# ERR: error: unknown section referenced: '.bar' by program header
# ERR: error: unknown section or fill referenced: '.foo' by program header
# ERR: error: unknown section or fill referenced: '.bar' by program header
--- !ELF
FileHeader:

View File

@ -78,7 +78,7 @@ class ELFDumper {
Expected<ELFYAML::StackSizesSection *>
dumpStackSizesSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::Section *> dumpSpecialSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::Chunk *> dumpSpecialSection(const Elf_Shdr *Shdr);
public:
ELFDumper(const object::ELFFile<ELFT> &O);
@ -221,7 +221,7 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
Expected<ELFYAML::DynamicSection *> SecOrErr = dumpDynamicSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_STRTAB:
@ -234,7 +234,7 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
dumpSymtabShndxSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_REL:
@ -242,77 +242,77 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
Expected<ELFYAML::RelocationSection *> SecOrErr = dumpRelocSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_GROUP: {
Expected<ELFYAML::Group *> GroupOrErr = dumpGroup(&Sec);
if (!GroupOrErr)
return GroupOrErr.takeError();
Y->Sections.emplace_back(*GroupOrErr);
Y->Chunks.emplace_back(*GroupOrErr);
break;
}
case ELF::SHT_MIPS_ABIFLAGS: {
Expected<ELFYAML::MipsABIFlags *> SecOrErr = dumpMipsABIFlags(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_NOBITS: {
Expected<ELFYAML::NoBitsSection *> SecOrErr = dumpNoBitsSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_NOTE: {
Expected<ELFYAML::NoteSection *> SecOrErr = dumpNoteSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_HASH: {
Expected<ELFYAML::HashSection *> SecOrErr = dumpHashSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_GNU_HASH: {
Expected<ELFYAML::GnuHashSection *> SecOrErr = dumpGnuHashSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_GNU_verdef: {
Expected<ELFYAML::VerdefSection *> SecOrErr = dumpVerdefSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_GNU_versym: {
Expected<ELFYAML::SymverSection *> SecOrErr = dumpSymverSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_GNU_verneed: {
Expected<ELFYAML::VerneedSection *> SecOrErr = dumpVerneedSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_LLVM_ADDRSIG: {
Expected<ELFYAML::AddrsigSection *> SecOrErr = dumpAddrsigSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_NULL: {
@ -330,11 +330,11 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
default: {
// Recognize some special SHT_PROGBITS sections by name.
if (Sec.sh_type == ELF::SHT_PROGBITS) {
Expected<ELFYAML::Section *> SpecialSecOrErr = dumpSpecialSection(&Sec);
Expected<ELFYAML::Chunk *> SpecialSecOrErr = dumpSpecialSection(&Sec);
if (!SpecialSecOrErr)
return SpecialSecOrErr.takeError();
if (*SpecialSecOrErr) {
Y->Sections.emplace_back(*SpecialSecOrErr);
Y->Chunks.emplace_back(*SpecialSecOrErr);
break;
}
}
@ -343,7 +343,7 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
dumpContentSection(&Sec);
if (!SecOrErr)
return SecOrErr.takeError();
Y->Sections.emplace_back(*SecOrErr);
Y->Chunks.emplace_back(*SecOrErr);
}
}
}
@ -486,7 +486,7 @@ Error ELFDumper<ELFT>::dumpCommonSection(const Elf_Shdr *Shdr,
}
template <class ELFT>
Expected<ELFYAML::Section *>
Expected<ELFYAML::Chunk *>
ELFDumper<ELFT>::dumpSpecialSection(const Elf_Shdr *Shdr) {
auto NameOrErr = getUniquedSectionName(Shdr);
if (!NameOrErr)