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 @@ -296,13 +296,15 @@ Optional NoHeaders; size_t getNumHeaders(size_t SectionsNum) const { - if (IsImplicit) + if (IsImplicit || isDefault()) return SectionsNum; if (NoHeaders) return (*NoHeaders) ? 0 : SectionsNum; return (Sections ? Sections->size() : 0) + /*Null section*/ 1; } + bool isDefault() const { return !Sections && !Excluded && !NoHeaders; } + static constexpr StringRef TypeStr = "SectionHeaderTable"; }; diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -555,7 +555,8 @@ const ELFYAML::SectionHeaderTable &SectionHeaders = Doc.getSectionHeaderTable(); if (SectionHeaders.IsImplicit || - (SectionHeaders.NoHeaders && !SectionHeaders.NoHeaders.getValue())) + (SectionHeaders.NoHeaders && !SectionHeaders.NoHeaders.getValue()) || + SectionHeaders.isDefault()) return Index; assert(!SectionHeaders.NoHeaders.getValueOr(false) || @@ -1744,7 +1745,8 @@ DenseMap ELFState::buildSectionHeaderReorderMap() { const ELFYAML::SectionHeaderTable &SectionHeaders = Doc.getSectionHeaderTable(); - if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders) + if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders || + SectionHeaders.isDefault()) return DenseMap(); DenseMap Ret; diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1474,9 +1474,6 @@ if (const auto *SHT = dyn_cast(C.get())) { if (SHT->NoHeaders && (SHT->Sections || SHT->Excluded || SHT->Offset)) return "NoHeaders can't be used together with Offset/Sections/Excluded"; - if (!SHT->NoHeaders && !SHT->Sections && !SHT->Excluded) - return "SectionHeaderTable can't be empty. Use 'NoHeaders' key to drop " - "the section header table"; return ""; } diff --git a/llvm/test/tools/yaml2obj/ELF/section-headers.yaml b/llvm/test/tools/yaml2obj/ELF/section-headers.yaml --- a/llvm/test/tools/yaml2obj/ELF/section-headers.yaml +++ b/llvm/test/tools/yaml2obj/ELF/section-headers.yaml @@ -151,10 +151,18 @@ Sections: [] NoHeaders: [[NOHEADERS]] -## Check that we do not allow an empty SectionHeaderTable tag and suggest to use an explicit syntax instead. -# RUN: not yaml2obj %s --docnum=5 -o /dev/null 2>&1 | FileCheck %s --check-prefix=NO-VALUE +## Check that we allow using an empty SectionHeaderTable definition. +## It can be used to emit the default section header table at an arbitrary position. -# NO-VALUE: SectionHeaderTable can't be empty. Use 'NoHeaders' key to drop the section header table +# RUN: yaml2obj %s --docnum=5 -o %t5.novalues +# RUN: llvm-readelf --sections %t5.novalues | \ +# RUN: FileCheck %s --check-prefix=NO-VALUES + +## Check we placed the section header table before the .foo section. + +# NO-VALUES: There are 4 section headers, starting at offset 0x40: +# NO-VALUES: [Nr] Name Type Address Off Size +# NO-VALUES: [ 1] .foo PROGBITS 0000000000000000 000140 000000 --- !ELF FileHeader: @@ -162,9 +170,9 @@ Data: ELFDATA2LSB Type: ET_REL Sections: + - Type: SectionHeaderTable - Name: .foo Type: SHT_PROGBITS - - Type: SectionHeaderTable ## Test that we are still able to override e_shoff, e_shnum and e_shstrndx ## fields even when we do not produce section headers.