[llvm] c781e73 - [yaml2obj] - Add a way to exclude specified sections from the section header.

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 4 03:51:06 PDT 2020


Author: Georgii Rymar
Date: 2020-06-04T13:50:35+03:00
New Revision: c781e7370e9b408f27996175fcf07b02905e6db4

URL: https://github.com/llvm/llvm-project/commit/c781e7370e9b408f27996175fcf07b02905e6db4
DIFF: https://github.com/llvm/llvm-project/commit/c781e7370e9b408f27996175fcf07b02905e6db4.diff

LOG: [yaml2obj] - Add a way to exclude specified sections from the section header.

This implements a new "Excluded" key that can be used
to exclude entries from section header:

```
SectionHeaderTable:
  Sections:
    ...
  Excluded:
    - Name: .foo
```

Differential revision: https://reviews.llvm.org/D81005

Added: 
    llvm/test/tools/yaml2obj/ELF/section-headers-exclude.yaml

Modified: 
    llvm/include/llvm/ObjectYAML/ELFYAML.h
    llvm/lib/ObjectYAML/ELFEmitter.cpp
    llvm/lib/ObjectYAML/ELFYAML.cpp
    llvm/test/tools/yaml2obj/ELF/section-headers.yaml

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 5b96283b786e..b88a10eecad7 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -93,6 +93,7 @@ struct SectionHeader {
 
 struct SectionHeaderTable {
   std::vector<SectionHeader> Sections;
+  Optional<std::vector<SectionHeader>> Excluded;
 };
 
 struct SectionName {

diff  --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 8cc322f8275a..02b2c94516fb 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -128,6 +128,8 @@ template <class ELFT> class ELFState {
   NameToIdxMap DynSymN2I;
   ELFYAML::Object &Doc;
 
+  StringSet<> ExcludedSectionHeaders;
+
   uint64_t LocationCounter = 0;
   bool HasError = false;
   yaml::ErrorHandler ErrHandler;
@@ -230,6 +232,8 @@ template <class ELFT> class ELFState {
   uint64_t alignToOffset(ContiguousBlobAccumulator &CBA, uint64_t Align,
                          llvm::Optional<llvm::yaml::Hex64> Offset);
 
+  uint64_t getSectionNameOffset(StringRef Name);
+
 public:
   static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
                        yaml::ErrorHandler EH);
@@ -350,7 +354,8 @@ void ELFState<ELFT>::writeELFHeader(ContiguousBlobAccumulator &CBA, raw_ostream
 
   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 @@ void ELFState<ELFT>::initProgramHeaders(std::vector<Elf_Phdr> &PHeaders) {
 template <class ELFT>
 unsigned ELFState<ELFT>::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 <class ELFT>
@@ -498,6 +517,15 @@ StringRef llvm::ELFYAML::dropUniqueSuffix(StringRef S) {
   return S.substr(0, SuffixPos - 1);
 }
 
+template <class ELFT>
+uint64_t ELFState<ELFT>::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 <class ELFT>
 void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
                                         ContiguousBlobAccumulator &CBA) {
@@ -531,7 +559,7 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
                   "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 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
   }
 
   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 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
     // 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 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
                                              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 @@ void ELFState<ELFT>::initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,
                                             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 @@ void ELFState<ELFT>::initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,
   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 @@ void ELFState<ELFT>::writeSectionContent(
 
   // 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 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
          "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 @@ void ELFState<ELFT>::writeSectionContent(
     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 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                          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 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                          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 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                          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<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() {
   DenseMap<StringRef, size_t> 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 @@ DenseMap<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() {
       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 @@ DenseMap<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() {
   return Ret;
 }
 
+static bool hasSectionHeader(const ELFYAML::Object &Doc, size_t SecNdx) {
+  if (!Doc.SectionHeaders)
+    return true;
+  return SecNdx < Doc.SectionHeaders->Sections.size();
+}
+
 template <class ELFT> void ELFState<ELFT>::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<StringRef, size_t> 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<ELFYAML::Chunk> &C : Doc.Chunks) {
-    if (!isa<ELFYAML::Section>(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 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
   State.buildSectionIndex();
   State.buildSymbolIndexes();
 
+  if (State.HasError)
+    return false;
+
   std::vector<Elf_Phdr> PHeaders;
   State.initProgramHeaders(PHeaders);
 

diff  --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 98a40c906bee..87f4eea126ae 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -840,6 +840,7 @@ void MappingTraits<ELFYAML::SectionHeader>::mapping(
 void MappingTraits<ELFYAML::SectionHeaderTable>::mapping(
     IO &IO, ELFYAML::SectionHeaderTable &SectionHeader) {
   IO.mapRequired("Sections", SectionHeader.Sections);
+  IO.mapOptional("Excluded", SectionHeader.Excluded);
 }
 
 void MappingTraits<ELFYAML::FileHeader>::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
index 000000000000..a244643f93e3
--- /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
index ee0049d4d31d..8e2f6f5a3091 100644
--- a/llvm/test/tools/yaml2obj/ELF/section-headers.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/section-headers.yaml
@@ -68,15 +68,15 @@ SectionHeaderTable:
 # 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


        


More information about the llvm-commits mailing list