diff --git a/lib/ObjectYAML/XCOFFEmitter.cpp b/lib/ObjectYAML/XCOFFEmitter.cpp index c113fae20f1..2fd73a77cae 100644 --- a/lib/ObjectYAML/XCOFFEmitter.cpp +++ b/lib/ObjectYAML/XCOFFEmitter.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/XCOFFObjectFile.h" #include "llvm/ObjectYAML/ObjectYAML.h" #include "llvm/ObjectYAML/yaml2obj.h" @@ -31,12 +32,14 @@ constexpr uint32_t MaxRawDataSize = UINT32_MAX; class XCOFFWriter { public: XCOFFWriter(XCOFFYAML::Object &Obj, raw_ostream &OS, yaml::ErrorHandler EH) - : Obj(Obj), W(OS, support::big), ErrHandler(EH) { + : Obj(Obj), W(OS, support::big), ErrHandler(EH), + Strings(StringTableBuilder::XCOFF) { Is64Bit = Obj.Header.Magic == (llvm::yaml::Hex16)XCOFF::XCOFF64; } bool writeXCOFF(); private: + bool nameShouldBeInStringTable(StringRef SymbolName); bool initFileHeader(uint64_t CurrentOffset); bool initSectionHeader(uint64_t &CurrentOffset); bool initRelocations(uint64_t &CurrentOffset); @@ -51,6 +54,7 @@ private: bool Is64Bit = false; support::endian::Writer W; yaml::ErrorHandler ErrHandler; + StringTableBuilder Strings; uint64_t StartOffset; // Map the section name to its corrresponding section index. DenseMap SectionIndexMap = { @@ -70,6 +74,10 @@ static void writeName(StringRef StrName, support::endian::Writer W) { W.write(NameRef); } +bool XCOFFWriter::nameShouldBeInStringTable(StringRef SymbolName) { + return SymbolName.size() > XCOFF::NameSize; +} + bool XCOFFWriter::initRelocations(uint64_t &CurrentOffset) { for (uint16_t I = 0, E = InitSections.size(); I < E; ++I) { if (!InitSections[I].Relocations.empty()) { @@ -139,7 +147,11 @@ bool XCOFFWriter::initFileHeader(uint64_t CurrentOffset) { 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) { @@ -157,6 +169,7 @@ bool XCOFFWriter::initFileHeader(uint64_t CurrentOffset) { } bool XCOFFWriter::assignAddressesAndIndices() { + Strings.clear(); uint64_t CurrentOffset = XCOFF::FileHeaderSize32 /* TODO: + auxiliaryHeaderSize() */ + InitSections.size() * XCOFF::SectionHeaderSize32; @@ -260,7 +273,14 @@ bool XCOFFWriter::writeSymbols() { if (PaddingSize > 0) W.OS.write_zeros(PaddingSize); for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) { - writeName(YamlSym.SymbolName, W); + if (nameShouldBeInStringTable(YamlSym.SymbolName)) { + // For XCOFF32: A value of 0 indicates that the symbol name is in the + // string table. + W.write(0); + W.write(Strings.getOffset(YamlSym.SymbolName)); + } else { + writeName(YamlSym.SymbolName, W); + } W.write(YamlSym.Value); W.write( YamlSym.SectionName.size() ? SectionIndexMap[YamlSym.SectionName] : 0); @@ -297,8 +317,12 @@ bool XCOFFWriter::writeXCOFF() { if (!writeRelocations()) return false; } - if (!Obj.Symbols.empty()) - return writeSymbols(); + if (!Obj.Symbols.empty()) { + if (!writeSymbols()) + return false; + // Write the string table. + Strings.write(W.OS); + } return true; } diff --git a/test/tools/yaml2obj/XCOFF/long-symbol-name.yaml b/test/tools/yaml2obj/XCOFF/long-symbol-name.yaml new file mode 100644 index 00000000000..d800f6cd73f --- /dev/null +++ b/test/tools/yaml2obj/XCOFF/long-symbol-name.yaml @@ -0,0 +1,33 @@ +## Test that the string table works well for long symbol names. +## TODO: Dump the raw string table and check the contents. +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj --symbols %t | FileCheck %s + +# CHECK: AddressSize: 32bit +# CHECK-NEXT: Symbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: Name: .symname +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Section: N_UNDEF +# CHECK-NEXT: Type: 0x0 +# CHECK-NEXT: StorageClass: C_NULL (0x0) +# CHECK-NEXT: NumberOfAuxEntries: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Name: .longname +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Section: N_UNDEF +# CHECK-NEXT: Type: 0x0 +# CHECK-NEXT: StorageClass: C_NULL (0x0) +# CHECK-NEXT: NumberOfAuxEntries: 0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Symbols: + - Name: .symname + - Name: .longname