forked from OSchip/llvm-project
[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
This commit is contained in:
parent
bbada9ff45
commit
909f3d7380
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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 @@ private:
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -77,4 +77,4 @@
|
|||
# CHECK-NEXT: Type: 0x0
|
||||
# CHECK-NEXT: StorageClass: C_HIDEXT
|
||||
# CHECK-NEXT: NumberOfAuxEntries: 1
|
||||
# CHECK-NEXT: ...
|
||||
## TODO: Dump the string table.
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue