Index: lib/ObjectYAML/ELFYAML.cpp =================================================================== --- lib/ObjectYAML/ELFYAML.cpp +++ lib/ObjectYAML/ELFYAML.cpp @@ -388,7 +388,7 @@ #define ECase(X) IO.enumCase(Value, #X, ELF::X) ECase(SHT_NULL); ECase(SHT_PROGBITS); - // No SHT_SYMTAB. Use the top-level `Symbols` key instead. + ECase(SHT_SYMTAB); // FIXME: Issue a diagnostic with this information. ECase(SHT_STRTAB); ECase(SHT_RELA); Index: test/tools/yaml2obj/section-ordering.yaml =================================================================== --- /dev/null +++ test/tools/yaml2obj/section-ordering.yaml @@ -0,0 +1,29 @@ +# Ensures that implicitly added sections can be ordered within Sections. +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj -sections %t | FileCheck %s + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + - Name: .symtab + Type: SHT_SYMTAB + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_WRITE ] + - Name: .shstrtab + Type: SHT_STRTAB + - Name: .strtab + Type: SHT_STRTAB + +# CHECK: Name: .text +# CHECK: Name: .symtab +# CHECK: Name: .data +# CHECK: Name: .shstrtab +# CHECK: Name: .strtab Index: tools/yaml2obj/yaml2elf.cpp =================================================================== --- tools/yaml2obj/yaml2elf.cpp +++ tools/yaml2obj/yaml2elf.cpp @@ -74,6 +74,13 @@ Idx = I->getValue(); return false; } + /// asserts if name is not present in the map + unsigned get(StringRef Name) const { + unsigned Idx; + assert(!lookup(Name, Idx) && "Expected section not found in index"); + return Idx; + } + unsigned size() const { return Map.size(); } }; } // end anonymous namespace @@ -144,19 +151,21 @@ ContiguousBlobAccumulator &CBA); // - SHT_NULL entry (placed first, i.e. 0'th entry) - // - symbol table (.symtab) (placed third to last) - // - string table (.strtab) (placed second to last) - // - section header string table (.shstrtab) (placed last) - unsigned getDotSymTabSecNo() const { return Doc.Sections.size() + 1; } - unsigned getDotStrTabSecNo() const { return Doc.Sections.size() + 2; } - unsigned getDotShStrTabSecNo() const { return Doc.Sections.size() + 3; } - unsigned getSectionCount() const { return Doc.Sections.size() + 4; } + // - symbol table (.symtab) (defaults to third to last) + // - string table (.strtab) (defaults to second to last) + // - section header string table (.shstrtab) (defaults to last) + unsigned getDotSymTabSecNo() const { return SN2I.get(".symtab"); } + unsigned getDotStrTabSecNo() const { return SN2I.get(".strtab"); } + unsigned getDotShStrTabSecNo() const { return SN2I.get(".shstrtab"); } + unsigned getSectionCount() const { return SN2I.size() + 1; } ELFState(const ELFYAML::Object &D) : Doc(D) {} public: static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc); }; + +static const char * const ImplicitSecNames[] = {".symtab", ".strtab", ".shstrtab"}; } // end anonymous namespace template @@ -211,10 +220,6 @@ zero(SHeader); SHeaders.push_back(SHeader); - for (const auto &Sec : Doc.Sections) - DotShStrtab.add(Sec->Name); - DotShStrtab.finalize(); - for (const auto &Sec : Doc.Sections) { zero(SHeader); SHeader.sh_name = DotShStrtab.getOffset(Sec->Name); @@ -547,10 +552,6 @@ } template bool ELFState::buildSectionIndex() { - SN2I.addName(".symtab", getDotSymTabSecNo()); - SN2I.addName(".strtab", getDotStrTabSecNo()); - SN2I.addName(".shstrtab", getDotShStrTabSecNo()); - for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) { StringRef Name = Doc.Sections[i]->Name; if (Name.empty()) @@ -561,7 +562,19 @@ << "' at YAML section number " << i << ".\n"; return false; } + DotShStrtab.add(Name); } + + auto SecNo = 1 + Doc.Sections.size(); + // Add special sections after input sections, if necessary. + for (const auto &Name : ImplicitSecNames) + if (!SN2I.addName(Name, SecNo)) { + // Account for this section, since it wasn't in the Doc + ++SecNo; + DotShStrtab.add(Name); + } + + DotShStrtab.finalize(); return true; } @@ -608,32 +621,23 @@ Header.e_shentsize * Header.e_shnum; ContiguousBlobAccumulator CBA(SectionContentBeginOffset); - // Doc might not contain .symtab, .strtab and .shstrtab sections, - // but we will emit them, so make sure to add them to ShStrTabSHeader. - State.DotShStrtab.add(".symtab"); - State.DotShStrtab.add(".strtab"); - State.DotShStrtab.add(".shstrtab"); - std::vector SHeaders; + SHeaders.reserve(State.SN2I.size()); if(!State.initSectionHeaders(SHeaders, CBA)) return 1; - // .symtab section. - Elf_Shdr SymtabSHeader; - State.initSymtabSectionHeader(SymtabSHeader, CBA); - SHeaders.push_back(SymtabSHeader); - - // .strtab string table header. - Elf_Shdr DotStrTabSHeader; - State.initStrtabSectionHeader(DotStrTabSHeader, ".strtab", State.DotStrtab, - CBA); - SHeaders.push_back(DotStrTabSHeader); - - // .shstrtab string table header. - Elf_Shdr ShStrTabSHeader; - State.initStrtabSectionHeader(ShStrTabSHeader, ".shstrtab", State.DotShStrtab, - CBA); - SHeaders.push_back(ShStrTabSHeader); + // Populate SHeaders with implicit sections not present in the Doc + for (const auto &Name : ImplicitSecNames) + if (State.SN2I.get(Name) >= SHeaders.size()) + SHeaders.push_back({}); + + // Initialize the implicit sections + auto Index = State.SN2I.get(".symtab"); + State.initSymtabSectionHeader(SHeaders[Index], CBA); + Index = State.SN2I.get(".strtab"); + State.initStrtabSectionHeader(SHeaders[Index], ".strtab", State.DotStrtab, CBA); + Index = State.SN2I.get(".shstrtab"); + State.initStrtabSectionHeader(SHeaders[Index], ".shstrtab", State.DotShStrtab, CBA); // Now we can decide segment offsets State.setProgramHeaderLayout(PHeaders, SHeaders);