[llvm] 909f3d7 - [yaml2obj][XCOFF] customize the string table

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 13 02:25:05 PDT 2021


Author: Esme-Yi
Date: 2021-09-13T09:24:38Z
New Revision: 909f3d738079eb5971f584e2a4119de43744c73f

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

LOG: [yaml2obj][XCOFF] customize the string table

Summary: The patch adds support for yaml2obj customizing the string table.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D107421

Added: 
    llvm/test/tools/yaml2obj/XCOFF/string-table.yaml

Modified: 
    llvm/include/llvm/ObjectYAML/XCOFFYAML.h
    llvm/lib/ObjectYAML/XCOFFEmitter.cpp
    llvm/lib/ObjectYAML/XCOFFYAML.cpp
    llvm/test/tools/obj2yaml/XCOFF/aix.yaml

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
index 2630175642c40..1fa3974b9ef14 100644
--- a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
@@ -59,10 +59,19 @@ struct Symbol {
   uint8_t NumberOfAuxEntries;
 };
 
+struct StringTable {
+  Optional<uint32_t> ContentSize; // The total size of the string table.
+  Optional<uint32_t> Length;      // The value of the length field for the first
+                                  // 4 bytes of the table.
+  Optional<std::vector<StringRef>> Strings;
+  Optional<yaml::BinaryRef> RawContent;
+};
+
 struct Object {
   FileHeader Header;
   std::vector<Section> Sections;
   std::vector<Symbol> Symbols;
+  StringTable StrTbl;
   Object();
 };
 } // namespace XCOFFYAML
@@ -100,6 +109,10 @@ template <> struct MappingTraits<XCOFFYAML::Section> {
   static void mapping(IO &IO, XCOFFYAML::Section &Sec);
 };
 
+template <> struct MappingTraits<XCOFFYAML::StringTable> {
+  static void mapping(IO &IO, XCOFFYAML::StringTable &Str);
+};
+
 template <> struct MappingTraits<XCOFFYAML::Object> {
   static void mapping(IO &IO, XCOFFYAML::Object &Obj);
 };

diff  --git a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
index 8b132ebf5e5de..eaaf53ab63dfd 100644
--- a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
@@ -18,8 +18,9 @@
 #include "llvm/ObjectYAML/ObjectYAML.h"
 #include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/Support/EndianStream.h"
-#include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/LEB128.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 
@@ -33,7 +34,7 @@ class XCOFFWriter {
 public:
   XCOFFWriter(XCOFFYAML::Object &Obj, raw_ostream &OS, yaml::ErrorHandler EH)
       : Obj(Obj), W(OS, support::big), ErrHandler(EH),
-        Strings(StringTableBuilder::XCOFF) {
+        StrTblBuilder(StringTableBuilder::XCOFF) {
     Is64Bit = Obj.Header.Magic == (llvm::yaml::Hex16)XCOFF::XCOFF64;
   }
   bool writeXCOFF();
@@ -43,18 +44,20 @@ class XCOFFWriter {
   bool initFileHeader(uint64_t CurrentOffset);
   bool initSectionHeader(uint64_t &CurrentOffset);
   bool initRelocations(uint64_t &CurrentOffset);
+  bool initStringTable();
   bool assignAddressesAndIndices();
   void writeFileHeader();
   void writeSectionHeader();
   bool writeSectionData();
   bool writeRelocations();
   bool writeSymbols();
+  void writeStringTable();
 
   XCOFFYAML::Object &Obj;
   bool Is64Bit = false;
   support::endian::Writer W;
   yaml::ErrorHandler ErrHandler;
-  StringTableBuilder Strings;
+  StringTableBuilder StrTblBuilder;
   uint64_t StartOffset;
   // Map the section name to its corrresponding section index.
   DenseMap<StringRef, int16_t> SectionIndexMap = {
@@ -140,20 +143,79 @@ bool XCOFFWriter::initSectionHeader(uint64_t &CurrentOffset) {
   return initRelocations(CurrentOffset);
 }
 
+bool XCOFFWriter::initStringTable() {
+  if (Obj.StrTbl.RawContent) {
+    size_t RawSize = Obj.StrTbl.RawContent->binary_size();
+    if (Obj.StrTbl.Strings || Obj.StrTbl.Length) {
+      ErrHandler(
+          "can't specify Strings or Length when RawContent is specified");
+      return false;
+    }
+    if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize < RawSize) {
+      ErrHandler("specified ContentSize (" + Twine(*Obj.StrTbl.ContentSize) +
+                 ") is less than the RawContent data size (" + Twine(RawSize) +
+                 ")");
+      return false;
+    }
+    return true;
+  }
+  if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize <= 3) {
+    ErrHandler("ContentSize shouldn't be less than 4 without RawContent");
+    return false;
+  }
+
+  // Build the string table.
+  StrTblBuilder.clear();
+
+  if (Obj.StrTbl.Strings) {
+    // All specified strings should be added to the string table.
+    for (StringRef StringEnt : *Obj.StrTbl.Strings)
+      StrTblBuilder.add(StringEnt);
+
+    size_t StrTblIdx = 0;
+    size_t NumOfStrings = Obj.StrTbl.Strings->size();
+    for (XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
+      if (nameShouldBeInStringTable(YamlSym.SymbolName)) {
+        if (StrTblIdx < NumOfStrings) {
+          // Overwrite the symbol name with the specified string.
+          YamlSym.SymbolName = (*Obj.StrTbl.Strings)[StrTblIdx];
+          ++StrTblIdx;
+        } else
+          // Names that are not overwritten are still stored in the string
+          // table.
+          StrTblBuilder.add(YamlSym.SymbolName);
+      }
+    }
+  } else {
+    for (XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
+      if (nameShouldBeInStringTable(YamlSym.SymbolName))
+        StrTblBuilder.add(YamlSym.SymbolName);
+    }
+  }
+
+  StrTblBuilder.finalize();
+
+  size_t StrTblSize = StrTblBuilder.getSize();
+  if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize < StrTblSize) {
+    ErrHandler("specified ContentSize (" + Twine(*Obj.StrTbl.ContentSize) +
+               ") is less than the size of the data that would otherwise be "
+               "written (" +
+               Twine(StrTblSize) + ")");
+    return false;
+  }
+
+  return true;
+}
+
 bool XCOFFWriter::initFileHeader(uint64_t CurrentOffset) {
   // The default format of the object file is XCOFF32.
   InitFileHdr.Magic = XCOFF::XCOFF32;
   InitFileHdr.NumberOfSections = Obj.Sections.size();
   InitFileHdr.NumberOfSymTableEntries = Obj.Symbols.size();
 
-  for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
+  for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols)
     // Add the number of auxiliary symbols to the total number.
     InitFileHdr.NumberOfSymTableEntries += YamlSym.NumberOfAuxEntries;
-    if (nameShouldBeInStringTable(YamlSym.SymbolName))
-      Strings.add(YamlSym.SymbolName);
-  }
-  // Finalize the string table.
-  Strings.finalize();
 
   // Calculate SymbolTableOffset for the file header.
   if (InitFileHdr.NumberOfSymTableEntries) {
@@ -171,7 +233,6 @@ bool XCOFFWriter::initFileHeader(uint64_t CurrentOffset) {
 }
 
 bool XCOFFWriter::assignAddressesAndIndices() {
-  Strings.clear();
   uint64_t FileHdrSize =
       Is64Bit ? XCOFF::FileHeaderSize64 : XCOFF::FileHeaderSize32;
   uint64_t SecHdrSize =
@@ -182,8 +243,13 @@ bool XCOFFWriter::assignAddressesAndIndices() {
   // Calculate section header info.
   if (!initSectionHeader(CurrentOffset))
     return false;
+
   // Calculate file header info.
-  return initFileHeader(CurrentOffset);
+  if (!initFileHeader(CurrentOffset))
+    return false;
+
+  // Initialize the string table.
+  return initStringTable();
 }
 
 void XCOFFWriter::writeFileHeader() {
@@ -309,13 +375,13 @@ bool XCOFFWriter::writeSymbols() {
   for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
     if (Is64Bit) {
       W.write<uint64_t>(YamlSym.Value);
-      W.write<uint32_t>(Strings.getOffset(YamlSym.SymbolName));
+      W.write<uint32_t>(StrTblBuilder.getOffset(YamlSym.SymbolName));
     } else {
       if (nameShouldBeInStringTable(YamlSym.SymbolName)) {
         // For XCOFF32: A value of 0 indicates that the symbol name is in the
         // string table.
         W.write<int32_t>(0);
-        W.write<uint32_t>(Strings.getOffset(YamlSym.SymbolName));
+        W.write<uint32_t>(StrTblBuilder.getOffset(YamlSym.SymbolName));
       } else {
         writeName(YamlSym.SymbolName, W);
       }
@@ -340,6 +406,48 @@ bool XCOFFWriter::writeSymbols() {
   return true;
 }
 
+void XCOFFWriter::writeStringTable() {
+  if (Obj.StrTbl.RawContent) {
+    Obj.StrTbl.RawContent->writeAsBinary(W.OS);
+    if (Obj.StrTbl.ContentSize) {
+      assert(*Obj.StrTbl.ContentSize >= Obj.StrTbl.RawContent->binary_size() &&
+             "Specified ContentSize is less than the RawContent size.");
+      W.OS.write_zeros(*Obj.StrTbl.ContentSize -
+                       Obj.StrTbl.RawContent->binary_size());
+    }
+    return;
+  }
+
+  size_t StrTblBuilderSize = StrTblBuilder.getSize();
+  // If neither Length nor ContentSize is specified, write the StrTblBuilder
+  // directly, which contains the auto-generated Length value.
+  if (!Obj.StrTbl.Length && !Obj.StrTbl.ContentSize) {
+    if (StrTblBuilderSize <= 4)
+      return;
+    StrTblBuilder.write(W.OS);
+    return;
+  }
+
+  // Serialize the string table's content to a temporary buffer.
+  std::unique_ptr<WritableMemoryBuffer> Buf =
+      WritableMemoryBuffer::getNewMemBuffer(StrTblBuilderSize);
+  uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart());
+  StrTblBuilder.write(Ptr);
+  // Replace the first 4 bytes, which contain the auto-generated Length value,
+  // with the specified value.
+  memset(Ptr, 0, 4);
+  support::endian::write32be(Ptr, Obj.StrTbl.Length ? *Obj.StrTbl.Length
+                                                    : *Obj.StrTbl.ContentSize);
+  // Copy the buffer content to the actual output stream.
+  W.OS.write(Buf->getBufferStart(), Buf->getBufferSize());
+  // Add zeros as padding after strings.
+  if (Obj.StrTbl.ContentSize) {
+    assert(*Obj.StrTbl.ContentSize >= StrTblBuilderSize &&
+           "Specified ContentSize is less than the StringTableBuilder size.");
+    W.OS.write_zeros(*Obj.StrTbl.ContentSize - StrTblBuilderSize);
+  }
+}
+
 bool XCOFFWriter::writeXCOFF() {
   if (!assignAddressesAndIndices())
     return false;
@@ -354,9 +462,7 @@ bool XCOFFWriter::writeXCOFF() {
   }
   if (!Obj.Symbols.empty() && !writeSymbols())
     return false;
-  // Write the string table.
-  if (Strings.getSize() > 4)
-    Strings.write(W.OS);
+  writeStringTable();
   return true;
 }
 

diff  --git a/llvm/lib/ObjectYAML/XCOFFYAML.cpp b/llvm/lib/ObjectYAML/XCOFFYAML.cpp
index 73d188e274b12..9554f093dfa6c 100644
--- a/llvm/lib/ObjectYAML/XCOFFYAML.cpp
+++ b/llvm/lib/ObjectYAML/XCOFFYAML.cpp
@@ -143,7 +143,7 @@ void MappingTraits<XCOFFYAML::Section>::mapping(IO &IO,
 }
 
 void MappingTraits<XCOFFYAML::Symbol>::mapping(IO &IO, XCOFFYAML::Symbol &S) {
-  IO.mapRequired("Name", S.SymbolName);
+  IO.mapOptional("Name", S.SymbolName);
   IO.mapOptional("Value", S.Value);
   IO.mapOptional("Section", S.SectionName);
   IO.mapOptional("Type", S.Type);
@@ -151,11 +151,19 @@ void MappingTraits<XCOFFYAML::Symbol>::mapping(IO &IO, XCOFFYAML::Symbol &S) {
   IO.mapOptional("NumberOfAuxEntries", S.NumberOfAuxEntries);
 }
 
+void MappingTraits<XCOFFYAML::StringTable>::mapping(IO &IO, XCOFFYAML::StringTable &Str) {
+  IO.mapOptional("ContentSize", Str.ContentSize);
+  IO.mapOptional("Length", Str.Length);
+  IO.mapOptional("Strings", Str.Strings);
+  IO.mapOptional("RawContent", Str.RawContent);
+}
+
 void MappingTraits<XCOFFYAML::Object>::mapping(IO &IO, XCOFFYAML::Object &Obj) {
   IO.mapTag("!XCOFF", true);
   IO.mapRequired("FileHeader", Obj.Header);
   IO.mapOptional("Sections", Obj.Sections);
   IO.mapOptional("Symbols", Obj.Symbols);
+  IO.mapOptional("StringTable", Obj.StrTbl);
 }
 
 } // namespace yaml

diff  --git a/llvm/test/tools/obj2yaml/XCOFF/aix.yaml b/llvm/test/tools/obj2yaml/XCOFF/aix.yaml
index 640331a2c7ceb..a67a52b5ac007 100644
--- a/llvm/test/tools/obj2yaml/XCOFF/aix.yaml
+++ b/llvm/test/tools/obj2yaml/XCOFF/aix.yaml
@@ -77,4 +77,4 @@
 # CHECK-NEXT:     Type:      0x0
 # CHECK-NEXT:     StorageClass:    C_HIDEXT
 # CHECK-NEXT:     NumberOfAuxEntries: 1
-# CHECK-NEXT: ...
+## TODO: Dump the string table.

diff  --git a/llvm/test/tools/yaml2obj/XCOFF/string-table.yaml b/llvm/test/tools/yaml2obj/XCOFF/string-table.yaml
new file mode 100644
index 0000000000000..0ad5ece9858f7
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/XCOFF/string-table.yaml
@@ -0,0 +1,291 @@
+## Check that yaml2obj is able to customize the string table.
+## `ContentSize`, `Length`, `Strings` and/or `RawContent` can be specified in
+##  YAML. Here we test the behaviour in various cases.
+
+## Case 1: yaml2obj writes the default content (i.e. long symbol names in
+##         XCOFF32 or any symbol names in XCOFF64) when no StringTable field
+##         is specified.
+# RUN: yaml2obj --docnum=1 %s -DSYMNAME='nameInStrTbl' -o %t1
+# RUN: llvm-readobj %t1 --string-table | FileCheck %s --check-prefix=CASE1
+
+# CASE1:      StringTable {
+# CASE1-NEXT:   Length: 17
+# CASE1-NEXT:   [     4]   nameInStrTbl
+# CASE1-NEXT: }
+
+--- !XCOFF
+FileHeader:
+  MagicNumber: 0x1DF
+Symbols:
+  - Name: [[SYMNAME=<none>]]
+  - Name: [[SYMNAME2=<none>]]
+StringTable:
+  ContentSize: [[CONTENTSIZE=<none>]]
+  Length: [[LENGTHVALUE=<none>]]
+  RawContent: [[RAWCONTENT=<none>]]
+
+## We can specify `ContentSize` only when the value is equal to or greater
+## than the content size. For greater cases, zeros are added as padding.
+## Cases 2-6 are trying to check this.
+
+## Case 2: produce a string table with a specified `ContentSize`. In this case,
+##         there is no default content and the content is filled with zeroes.
+# RUN: yaml2obj --docnum=1 %s -DCONTENTSIZE=20 -o %t2
+# RUN: llvm-readobj %t2 -s --string-table | FileCheck %s --check-prefix=CASE2
+
+# CASE2:      StringTable {
+# CASE2-NEXT:   Length: 20
+# CASE2-NEXT: }
+
+## Case 3: if the value of `ContentSize` is greater than the content size,
+##         yaml2obj adds zeros as padding after the default content.
+# RUN: yaml2obj --docnum=1 %s -DSYMNAME='nameInStrTbl' -DCONTENTSIZE=20 -o %t3
+# RUN: llvm-readobj %t3 --string-table | FileCheck %s --check-prefix=CASE3
+
+# CASE3:      StringTable {
+# CASE3-NEXT:   Length: 20
+# CASE3-NEXT:   [     4]   nameInStrTbl
+# CASE3-NEXT: }
+
+## Case 4: the value of `ContentSize` matches the actual content size.
+# RUN: yaml2obj --docnum=1 %s -DSYMNAME='nameInStrTbl' -DCONTENTSIZE=17 -o %t4
+# RUN: llvm-readobj %t4 --string-table | FileCheck %s --check-prefix=CASE4
+
+# CASE4:      StringTable {
+# CASE4-NEXT:   Length: 17
+# CASE4-NEXT:   [     4]   nameInStrTbl
+# CASE4-NEXT: }
+
+## Case 5: an error is reported when the value of "ContentSize" is less than
+##         the content size.
+# RUN: not yaml2obj --docnum=1 %s -DSYMNAME='nameInStrTbl' -DCONTENTSIZE=16 \
+# RUN:   -o %t5 2>&1 | FileCheck %s --check-prefix=CASE5
+
+# CASE5: error: specified ContentSize (16) is less than the size of the data that would otherwise be written (17)
+
+## Case 6: an error is reported when `ContentSize` is less than 4 without
+##         `RawContent`.
+# RUN: not yaml2obj --docnum=1 %s -DCONTENTSIZE=3 -o %t6 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=CASE6
+
+# CASE6: error: ContentSize shouldn't be less than 4 without RawContent
+
+## We can specify `Strings` for a string table. Default contents (ie. symbol
+## names in string table) will be overwritten by specified values. Cases 7-9
+## are trying to check this function.
+
+## Case 7: produce a string table with specified `Strings` directly. In this
+##         case, there is no default content.
+# RUN: yaml2obj --docnum=2 %s -o %t7
+# RUN: llvm-readobj %t7 --string-table | FileCheck %s --check-prefix=CASE7
+
+# CASE7:      StringTable {
+# CASE7-NEXT:   Length: 8
+# CASE7-NEXT:   [     4]   b
+# CASE7-NEXT:   [     6]   a
+# CASE7-NEXT: }
+
+--- !XCOFF
+FileHeader:
+  MagicNumber: 0x1DF
+Symbols:
+  - Name: [[SYMNAME=<none>]]
+  - Name: [[SYMNAME2=<none>]]
+  - Name: [[SYMNAME3=<none>]]
+StringTable:
+  ContentSize: [[CONTENTSIZE=<none>]]
+  Length: [[LENGTHVALUE=<none>]]
+  RawContent: [[RAWCONTENT=<none>]]
+  Strings:
+    - a
+    - b
+
+## Case 8: if the number of `Strings` is greater than or equal to the number
+##         of default strings, all default strings will be overwritten by
+##         specified ones.
+# RUN: yaml2obj --docnum=2 %s -DSYMNAME='nameInStrTbl' -o %t8
+# RUN: llvm-readobj %t8 -s --string-table | FileCheck %s --check-prefix=CASE8
+
+# CASE8:      Symbols [
+# CASE8-NEXT:   Symbol {
+# CASE8-NEXT:     Index: 0
+# CASE8-NEXT:     Name: a
+# CASE8-NEXT:     Value: 0x0
+# CASE8-NEXT:     Section: N_UNDEF
+# CASE8-NEXT:     Type: 0x0
+# CASE8-NEXT:     StorageClass: C_NULL (0x0)
+# CASE8-NEXT:     NumberOfAuxEntries: 0
+# CASE8-NEXT:   }
+# CASE8-NEXT:   Symbol {
+# CASE8-NEXT:     Index: 1
+# CASE8-NEXT:     Name: <none>
+# CASE8-NEXT:     Value: 0x0
+# CASE8-NEXT:     Section: N_UNDEF
+# CASE8-NEXT:     Type: 0x0
+# CASE8-NEXT:     StorageClass: C_NULL (0x0)
+# CASE8-NEXT:     NumberOfAuxEntries: 0
+# CASE8-NEXT:   }
+# CASE8-NEXT:   Symbol {
+# CASE8-NEXT:     Index: 2
+# CASE8-NEXT:     Name: <none>
+# CASE8-NEXT:     Value: 0x0
+# CASE8-NEXT:     Section: N_UNDEF
+# CASE8-NEXT:     Type: 0x0
+# CASE8-NEXT:     StorageClass: C_NULL (0x0)
+# CASE8-NEXT:     NumberOfAuxEntries: 0
+# CASE8-NEXT:   }
+# CASE8-NEXT: ]
+# CASE8-NEXT: StringTable {
+# CASE8-NEXT:   Length: 8
+# CASE8-NEXT:   [     4]   b
+# CASE8-NEXT:   [     6]   a
+# CASE8-NEXT: }
+
+## Case 9: if the number of `Strings` is less than the number of default
+##         strings, default strings will be partially overwritten. The
+##         remaining strings will still be stored after the specified strings
+##         in the string table.
+# RUN: yaml2obj --docnum=2 %s -DSYMNAME='nameInStrTbl' \
+# RUN:   -DSYMNAME2='name2InStrTbl' -DSYMNAME3='name3InStrTbl' -o %t9
+# RUN: llvm-readobj %t9 -s --string-table | FileCheck %s --check-prefix=CASE9
+
+# CASE9:      Symbols [
+# CASE9-NEXT:   Symbol {
+# CASE9-NEXT:     Index: 0
+# CASE9-NEXT:     Name: a
+# CASE9-NEXT:     Value: 0x0
+# CASE9-NEXT:     Section: N_UNDEF
+# CASE9-NEXT:     Type: 0x0
+# CASE9-NEXT:     StorageClass: C_NULL (0x0)
+# CASE9-NEXT:     NumberOfAuxEntries: 0
+# CASE9-NEXT:   }
+# CASE9-NEXT:   Symbol {
+# CASE9-NEXT:     Index: 1
+# CASE9-NEXT:     Name: b
+# CASE9-NEXT:     Value: 0x0
+# CASE9-NEXT:     Section: N_UNDEF
+# CASE9-NEXT:     Type: 0x0
+# CASE9-NEXT:     StorageClass: C_NULL (0x0)
+# CASE9-NEXT:     NumberOfAuxEntries: 0
+# CASE9-NEXT:   }
+# CASE9-NEXT:   Symbol {
+# CASE9-NEXT:     Index: 2
+# CASE9-NEXT:     Name: name3InStrTbl
+# CASE9-NEXT:     Value: 0x0
+# CASE9-NEXT:     Section: N_UNDEF
+# CASE9-NEXT:     Type: 0x0
+# CASE9-NEXT:     StorageClass: C_NULL (0x0)
+# CASE9-NEXT:     NumberOfAuxEntries: 0
+# CASE9-NEXT:   }
+# CASE9-NEXT: ]
+# CASE9-NEXT: StringTable {
+# CASE9-NEXT:   Length: 22
+# CASE9-NEXT:   [     4]   name3InStrTbl
+# CASE9-NEXT:   [    12]   b
+# CASE9-NEXT:   [    14]   a
+# CASE9-NEXT: }
+
+## We can specify both `ContentSize` and `Strings` when `ContentSize` is equal
+## to or greater than the content size. Cases 10-12 are trying to check this.
+
+## Case 10: produce a string table with specified `ContentSize` and `Strings`
+##          when the value is greater than the size of specified strings.
+##          In this case, there is no default content.
+# RUN: yaml2obj --docnum=2 %s -DCONTENTSIZE=20 -o %t10
+# RUN: llvm-readobj %t10 --string-table | FileCheck %s --check-prefix=CASE10
+
+# CASE10:      StringTable {
+# CASE10-NEXT:   Length: 20
+# CASE10-NEXT:   [     4]   b
+# CASE10-NEXT:   [     6]   a
+# CASE10-NEXT: }
+
+## Case 11: for a string table with default contents, we can specify
+##          `ContentSize` and `Strings` when the `ContentSize` is greater
+##          than the data that would otherwise be written.
+# RUN: yaml2obj --docnum=2 %s -DCONTENTSIZE=30 -DSYMNAME='nameInStrTbl' \
+# RUN:   -DSYMNAME2='name2InStrTbl' -DSYMNAME3='name3InStrTbl' -o %t11
+# RUN: llvm-readobj %t11 --string-table | FileCheck %s --check-prefix=CASE11
+
+# CASE11:      StringTable {
+# CASE11-NEXT:   Length: 30
+# CASE11-NEXT:   [     4]   name3InStrTbl
+# CASE11-NEXT:   [    12]   b
+# CASE11-NEXT:   [    14]   a
+# CASE11-NEXT: }
+
+## Case 12: an error is reported when the value of `ContentSize` is less
+##          than the final content size. None of `ContentSize`, `Strings` or
+##          default contents is empty in this case.
+# RUN: not yaml2obj --docnum=2 %s  -DCONTENTSIZE=10 -DSYMNAME='nameInStrTbl' \
+# RUN:   -DSYMNAME2='name2InStrTbl' -DSYMNAME3='name3InStrTbl' -o %t12 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=CASE12
+
+# CASE12: error: specified ContentSize (10) is less than the size of the data that would otherwise be written (22)
+
+## We can use `RawContent` to generate a string table. Cases 13-16 are trying to
+## check the `RawContent`.
+
+## Case 13: if `RawContent` is specified and no `ContentSize` is specified.
+##          Write the `RawContent` data.
+# RUN: yaml2obj --docnum=1 %s -DRAWCONTENT="000000090062006300" -o %t13
+# RUN: llvm-readobj %t13 --string-table | FileCheck %s --check-prefix=CASE13
+
+# CASE13:      StringTable {
+# CASE13-NEXT:   Length: 9
+# CASE13-NEXT:   [     5]   b
+# CASE13-NEXT:   [     7]   c
+# CASE13-NEXT: }
+
+## Case 14: if `RawContent` is specified and `ContentSize` matches the size
+##          of the `RawContent` data. Write the `RawContent` data.
+# RUN: yaml2obj --docnum=1 %s -DRAWCONTENT="000000090062006300" -DCONTENTSIZE=9 -o %t14
+# RUN: llvm-readobj %t14 --string-table | FileCheck %s --check-prefix=CASE14
+
+# CASE14:      StringTable {
+# CASE14-NEXT:   Length: 9
+# CASE14-NEXT:   [     5]   b
+# CASE14-NEXT:   [     7]   c
+# CASE14-NEXT: }
+
+## Case 15: an error is reported when `ContentSize` is less than the `RawContent`
+##          data size.
+# RUN: not yaml2obj --docnum=1 %s -DRAWCONTENT="000000090062006300" -DCONTENTSIZE=6 \
+# RUN:   -o %t15 2>&1 | FileCheck %s --check-prefix=CASE15
+
+# CASE15: error: specified ContentSize (6) is less than the RawContent data size (9)
+
+## Case 16: if `RawContent` is specified and `ContentSize` is greater than the
+##          `RawContent` data size, pad the RawContent with trailing zeroes.
+# RUN: yaml2obj --docnum=1 %s -DRAWCONTENT="000000090062006300" -DCONTENTSIZE=11 -o %t16
+# RUN: llvm-readobj %t16 --string-table | FileCheck %s --check-prefix=CASE16
+
+# CASE16:      StringTable {
+# CASE16-NEXT:   Length: 9
+# CASE16-NEXT:   [     5]   b
+# CASE16-NEXT:   [     7]   c
+# CASE16-NEXT: }
+
+## We can specify `Length`. Use the value of the `Length` field for the first
+## 4 bytes of the table. The value may not make sense for the data that is
+## being written. Cases 17-20 are trying to check this.
+
+## Case 17: report an error if the `Length` is specified as well as `RawContent`.
+# RUN: not yaml2obj --docnum=1 %s -DRAWCONTENT="0062006300" -DLENGTHVALUE=9 \
+# RUN:    -o %t17 2>&1 | FileCheck %s --check-prefix=CASE17
+
+# CASE17: error: can't specify Strings or Length when RawContent is specified
+
+## Case 18: report an error if both `RawContent` and `Strings` are specified.
+# RUN: not yaml2obj --docnum=2 %s -DRAWCONTENT="0062006300" -o %t18 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=CASE18
+
+# CASE18: error: can't specify Strings or Length when RawContent is specified
+
+## Case 19: use the value of the `Length` field for the first 4 bytes of the
+##          table. We dump the string table from the offset of 0x38.
+# RUN: yaml2obj --docnum=1 %s -DSYMNAME='nameInStrTbl' -DLENGTHVALUE=20 -o %t19
+# RUN: od -A n -t x1 -v -j 0x38 %t19 | FileCheck %s --check-prefix=CASE19
+
+# CASE19:      00 00 00 14 6e 61 6d 65 49 6e 53 74 72 54 62 6c
+# CASE19-NEXT: 00


        


More information about the llvm-commits mailing list