diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -148,7 +148,12 @@ // content written. Optional ShSize; - Section(SectionKind Kind) : Kind(Kind) {} + // Usually sections are not created implicitly, but loaded from YAML. + // 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(); }; diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp --- a/llvm/tools/yaml2obj/yaml2elf.cpp +++ b/llvm/tools/yaml2obj/yaml2elf.cpp @@ -17,6 +17,7 @@ #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/ObjectYAML/ELFYAML.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/WithColor.h" @@ -130,7 +131,7 @@ NameToIdxMap SN2I; NameToIdxMap SymN2I; - const ELFYAML::Object &Doc; + ELFYAML::Object &Doc; bool buildSectionIndex(); bool buildSymbolIndex(ArrayRef Symbols); @@ -174,12 +175,10 @@ bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::DynamicSection &Section, ContiguousBlobAccumulator &CBA); - std::vector implicitSectionNames() const; - - ELFState(const ELFYAML::Object &D) : Doc(D) {} + ELFState(ELFYAML::Object &D); public: - static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc); + static int writeELF(raw_ostream &OS, ELFYAML::Object &Doc); private: void finalizeStrings(); @@ -187,6 +186,30 @@ } // end anonymous namespace template +ELFState::ELFState(ELFYAML::Object &D) : Doc(D) { + StringSet<> DocSections; + for (std::unique_ptr &D : Doc.Sections) + if (!D->Name.empty()) + DocSections.insert(D->Name); + + std::vector ImplicitSections = {".symtab", ".strtab", ".shstrtab"}; + if (!Doc.DynamicSymbols.empty()) + ImplicitSections.insert(ImplicitSections.end(), {".dynsym", ".dynstr"}); + + // Insert placeholders for implicit sections that are not + // defined explicitly in YAML. + for (StringRef SecName : ImplicitSections) { + if (DocSections.count(SecName)) + continue; + + std::unique_ptr Sec = llvm::make_unique( + ELFYAML::Section::SectionKind::RawContent, true /*IsImplicit*/); + Sec->Name = SecName; + Doc.Sections.push_back(std::move(Sec)); + } +} + +template void ELFState::initELFHeader(Elf_Ehdr &Header) { using namespace llvm::ELF; zero(Header); @@ -292,36 +315,28 @@ bool ELFState::initSectionHeaders(ELFState &State, std::vector &SHeaders, ContiguousBlobAccumulator &CBA) { - // Build a list of sections we are going to add implicitly. - std::vector ImplicitSections; - for (StringRef Name : State.implicitSectionNames()) - if (State.SN2I.get(Name) > Doc.Sections.size()) - ImplicitSections.push_back(Name); - // 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() + ImplicitSections.size() + 1); + SHeaders.resize(Doc.Sections.size() + 1); zero(SHeaders[0]); - for (size_t I = 1; I < Doc.Sections.size() + ImplicitSections.size() + 1; ++I) { + for (size_t I = 1; I < Doc.Sections.size() + 1; ++I) { Elf_Shdr &SHeader = SHeaders[I]; zero(SHeader); - ELFYAML::Section *Sec = - I > Doc.Sections.size() ? nullptr : Doc.Sections[I - 1].get(); + ELFYAML::Section *Sec = Doc.Sections[I - 1].get(); // 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. - StringRef SecName = - Sec ? Sec->Name : ImplicitSections[I - Doc.Sections.size() - 1]; - if (initImplicitHeader(State, CBA, SHeader, SecName, Sec)) + if (initImplicitHeader(State, CBA, SHeader, Sec->Name, + Sec->IsImplicit ? nullptr : Sec)) continue; assert(Sec && "It can't be null unless it is an implicit section. But all " "implicit sections should already have been handled above."); - SHeader.sh_name = DotShStrtab.getOffset(dropUniqueSuffix(SecName)); + SHeader.sh_name = DotShStrtab.getOffset(dropUniqueSuffix(Sec->Name)); SHeader.sh_type = Sec->Type; if (Sec->Flags) SHeader.sh_flags = *Sec->Flags; @@ -940,15 +955,6 @@ } } - auto SecNo = 1 + Doc.Sections.size(); - // Add special sections after input sections, if necessary. - for (StringRef Name : implicitSectionNames()) - if (SN2I.addName(Name, SecNo)) { - // Account for this section, since it wasn't in the Doc - ++SecNo; - DotShStrtab.add(Name); - } - DotShStrtab.finalize(); return true; } @@ -1007,7 +1013,7 @@ } template -int ELFState::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { +int ELFState::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) { ELFState State(Doc); // Finalize .strtab and .dynstr sections. We do that early because want to @@ -1050,13 +1056,6 @@ return 0; } -template -std::vector ELFState::implicitSectionNames() const { - if (Doc.DynamicSymbols.empty()) - return {".symtab", ".strtab", ".shstrtab"}; - return {".symtab", ".strtab", ".shstrtab", ".dynsym", ".dynstr"}; -} - int yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) { bool IsLE = Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB); bool Is64Bit = Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);