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 @@ -93,6 +93,7 @@ struct SectionHeaderTable { std::vector Sections; + Optional> Excluded; }; struct SectionName { 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 @@ -128,6 +128,8 @@ NameToIdxMap DynSymN2I; ELFYAML::Object &Doc; + StringSet<> ExcludedSectionHeaders; + uint64_t LocationCounter = 0; bool HasError = false; yaml::ErrorHandler ErrHandler; @@ -230,6 +232,8 @@ uint64_t alignToOffset(ContiguousBlobAccumulator &CBA, uint64_t Align, llvm::Optional Offset); + uint64_t getSectionNameOffset(StringRef Name); + public: static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc, yaml::ErrorHandler EH); @@ -350,7 +354,8 @@ if (Doc.Header.SHStrNdx) Header.e_shstrndx = *Doc.Header.SHStrNdx; - else if (!Doc.SectionHeaders || !Doc.SectionHeaders->Sections.empty()) + else if ((!Doc.SectionHeaders || !Doc.SectionHeaders->Sections.empty()) && + !ExcludedSectionHeaders.count(".shstrtab")) Header.e_shstrndx = SN2I.get(".shstrtab"); else Header.e_shstrndx = 0; @@ -397,18 +402,32 @@ template unsigned ELFState::toSectionIndex(StringRef S, StringRef LocSec, StringRef LocSym) { + assert(LocSec.empty() || LocSym.empty()); + unsigned Index; - if (SN2I.lookup(S, Index) || to_integer(S, Index)) + if (!SN2I.lookup(S, Index) && !to_integer(S, Index)) { + if (!LocSym.empty()) + reportError("unknown section referenced: '" + S + "' by YAML symbol '" + + LocSym + "'"); + else + reportError("unknown section referenced: '" + S + "' by YAML section '" + + LocSec + "'"); + return 0; + } + + if (!Doc.SectionHeaders || !Doc.SectionHeaders->Excluded) return Index; - assert(LocSec.empty() || LocSym.empty()); - if (!LocSym.empty()) - reportError("unknown section referenced: '" + S + "' by YAML symbol '" + - LocSym + "'"); - else - reportError("unknown section referenced: '" + S + "' by YAML section '" + - LocSec + "'"); - return 0; + assert(!Doc.SectionHeaders->Sections.empty()); + if (Index >= Doc.SectionHeaders->Sections.size()) { + if (LocSym.empty()) + reportError("unable to link '" + LocSec + "' to excluded section '" + S + + "'"); + else + reportError("excluded section referenced: '" + S + "' by symbol '" + + LocSym + "'"); + } + return Index; } template @@ -499,6 +518,15 @@ } template +uint64_t ELFState::getSectionNameOffset(StringRef Name) { + // If a section is excluded from section headers, we do not save its name in + // the string table. + if (ExcludedSectionHeaders.count(Name)) + return 0; + return DotShStrtab.getOffset(Name); +} + +template void ELFState::initSectionHeaders(std::vector &SHeaders, ContiguousBlobAccumulator &CBA) { // Ensure SHN_UNDEF entry is present. An all-zero section header is a @@ -531,7 +559,7 @@ "implicit sections should already have been handled above."); SHeader.sh_name = - DotShStrtab.getOffset(ELFYAML::dropUniqueSuffix(Sec->Name)); + getSectionNameOffset(ELFYAML::dropUniqueSuffix(Sec->Name)); SHeader.sh_type = Sec->Type; if (Sec->Flags) SHeader.sh_flags = *Sec->Flags; @@ -716,7 +744,7 @@ } zero(SHeader); - SHeader.sh_name = DotShStrtab.getOffset(IsStatic ? ".symtab" : ".dynsym"); + SHeader.sh_name = getSectionNameOffset(IsStatic ? ".symtab" : ".dynsym"); if (YAMLSec) SHeader.sh_type = YAMLSec->Type; @@ -733,10 +761,13 @@ // added implicitly and we should be able to leave the Link zeroed if // .dynstr is not defined. unsigned Link = 0; - if (IsStatic) - Link = SN2I.get(".strtab"); - else - SN2I.lookup(".dynstr", Link); + if (IsStatic) { + if (!ExcludedSectionHeaders.count(".strtab")) + Link = SN2I.get(".strtab"); + } else { + if (!ExcludedSectionHeaders.count(".dynstr")) + SN2I.lookup(".dynstr", Link); + } SHeader.sh_link = Link; } @@ -777,7 +808,7 @@ ContiguousBlobAccumulator &CBA, ELFYAML::Section *YAMLSec) { zero(SHeader); - SHeader.sh_name = DotShStrtab.getOffset(Name); + SHeader.sh_name = getSectionNameOffset(Name); SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_STRTAB; SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1; @@ -832,7 +863,7 @@ ContiguousBlobAccumulator &CBA, ELFYAML::Section *YAMLSec) { zero(SHeader); - SHeader.sh_name = DotShStrtab.getOffset(ELFYAML::dropUniqueSuffix(Name)); + SHeader.sh_name = getSectionNameOffset(ELFYAML::dropUniqueSuffix(Name)); SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_PROGBITS; SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1; SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign, @@ -866,9 +897,8 @@ else if (Name == ".debug_str") SHeader.sh_flags = ELF::SHF_MERGE | ELF::SHF_STRINGS; - unsigned Link = 0; - if (YAMLSec && !YAMLSec->Link.empty() && SN2I.lookup(YAMLSec->Link, Link)) - SHeader.sh_link = Link; + if (YAMLSec && !YAMLSec->Link.empty()) + SHeader.sh_link = toSectionIndex(YAMLSec->Link, Name); assignSectionAddress(SHeader, YAMLSec); } @@ -992,7 +1022,8 @@ // For relocation section set link to .symtab by default. unsigned Link = 0; - if (Section.Link.empty() && SN2I.lookup(".symtab", Link)) + if (Section.Link.empty() && !ExcludedSectionHeaders.count(".symtab") && + SN2I.lookup(".symtab", Link)) SHeader.sh_link = Link; if (!Section.RelocatableSec.empty()) @@ -1065,7 +1096,8 @@ "Section type is not SHT_GROUP"); unsigned Link = 0; - if (Section.Link.empty() && SN2I.lookup(".symtab", Link)) + if (Section.Link.empty() && !ExcludedSectionHeaders.count(".symtab") && + SN2I.lookup(".symtab", Link)) SHeader.sh_link = Link; SHeader.sh_entsize = 4; @@ -1190,7 +1222,8 @@ SHeader.sh_entsize = 16; unsigned Link = 0; - if (Section.Link.empty() && SN2I.lookup(".symtab", Link)) + if (Section.Link.empty() && !ExcludedSectionHeaders.count(".symtab") && + SN2I.lookup(".symtab", Link)) SHeader.sh_link = Link; raw_ostream &OS = CBA.getOS(); @@ -1218,7 +1251,8 @@ const ELFYAML::HashSection &Section, ContiguousBlobAccumulator &CBA) { unsigned Link = 0; - if (Section.Link.empty() && SN2I.lookup(".dynsym", Link)) + if (Section.Link.empty() && !ExcludedSectionHeaders.count(".dynsym") && + SN2I.lookup(".dynsym", Link)) SHeader.sh_link = Link; raw_ostream &OS = CBA.getOS(); @@ -1408,7 +1442,8 @@ const ELFYAML::AddrsigSection &Section, ContiguousBlobAccumulator &CBA) { unsigned Link = 0; - if (Section.Link.empty() && SN2I.lookup(".symtab", Link)) + if (Section.Link.empty() && !ExcludedSectionHeaders.count(".symtab") && + SN2I.lookup(".symtab", Link)) SHeader.sh_link = Link; raw_ostream &OS = CBA.getOS(); @@ -1474,7 +1509,8 @@ const ELFYAML::GnuHashSection &Section, ContiguousBlobAccumulator &CBA) { unsigned Link = 0; - if (Section.Link.empty() && SN2I.lookup(".dynsym", Link)) + if (Section.Link.empty() && !ExcludedSectionHeaders.count(".dynsym") && + SN2I.lookup(".dynsym", Link)) SHeader.sh_link = Link; raw_ostream &OS = CBA.getOS(); @@ -1556,12 +1592,20 @@ DenseMap Ret; size_t SecNdx = 0; StringSet<> Seen; - for (const ELFYAML::SectionHeader &Hdr : Doc.SectionHeaders->Sections) { + + auto AddSection = [&](const ELFYAML::SectionHeader &Hdr) { if (!Ret.try_emplace(Hdr.Name, ++SecNdx).second) reportError("repeated section name: '" + Hdr.Name + "' in the section header description"); Seen.insert(Hdr.Name); - } + }; + + for (const ELFYAML::SectionHeader &Hdr : Doc.SectionHeaders->Sections) + AddSection(Hdr); + + if (Doc.SectionHeaders->Excluded) + for (const ELFYAML::SectionHeader &Hdr : *Doc.SectionHeaders->Excluded) + AddSection(Hdr); for (const ELFYAML::Section *S : Doc.getSections()) { // Ignore special first SHT_NULL section. @@ -1569,7 +1613,7 @@ continue; if (!Seen.count(S->Name)) reportError("section '" + S->Name + - "' should be present in the 'Sections' list"); + "' should be present in the 'Sections' or 'Excluded' lists"); Seen.erase(S->Name); } @@ -1579,21 +1623,36 @@ return Ret; } +static bool hasSectionHeader(const ELFYAML::Object &Doc, size_t SecNdx) { + if (!Doc.SectionHeaders) + return true; + return SecNdx < Doc.SectionHeaders->Sections.size(); +} + template void ELFState::buildSectionIndex() { - // A YAML description can have an explicit section header declaration that allows - // to change the order of section headers. + // A YAML description can have an explicit section header declaration that + // allows to change the order of section headers. DenseMap ReorderMap = buildSectionHeaderReorderMap(); + if (HasError) + return; + + // Build excluded section headers map. + if (Doc.SectionHeaders && Doc.SectionHeaders->Excluded) + for (const ELFYAML::SectionHeader &Hdr : *Doc.SectionHeaders->Excluded) + if (!ExcludedSectionHeaders.insert(Hdr.Name).second) + llvm_unreachable("buildSectionIndex() failed"); + size_t SecNdx = -1; - for (const std::unique_ptr &C : Doc.Chunks) { - if (!isa(C.get())) - continue; + for (const ELFYAML::Section *S : Doc.getSections()) { ++SecNdx; - size_t Index = ReorderMap.empty() ? SecNdx : ReorderMap.lookup(C->Name); - if (!SN2I.addName(C->Name, Index)) + size_t Index = ReorderMap.empty() ? SecNdx : ReorderMap.lookup(S->Name); + if (!SN2I.addName(S->Name, Index)) llvm_unreachable("buildSectionIndex() failed"); - DotShStrtab.add(ELFYAML::dropUniqueSuffix(C->Name)); + + if (!ExcludedSectionHeaders.count(S->Name)) + DotShStrtab.add(ELFYAML::dropUniqueSuffix(S->Name)); } DotShStrtab.finalize(); @@ -1663,6 +1722,9 @@ State.buildSectionIndex(); State.buildSymbolIndexes(); + if (State.HasError) + return false; + std::vector PHeaders; State.initProgramHeaders(PHeaders); 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 @@ -840,6 +840,7 @@ void MappingTraits::mapping( IO &IO, ELFYAML::SectionHeaderTable &SectionHeader) { IO.mapRequired("Sections", SectionHeader.Sections); + IO.mapOptional("Excluded", SectionHeader.Excluded); } void MappingTraits::mapping(IO &IO, diff --git a/llvm/test/tools/yaml2obj/ELF/section-headers-exclude.yaml b/llvm/test/tools/yaml2obj/ELF/section-headers-exclude.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/yaml2obj/ELF/section-headers-exclude.yaml @@ -0,0 +1,478 @@ +## Check how we can use the "Excluded" key of the "SectionHeaderTable" tag to exclude +## entries from the section header table. + +## Check we can use the "Excluded" key to omit a section from the section header table. +## Check we do not include the name of the excluded section in the string table. +# RUN: yaml2obj %s -DINCLUDED=.foo -DEXCLUDED=.bar --docnum=1 -o %t1 +# RUN: llvm-readelf --section-headers -p .shstrtab %t1 | \ +# RUN: FileCheck %s -DSEC=.foo --check-prefixes=INCLUDE-SEC,INCLUDE-FOO +# RUN: yaml2obj %s -DINCLUDED=.bar -DEXCLUDED=.foo --docnum=1 -o %t2 +# RUN: llvm-readelf --section-headers -p .shstrtab %t2 | \ +# RUN: FileCheck %s -DSEC=.bar --check-prefixes=INCLUDE-SEC,INCLUDE-BAR + +# INCLUDE-SEC: [Nr] Name +# INCLUDE-SEC: [ 1] [[SEC]] +# INCLUDE-SEC-NEXT: [ 2] .strtab +# INCLUDE-SEC-NEXT: [ 3] .shstrtab + +# INCLUDE-SEC: String dump of section '.shstrtab': +# INCLUDE-FOO-NEXT: [ 1] .foo +# INCLUDE-BAR-NEXT: [ 1] .bar +# INCLUDE-SEC-NEXT: [ 6] .shstrtab +# INCLUDE-SEC-NEXT: [ 10] .strtab +# INCLUDE-SEC-NOT: {{.}} + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + - Name: .bar + Type: SHT_PROGBITS +SectionHeaderTable: + Sections: + - Name: [[INCLUDED]] + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: [[EXCLUDED]] + +## Check we report an error when a section is in both the "Sections" and "Excluded" lists at the same time. +## Also check that we report an error if a section is missing from the lists. +# RUN: not yaml2obj %s -DINCLUDED=.bar -DEXCLUDED=.strtab --docnum=1 -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=EXCLUDE-INCLUDED + +# EXCLUDE-INCLUDED: error: repeated section name: '.strtab' in the section header description +# EXCLUDE-INCLUDED: error: section '.foo' should be present in the 'Sections' or 'Excluded' lists + +## Check we report an error when the `Excluded` key mentions an unknown section. +# RUN: not yaml2obj %s -DINCLUDED=.bar -DEXCLUDED=.unknown --docnum=1 -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=EXCLUDE-UNKNOWN + +# EXCLUDE-UNKNOWN: error: section '.foo' should be present in the 'Sections' or 'Excluded' lists +# EXCLUDE-UNKNOWN: error: section header contains undefined section '.unknown' + +## Check we report an error when the `Excluded` key mentions a section more than once. +# RUN: not yaml2obj %s --docnum=2 -o /dev/null 2>&1 | FileCheck %s --check-prefix=EXCLUDE-TWICE + +# EXCLUDE-TWICE: error: repeated section name: '.strtab' in the section header description +# EXCLUDE-TWICE: error: repeated section name: '.strtab' in the section header description + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +SectionHeaderTable: + Sections: + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: .strtab + - Name: .strtab + +## Check we are able to exclude all sections. +# RUN: yaml2obj %s --docnum=3 -o %t3 +# RUN: llvm-readelf --section-headers %t3 | FileCheck %s --check-prefix=NO-SECTIONS + +# NO-SECTIONS: There are 0 section headers, starting at offset 0x0: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +SectionHeaderTable: + Sections: [] + Excluded: + - Name: .strtab + +## Check how we handle cases when a section is excluded, but its section index is needed. +## The general rule is: when a section is explicitly linked with another section, which is +## excluded, then we report an error. In the case when it is linked implicitly with an excluded +## section, we use 0 as index value. + +## Case A: check we report an error when a regular section has a Link field which +## points to an excluded section. +# RUN: not yaml2obj %s --docnum=4 -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LINK -DSEC=.foo -DTARGET=.bar + +# LINK: error: unable to link '[[SEC]]' to excluded section '[[TARGET]]' + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Link: .bar + - Name: .bar + Type: SHT_PROGBITS +SectionHeaderTable: + Sections: + - Name: .foo + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: .bar + +## Case B.1: check we report an error when a symbol table section has a Link field which +## points to an excluded section. +# RUN: not yaml2obj %s --docnum=5 -DNAME=.symtab -DTYPE=SHT_SYMTAB -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LINK -DSEC=.symtab -DTARGET=.foo +# RUN: not yaml2obj %s --docnum=5 -DNAME=.dynsym -DTYPE=SHT_DYNSYM -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LINK -DSEC=.dynsym -DTARGET=.foo + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: [[NAME]] + Type: [[TYPE]] + Link: .foo + - Name: .foo + Type: SHT_PROGBITS +SectionHeaderTable: + Sections: + - Name: [[NAME]] + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: .foo + +## Case B.2: check we do not link .dynsym with .dynstr implicitly when the latter is excluded. +# RUN: yaml2obj %s --docnum=6 -o %t4 +# RUN: llvm-readelf %t4 --section-headers | FileCheck %s --check-prefix=LINK-DYNSYM + +# LINK-DYNSYM: [Nr] Name Type Address Off Size ES Flg Lk +# LINK-DYNSYM: [ 1] .dynsym DYNSYM 0000000000000000 000040 000018 18 A 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .dynsym + Type: SHT_DYNSYM + - Name: .dynstr + Type: SHT_PROGBITS +SectionHeaderTable: + Sections: + - Name: .dynsym + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: .dynstr + +## Case B.3: check we do not link .symtab with .strtab implicitly when the latter is excluded. +# RUN: yaml2obj %s --docnum=7 -o %t5 +# RUN: llvm-readelf %t5 --section-headers | FileCheck %s --check-prefix=LINK-SYMTAB + +# LINK-SYMTAB: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# LINK-SYMTAB: [ 1] .symtab SYMTAB 0000000000000000 000040 000018 18 0 1 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .symtab + Type: SHT_SYMTAB + - Name: .strtab + Type: SHT_PROGBITS +SectionHeaderTable: + Sections: + - Name: .symtab + - Name: .shstrtab + Excluded: + - Name: .strtab + +## Case C: check we report an error when a debug section has a Link field which +## points to an excluded section. +# RUN: not yaml2obj %s --docnum=8 -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LINK -DSEC=.debug_unknown -DTARGET=.strtab + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_unknown + Type: SHT_PROGBITS + Link: .strtab +SectionHeaderTable: + Sections: + - Name: .debug_unknown + - Name: .shstrtab + Excluded: + - Name: .strtab + +## Case D.1: check we report an error when a relocatable section has an Info field which +## points to an excluded section. +# RUN: not yaml2obj %s --docnum=9 -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LINK -DSEC=.rela -DTARGET=.strtab + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .rela + Type: SHT_RELA + Info: .strtab + Relocations: [] +SectionHeaderTable: + Sections: + - Name: .rela + - Name: .shstrtab + Excluded: + - Name: .strtab + +## Case D.2: check we report an error when the SHT_REL[A] section is linked +## with an excluded section explicitly. +# RUN: not yaml2obj %s --docnum=10 -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LINK -DSEC=.rela -DTARGET=.symtab + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .rela + Type: SHT_RELA + Link: .symtab + Relocations: [] + - Name: .symtab + Type: SHT_PROGBITS +SectionHeaderTable: + Sections: + - Name: .rela + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: .symtab + +## Case E: check we report an error when a symbol references an excluded section. +# RUN: not yaml2obj %s --docnum=11 -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=SYMBOL-SECTION + +# SYMBOL-SECTION: error: excluded section referenced: '.foo' by symbol 'foo' + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS +Symbols: + - Name: foo + Type: STT_OBJECT + Section: .foo +SectionHeaderTable: + Sections: + - Name: .symtab + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: .foo + +## Case F.1: check we report an error when a group section +## contains an excluded section member. +# RUN: not yaml2obj %s --docnum=12 -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LINK -DSEC=.group -DTARGET=.strtab + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .group + Type: SHT_GROUP + Members: + - SectionOrType: .strtab +SectionHeaderTable: + Sections: + - Name: .group + - Name: .shstrtab + Excluded: + - Name: .strtab + +## Case F.2: check we report an error when the group section is linked +## to an excluded section explicitly. +# RUN: not yaml2obj %s --docnum=13 -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LINK -DSEC=.group -DTARGET=.symtab + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .group + Type: SHT_GROUP + Link: .symtab + Members: [] + - Name: .symtab + Type: SHT_SYMTAB +SectionHeaderTable: + Sections: + - Name: .group + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: .symtab + +## Case G: check we do not link SHT_LLVM_CALL_GRAPH_PROFILE/SHT_LLVM_ADDRSIG/SHT_GROUP/SHT_REL[A] sections +## with .symtab implicitly when the latter is excluded. +# RUN: yaml2obj %s --docnum=14 -o %t6 +# RUN: llvm-readelf %t6 --section-headers | FileCheck %s --check-prefix=LINK-IMPLICIT + +# LINK-IMPLICIT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# LINK-IMPLICIT: [ 1] .cgp LLVM_CALL_GRAPH_PROFILE 0000000000000000 000040 000000 10 0 0 0 +# LINK-IMPLICIT-NEXT: [ 2] .llvm_addrsig LLVM_ADDRSIG 0000000000000000 000040 000000 00 0 0 0 +# LINK-IMPLICIT-NEXT: [ 3] .group GROUP 0000000000000000 000040 000000 04 0 0 0 +# LINK-IMPLICIT-NEXT: [ 4] .rela RELA 0000000000000000 000040 000000 18 0 0 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .cgp + Type: SHT_LLVM_CALL_GRAPH_PROFILE + Content: "" + - Name: .llvm_addrsig + Type: SHT_LLVM_ADDRSIG + Content: "" + - Name: .group + Type: SHT_GROUP + Members: [] + - Name: .rela + Type: SHT_RELA + Relocations: [] + - Name: .symtab + Type: SHT_SYMTAB +SectionHeaderTable: + Sections: + - Name: .cgp + - Name: .llvm_addrsig + - Name: .group + - Name: .rela + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: .symtab + +## Case H: check we do not link SHT_HASH/SHT_GNU_HASH sections with .dynsym +## implicitly when the latter is excluded. +# RUN: yaml2obj %s --docnum=15 -o %t7 +# RUN: llvm-readelf %t7 --section-headers | FileCheck %s --check-prefix=LINK-HASH + +# LINK-HASH: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# LINK-HASH: [ 1] .hash HASH 0000000000000000 000040 000000 00 0 0 0 +# LINK-HASH-NEXT: [ 2] .gnu_hash GNU_HASH 0000000000000000 000040 000000 00 0 0 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .hash + Type: SHT_HASH + Content: "" + - Name: .gnu_hash + Type: SHT_GNU_HASH + Content: "" + - Name: .dynsym + Type: SHT_DYNSYM +SectionHeaderTable: + Sections: + - Name: .hash + - Name: .gnu_hash + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: .dynsym + +## Case I: document the case when an excluded section is explicitly linked to another excluded section. +## We report an error in this case, because: +## 1) It is a reasonable behavior, as it is perhaps usually a result of a mistake +## in a YAML description. +## 2) Helps to keep the code simpler. +# RUN: not yaml2obj %s --docnum=16 -o /dev/null 2>&1 | FileCheck %s --check-prefix=CROSS-LINK + +# CROSS-LINK: error: unable to link '.foo' to excluded section '.bar' +# CROSS-LINK-NEXT: error: unable to link '.bar' to excluded section '.foo' + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Link: .bar + - Name: .bar + Type: SHT_PROGBITS + Link: .foo +SectionHeaderTable: + Sections: + - Name: .strtab + - Name: .shstrtab + Excluded: + - Name: .foo + - Name: .bar + +## Check we set e_shstrndx field to 0 when the section header string table is excluded. +## Check that the e_shnum field is adjusted properly when a section is removed. +# RUN: yaml2obj --docnum=17 %s -o %t9 +# RUN: llvm-readelf --file-headers %t9 | FileCheck %s --check-prefix=SHSTRTAB + +# SHSTRTAB: Number of section headers: 2 +# SHSTRTAB: Section header string table index: 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +SectionHeaderTable: + Sections: + - Name: .strtab + Excluded: + - Name: .shstrtab 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 @@ -68,15 +68,15 @@ # RUN: FileCheck %s --check-prefix=ERR2 # ERR1: error: repeated section name: '.section.foo' in the section header description -# ERR1-NEXT: error: section '.section (1)' should be present in the 'Sections' list -# ERR1-NEXT: error: section '.section (2)' should be present in the 'Sections' list +# ERR1-NEXT: error: section '.section (1)' should be present in the 'Sections' or 'Excluded' lists +# ERR1-NEXT: error: section '.section (2)' should be present in the 'Sections' or 'Excluded' lists # ERR1-NEXT: error: section header contains undefined section 'unknown' # ERR2: error: repeated section name: '.strtab' in the section header description # ERR2-NEXT: error: repeated section name: '.shstrtab' in the section header description -# ERR2-NEXT: error: section '.section (1)' should be present in the 'Sections' list -# ERR2-NEXT: error: section '.section (2)' should be present in the 'Sections' list -# ERR2-NEXT: error: section '.section.foo' should be present in the 'Sections' list +# ERR2-NEXT: error: section '.section (1)' should be present in the 'Sections' or 'Excluded' lists +# ERR2-NEXT: error: section '.section (2)' should be present in the 'Sections' or 'Excluded' lists +# ERR2-NEXT: error: section '.section.foo' should be present in the 'Sections' or 'Excluded' lists # ERR2-NEXT: error: section header contains undefined section '.filler' ## Test that we are able to specify an empty sections list for