#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"
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);
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<StringRef, int16_t> SectionIndexMap = {
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()) {
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) {
}
bool XCOFFWriter::assignAddressesAndIndices() {
+ Strings.clear();
uint64_t CurrentOffset =
XCOFF::FileHeaderSize32 /* TODO: + auxiliaryHeaderSize() */ +
InitSections.size() * XCOFF::SectionHeaderSize32;
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<int32_t>(0);
+ W.write<uint32_t>(Strings.getOffset(YamlSym.SymbolName));
+ } else {
+ writeName(YamlSym.SymbolName, W);
+ }
W.write<uint32_t>(YamlSym.Value);
W.write<int16_t>(
YamlSym.SectionName.size() ? SectionIndexMap[YamlSym.SectionName] : 0);
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;
}
--- /dev/null
+## 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