[llvm] r238073 - Produce a single string table in a ELF .o

Rafael Espindola rafael.espindola at gmail.com
Fri May 22 16:58:30 PDT 2015


Author: rafael
Date: Fri May 22 18:58:30 2015
New Revision: 238073

URL: http://llvm.org/viewvc/llvm-project?rev=238073&view=rev
Log:
Produce a single string table in a ELF .o

Normally an ELF .o has two string tables, one for symbols, one for section
names.

With the scheme of naming sections like ".text.foo" where foo is a symbol,
there is a big potential saving in using a single one.

Building llvm+clang+lld with master and with this patch the results were:

master:                          193,267,008 bytes
patch:                           186,107,952 bytes
master non unique section names: 183,260,192 bytes
patch non unique section names:  183,118,632 bytes

So using non usique saves 10,006,816 bytes, and the patch saves 7,159,056 while
still using distinct names for the sections.

Modified:
    llvm/trunk/lib/MC/ELFObjectWriter.cpp
    llvm/trunk/test/MC/ELF/empty.s
    llvm/trunk/test/MC/ELF/strtab-suffix-opt.s

Modified: llvm/trunk/lib/MC/ELFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/ELFObjectWriter.cpp?rev=238073&r1=238072&r2=238073&view=diff
==============================================================================
--- llvm/trunk/lib/MC/ELFObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/ELFObjectWriter.cpp Fri May 22 18:58:30 2015
@@ -107,7 +107,6 @@ class ELFObjectWriter : public MCObjectW
 
     llvm::DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>>
         Relocations;
-    StringTableBuilder ShStrTabBuilder;
 
     /// @}
     /// @name Symbol Table Data
@@ -129,8 +128,8 @@ class ELFObjectWriter : public MCObjectW
     unsigned StringTableIndex;
     // This holds the .symtab section index.
     unsigned SymbolTableIndex;
-
-    unsigned ShstrtabIndex;
+    // This holds the .symtab_shndx section index.
+    unsigned SymtabShndxSectionIndex = 0;
 
     // Sections in the order they are to be output in the section table.
     std::vector<MCSectionELF *> SectionTable;
@@ -157,7 +156,6 @@ class ELFObjectWriter : public MCObjectW
       WeakrefUsedInReloc.clear();
       Renames.clear();
       Relocations.clear();
-      ShStrTabBuilder.clear();
       StrTabBuilder.clear();
       FileSymbolData.clear();
       LocalSymbolData.clear();
@@ -224,7 +222,6 @@ class ELFObjectWriter : public MCObjectW
     MCSectionELF *createRelocationSection(MCContext &Ctx,
                                           const MCSectionELF &Sec);
 
-    const MCSectionELF *createSectionHeaderStringTable();
     const MCSectionELF *createStringTable(MCContext &Ctx);
 
     void ExecutePostLayoutBinding(MCAssembler &Asm,
@@ -261,7 +258,7 @@ class ELFObjectWriter : public MCObjectW
 
 unsigned ELFObjectWriter::addToSectionTable(MCSectionELF *Sec) {
   SectionTable.push_back(Sec);
-  ShStrTabBuilder.add(Sec->getSectionName());
+  StrTabBuilder.add(Sec->getSectionName());
   return SectionTable.size();
 }
 
@@ -395,8 +392,8 @@ void ELFObjectWriter::writeHeader(const
   Write16(0);
 
   // e_shstrndx  = Section # of '.shstrtab'
-  assert(ShstrtabIndex < ELF::SHN_LORESERVE);
-  Write16(ShstrtabIndex);
+  assert(StringTableIndex < ELF::SHN_LORESERVE);
+  Write16(StringTableIndex);
 }
 
 uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym,
@@ -541,13 +538,7 @@ void ELFObjectWriter::WriteSymbol(Symbol
 void ELFObjectWriter::writeSymbolTable(MCContext &Ctx,
                                        const MCAsmLayout &Layout,
                                        SectionOffsetsTy &SectionOffsets) {
-  unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
-
-  // Symbol table
-  MCSectionELF *SymtabSection =
-      Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, "");
-  SymtabSection->setAlignment(is64Bit() ? 8 : 4);
-  SymbolTableIndex = addToSectionTable(SymtabSection);
+  MCSectionELF *SymtabSection = SectionTable[SymbolTableIndex - 1];
 
   // The string table must be emitted first because we need the index
   // into the string table for all the symbol names.
@@ -599,14 +590,14 @@ void ELFObjectWriter::writeSymbolTable(M
   SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd);
 
   ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
-  if (ShndxIndexes.empty())
+  if (ShndxIndexes.empty()) {
+    assert(SymtabShndxSectionIndex == 0);
     return;
+  }
+  assert(SymtabShndxSectionIndex != 0);
 
   SecStart = OS.tell();
-  MCSectionELF *SymtabShndxSection =
-      Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
-  addToSectionTable(SymtabShndxSection);
-  SymtabShndxSection->setAlignment(4);
+  MCSectionELF *SymtabShndxSection = SectionTable[SymtabShndxSectionIndex - 1];
   for (uint32_t Index : ShndxIndexes)
     write(Index);
   SecEnd = OS.tell();
@@ -917,6 +908,14 @@ void ELFObjectWriter::computeSymbolTable
     MCAssembler &Asm, const MCAsmLayout &Layout,
     const SectionIndexMapTy &SectionIndexMap,
     const RevGroupMapTy &RevGroupMap) {
+  MCContext &Ctx = Asm.getContext();
+  // Symbol table
+  unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
+  MCSectionELF *SymtabSection =
+      Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, "");
+  SymtabSection->setAlignment(is64Bit() ? 8 : 4);
+  SymbolTableIndex = addToSectionTable(SymtabSection);
+
   // FIXME: Is this the correct place to do this?
   // FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed?
   if (NeedsGOT) {
@@ -928,6 +927,7 @@ void ELFObjectWriter::computeSymbolTable
   }
 
   // Add the data for the symbols.
+  bool HasLargeSectionIndex = false;
   for (const MCSymbol &Symbol : Asm.symbols()) {
     MCSymbolData &SD = Symbol.getData();
 
@@ -959,10 +959,13 @@ void ELFObjectWriter::computeSymbolTable
       assert(!Local);
       MSD.SectionIndex = ELF::SHN_COMMON;
     } else if (BaseSymbol->isUndefined()) {
-      if (isSignature && !Used)
+      if (isSignature && !Used) {
         MSD.SectionIndex = RevGroupMap.lookup(&Symbol);
-      else
+        if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
+          HasLargeSectionIndex = true;
+      } else {
         MSD.SectionIndex = ELF::SHN_UNDEF;
+      }
       if (!Used && WeakrefUsed)
         MCELF::SetBinding(SD, ELF::STB_WEAK);
     } else {
@@ -970,6 +973,8 @@ void ELFObjectWriter::computeSymbolTable
         static_cast<const MCSectionELF&>(BaseSymbol->getSection());
       MSD.SectionIndex = SectionIndexMap.lookup(&Section);
       assert(MSD.SectionIndex && "Invalid section index!");
+      if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
+        HasLargeSectionIndex = true;
     }
 
     // The @@@ in symbol version is replaced with @ in undefined symbols and @@
@@ -1023,6 +1028,13 @@ void ELFObjectWriter::computeSymbolTable
       ExternalSymbolData.push_back(MSD);
   }
 
+  if (HasLargeSectionIndex) {
+    MCSectionELF *SymtabShndxSection =
+        Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
+    SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);
+    SymtabShndxSection->setAlignment(4);
+  }
+
   for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
     StrTabBuilder.add(*i);
 
@@ -1227,17 +1239,8 @@ void ELFObjectWriter::writeRelocations(c
   }
 }
 
-const MCSectionELF *ELFObjectWriter::createSectionHeaderStringTable() {
-  const MCSectionELF *ShstrtabSection = SectionTable[ShstrtabIndex - 1];
-  ShStrTabBuilder.finalize(StringTableBuilder::ELF);
-  OS << ShStrTabBuilder.data();
-  return ShstrtabSection;
-}
-
 const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) {
-  MCSectionELF *StrtabSection =
-      Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
-  StringTableIndex = addToSectionTable(StrtabSection);
+  MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1];
   OS << StrTabBuilder.data();
   return StrtabSection;
 }
@@ -1285,7 +1288,7 @@ void ELFObjectWriter::writeSection(const
       Section.getType() == ELF::SHT_ARM_EXIDX)
     sh_link = SectionIndexMap.lookup(Section.getAssociatedSection());
 
-  WriteSecHdrEntry(ShStrTabBuilder.getOffset(Section.getSectionName()),
+  WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()),
                    Section.getType(), Section.getFlags(), 0, Offset, Size,
                    sh_link, sh_info, Section.getAlignment(),
                    Section.getEntrySize());
@@ -1328,9 +1331,9 @@ void ELFObjectWriter::writeSectionHeader
 void ELFObjectWriter::WriteObject(MCAssembler &Asm,
                                   const MCAsmLayout &Layout) {
   MCContext &Ctx = Asm.getContext();
-  MCSectionELF *ShstrtabSection =
-      Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0);
-  ShstrtabIndex = addToSectionTable(ShstrtabSection);
+  MCSectionELF *StrtabSection =
+      Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
+  StringTableIndex = addToSectionTable(StrtabSection);
 
   RevGroupMapTy RevGroupMap;
   SectionIndexMapTy SectionIndexMap;
@@ -1425,13 +1428,6 @@ void ELFObjectWriter::WriteObject(MCAsse
     uint64_t SecEnd = OS.tell();
     SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
   }
-
-  {
-    uint64_t SecStart = OS.tell();
-    const MCSectionELF *Sec = createSectionHeaderStringTable();
-    uint64_t SecEnd = OS.tell();
-    SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
-  }
 
   uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
   uint64_t Padding = OffsetToAlignment(OS.tell(), NaturalAlignment);

Modified: llvm/trunk/test/MC/ELF/empty.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/empty.s?rev=238073&r1=238072&r2=238073&view=diff
==============================================================================
--- llvm/trunk/test/MC/ELF/empty.s (original)
+++ llvm/trunk/test/MC/ELF/empty.s Fri May 22 18:58:30 2015
@@ -11,16 +11,16 @@
 // WINDOWS-NEXT: Arch: x86_64
 
 // Test that like gnu as we create text, data and bss by default. Also test
-// that shstrtab, symtab and strtab are listed.
+// that symtab and strtab are listed.
 
 // CHECK:        Section {
-// CHECK:          Name: .shstrtab
+// CHECK:          Name: .strtab
 // CHECK-NEXT:     Type: SHT_STRTAB
 // CHECK-NEXT:     Flags [
 // CHECK-NEXT:     ]
 // CHECK-NEXT:     Address: 0x0
 // CHECK-NEXT:     Offset:
-// CHECK-NEXT:     Size: 44
+// CHECK-NEXT:     Size: 34
 // CHECK-NEXT:     Link: 0
 // CHECK-NEXT:     Info: 0
 // CHECK-NEXT:     AddressAlignment: 1
@@ -84,16 +84,3 @@
 // CHECK-NEXT:     AddressAlignment: 8
 // CHECK-NEXT:     EntrySize: 24
 // CHECK-NEXT:   }
-// CHECK:        Section {
-// CHECK:          Name: .strtab
-// CHECK-NEXT:     Type: SHT_STRTAB
-// CHECK-NEXT:     Flags [
-// CHECK-NEXT:     ]
-// CHECK-NEXT:     Address: 0x0
-// CHECK-NEXT:     Offset:
-// CHECK-NEXT:     Size: 1
-// CHECK-NEXT:     Link: 0
-// CHECK-NEXT:     Info: 0
-// CHECK-NEXT:     AddressAlignment: 1
-// CHECK-NEXT:     EntrySize: 0
-// CHECK-NEXT:   }

Modified: llvm/trunk/test/MC/ELF/strtab-suffix-opt.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/strtab-suffix-opt.s?rev=238073&r1=238072&r2=238073&view=diff
==============================================================================
--- llvm/trunk/test/MC/ELF/strtab-suffix-opt.s (original)
+++ llvm/trunk/test/MC/ELF/strtab-suffix-opt.s Fri May 22 18:58:30 2015
@@ -16,6 +16,6 @@ foobar:
 .Ltmp3:
 	.size	foobar, .Ltmp3-foobar
 
-// CHECK:     Name: foobar (1)
-// CHECK:     Name: bar (4)
-// CHECK:     Name: foo (8)
+// CHECK:     Name: foobar (16)
+// CHECK:     Name: bar (19)
+// CHECK:     Name: foo (23)





More information about the llvm-commits mailing list