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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238073 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2015-05-22 23:58:30 +00:00
parent e00c0df2c4
commit 7c4f3dcc5e
3 changed files with 45 additions and 62 deletions

View File

@ -107,7 +107,6 @@ class ELFObjectWriter : public MCObjectWriter {
llvm::DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>>
Relocations;
StringTableBuilder ShStrTabBuilder;
/// @}
/// @name Symbol Table Data
@ -129,8 +128,8 @@ class ELFObjectWriter : public MCObjectWriter {
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 MCObjectWriter {
WeakrefUsedInReloc.clear();
Renames.clear();
Relocations.clear();
ShStrTabBuilder.clear();
StrTabBuilder.clear();
FileSymbolData.clear();
LocalSymbolData.clear();
@ -224,7 +222,6 @@ class ELFObjectWriter : public MCObjectWriter {
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 MCObjectWriter {
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 MCAssembler &Asm) {
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(SymbolTableWriter &Writer, ELFSymbolData &MSD,
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(MCContext &Ctx,
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(const MCAssembler &Asm,
}
}
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 SectionIndexMapTy &SectionIndexMap,
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;
@ -1426,13 +1429,6 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
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);
WriteZeros(Padding);

View File

@ -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: }

View File

@ -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)