Index: llvm/include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- llvm/include/llvm/ObjectYAML/ELFYAML.h +++ llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -146,10 +146,18 @@ SymtabShndxSection, Symver, MipsABIFlags, - Addrsig + Addrsig, + SyntheticFiller }; + SectionKind Kind; StringRef Name; + + Section(SectionKind K) : Kind(K) {} + virtual ~Section(); +}; + +struct RegularSection : public Section { ELF_SHT Type; Optional Flags; llvm::yaml::Hex64 Address; @@ -161,9 +169,12 @@ // 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(); + RegularSection(SectionKind Kind, bool IsImplicit = false) + : Section(Kind), IsImplicit(IsImplicit) {} + + static bool classof(const Section *S) { + return S->Kind != SectionKind::SyntheticFiller; + } // The following members are used to override section fields which is // useful for creating invalid objects. @@ -181,73 +192,96 @@ Optional ShSize; }; -struct StackSizesSection : Section { +// SyntheticFiller 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. +struct SyntheticFiller : Section { + yaml::BinaryRef Pattern; + llvm::yaml::Hex64 Size; + + // We have to remember the offset of the filler, because it does not have + // a corresponding section header, like normal section. But we still might + // need this information when writing the output. + uint64_t ShOffset; + + SyntheticFiller() : Section(SectionKind::SyntheticFiller) {} + + static bool classof(const Section *S) { + return S->Kind == SectionKind::SyntheticFiller; + } +}; + +struct StackSizesSection : RegularSection { Optional Content; Optional Size; Optional> Entries; - StackSizesSection() : Section(SectionKind::StackSizes) {} + StackSizesSection() : RegularSection(SectionKind::StackSizes) {} static bool classof(const Section *S) { return S->Kind == SectionKind::StackSizes; } - static bool nameMatches(StringRef Name) { - return Name == ".stack_sizes"; - } + static bool nameMatches(StringRef Name) { return Name == ".stack_sizes"; } }; -struct DynamicSection : Section { +struct DynamicSection : RegularSection { std::vector Entries; Optional Content; - DynamicSection() : Section(SectionKind::Dynamic) {} + DynamicSection() : RegularSection(SectionKind::Dynamic) {} static bool classof(const Section *S) { return S->Kind == SectionKind::Dynamic; } }; -struct RawContentSection : Section { +struct RawContentSection : RegularSection { Optional Content; Optional Size; Optional Info; - RawContentSection() : Section(SectionKind::RawContent) {} + RawContentSection() : RegularSection(SectionKind::RawContent) {} static bool classof(const Section *S) { return S->Kind == SectionKind::RawContent; } }; -struct NoBitsSection : Section { +struct NoBitsSection : RegularSection { llvm::yaml::Hex64 Size; - NoBitsSection() : Section(SectionKind::NoBits) {} + NoBitsSection() : RegularSection(SectionKind::NoBits) {} static bool classof(const Section *S) { return S->Kind == SectionKind::NoBits; } }; -struct NoteSection : Section { +struct NoteSection : RegularSection { Optional Content; Optional Size; Optional> Notes; - NoteSection() : Section(SectionKind::Note) {} - static bool classof(const Section *S) { return S->Kind == SectionKind::Note; } + NoteSection() : RegularSection(SectionKind::Note) {} + + static bool classof(const Section *S) { + return S->Kind == SectionKind::Note; + } }; -struct HashSection : Section { +struct HashSection : RegularSection { Optional Content; Optional Size; Optional> Bucket; Optional> Chain; - HashSection() : Section(SectionKind::Hash) {} + HashSection() : RegularSection(SectionKind::Hash) {} - static bool classof(const Section *S) { return S->Kind == SectionKind::Hash; } + static bool classof(const Section *S) { + return S->Kind == SectionKind::Hash; + } }; struct GnuHashHeader { @@ -270,7 +304,7 @@ llvm::yaml::Hex32 Shift2; }; -struct GnuHashSection : Section { +struct GnuHashSection : RegularSection { Optional Content; Optional Header; @@ -278,9 +312,11 @@ Optional> HashBuckets; Optional> HashValues; - GnuHashSection() : Section(SectionKind::GnuHash) {} + GnuHashSection() : RegularSection(SectionKind::GnuHash) {} - static bool classof(const Section *S) { return S->Kind == SectionKind::GnuHash; } + static bool classof(const Section *S) { + return S->Kind == SectionKind::GnuHash; + } }; struct VernauxEntry { @@ -296,11 +332,11 @@ std::vector AuxV; }; -struct VerneedSection : Section { +struct VerneedSection : RegularSection { std::vector VerneedV; llvm::yaml::Hex64 Info; - VerneedSection() : Section(SectionKind::Verneed) {} + VerneedSection() : RegularSection(SectionKind::Verneed) {} static bool classof(const Section *S) { return S->Kind == SectionKind::Verneed; @@ -316,21 +352,22 @@ Optional Index; }; -struct AddrsigSection : Section { +struct AddrsigSection : RegularSection { Optional Content; Optional Size; Optional> Symbols; - AddrsigSection() : Section(SectionKind::Addrsig) {} + AddrsigSection() : RegularSection(SectionKind::Addrsig) {} + static bool classof(const Section *S) { return S->Kind == SectionKind::Addrsig; } }; -struct SymverSection : Section { +struct SymverSection : RegularSection { std::vector Entries; - SymverSection() : Section(SectionKind::Symver) {} + SymverSection() : RegularSection(SectionKind::Symver) {} static bool classof(const Section *S) { return S->Kind == SectionKind::Symver; @@ -345,24 +382,24 @@ std::vector VerNames; }; -struct VerdefSection : Section { +struct VerdefSection : RegularSection { std::vector Entries; llvm::yaml::Hex64 Info; - VerdefSection() : Section(SectionKind::Verdef) {} + VerdefSection() : RegularSection(SectionKind::Verdef) {} static bool classof(const Section *S) { return S->Kind == SectionKind::Verdef; } }; -struct Group : Section { +struct Group : RegularSection { // Members of a group contain a flag and a list of section indices // that are part of the group. std::vector Members; Optional Signature; /* Info */ - Group() : Section(SectionKind::Group) {} + Group() : RegularSection(SectionKind::Group) {} static bool classof(const Section *S) { return S->Kind == SectionKind::Group; @@ -376,21 +413,21 @@ Optional Symbol; }; -struct RelocationSection : Section { +struct RelocationSection : RegularSection { std::vector Relocations; StringRef RelocatableSec; /* Info */ - RelocationSection() : Section(SectionKind::Relocation) {} + RelocationSection() : RegularSection(SectionKind::Relocation) {} static bool classof(const Section *S) { return S->Kind == SectionKind::Relocation; } }; -struct SymtabShndxSection : Section { +struct SymtabShndxSection : RegularSection { std::vector Entries; - SymtabShndxSection() : Section(SectionKind::SymtabShndxSection) {} + SymtabShndxSection() : RegularSection(SectionKind::SymtabShndxSection) {} static bool classof(const Section *S) { return S->Kind == SectionKind::SymtabShndxSection; @@ -398,7 +435,7 @@ }; // Represents .MIPS.abiflags section -struct MipsABIFlags : Section { +struct MipsABIFlags : RegularSection { llvm::yaml::Hex16 Version; MIPS_ISA ISALevel; llvm::yaml::Hex8 ISARevision; @@ -411,7 +448,7 @@ MIPS_AFL_FLAGS1 Flags1; llvm::yaml::Hex32 Flags2; - MipsABIFlags() : Section(SectionKind::MipsABIFlags) {} + MipsABIFlags() : RegularSection(SectionKind::MipsABIFlags) {} static bool classof(const Section *S) { return S->Kind == SectionKind::MipsABIFlags; @@ -421,13 +458,25 @@ struct Object { FileHeader Header; std::vector ProgramHeaders; - std::vector> Sections; + + // An object might contain output section descriptions as well as + // custom data that does not belong to any section. + std::vector> Descriptions; + // 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> Symbols; std::vector DynamicSymbols; + + std::vector getSections() { + std::vector Ret; + for (const std::unique_ptr
&Sec : Descriptions) + if (auto S = dyn_cast(Sec.get())) + Ret.push_back(S); + return Ret; + } }; } // end namespace ELFYAML Index: llvm/include/llvm/ObjectYAML/YAML.h =================================================================== --- llvm/include/llvm/ObjectYAML/YAML.h +++ llvm/include/llvm/ObjectYAML/YAML.h @@ -85,7 +85,8 @@ /// 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 number of the bytes to write. + 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. Index: llvm/lib/ObjectYAML/ELFEmitter.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFEmitter.cpp +++ llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -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 @@ unsigned size() const { return Map.size(); } }; +namespace { +struct PhdrEntry { + uint64_t ShOffset; + uint64_t ShSize; + uint32_t ShType; + uint64_t ShAddrAlign; +}; +}; // 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". @@ -130,18 +140,23 @@ void buildSymbolIndexes(); void initProgramHeaders(std::vector &PHeaders); bool initImplicitHeader(ContiguousBlobAccumulator &CBA, Elf_Shdr &Header, - StringRef SecName, ELFYAML::Section *YAMLSec); + StringRef SecName, ELFYAML::RegularSection *YAMLSec); void initSectionHeaders(std::vector &SHeaders, ContiguousBlobAccumulator &CBA); void initSymtabSectionHeader(Elf_Shdr &SHeader, SymtabType STType, ContiguousBlobAccumulator &CBA, - ELFYAML::Section *YAMLSec); + ELFYAML::RegularSection *YAMLSec); void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, StringTableBuilder &STB, ContiguousBlobAccumulator &CBA, - ELFYAML::Section *YAMLSec); + ELFYAML::RegularSection *YAMLSec); void setProgramHeaderLayout(std::vector &PHeaders, std::vector &SHeaders); + + std::vector + getEntriesForPhdr(const ELFYAML::ProgramHeader &Phdr, + std::vector &SHeaders); + void finalizeStrings(); void writeELFHeader(ContiguousBlobAccumulator &CBA, raw_ostream &OS); void writeSectionContent(Elf_Shdr &SHeader, @@ -186,6 +201,9 @@ const ELFYAML::GnuHashSection &Section, ContiguousBlobAccumulator &CBA); + void writeFiller(ELFYAML::SyntheticFiller &Filler, + ContiguousBlobAccumulator &CBA); + ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH); public: @@ -208,15 +226,16 @@ ELFState::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH) : Doc(D), ErrHandler(EH) { StringSet<> DocSections; - for (std::unique_ptr &D : Doc.Sections) - if (!D->Name.empty()) - DocSections.insert(D->Name); + for (const ELFYAML::Section *Sec : Doc.getSections()) + 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(), - std::make_unique( + std::vector Sections = Doc.getSections(); + if (Sections.empty() || Sections.front()->Type != ELF::SHT_NULL) + Doc.Descriptions.insert( + Doc.Descriptions.begin(), + std::make_unique( ELFYAML::Section::SectionKind::RawContent, /*IsImplicit=*/true)); std::vector ImplicitSections; @@ -233,10 +252,11 @@ if (DocSections.count(SecName)) continue; - std::unique_ptr Sec = std::make_unique( - ELFYAML::Section::SectionKind::RawContent, true /*IsImplicit*/); + std::unique_ptr Sec = + std::make_unique( + ELFYAML::Section::SectionKind::RawContent, true /*IsImplicit*/); Sec->Name = SecName; - Doc.Sections.push_back(std::move(Sec)); + Doc.Descriptions.push_back(std::move(Sec)); } } @@ -274,7 +294,7 @@ 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"); @@ -328,7 +348,7 @@ template bool ELFState::initImplicitHeader(ContiguousBlobAccumulator &CBA, Elf_Shdr &Header, StringRef SecName, - ELFYAML::Section *YAMLSec) { + ELFYAML::RegularSection *YAMLSec) { // Check if the header was already initialized. if (Header.sh_offset) return false; @@ -371,18 +391,25 @@ 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()); + + size_t SecNdx = -1; + for (const std::unique_ptr& D : Doc.Descriptions) { + if (auto S = dyn_cast(D.get())) { + writeFiller(*S, CBA); + continue; + } - for (size_t I = 0; I < Doc.Sections.size(); ++I) { - ELFYAML::Section *Sec = Doc.Sections[I].get(); - if (I == 0 && Sec->IsImplicit) + ++SecNdx; + ELFYAML::RegularSection *Sec = cast(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 +428,7 @@ if (!Sec->Link.empty()) SHeader.sh_link = toSectionIndex(Sec->Link, Sec->Name); - if (I == 0) { + if (SecNdx == 0) { if (auto RawSec = dyn_cast(Sec)) { // We do not write any content for special SHN_UNDEF section. if (RawSec->Size) @@ -521,7 +548,7 @@ void ELFState::initSymtabSectionHeader(Elf_Shdr &SHeader, SymtabType STType, ContiguousBlobAccumulator &CBA, - ELFYAML::Section *YAMLSec) { + ELFYAML::RegularSection *YAMLSec) { bool IsStatic = STType == SymtabType::Static; ArrayRef Symbols; @@ -601,7 +628,7 @@ void ELFState::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, StringTableBuilder &STB, ContiguousBlobAccumulator &CBA, - ELFYAML::Section *YAMLSec) { + ELFYAML::RegularSection *YAMLSec) { zero(SHeader); SHeader.sh_name = DotShStrtab.getOffset(Name); SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_STRTAB; @@ -640,23 +667,47 @@ HasError = true; } +template +std::vector +ELFState::getEntriesForPhdr(const ELFYAML::ProgramHeader &Phdr, + std::vector &SHeaders) { + DenseMap NameToFiller; + for (const std::unique_ptr &D : Doc.Descriptions) + if (auto S = dyn_cast(D.get())) + NameToFiller[S->Name] = S; + + std::vector 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::SyntheticFiller *Filler = + NameToFiller.lookup(SecName.Section)) { + Ret.push_back({Filler->ShOffset, Filler->Size, llvm::ELF::SHT_PROGBITS, + /*ShAddrAlign=*/1}); + continue; + } + + StringRef ErrPrefix = NameToFiller.empty() + ? "unknown section referenced: '" + : "unknown section or filler referenced: '"; + reportError(ErrPrefix + SecName.Section + "' by program header"); + } + + return Ret; +} + template void ELFState::setProgramHeaderLayout(std::vector &PHeaders, std::vector &SHeaders) { uint32_t PhdrIdx = 0; for (auto &YamlPhdr : Doc.ProgramHeaders) { Elf_Phdr &PHeader = PHeaders[PhdrIdx++]; - - std::vector 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 Entries = getEntriesForPhdr(YamlPhdr, SHeaders); if (YamlPhdr.Offset) { PHeader.p_offset = *YamlPhdr.Offset; @@ -667,19 +718,19 @@ 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 PhdrEntry &E : Entries) + PHeader.p_offset = std::min((uint64_t)PHeader.p_offset, E.ShOffset); } // 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 PhdrEntry &E : Entries) { + uint64_t End = E.ShOffset + E.ShSize; MemOffset = std::max(MemOffset, End); - if (SHeader->sh_type != llvm::ELF::SHT_NOBITS) + if (E.ShType != llvm::ELF::SHT_NOBITS) FileOffset = std::max(FileOffset, End); } @@ -696,8 +747,8 @@ // 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 PhdrEntry &E : Entries) + PHeader.p_align = std::max((uint64_t)PHeader.p_align, E.ShAddrAlign); } } } @@ -1160,15 +1211,28 @@ Section.HashValues->size() * 4; } +template +void ELFState::writeFiller(ELFYAML::SyntheticFiller &Filler, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = CBA.getOSAndAlignedOffset(Filler.ShOffset, /*Align=*/1); + + uint64_t I = 0; + size_t Size = Filler.Pattern.binary_size(); + for (; I + Size <= Filler.Size; I += Size) + Filler.Pattern.writeAsBinary(OS); + Filler.Pattern.writeAsBinary(OS, Filler.Size - I); +} + template void ELFState::buildSectionIndex() { - for (unsigned I = 0, E = Doc.Sections.size(); I != E; ++I) { - StringRef Name = Doc.Sections[I]->Name; - if (Name.empty()) + size_t I = -1; + for (ELFYAML::Section *Sec : Doc.getSections()) { + ++I; + if (Sec->Name.empty()) continue; - DotShStrtab.add(ELFYAML::dropUniqueSuffix(Name)); - if (!SN2I.addName(Name, I)) - reportError("repeated section name: '" + Name + + DotShStrtab.add(ELFYAML::dropUniqueSuffix(Sec->Name)); + if (!SN2I.addName(Sec->Name, I)) + reportError("repeated section name: '" + Sec->Name + "' at YAML section number " + Twine(I)); } @@ -1202,14 +1266,14 @@ // SHT_GNU_verdef and SHT_GNU_verneed sections might also // add strings to .dynstr section. - for (const std::unique_ptr &Sec : Doc.Sections) { - if (auto VerNeed = dyn_cast(Sec.get())) { + for (const ELFYAML::Section *Sec : Doc.getSections()) { + if (auto VerNeed = dyn_cast(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(Sec.get())) { + } else if (auto VerDef = dyn_cast(Sec)) { for (const ELFYAML::VerdefEntry &E : VerDef->Entries) for (StringRef Name : E.VerNames) DotDynstr.add(Name); Index: llvm/lib/ObjectYAML/ELFYAML.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFYAML.cpp +++ llvm/lib/ObjectYAML/ELFYAML.cpp @@ -985,7 +985,7 @@ return StringRef(); } -static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) { +static void commonSectionMapping(IO &IO, ELFYAML::RegularSection &Section) { IO.mapOptional("Name", Section.Name, StringRef()); IO.mapRequired("Type", Section.Type); IO.mapOptional("Flags", Section.Flags); @@ -1094,6 +1094,12 @@ IO.mapOptional("Symbols", Section.Symbols); } +static void fillerMapping(IO &IO, ELFYAML::SyntheticFiller &Filler) { + IO.mapOptional("Name", Filler.Name, StringRef()); + IO.mapRequired("Pattern", Filler.Pattern); + IO.mapRequired("Size", Filler.Size); +} + void MappingTraits::mapping( IO &IO, ELFYAML::SectionOrType §ionOrType) { IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType); @@ -1126,13 +1132,25 @@ void MappingTraits>::mapping( IO &IO, std::unique_ptr &Section) { - ELFYAML::ELF_SHT sectionType; - if (IO.outputting()) - sectionType = Section->Type; - else - IO.mapRequired("Type", sectionType); + ELFYAML::ELF_SHT Type; + if (IO.outputting()) { + Type = cast(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 a one + // special type named "CustomFiller". See comments for SyntheticFiller. + StringRef StrType; + IO.mapRequired("Type", StrType); + if (StrType == "CustomFiller") { + Section.reset(new ELFYAML::SyntheticFiller()); + fillerMapping(IO, *cast(Section.get())); + return; + } + + IO.mapRequired("Type", Type); + } - switch (sectionType) { + switch (Type) { case ELF::SHT_DYNAMIC: if (!IO.outputting()) Section.reset(new ELFYAML::DynamicSection()); @@ -1455,7 +1473,7 @@ IO.mapTag("!ELF", true); IO.mapRequired("FileHeader", Object.Header); IO.mapOptional("ProgramHeaders", Object.ProgramHeaders); - IO.mapOptional("Sections", Object.Sections); + IO.mapOptional("Sections", Object.Descriptions); IO.mapOptional("Symbols", Object.Symbols); IO.mapOptional("DynamicSymbols", Object.DynamicSymbols); IO.setContext(nullptr); Index: llvm/lib/ObjectYAML/YAML.cpp =================================================================== --- llvm/lib/ObjectYAML/YAML.cpp +++ llvm/lib/ObjectYAML/YAML.cpp @@ -37,15 +37,19 @@ 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()); + assert(N == UINT64_MAX || N <= 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]); + + assert(Data.size() % 2 == 0); + assert(N == UINT64_MAX || N <= Data.size() / 2); + 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); } } Index: llvm/test/tools/yaml2obj/custom-filler.yaml =================================================================== --- /dev/null +++ llvm/test/tools/yaml2obj/custom-filler.yaml @@ -0,0 +1,80 @@ +## Here we check that able to define sections with a type of "CustomFiller". +## Fillers are custom pieces of data that can be placed anywhere jsut like a normal +## output section. But they are not real output sections and you'll never +## see them in the sections header. + +## Check we can create unnamed fillers and use "Pattern" and "Size" to describe filling +## patterns. Check placing fillers affect on regular sections offsets. + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readelf --sections %t1 | FileCheck %s --ignore-case --check-prefix=BASIC + +# BASIC: Section Headers: +# BASIC: [Nr] Name Type Address Off Size +# BASIC: [ 1] .foo PROGBITS 0000000000000000 000043 000002 +# BASIC: [ 2] .bar PROGBITS 0000000000000000 000049 000001 + +# RUN: od -t x1 -v %t1 | FileCheck %s --ignore-case --check-prefix=DATA +# DATA: aa bb aa 11 22 cc dd cc dd ff + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Type: CustomFiller + Pattern: "AABB" + Size: 0x3 + - Name: .foo + Type: SHT_PROGBITS + Content: "1122" + - Type: CustomFiller + Pattern: "CCDD" + Size: 4 + - Name: .bar + Type: SHT_PROGBITS + Content: "FF" + +## Check we can use named fillers when describing program headers. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: llvm-readelf --sections --program-headers %t2 | FileCheck %s --check-prefix=PHDR + +# PHDR: [Nr] Name Type Address Off Size ES Flg Lk Inf +# PHDR: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 +# PHDR: [ 1] .bar PROGBITS 0000000000000100 0000b0 000005 00 0 0 0 +# PHDR: [ 2] .strtab STRTAB 0000000000000000 0000fa 000001 00 0 0 1 +# PHDR: [ 3] .shstrtab STRTAB 0000000000000000 0000fb 000018 00 0 0 1 + +# PHDR: Program Headers: +# PHDR: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# PHDR: LOAD 0x0000b0 0x0000000000000000 0x0000000000000000 0x00004a 0x00004a R 0x1 +# PHDR: LOAD 0x0000b5 0x0000000000000000 0x0000000000000000 0x000045 0x000045 R 0x1 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .bar + Type: SHT_PROGBITS + Size: 0x5 + Address: 0x100 + - Type: CustomFiller + Name: filler + Pattern: "00" + Size: 0x45 +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_R ] + Sections: + - Section: .bar + - Section: filler + - Type: PT_LOAD + Flags: [ PF_R ] + Sections: + - Section: filler Index: llvm/tools/obj2yaml/elf2yaml.cpp =================================================================== --- llvm/tools/obj2yaml/elf2yaml.cpp +++ llvm/tools/obj2yaml/elf2yaml.cpp @@ -52,7 +52,7 @@ std::vector &Symbols); Error dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab, StringRef StrTable, ELFYAML::Symbol &S); - Error dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S); + Error dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::RegularSection &S); Error dumpCommonRelocationSection(const Elf_Shdr *Shdr, ELFYAML::RelocationSection &S); template @@ -221,7 +221,7 @@ Expected SecOrErr = dumpDynamicSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_STRTAB: @@ -234,7 +234,7 @@ dumpSymtabShndxSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_REL: @@ -242,77 +242,77 @@ Expected SecOrErr = dumpRelocSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_GROUP: { Expected GroupOrErr = dumpGroup(&Sec); if (!GroupOrErr) return GroupOrErr.takeError(); - Y->Sections.emplace_back(*GroupOrErr); + Y->Descriptions.emplace_back(*GroupOrErr); break; } case ELF::SHT_MIPS_ABIFLAGS: { Expected SecOrErr = dumpMipsABIFlags(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_NOBITS: { Expected SecOrErr = dumpNoBitsSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_NOTE: { Expected SecOrErr = dumpNoteSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_HASH: { Expected SecOrErr = dumpHashSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_GNU_HASH: { Expected SecOrErr = dumpGnuHashSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_GNU_verdef: { Expected SecOrErr = dumpVerdefSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_GNU_versym: { Expected SecOrErr = dumpSymverSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_GNU_verneed: { Expected SecOrErr = dumpVerneedSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_LLVM_ADDRSIG: { Expected SecOrErr = dumpAddrsigSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); break; } case ELF::SHT_NULL: { @@ -334,7 +334,7 @@ if (!SpecialSecOrErr) return SpecialSecOrErr.takeError(); if (*SpecialSecOrErr) { - Y->Sections.emplace_back(*SpecialSecOrErr); + Y->Descriptions.emplace_back(*SpecialSecOrErr); break; } } @@ -343,7 +343,7 @@ dumpContentSection(&Sec); if (!SecOrErr) return SecOrErr.takeError(); - Y->Sections.emplace_back(*SecOrErr); + Y->Descriptions.emplace_back(*SecOrErr); } } } @@ -452,7 +452,7 @@ template Error ELFDumper::dumpCommonSection(const Elf_Shdr *Shdr, - ELFYAML::Section &S) { + ELFYAML::RegularSection &S) { // Dump fields. We do not dump the ShOffset field. When not explicitly // set, the value is set by yaml2obj automatically. S.Type = Shdr->sh_type;