ELFObjectWriter: deduplicate suffices in strtab

We already do this for shstrtab, so might as well do it for strtab. This
extracts the string table building code into a separate class. The idea
is to use it for other object formats too.

I mostly wanted to do this for the general principle, but it does save a
little bit on object file size. I tried this on a clang bootstrap and
saved 0.54% on the sum of object file sizes (1.14 MB out of 212 MB for
a release build).

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207670 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Hans Wennborg 2014-04-30 16:25:02 +00:00
parent b1c1b8a78d
commit a8febf2283
22 changed files with 282 additions and 165 deletions

View File

@ -0,0 +1,59 @@
//===-- StringTableBuilder.h - String table building utility ------*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_STRINGTABLE_BUILDER_H
#define LLVM_OBJECT_STRINGTABLE_BUILDER_H
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include <cassert>
namespace llvm {
/// \brief Utility for building string tables with deduplicated suffixes.
class StringTableBuilder {
SmallString<256> StringTable;
StringMap<size_t> StringIndexMap;
public:
/// \brief Add a string to the builder. Returns a StringRef to the internal
/// copy of s. Can only be used before the table is finalized.
StringRef add(StringRef s) {
assert(!isFinalized());
return StringIndexMap.GetOrCreateValue(s, 0).getKey();
}
/// \brief Analyze the strings and build the final table. No more strings can
/// be added after this point.
void finalize();
/// \brief Retrieve the string table data. Can only be used after the table
/// is finalized.
StringRef data() {
assert(isFinalized());
return StringTable;
}
/// \brief Get the offest of a string in the string table. Can only be used
/// after the table is finalized.
size_t getOffset(StringRef s) {
assert(isFinalized());
assert(StringIndexMap.count(s) && "String is not in table!");
return StringIndexMap[s];
}
private:
bool isFinalized() {
return !StringTable.empty();
}
};
} // end llvm namespace
#endif

View File

@ -28,6 +28,7 @@
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Object/StringTableBuilder.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
@ -132,11 +133,11 @@ class ELFObjectWriter : public MCObjectWriter {
MCSymbolData *SymbolData;
uint64_t StringIndex;
uint32_t SectionIndex;
StringRef Name;
// Support lexicographic sorting.
bool operator<(const ELFSymbolData &RHS) const {
return SymbolData->getSymbol().getName() <
RHS.SymbolData->getSymbol().getName();
return Name < RHS.Name;
}
};
@ -149,13 +150,13 @@ class ELFObjectWriter : public MCObjectWriter {
llvm::DenseMap<const MCSectionData *, std::vector<ELFRelocationEntry>>
Relocations;
DenseMap<const MCSection*, uint64_t> SectionStringTableIndex;
StringTableBuilder ShStrTabBuilder;
/// @}
/// @name Symbol Table Data
/// @{
SmallString<256> StringTable;
StringTableBuilder StrTabBuilder;
std::vector<uint64_t> FileSymbolData;
std::vector<ELFSymbolData> LocalSymbolData;
std::vector<ELFSymbolData> ExternalSymbolData;
@ -676,7 +677,6 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
SectionIndexMapTy &SectionIndexMap) {
// The string table must be emitted first because we need the index
// into the string table for all the symbol names.
assert(StringTable.size() && "Missing string table");
// FIXME: Make sure the start of the symbol table is aligned.
@ -1031,27 +1031,6 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
MCELF::SetBinding(Data, ELF::STB_GLOBAL);
}
// Index 0 is always the empty string.
StringMap<uint64_t> StringIndexMap;
StringTable += '\x00';
// FIXME: We could optimize suffixes in strtab in the same way we
// optimize them in shstrtab.
for (MCAssembler::const_file_name_iterator it = Asm.file_names_begin(),
ie = Asm.file_names_end();
it != ie;
++it) {
StringRef Name = *it;
uint64_t &Entry = StringIndexMap[Name];
if (!Entry) {
Entry = StringTable.size();
StringTable += Name;
StringTable += '\x00';
}
FileSymbolData.push_back(Entry);
}
// Add the data for the symbols.
for (MCSymbolData &SD : Asm.symbols()) {
const MCSymbol &Symbol = SD.getSymbol();
@ -1102,7 +1081,6 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
// @@ in defined ones.
StringRef Name = Symbol.getName();
SmallString<32> Buf;
size_t Pos = Name.find("@@@");
if (Pos != StringRef::npos) {
Buf += Name.substr(0, Pos);
@ -1110,14 +1088,8 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
Buf += Name.substr(Pos + Skip);
Name = Buf;
}
MSD.Name = StrTabBuilder.add(Name);
uint64_t &Entry = StringIndexMap[Name];
if (!Entry) {
Entry = StringTable.size();
StringTable += Name;
StringTable += '\x00';
}
MSD.StringIndex = Entry;
if (MSD.SectionIndex == ELF::SHN_UNDEF)
UndefinedSymbolData.push_back(MSD);
else if (Local)
@ -1126,6 +1098,21 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
ExternalSymbolData.push_back(MSD);
}
for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
StrTabBuilder.add(*i);
StrTabBuilder.finalize();
for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
FileSymbolData.push_back(StrTabBuilder.getOffset(*i));
for (ELFSymbolData& MSD : LocalSymbolData)
MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
for (ELFSymbolData& MSD : ExternalSymbolData)
MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
for (ELFSymbolData& MSD : UndefinedSymbolData)
MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
// Symbols are required to be in lexicographic order.
array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end());
array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
@ -1436,23 +1423,6 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm,
}
}
static int compareBySuffix(const MCSectionELF *const *a,
const MCSectionELF *const *b) {
const StringRef &NameA = (*a)->getSectionName();
const StringRef &NameB = (*b)->getSectionName();
const unsigned sizeA = NameA.size();
const unsigned sizeB = NameB.size();
const unsigned len = std::min(sizeA, sizeB);
for (unsigned int i = 0; i < len; ++i) {
char ca = NameA[sizeA - i - 1];
char cb = NameB[sizeB - i - 1];
if (ca != cb)
return cb - ca;
}
return sizeB - sizeA;
}
void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
MCAsmLayout &Layout,
SectionIndexMapTy &SectionIndexMap,
@ -1493,45 +1463,20 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
WriteSymbolTable(F, Asm, Layout, SectionIndexMap);
F = new MCDataFragment(&StrtabSD);
F->getContents().append(StringTable.begin(), StringTable.end());
F->getContents().append(StrTabBuilder.data().begin(),
StrTabBuilder.data().end());
F = new MCDataFragment(&ShstrtabSD);
std::vector<const MCSectionELF*> Sections;
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) {
// Section header string table.
for (auto it = Asm.begin(), ie = Asm.end(); it != ie; ++it) {
const MCSectionELF &Section =
static_cast<const MCSectionELF&>(it->getSection());
Sections.push_back(&Section);
}
array_pod_sort(Sections.begin(), Sections.end(), compareBySuffix);
// Section header string table.
//
// The first entry of a string table holds a null character so skip
// section 0.
uint64_t Index = 1;
F->getContents().push_back('\x00');
for (unsigned int I = 0, E = Sections.size(); I != E; ++I) {
const MCSectionELF &Section = *Sections[I];
StringRef Name = Section.getSectionName();
if (I != 0) {
StringRef PreviousName = Sections[I - 1]->getSectionName();
if (PreviousName.endswith(Name)) {
SectionStringTableIndex[&Section] = Index - Name.size() - 1;
continue;
}
}
// Remember the index into the string table so we can write it
// into the sh_name field of the section header table.
SectionStringTableIndex[&Section] = Index;
Index += Name.size() + 1;
F->getContents().append(Name.begin(), Name.end());
F->getContents().push_back('\x00');
ShStrTabBuilder.add(Section.getSectionName());
}
ShStrTabBuilder.finalize();
F->getContents().append(ShStrTabBuilder.data().begin(),
ShStrTabBuilder.data().end());
}
void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm,
@ -1599,7 +1544,7 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm,
switch(Section.getType()) {
case ELF::SHT_DYNAMIC:
sh_link = SectionStringTableIndex[&Section];
sh_link = ShStrTabBuilder.getOffset(Section.getSectionName());
sh_info = 0;
break;
@ -1680,7 +1625,8 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm,
}
}
WriteSecHdrEntry(SectionStringTableIndex[&Section], Section.getType(),
WriteSecHdrEntry(ShStrTabBuilder.getOffset(Section.getSectionName()),
Section.getType(),
Section.getFlags(), 0, Offset, Size, sh_link, sh_info,
Alignment, Section.getEntrySize());
}

View File

@ -12,6 +12,7 @@ add_llvm_library(LLVMObject
MachOUniversal.cpp
Object.cpp
ObjectFile.cpp
StringTableBuilder.cpp
SymbolicFile.cpp
YAML.cpp
)

View File

@ -0,0 +1,51 @@
//===-- StringTableBuilder.cpp - String table building utility ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/SmallVector.h"
#include "llvm/Object/StringTableBuilder.h"
using namespace llvm;
static bool compareBySuffix(StringRef a, StringRef b) {
size_t sizeA = a.size();
size_t sizeB = b.size();
size_t len = std::min(sizeA, sizeB);
for (size_t i = 0; i < len; ++i) {
char ca = a[sizeA - i - 1];
char cb = b[sizeB - i - 1];
if (ca != cb)
return ca > cb;
}
return sizeA > sizeB;
}
void StringTableBuilder::finalize() {
SmallVector<StringRef, 8> Strings;
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';
StringRef Previous;
for (StringRef s : Strings) {
if (Previous.endswith(s)) {
StringIndexMap[s] = StringTable.size() - 1 - s.size();
continue;
}
StringIndexMap[s] = StringTable.size();
StringTable += s;
StringTable += '\x00';
Previous = s;
}
}

View File

@ -543,7 +543,7 @@
// CHECK-ELF: Symbols [
// CHECK-ELF: Symbol {
// CHECK-ELF: Name: var (6)
// CHECK-ELF: Name: var
// CHECK-ELF-NEXT: Value:
// CHECK-ELF-NEXT: Size:
// CHECK-ELF-NEXT: Binding: Global

View File

@ -313,7 +313,7 @@
// CHECK-ELF: Symbols [
// CHECK-ELF: Symbol {
// CHECK-ELF: Name: var (6)
// CHECK-ELF: Name: var
// CHECK-ELF-NEXT: Value:
// CHECK-ELF-NEXT: Size:
// CHECK-ELF-NEXT: Binding: Global

View File

@ -49,7 +49,7 @@
// Test that g1 and g2 are local, but g3 is an undefined global.
// CHECK: Symbol {
// CHECK: Name: g1 (1)
// CHECK: Name: g1
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -58,7 +58,7 @@
// CHECK-NEXT: Section: .foo (0x7)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: g2 (4)
// CHECK-NEXT: Name: g2
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -68,7 +68,7 @@
// CHECK-NEXT: }
// CHECK: Symbol {
// CHECK: Name: g3 (7)
// CHECK: Name: g3
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global

View File

@ -9,7 +9,7 @@
.comm common1,1,1
// CHECK: Symbol {
// CHECK: Name: common1 (1)
// CHECK: Name: common1
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 1
// CHECK-NEXT: Binding: Local
@ -25,7 +25,7 @@
.comm common2,1,1
// CHECK: Symbol {
// CHECK: Name: common2 (9)
// CHECK: Name: common2
// CHECK-NEXT: Value: 0x1
// CHECK-NEXT: Size: 1
// CHECK-NEXT: Binding: Local
@ -39,7 +39,7 @@
.comm common6,8,16
// CHECK: Symbol {
// CHECK: Name: common6 (17)
// CHECK: Name: common6
// CHECK-NEXT: Value: 0x10
// CHECK-NEXT: Size: 8
// CHECK-NEXT: Binding: Local
@ -54,7 +54,7 @@
.comm common3,4,4
// CHECK: Symbol {
// CHECK: Name: common3 (25)
// CHECK: Name: common3
// CHECK-NEXT: Value: 0x4
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Binding: Global
@ -76,7 +76,7 @@ foo:
.comm common4,40,16
// CHECK: Symbol {
// CHECK: Name: common4 (37)
// CHECK: Name: common4
// CHECK-NEXT: Value: 0x10
// CHECK-NEXT: Size: 40
// CHECK-NEXT: Binding: Global
@ -89,7 +89,7 @@ foo:
.comm common5,4,4
// CHECK: Symbol {
// CHECK: Name: common5 (45)
// CHECK: Name: common5
// CHECK-NEXT: Value: 0x4
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Binding: Global

View File

@ -11,7 +11,7 @@ foo.c:
bar.c:
// CHECK: Symbol {
// CHECK: Name: foo.c (1)
// CHECK: Name: foo.c
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -19,7 +19,7 @@ bar.c:
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: Absolute (0xFFF1)
// CHECK-NEXT: }
// CHECK: Name: bar.c (7)
// CHECK: Name: bar.c
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -28,7 +28,7 @@ bar.c:
// CHECK-NEXT: Section: Absolute (0xFFF1)
// CHECK-NEXT: }
// CHECK: Symbol {
// CHECK: Name: bar.c (7)
// CHECK: Name: bar.c
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -37,7 +37,7 @@ bar.c:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK: Symbol {
// CHECK: Name: foo.c (1)
// CHECK: Name: foo.c
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global

View File

@ -4,7 +4,7 @@
.lcomm B, 32 << 20
// CHECK: Symbol {
// CHECK: Name: A (1)
// CHECK: Name: A
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 5
// CHECK-NEXT: Binding: Local
@ -13,7 +13,7 @@
// CHECK-NEXT: Section: .bss (0x3)
// CHECK-NEXT: }
// CHECK: Symbol {
// CHECK: Name: B (3)
// CHECK: Name: B
// CHECK-NEXT: Value: 0x5
// CHECK-NEXT: Size: 33554432
// CHECK-NEXT: Binding: Local

View File

@ -12,7 +12,7 @@
// Test that both a and b show up in the correct section.
// SYMBOLS: Name: a (1)
// SYMBOLS: Name: a
// SYMBOLS-NEXT: Value: 0x0
// SYMBOLS-NEXT: Size: 0
// SYMBOLS-NEXT: Binding: Local (0x0)
@ -21,7 +21,7 @@
// SYMBOLS-NEXT: Section: last (0xFF00)
// SYMBOLS-NEXT: }
// SYMBOLS-NEXT: Symbol {
// SYMBOLS-NEXT: Name: b (3)
// SYMBOLS-NEXT: Name: b
// SYMBOLS-NEXT: Value: 0x1
// SYMBOLS-NEXT: Size: 0
// SYMBOLS-NEXT: Binding: Local (0x0)
@ -32,7 +32,7 @@
// Test that this file has one section too many.
// SYMBOLS: Name: last (0)
// SYMBOLS: Name: last
// SYMBOLS-NEXT: Value: 0x0
// SYMBOLS-NEXT: Size: 0
// SYMBOLS-NEXT: Binding: Local (0x0)

View File

@ -7,7 +7,7 @@
// CHECK-NEXT: ]
// CHECK: Symbol {
// CHECK: Name: baz (5)
// CHECK: Name: baz
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global

View File

@ -8,7 +8,7 @@ mov %eax,bar
// CHECK: Symbol {
// CHECK: Name: bar (5)
// CHECK: Name: bar
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -17,7 +17,7 @@ mov %eax,bar
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo (1)
// CHECK-NEXT: Name: foo
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global

View File

@ -5,7 +5,7 @@
.set kernbase,0xffffffff80000000
// CHECK: Symbol {
// CHECK: Name: kernbase (1)
// CHECK: Name: kernbase
// CHECK-NEXT: Value: 0xFFFFFFFF80000000
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -26,7 +26,7 @@
// Test that there is an undefined reference to bar
// CHECK: Symbol {
// CHECK: Name: bar (10)
// CHECK: Name: bar
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global

View File

@ -0,0 +1,21 @@
// RUN: llvm-mc -filetype=obj -triple i686-pc-linux-gnu %s -o - | llvm-readobj -symbols | FileCheck %s
.text
.globl foobar
.align 16, 0x90
.type foobar,@function
foobar:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
calll foo
calll bar
addl $8, %esp
popl %ebp
retl
.Ltmp3:
.size foobar, .Ltmp3-foobar
// CHECK: Name: foobar (1)
// CHECK: Name: bar (4)
// CHECK: Name: foo (8)

View File

@ -18,7 +18,7 @@
.long fooE@INDNTPOFF
// CHECK: Symbol {
// CHECK: Name: foo1 (1)
// CHECK: Name: foo1
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -27,7 +27,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo2 (6)
// CHECK-NEXT: Name: foo2
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -36,7 +36,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo3 (11)
// CHECK-NEXT: Name: foo3
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -45,7 +45,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo4 (16)
// CHECK-NEXT: Name: foo4
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -54,7 +54,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo5 (21)
// CHECK-NEXT: Name: foo5
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -63,7 +63,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo6 (26)
// CHECK-NEXT: Name: foo6
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -72,7 +72,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo7 (31)
// CHECK-NEXT: Name: foo7
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -81,7 +81,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo8 (36)
// CHECK-NEXT: Name: foo8
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -90,7 +90,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo9 (41)
// CHECK-NEXT: Name: foo9
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -99,7 +99,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: fooA (46)
// CHECK-NEXT: Name: fooA
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -108,7 +108,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: fooB (51)
// CHECK-NEXT: Name: fooB
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -117,7 +117,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: fooC (56)
// CHECK-NEXT: Name: fooC
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -126,7 +126,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: fooD (61)
// CHECK-NEXT: Name: fooD
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -135,7 +135,7 @@
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: fooE (66)
// CHECK-NEXT: Name: fooE
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global

View File

@ -13,7 +13,7 @@ foobar:
.long 43
// CHECK: Symbol {
// CHECK: Name: foobar (31)
// CHECK: Name: foobar
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -23,7 +23,7 @@ foobar:
// CHECK-NEXT: }
// CHECK: Symbol {
// CHECK: Name: foo1 (1)
// CHECK: Name: foo1
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -32,7 +32,7 @@ foobar:
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo2 (6)
// CHECK-NEXT: Name: foo2
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -41,7 +41,7 @@ foobar:
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo3 (11)
// CHECK-NEXT: Name: foo3
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -50,7 +50,7 @@ foobar:
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo4 (16)
// CHECK-NEXT: Name: foo4
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -59,7 +59,7 @@ foobar:
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo5 (21)
// CHECK-NEXT: Name: foo5
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -68,7 +68,7 @@ foobar:
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo6 (26)
// CHECK-NEXT: Name: foo6
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global

View File

@ -176,7 +176,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym1 (54)
// CHECK-NEXT: Name: sym1
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -185,7 +185,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym10 (162)
// CHECK-NEXT: Name: sym10
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -194,7 +194,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym11 (176)
// CHECK-NEXT: Name: sym11
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -203,7 +203,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym12 (190)
// CHECK-NEXT: Name: sym12
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -212,7 +212,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym2 (66)
// CHECK-NEXT: Name: sym2
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -221,7 +221,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym3 (78)
// CHECK-NEXT: Name: sym3
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -230,7 +230,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym4 (90)
// CHECK-NEXT: Name: sym4
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -239,7 +239,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym5 (102)
// CHECK-NEXT: Name: sym5
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -248,7 +248,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym6 (114)
// CHECK-NEXT: Name: sym6
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -257,7 +257,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym7 (126)
// CHECK-NEXT: Name: sym7
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -266,7 +266,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym8 (138)
// CHECK-NEXT: Name: sym8
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)
@ -275,7 +275,7 @@ alias12:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: sym9 (150)
// CHECK-NEXT: Name: sym9
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global (0x1)

View File

@ -80,7 +80,7 @@ bar15:
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar6 (21)
// CHECK-NEXT: Name: bar6
// CHECK-NEXT: Value: 0x18
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -89,7 +89,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar7 (26)
// CHECK-NEXT: Name: bar7
// CHECK-NEXT: Value: 0x18
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -98,7 +98,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar8 (31)
// CHECK-NEXT: Name: bar8
// CHECK-NEXT: Value: 0x1C
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -107,7 +107,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar9 (36)
// CHECK-NEXT: Name: bar9
// CHECK-NEXT: Value: 0x20
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -116,7 +116,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: .text (0)
// CHECK-NEXT: Name: .text
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -125,7 +125,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: .data (0)
// CHECK-NEXT: Name: .data
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -134,7 +134,7 @@ bar15:
// CHECK-NEXT: Section: .data (0x3)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: .bss (0)
// CHECK-NEXT: Name: .bss
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
@ -143,7 +143,7 @@ bar15:
// CHECK-NEXT: Section: .bss (0x4)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar10 (41)
// CHECK-NEXT: Name: bar10
// CHECK-NEXT: Value: 0x28
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -152,7 +152,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar11 (47)
// CHECK-NEXT: Name: bar11
// CHECK-NEXT: Value: 0x30
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -161,7 +161,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar12 (53)
// CHECK-NEXT: Name: bar12
// CHECK-NEXT: Value: 0x30
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -170,7 +170,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar13 (59)
// CHECK-NEXT: Name: bar13
// CHECK-NEXT: Value: 0x34
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -179,7 +179,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar14 (65)
// CHECK-NEXT: Name: bar14
// CHECK-NEXT: Value: 0x38
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -188,7 +188,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar15 (71)
// CHECK-NEXT: Name: bar15
// CHECK-NEXT: Value: 0x40
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -197,7 +197,7 @@ bar15:
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar2 (1)
// CHECK-NEXT: Name: bar2
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -206,7 +206,7 @@ bar15:
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar3 (6)
// CHECK-NEXT: Name: bar3
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Weak
@ -215,7 +215,7 @@ bar15:
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar4 (11)
// CHECK-NEXT: Name: bar4
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
@ -224,7 +224,7 @@ bar15:
// CHECK-NEXT: Section: Undefined (0x0)
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar5 (16)
// CHECK-NEXT: Name: bar5
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global

View File

@ -30,10 +30,8 @@ using namespace llvm;
// This class has a deliberately small interface, since a lot of
// implementation variation is possible.
//
// TODO: Use an ordered container with a suffix-based comparison in order
// to deduplicate suffixes. std::map<> with a custom comparator is likely
// to be the simplest implementation, but a suffix trie could be more
// suitable for the job.
// TODO: Use the StringTable builder from lib/Object instead, since it
// will deduplicate suffixes.
namespace {
class StringTableBuilder {
/// \brief Indices of strings currently present in `Buf`.

View File

@ -4,5 +4,6 @@ set(LLVM_LINK_COMPONENTS
)
add_llvm_unittest(ObjectTests
StringTableBuilderTest.cpp
YAMLTest.cpp
)

View File

@ -0,0 +1,40 @@
//===----------- StringTableBuilderTest.cpp -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "gtest/gtest.h"
#include "llvm/Object/StringTableBuilder.h"
#include <string>
using namespace llvm;
namespace {
TEST(StringTableBuilderTest, Basic) {
StringTableBuilder B;
B.add("foo");
B.add("bar");
B.add("foobar");
B.finalize();
std::string Expected;
Expected += '\x00';
Expected += "foobar";
Expected += '\x00';
Expected += "foo";
Expected += '\x00';
EXPECT_EQ(Expected, B.data());
EXPECT_EQ(1U, B.getOffset("foobar"));
EXPECT_EQ(4U, B.getOffset("bar"));
EXPECT_EQ(8U, B.getOffset("foo"));
}
}