WinCOFFObjectWriter: optimize the string table for common suffices
authorHans Wennborg <hans@hanshq.net>
Mon, 29 Sep 2014 22:43:20 +0000 (22:43 +0000)
committerHans Wennborg <hans@hanshq.net>
Mon, 29 Sep 2014 22:43:20 +0000 (22:43 +0000)
This is a follow-up from r207670 which did the same for ELF.

Differential Revision: http://reviews.llvm.org/D5530

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218636 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/StringTableBuilder.h
lib/MC/ELFObjectWriter.cpp
lib/MC/StringTableBuilder.cpp
lib/MC/WinCOFFObjectWriter.cpp
test/MC/COFF/section-name-encoding.s
tools/yaml2obj/yaml2elf.cpp
unittests/MC/StringTableBuilderTest.cpp

index ec9910118209a502a34e33b514c746bea4e9ac67..0c58f5c84f6809a488b807e7783bb890a27468ab 100644 (file)
@@ -29,9 +29,14 @@ public:
     return StringIndexMap.GetOrCreateValue(s, 0).getKey();
   }
 
     return StringIndexMap.GetOrCreateValue(s, 0).getKey();
   }
 
+  enum Kind {
+    ELF,
+    WinCOFF
+  };
+
   /// \brief Analyze the strings and build the final table. No more strings can
   /// be added after this point.
   /// \brief Analyze the strings and build the final table. No more strings can
   /// be added after this point.
-  void finalize();
+  void finalize(Kind kind);
 
   /// \brief Retrieve the string table data. Can only be used after the table
   /// is finalized.
 
   /// \brief Retrieve the string table data. Can only be used after the table
   /// is finalized.
@@ -48,6 +53,8 @@ public:
     return StringIndexMap[s];
   }
 
     return StringIndexMap[s];
   }
 
+  void clear();
+
 private:
   bool isFinalized() {
     return !StringTable.empty();
 private:
   bool isFinalized() {
     return !StringTable.empty();
index a36f3143e14fa24113236948a83aafd2addec36a..efc9cbdd89adcb9c9967680236fa284333ea554d 100644 (file)
@@ -1073,7 +1073,7 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
   for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
     StrTabBuilder.add(*i);
 
   for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
     StrTabBuilder.add(*i);
 
-  StrTabBuilder.finalize();
+  StrTabBuilder.finalize(StringTableBuilder::ELF);
 
   for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
     FileSymbolData.push_back(StrTabBuilder.getOffset(*i));
 
   for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
     FileSymbolData.push_back(StrTabBuilder.getOffset(*i));
@@ -1446,7 +1446,7 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
       static_cast<const MCSectionELF&>(it->getSection());
     ShStrTabBuilder.add(Section.getSectionName());
   }
       static_cast<const MCSectionELF&>(it->getSection());
     ShStrTabBuilder.add(Section.getSectionName());
   }
-  ShStrTabBuilder.finalize();
+  ShStrTabBuilder.finalize(StringTableBuilder::ELF);
   F->getContents().append(ShStrTabBuilder.data().begin(),
                           ShStrTabBuilder.data().end());
 }
   F->getContents().append(ShStrTabBuilder.data().begin(),
                           ShStrTabBuilder.data().end());
 }
index db58ece5c86679486d2586309cb1ccb6039c7773..34e7e6fdfbbb7069f81125f3dc51e2c57740763a 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/ADT/SmallVector.h"
 
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/Endian.h"
 
 using namespace llvm;
 
 
 using namespace llvm;
 
@@ -25,19 +27,28 @@ static bool compareBySuffix(StringRef a, StringRef b) {
   return sizeA > sizeB;
 }
 
   return sizeA > sizeB;
 }
 
-void StringTableBuilder::finalize() {
+void StringTableBuilder::finalize(Kind kind) {
   SmallVector<StringRef, 8> Strings;
   SmallVector<StringRef, 8> Strings;
+  Strings.reserve(StringIndexMap.size());
+
   for (auto i = StringIndexMap.begin(), e = StringIndexMap.end(); i != e; ++i)
     Strings.push_back(i->getKey());
 
   std::sort(Strings.begin(), Strings.end(), compareBySuffix);
 
   for (auto i = StringIndexMap.begin(), e = StringIndexMap.end(); i != e; ++i)
     Strings.push_back(i->getKey());
 
   std::sort(Strings.begin(), Strings.end(), compareBySuffix);
 
-  // FIXME: Starting with a null byte is ELF specific. Generalize this so we
-  // can use the class with other object formats.
-  StringTable += '\x00';
+  if (kind == ELF) {
+    // Start the table with a NUL byte.
+    StringTable += '\x00';
+  } else if (kind == WinCOFF) {
+    // Make room to write the table size later.
+    StringTable.append(4, '\x00');
+  }
 
   StringRef Previous;
   for (StringRef s : Strings) {
 
   StringRef Previous;
   for (StringRef s : Strings) {
+    if (kind == WinCOFF)
+      assert(s.size() > COFF::NameSize && "Short string in COFF string table!");
+
     if (Previous.endswith(s)) {
       StringIndexMap[s] = StringTable.size() - 1 - s.size();
       continue;
     if (Previous.endswith(s)) {
       StringIndexMap[s] = StringTable.size() - 1 - s.size();
       continue;
@@ -48,4 +59,16 @@ void StringTableBuilder::finalize() {
     StringTable += '\x00';
     Previous = s;
   }
     StringTable += '\x00';
     Previous = s;
   }
+
+  if (kind == WinCOFF) {
+    assert(StringTable.size() <= std::numeric_limits<uint32_t>::max());
+    uint32_t size = static_cast<uint32_t>(StringTable.size());
+    support::endian::write<uint32_t, support::little, support::unaligned>(
+        StringTable.data(), size);
+  }
+}
+
+void StringTableBuilder::clear() {
+  StringTable.clear();
+  StringIndexMap.clear();
 }
 }
index 5ffa107da9afc7ca6f8ec42db261c9a9fcfd169a..396683ffceadbbaa194bc795f66b05f575bb77dc 100644 (file)
@@ -26,6 +26,7 @@
 #include "llvm/MC/MCSectionCOFF.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCValue.h"
 #include "llvm/MC/MCSectionCOFF.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCValue.h"
+#include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Support/COFF.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/COFF.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Endian.h"
@@ -102,25 +103,6 @@ public:
   static size_t size();
 };
 
   static size_t size();
 };
 
-// This class holds the COFF string table.
-class StringTable {
-  typedef StringMap<size_t> map;
-  map Map;
-
-  void update_length();
-public:
-  std::vector<char> Data;
-
-  StringTable();
-  size_t size() const;
-  size_t insert(StringRef String);
-  void clear() {
-    Map.clear();
-    Data.resize(4);
-    update_length();
-  }  
-};
-
 class WinCOFFObjectWriter : public MCObjectWriter {
 public:
 
 class WinCOFFObjectWriter : public MCObjectWriter {
 public:
 
@@ -136,7 +118,7 @@ public:
   COFF::header Header;
   sections     Sections;
   symbols      Symbols;
   COFF::header Header;
   sections     Sections;
   symbols      Symbols;
-  StringTable  Strings;
+  StringTableBuilder Strings;
 
   // Maps used during object file creation.
   section_map SectionMap;
 
   // Maps used during object file creation.
   section_map SectionMap;
@@ -168,8 +150,8 @@ public:
   void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler,
                     const MCAsmLayout &Layout);
 
   void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler,
                     const MCAsmLayout &Layout);
 
-  void MakeSymbolReal(COFFSymbol &S, size_t Index);
-  void MakeSectionReal(COFFSection &S, size_t Number);
+  void SetSymbolName(COFFSymbol &S);
+  void SetSectionName(COFFSection &S);
 
   bool ExportSymbol(const MCSymbol &Symbol, MCAssembler &Asm);
 
 
   bool ExportSymbol(const MCSymbol &Symbol, MCAssembler &Asm);
 
@@ -264,49 +246,6 @@ size_t COFFSection::size() {
   return COFF::SectionSize;
 }
 
   return COFF::SectionSize;
 }
 
-//------------------------------------------------------------------------------
-// StringTable class implementation
-
-/// Write the length of the string table into Data.
-/// The length of the string table includes uint32 length header.
-void StringTable::update_length() {
-  write_uint32_le(&Data.front(), Data.size());
-}
-
-StringTable::StringTable() {
-  // The string table data begins with the length of the entire string table
-  // including the length header. Allocate space for this header.
-  Data.resize(4);
-  update_length();
-}
-
-size_t StringTable::size() const {
-  return Data.size();
-}
-
-/// Add String to the table iff it is not already there.
-/// @returns the index into the string table where the string is now located.
-size_t StringTable::insert(StringRef String) {
-  map::iterator i = Map.find(String);
-
-  if (i != Map.end())
-    return i->second;
-
-  size_t Offset = Data.size();
-
-  // Insert string data into string table.
-  Data.insert(Data.end(), String.begin(), String.end());
-  Data.push_back('\0');
-
-  // Put a reference to it in the map.
-  Map[String] = Offset;
-
-  // Update the internal length field.
-  update_length();
-
-  return Offset;
-}
-
 //------------------------------------------------------------------------------
 // WinCOFFObjectWriter class implementation
 
 //------------------------------------------------------------------------------
 // WinCOFFObjectWriter class implementation
 
@@ -521,11 +460,9 @@ static void encodeBase64StringEntry(char* Buffer, uint64_t Value) {
   }
 }
 
   }
 }
 
-/// making a section real involves assigned it a number and putting
-/// name into the string table if needed
-void WinCOFFObjectWriter::MakeSectionReal(COFFSection &S, size_t Number) {
+void WinCOFFObjectWriter::SetSectionName(COFFSection &S) {
   if (S.Name.size() > COFF::NameSize) {
   if (S.Name.size() > COFF::NameSize) {
-    uint64_t StringTableEntry = Strings.insert(S.Name.c_str());
+    uint64_t StringTableEntry = Strings.getOffset(S.Name);
 
     if (StringTableEntry <= Max6DecimalOffset) {
       std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry));
 
     if (StringTableEntry <= Max6DecimalOffset) {
       std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry));
@@ -543,20 +480,13 @@ void WinCOFFObjectWriter::MakeSectionReal(COFFSection &S, size_t Number) {
     }
   } else
     std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
     }
   } else
     std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
-
-  S.Number = Number;
-  S.Symbol->Data.SectionNumber = S.Number;
-  S.Symbol->Aux[0].Aux.SectionDefinition.Number = S.Number;
 }
 
 }
 
-void WinCOFFObjectWriter::MakeSymbolReal(COFFSymbol &S, size_t Index) {
-  if (S.Name.size() > COFF::NameSize) {
-    size_t StringTableEntry = Strings.insert(S.Name.c_str());
-
-    S.set_name_offset(StringTableEntry);
-  } else
+void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) {
+  if (S.Name.size() > COFF::NameSize)
+    S.set_name_offset(Strings.getOffset(S.Name));
+  else
     std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
     std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
-  S.Index = Index;
 }
 
 bool WinCOFFObjectWriter::ExportSymbol(const MCSymbol &Symbol,
 }
 
 bool WinCOFFObjectWriter::ExportSymbol(const MCSymbol &Symbol,
@@ -860,10 +790,14 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
 
   DenseMap<COFFSection *, int32_t> SectionIndices(
       NextPowerOf2(NumberOfSections));
 
   DenseMap<COFFSection *, int32_t> SectionIndices(
       NextPowerOf2(NumberOfSections));
+
+  // Assign section numbers.
   size_t Number = 1;
   for (const auto &Section : Sections) {
     SectionIndices[Section.get()] = Number;
   size_t Number = 1;
   for (const auto &Section : Sections) {
     SectionIndices[Section.get()] = Number;
-    MakeSectionReal(*Section, Number);
+    Section->Number = Number;
+    Section->Symbol->Data.SectionNumber = Number;
+    Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Number;
     ++Number;
   }
 
     ++Number;
   }
 
@@ -903,10 +837,8 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
     // Update section number & offset for symbols that have them.
     if (Symbol->Section)
       Symbol->Data.SectionNumber = Symbol->Section->Number;
     // Update section number & offset for symbols that have them.
     if (Symbol->Section)
       Symbol->Data.SectionNumber = Symbol->Section->Number;
-
     if (Symbol->should_keep()) {
     if (Symbol->should_keep()) {
-      MakeSymbolReal(*Symbol, Header.NumberOfSymbols++);
-
+      Symbol->Index = Header.NumberOfSymbols++;
       // Update auxiliary symbol info.
       Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
       Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols;
       // Update auxiliary symbol info.
       Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
       Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols;
@@ -914,6 +846,22 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
       Symbol->Index = -1;
   }
 
       Symbol->Index = -1;
   }
 
+  // Build string table.
+  for (const auto &S : Sections)
+    if (S->Name.size() > COFF::NameSize)
+      Strings.add(S->Name);
+  for (const auto &S : Symbols)
+    if (S->should_keep() && S->Name.size() > COFF::NameSize)
+      Strings.add(S->Name);
+  Strings.finalize(StringTableBuilder::WinCOFF);
+
+  // Set names.
+  for (const auto &S : Sections)
+    SetSectionName(*S);
+  for (auto &S : Symbols)
+    if (S->should_keep())
+      SetSymbolName(*S);
+
   // Fixup weak external references.
   for (auto & Symbol : Symbols) {
     if (Symbol->Other) {
   // Fixup weak external references.
   for (auto & Symbol : Symbols) {
     if (Symbol->Other) {
@@ -1076,7 +1024,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
     if (Symbol->Index != -1)
       WriteSymbol(*Symbol);
 
     if (Symbol->Index != -1)
       WriteSymbol(*Symbol);
 
-  OS.write((char const *)&Strings.Data.front(), Strings.Data.size());
+  OS.write(Strings.data().data(), Strings.data().size());
 }
 
 MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_) :
 }
 
 MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_) :
index 7edd6d7446d9825c4176aae174554e5015943926..73ab4bdb770f56e9411c32bdebb36e330ac8eac8 100644 (file)
 .section s1234567; .long 1
 
 
 .section s1234567; .long 1
 
 
+// Note: the names in the string table will be sorted in reverse
+// lexicographical order. Use a suffix letter (z, y, x, ...) to
+// get the preferred ordering of names in the test.
+
 // Base 10 encoding
 // Base 10 encoding
+// Ending in z should put the name first in the string table.
 
 // /4
 // CHECK:   Section {
 // CHECK:     Number: 6
 
 // /4
 // CHECK:   Section {
 // CHECK:     Number: 6
-// CHECK:     Name: s12345678 (2F 34 00 00 00 00 00 00)
+// CHECK:     Name: s1234567z (2F 34 00 00 00 00 00 00)
 // CHECK:   }
 // CHECK:   }
-.section s12345678; .long 1
+.section s1234567z; .long 1
 
 
 // Generate padding sections to increase the string table size to at least
 
 
 // Generate padding sections to increase the string table size to at least
   pad_sections2 \pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad
 .endm
 
   pad_sections2 \pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad\pad
 .endm
 
-// 1000x 'a'
-pad_sections aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+// 1000x 'y'
+pad_sections yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
 
 
 // /1000029 == 4 + 10 + (5 * (2 + (20 * 10 * 1000) + 1))
 //             v   |     |    v    ~~~~~~~~~~~~~~    v
 //    table size   v     v   "p0"        pad         NUL separator
 
 
 // /1000029 == 4 + 10 + (5 * (2 + (20 * 10 * 1000) + 1))
 //             v   |     |    v    ~~~~~~~~~~~~~~    v
 //    table size   v     v   "p0"        pad         NUL separator
-//     "s12345678\0"     # of pad sections
+//     "s1234567z\0"     # of pad sections
 //
 // CHECK:   Section {
 // CHECK:     Number: 12
 //
 // CHECK:   Section {
 // CHECK:     Number: 12
-// CHECK:     Name: seven_digit (2F 31 30 30 30 30 32 39)
+// CHECK:     Name: sevendigitx (2F 31 30 30 30 30 32 39)
 // CHECK:   }
 // CHECK:   }
-.section seven_digit; .long 1
+.section sevendigitx; .long 1
 
 
 // Generate padding sections to increase the string table size to at least
 
 
 // Generate padding sections to increase the string table size to at least
@@ -71,18 +76,18 @@ pad_sections aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 .endm
 
 // 1000x 'a'
 .endm
 
 // 1000x 'a'
-pad_sections_ex aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+pad_sections_ex wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
 
 
 // //AAmJa4 == 1000029 + 12 + (5 * (2 + (9 * 20 * 10 * 1000) + 1)) == 38*64^3 + 9*64^2 + 26*64 + 56
 //             v         |     |    v    ~~~~~~~~~~~~~~~~~~    v
 // seven_digit offset    v     v   "p0"         pad            NUL separator
 
 
 // //AAmJa4 == 1000029 + 12 + (5 * (2 + (9 * 20 * 10 * 1000) + 1)) == 38*64^3 + 9*64^2 + 26*64 + 56
 //             v         |     |    v    ~~~~~~~~~~~~~~~~~~    v
 // seven_digit offset    v     v   "p0"         pad            NUL separator
-//         "seven_digit\0"     # of pad sections
+//         "sevendigitx\0"     # of pad sections
 //
 // "2F 2F 41 41 6D 4A 61 34" is "//AAmJa4", which decodes to "0 0 38 9 26 56".
 //
 // CHECK:   Section {
 // CHECK:     Number: 18
 //
 // "2F 2F 41 41 6D 4A 61 34" is "//AAmJa4", which decodes to "0 0 38 9 26 56".
 //
 // CHECK:   Section {
 // CHECK:     Number: 18
-// CHECK:     Name: double_slash (2F 2F 41 41 6D 4A 61 34)
+// CHECK:     Name: doubleslashv (2F 2F 41 41 6D 4A 61 34)
 // CHECK:   }
 // CHECK:   }
-.section double_slash; .long 1
+.section doubleslashv; .long 1
index 6eeecaedcabd74400f64a56fe8167ad41ebc558b..6fbeb2117af55a36e9808d22603a99968c03a3b3 100644 (file)
@@ -190,7 +190,7 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
 
   for (const auto &Sec : Doc.Sections)
     DotShStrtab.add(Sec->Name);
 
   for (const auto &Sec : Doc.Sections)
     DotShStrtab.add(Sec->Name);
-  DotShStrtab.finalize();
+  DotShStrtab.finalize(StringTableBuilder::ELF);
 
   for (const auto &Sec : Doc.Sections) {
     zero(SHeader);
 
   for (const auto &Sec : Doc.Sections) {
     zero(SHeader);
@@ -261,7 +261,7 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
     DotStrtab.add(Sym.Name);
   for (const auto &Sym : Doc.Symbols.Weak)
     DotStrtab.add(Sym.Name);
     DotStrtab.add(Sym.Name);
   for (const auto &Sym : Doc.Symbols.Weak)
     DotStrtab.add(Sym.Name);
-  DotStrtab.finalize();
+  DotStrtab.finalize(StringTableBuilder::ELF);
 
   addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
   addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
 
   addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
   addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
index d30dc6222d23e333a748033c715cd58642106c9c..6b5185cfeb17c42620287d92286665c23cb504b5 100644 (file)
@@ -9,20 +9,21 @@
 
 #include "llvm/MC/StringTableBuilder.h"
 #include "gtest/gtest.h"
 
 #include "llvm/MC/StringTableBuilder.h"
 #include "gtest/gtest.h"
+#include "llvm/Support/Endian.h"
 #include <string>
 
 using namespace llvm;
 
 namespace {
 
 #include <string>
 
 using namespace llvm;
 
 namespace {
 
-TEST(StringTableBuilderTest, Basic) {
+TEST(StringTableBuilderTest, BasicELF) {
   StringTableBuilder B;
 
   B.add("foo");
   B.add("bar");
   B.add("foobar");
 
   StringTableBuilder B;
 
   B.add("foo");
   B.add("bar");
   B.add("foobar");
 
-  B.finalize();
+  B.finalize(StringTableBuilder::ELF);
 
   std::string Expected;
   Expected += '\x00';
 
   std::string Expected;
   Expected += '\x00';
@@ -37,4 +38,34 @@ TEST(StringTableBuilderTest, Basic) {
   EXPECT_EQ(8U, B.getOffset("foo"));
 }
 
   EXPECT_EQ(8U, B.getOffset("foo"));
 }
 
+TEST(StringTableBuilderTest, BasicWinCOFF) {
+  StringTableBuilder B;
+
+  // Strings must be 9 chars or longer to go in the table.
+  B.add("hippopotamus");
+  B.add("pygmy hippopotamus");
+  B.add("river horse");
+
+  B.finalize(StringTableBuilder::WinCOFF);
+
+  // size_field + "pygmy hippopotamus\0" + "river horse\0"
+  uint32_t ExpectedSize = 4 + 19 + 12;
+  EXPECT_EQ(ExpectedSize, B.data().size());
+
+  std::string Expected;
+
+  ExpectedSize =
+      support::endian::byte_swap<uint32_t, support::little>(ExpectedSize);
+  Expected.append((const char*)&ExpectedSize, 4);
+  Expected += "pygmy hippopotamus";
+  Expected += '\x00';
+  Expected += "river horse";
+  Expected += '\x00';
+
+  EXPECT_EQ(Expected, B.data());
+  EXPECT_EQ(4U, B.getOffset("pygmy hippopotamus"));
+  EXPECT_EQ(10U, B.getOffset("hippopotamus"));
+  EXPECT_EQ(23U, B.getOffset("river horse"));
+}
+
 }
 }