Index: llvm/lib/ObjectYAML/ELFEmitter.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFEmitter.cpp +++ llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -221,6 +221,8 @@ void assignSectionAddress(Elf_Shdr &SHeader, ELFYAML::Section *YAMLSec); + BumpPtrAllocator StringAlloc; + public: static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc, yaml::ErrorHandler EH); @@ -241,11 +243,6 @@ ELFState::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH) : Doc(D), ErrHandler(EH) { std::vector Sections = Doc.getSections(); - StringSet<> DocSections; - 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 (Sections.empty() || Sections.front()->Type != ELF::SHT_NULL) Doc.Chunks.insert( @@ -253,6 +250,19 @@ std::make_unique( ELFYAML::Chunk::ChunkKind::RawContent, /*IsImplicit=*/true)); + // We add a technical prefix for each unnamed section/fill. It does not affect + // the output, but allows us to map them by name in the code and + // report better error messages. + StringSet<> DocSections; + StringRef SuffixPrefix = " [unnamed, index #"; + for (size_t I = 0; I < Doc.Chunks.size(); ++I) { + const std::unique_ptr &C = Doc.Chunks[I]; + if (C->Name.empty()) + C->Name = StringRef(Twine(SuffixPrefix + Twine(I) + "]").str()) + .copy(StringAlloc); + DocSections.insert(C->Name); + } + std::vector ImplicitSections; if (Doc.DynamicSymbols) ImplicitSections.insert(ImplicitSections.end(), {".dynsym", ".dynstr"}); @@ -415,7 +425,6 @@ // valid SHN_UNDEF entry since SHT_NULL == 0. SHeaders.resize(Doc.getSections().size()); - size_t SecNdx = -1; for (const std::unique_ptr &D : Doc.Chunks) { if (auto S = dyn_cast(D.get())) { writeFill(*S, CBA); @@ -423,15 +432,16 @@ continue; } - ++SecNdx; ELFYAML::Section *Sec = cast(D.get()); - if (SecNdx == 0 && Sec->IsImplicit) + bool IsSpecialUndefSec = D == Doc.Chunks.front(); + if (IsSpecialUndefSec && 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. + size_t SecNdx = IsSpecialUndefSec ? 0 : SN2I.get(Sec->Name); Elf_Shdr &SHeader = SHeaders[SecNdx]; if (initImplicitHeader(CBA, SHeader, Sec->Name, Sec->IsImplicit ? nullptr : Sec)) @@ -452,7 +462,7 @@ if (!Sec->Link.empty()) SHeader.sh_link = toSectionIndex(Sec->Link, Sec->Name); - if (SecNdx == 0) { + if (IsSpecialUndefSec) { if (auto RawSec = dyn_cast(Sec)) { // We do not write any content for special SHN_UNDEF section. if (RawSec->Size) @@ -1412,9 +1422,6 @@ if (IsSection) ++SecNdx; - if (C->Name.empty()) - continue; - if (!Seen.insert(C->Name).second) reportError("repeated section/fill name: '" + C->Name + "' at YAML section/fill number " + Twine(I)); Index: llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml =================================================================== --- llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml +++ llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml @@ -128,7 +128,8 @@ # RUN: not yaml2obj --docnum=6 %s -o %t6 2>&1 | FileCheck %s --check-prefix=CASE4 -# CASE4: error: unknown section referenced: '.foo' by YAML section '' +# CASE4: error: unknown section referenced: '.foo' by YAML section ' [unnamed, index #0]' +# CASE4-NEXT: error: unknown section referenced: '.bar' by YAML section ' [unnamed, index #1]' --- !ELF FileHeader: @@ -139,6 +140,8 @@ Sections: - Type: SHT_NULL Link: .foo + - Type: SHT_NULL + Link: .bar ## Check that null section fields are set to zero, if they are unspecified. Index: llvm/test/tools/yaml2obj/ELF/section-link.yaml =================================================================== --- llvm/test/tools/yaml2obj/ELF/section-link.yaml +++ llvm/test/tools/yaml2obj/ELF/section-link.yaml @@ -28,8 +28,10 @@ # RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --check-prefix=ERR -# ERR: error: unknown section referenced: '.unknown1' by YAML section '.foo' -# ERR: error: unknown section referenced: '.unknown2' by YAML section '.bar' +# ERR: error: unknown section referenced: '.unknown1' by YAML section '.foo' +# ERR-NEXT: error: unknown section referenced: '.unknown2' by YAML section ' [unnamed, index #2]' +# ERR-NEXT: error: unknown section referenced: '.unknown3' by YAML section '.bar' +# ERR-NEXT: error: unknown section referenced: '.unknown4' by YAML section ' [unnamed, index #4]' --- !ELF FileHeader: @@ -41,9 +43,13 @@ - Name: .foo Type: SHT_PROGBITS Link: .unknown1 + - Type: SHT_PROGBITS + Link: .unknown2 - Name: .bar Type: SHT_PROGBITS - Link: .unknown2 + Link: .unknown3 + - Type: SHT_PROGBITS + Link: .unknown4 ## Check we link SHT_GROUP to a symbol table by default if it exists. ## Also, check we can set an arbitrary value for sh_link.