[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