[llvm] d8bb30c - [yaml2obj] - Allow specifying no tags to create empty sections in few cases.

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 15 01:22:28 PDT 2020


Author: Georgii Rymar
Date: 2020-10-15T11:22:02+03:00
New Revision: d8bb30c5518054c787b4278ab5a4ab371d86defe

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

LOG: [yaml2obj] - Allow specifying no tags to create empty sections in few cases.

Currently we have a few sections that
does not support specifying no keys for them. E.g. it is required that one
of "Content", "Size" or "Entries" key is present. There is no reason to
have this restriction. We can allow this and emit an empty section instead.

This opens road for a simplification and generalization of the code in `validate()`
that is discussed in the D89039 thread.

Depends on D89039.

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

Added: 
    

Modified: 
    llvm/lib/ObjectYAML/ELFEmitter.cpp
    llvm/lib/ObjectYAML/ELFYAML.cpp
    llvm/test/tools/yaml2obj/ELF/gnu-hash-section.yaml
    llvm/test/tools/yaml2obj/ELF/hash-section.yaml
    llvm/test/tools/yaml2obj/ELF/llvm-addrsig-section.yaml
    llvm/test/tools/yaml2obj/ELF/note-section.yaml
    llvm/test/tools/yaml2obj/ELF/stack-sizes.yaml

Removed: 
    


################################################################################
diff  --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 33c4836d0883..155009bbb2ea 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -1322,6 +1322,9 @@ void ELFState<ELFT>::writeSectionContent(
     return;
   }
 
+  if (!Section.Entries)
+    return;
+
   for (const ELFYAML::StackSizeEntry &E : *Section.Entries) {
     CBA.write<uintX_t>(E.Address, ELFT::TargetEndianness);
     SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(E.Size);
@@ -1444,6 +1447,9 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
     return;
   }
 
+  if (!Section.Bucket)
+    return;
+
   CBA.write<uint32_t>(
       Section.NBucket.getValueOr(llvm::yaml::Hex64(Section.Bucket->size())),
       ELFT::TargetEndianness);
@@ -1648,6 +1654,9 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
     return;
   }
 
+  if (!Section.Symbols)
+    return;
+
   for (StringRef Sym : *Section.Symbols)
     SHeader.sh_size +=
         CBA.writeULEB128(toSymbolIndex(Sym, Section.Name, /*IsDynamic=*/false));
@@ -1663,6 +1672,9 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
     return;
   }
 
+  if (!Section.Notes)
+    return;
+
   for (const ELFYAML::NoteEntry &NE : *Section.Notes) {
     // Write name size.
     if (NE.Name.empty())
@@ -1710,6 +1722,9 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
     return;
   }
 
+  if (!Section.Header)
+    return;
+
   // We write the header first, starting with the hash buckets count. Normally
   // it is the number of entries in HashBuckets, but the "NBuckets" property can
   // be used to override this field, which is useful for producing broken

diff  --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index c66ead0dfea7..7bb8755aa4bd 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -1441,77 +1441,44 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::validate(
   }
 
   if (const auto *SS = dyn_cast<ELFYAML::StackSizesSection>(C.get())) {
-    if (!SS->Entries && !SS->Content && !SS->Size)
-      return ".stack_sizes: one of Content, Entries and Size must be specified";
-
-    // We accept Content, Size or both together when there are no Entries.
-    if (!SS->Entries)
-      return {};
-
-    if (SS->Size)
-      return ".stack_sizes: Size and Entries cannot be used together";
-    if (SS->Content)
-      return ".stack_sizes: Content and Entries cannot be used together";
+    if ((SS->Content || SS->Size) && SS->Entries)
+      return "\"Entries\" cannot be used with \"Content\" or \"Size\"";
     return {};
   }
 
   if (const auto *HS = dyn_cast<ELFYAML::HashSection>(C.get())) {
-    if (!HS->Content && !HS->Bucket && !HS->Chain && !HS->Size)
-      return "one of \"Content\", \"Size\", \"Bucket\" or \"Chain\" must be "
-             "specified";
-
-    if (HS->Content || HS->Size) {
-      if (HS->Bucket)
-        return "\"Bucket\" cannot be used with \"Content\" or \"Size\"";
-      if (HS->Chain)
-        return "\"Chain\" cannot be used with \"Content\" or \"Size\"";
-      return {};
-    }
-
+    if ((HS->Content || HS->Size) && (HS->Bucket || HS->Chain))
+      return "\"Bucket\" and \"Chain\" cannot be used with \"Content\" or "
+             "\"Size\"";
     if ((HS->Bucket && !HS->Chain) || (!HS->Bucket && HS->Chain))
       return "\"Bucket\" and \"Chain\" must be used together";
     return {};
   }
 
   if (const auto *Sec = dyn_cast<ELFYAML::AddrsigSection>(C.get())) {
-    if (!Sec->Symbols && !Sec->Content && !Sec->Size)
-      return "one of \"Content\", \"Size\" or \"Symbols\" must be specified";
-
     if ((Sec->Content || Sec->Size) && Sec->Symbols)
       return "\"Symbols\" cannot be used with \"Content\" or \"Size\"";
     return {};
   }
 
   if (const auto *NS = dyn_cast<ELFYAML::NoteSection>(C.get())) {
-    if (!NS->Content && !NS->Size && !NS->Notes)
-      return "one of \"Content\", \"Size\" or \"Notes\" must be "
-             "specified";
-
     if ((NS->Content || NS->Size) && NS->Notes)
       return "\"Notes\" cannot be used with \"Content\" or \"Size\"";
     return {};
   }
 
   if (const auto *Sec = dyn_cast<ELFYAML::GnuHashSection>(C.get())) {
-    if (!Sec->Content && !Sec->Size && !Sec->Header && !Sec->BloomFilter &&
-        !Sec->HashBuckets && !Sec->HashValues)
-      return "either \"Content\", \"Size\" or \"Header\", \"BloomFilter\", "
-             "\"HashBuckets\" and \"HashBuckets\" must be specified";
-
-    if (Sec->Header || Sec->BloomFilter || Sec->HashBuckets ||
-        Sec->HashValues) {
-      if (!Sec->Header || !Sec->BloomFilter || !Sec->HashBuckets ||
-          !Sec->HashValues)
-        return "\"Header\", \"BloomFilter\", "
-               "\"HashBuckets\" and \"HashValues\" must be used together";
-      if (Sec->Content || Sec->Size)
-        return "\"Header\", \"BloomFilter\", "
-               "\"HashBuckets\" and \"HashValues\" can't be used together with "
-               "\"Content\" or \"Size\"";
-      return {};
-    }
-
-    // Only Content is specified.
+    const bool HasSpecialFields =
+        Sec->Header || Sec->BloomFilter || Sec->HashBuckets || Sec->HashValues;
+    if (HasSpecialFields && (Sec->Content || Sec->Size))
+      return "\"Header\", \"BloomFilter\", "
+             "\"HashBuckets\" and \"HashValues\" can't be used together with "
+             "\"Content\" or \"Size\"";
+
+    if (HasSpecialFields && (!Sec->Header || !Sec->BloomFilter ||
+                             !Sec->HashBuckets || !Sec->HashValues))
+      return "\"Header\", \"BloomFilter\", "
+             "\"HashBuckets\" and \"HashValues\" must be used together";
     return {};
   }
 

diff  --git a/llvm/test/tools/yaml2obj/ELF/gnu-hash-section.yaml b/llvm/test/tools/yaml2obj/ELF/gnu-hash-section.yaml
index 846e40519624..3b58fa8ce407 100644
--- a/llvm/test/tools/yaml2obj/ELF/gnu-hash-section.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/gnu-hash-section.yaml
@@ -208,12 +208,15 @@ Sections:
     Header:
       SymNdx: 0x0
 
-## Either "Content" or "Header", "BloomFilter", "HashBuckets" and "HashBuckets" must be
-## specified when declaring a SHT_GNU_HASH section.
+## Check we emit an empty section if neither "Content", "Header",
+## "BloomFilter", "HashBuckets" nor "HashBuckets" were set.
 
-# RUN: not yaml2obj --docnum=10 %s -o %t10 2>&1 | FileCheck %s --check-prefix=NOKEYS
+# NOKEYS: Section Headers:
+# NOKEYS:  [Nr] Name      Type     Address          Off    Size
+# NOKEYS:  [ 1] .gnu.hash GNU_HASH 0000000000000000 000040 000000
 
-# NOKEYS: error: either "Content", "Size" or "Header", "BloomFilter", "HashBuckets" and "HashBuckets" must be specified
+# RUN: yaml2obj --docnum=10 %s -o %t10
+# RUN: llvm-readelf --sections %t10 | FileCheck %s --check-prefix=NOKEYS
 
 --- !ELF
 FileHeader:

diff  --git a/llvm/test/tools/yaml2obj/ELF/hash-section.yaml b/llvm/test/tools/yaml2obj/ELF/hash-section.yaml
index 4ec461d10612..cd087e4d7298 100644
--- a/llvm/test/tools/yaml2obj/ELF/hash-section.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/hash-section.yaml
@@ -73,7 +73,7 @@ Sections:
 
 # RUN: not yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --check-prefix=CONTENT-BUCKET
 
-# CONTENT-BUCKET: "Bucket" cannot be used with "Content" or "Size"
+# CONTENT-BUCKET: "Bucket" and "Chain" cannot be used with "Content" or "Size"
 
 --- !ELF
 FileHeader:
@@ -133,11 +133,14 @@ Sections:
     Type:  SHT_HASH
     Chain: [ 1 ]
 
-## Check we report an error if neither "Bucket", "Chain" nor "Content" were set.
+## Check we emit an empty section if neither "Bucket", "Chain",
+## "Content" nor "Size" were set.
 
-# RUN: not yaml2obj --docnum=7 %s 2>&1 | FileCheck %s --check-prefix=NO-TAGS
+# RUN: yaml2obj --docnum=7 %s -o %t7
+# RUN: llvm-readelf --sections %t7 | FileCheck %s --check-prefix=NO-TAGS
 
-# NO-TAGS: error: one of "Content", "Size", "Bucket" or "Chain" must be specified
+# NO-TAGS: [Nr] Name  Type Address  Off    Size
+# NO-TAGS: [ 1] .hash HASH 00000000 000034 000000
 
 --- !ELF
 FileHeader:

diff  --git a/llvm/test/tools/yaml2obj/ELF/llvm-addrsig-section.yaml b/llvm/test/tools/yaml2obj/ELF/llvm-addrsig-section.yaml
index 6cc0fedd8a37..f8659fe44814 100644
--- a/llvm/test/tools/yaml2obj/ELF/llvm-addrsig-section.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/llvm-addrsig-section.yaml
@@ -118,11 +118,13 @@ Sections:
     Type: SHT_LLVM_ADDRSIG
     Content: "1122334455"
 
-## Either "Content" or "Symbols" must be specifed for SHT_LLVM_ADDRSIG sections.
+## Check we emit an empty section if neither "Content", "Size" not "Symbols" were set.
 
-# RUN: not yaml2obj --docnum=6 %s 2>&1 | FileCheck %s --check-prefix=NO-TAGS
+# RUN: yaml2obj --docnum=6 %s -o %t6
+# RUN: llvm-readelf --sections %t6 | FileCheck %s --check-prefix=NO-TAGS
 
-# NO-TAGS: error: one of "Content", "Size" or "Symbols" must be specified
+# NO-TAGS: [Nr] Name          Type         Address          Off    Size
+# NO-TAGS: [ 1] .llvm_addrsig LLVM_ADDRSIG 0000000000000000 000040 000000
 
 --- !ELF
 FileHeader:

diff  --git a/llvm/test/tools/yaml2obj/ELF/note-section.yaml b/llvm/test/tools/yaml2obj/ELF/note-section.yaml
index af5d8675af68..ccb49caa5b25 100644
--- a/llvm/test/tools/yaml2obj/ELF/note-section.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/note-section.yaml
@@ -172,11 +172,13 @@ Sections:
     Type:    SHT_NOTE
     Content: "1122334455"
 
-## Either "Content", "Size" or "Notes" must be specifed for SHT_NOTE sections.
+## Check we emit an empty section if neither "Content", "Size" not "Notes" were set.
 
-# RUN: not yaml2obj --docnum=8 %s 2>&1 | FileCheck %s --check-prefix=NO-TAGS
+# RUN: yaml2obj --docnum=8 %s -o %t8
+# RUN: llvm-readelf --sections %t8 | FileCheck %s --check-prefix=NO-TAGS
 
-# NO-TAGS: error: one of "Content", "Size" or "Notes" must be specified
+# NO-TAGS: [Nr] Name      Type Address          Off    Size
+# NO-TAGS: [ 1] .note.foo NOTE 0000000000000000 000040 000000
 
 --- !ELF
 FileHeader:

diff  --git a/llvm/test/tools/yaml2obj/ELF/stack-sizes.yaml b/llvm/test/tools/yaml2obj/ELF/stack-sizes.yaml
index d2e77aeaa56e..0fc8f8106b4d 100644
--- a/llvm/test/tools/yaml2obj/ELF/stack-sizes.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/stack-sizes.yaml
@@ -147,7 +147,7 @@ Sections:
 
 # RUN: not yaml2obj --docnum=5 %s 2>&1 | FileCheck %s --check-prefix=ENTRIES-AND-CONTENT
 
-# ENTRIES-AND-CONTENT: error: .stack_sizes: Content and Entries cannot be used together
+# ENTRIES-AND-CONTENT: error: "Entries" cannot be used with "Content" or "Size"
 
 --- !ELF
 FileHeader:
@@ -162,11 +162,13 @@ Sections:
       - Address: 0x10
         Size:    0x20
 
-## Check we must specify either "Content", "Entries" or "Size" tag when describing .stack_sizes.
+## Check we emit an empty section if neither "Content", "Size" nor "Entries" were set.
 
-# RUN: not yaml2obj --docnum=6 %s 2>&1 | FileCheck %s --check-prefix=NO-TAGS
+# RUN: yaml2obj --docnum=6 %s -o %t6
+# RUN: llvm-readelf --sections %t6 | FileCheck %s --check-prefix=NO-TAGS
 
-# NO-TAGS: .stack_sizes: one of Content, Entries and Size must be specified
+# NO-TAGS: [Nr] Name         Type     Address          Off    Size
+# NO-TAGS: [ 1] .stack_sizes PROGBITS 0000000000000000 000040 000000
 
 --- !ELF
 FileHeader:
@@ -181,7 +183,7 @@ Sections:
 
 # RUN: not yaml2obj --docnum=7 %s 2>&1 | FileCheck %s --check-prefix=ENTRIES-AND-SIZE
 
-# ENTRIES-AND-SIZE: .stack_sizes: Size and Entries cannot be used together
+# ENTRIES-AND-SIZE: error: "Entries" cannot be used with "Content" or "Size"
 
 --- !ELF
 FileHeader:


        


More information about the llvm-commits mailing list