mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-20 08:54:08 +00:00
WinCOFFObjectWriter: optimize the string table for common suffices
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
This commit is contained in:
parent
6a2169eb6f
commit
4edcbaec90
@ -29,9 +29,14 @@ public:
|
||||
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.
|
||||
void finalize();
|
||||
void finalize(Kind kind);
|
||||
|
||||
/// \brief Retrieve the string table data. Can only be used after the table
|
||||
/// is finalized.
|
||||
@ -48,6 +53,8 @@ public:
|
||||
return StringIndexMap[s];
|
||||
}
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
bool isFinalized() {
|
||||
return !StringTable.empty();
|
||||
|
@ -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);
|
||||
|
||||
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));
|
||||
@ -1446,7 +1446,7 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
|
||||
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());
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include "llvm/MC/StringTableBuilder.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/COFF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -25,19 +27,28 @@ static bool compareBySuffix(StringRef a, StringRef b) {
|
||||
return sizeA > sizeB;
|
||||
}
|
||||
|
||||
void StringTableBuilder::finalize() {
|
||||
void StringTableBuilder::finalize(Kind kind) {
|
||||
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);
|
||||
|
||||
// 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) {
|
||||
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;
|
||||
@ -48,4 +59,16 @@ void StringTableBuilder::finalize() {
|
||||
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();
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#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"
|
||||
@ -102,25 +103,6 @@ public:
|
||||
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:
|
||||
|
||||
@ -136,7 +118,7 @@ public:
|
||||
COFF::header Header;
|
||||
sections Sections;
|
||||
symbols Symbols;
|
||||
StringTable Strings;
|
||||
StringTableBuilder Strings;
|
||||
|
||||
// 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 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);
|
||||
|
||||
@ -264,49 +246,6 @@ size_t COFFSection::size() {
|
||||
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
|
||||
|
||||
@ -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) {
|
||||
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));
|
||||
@ -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());
|
||||
|
||||
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());
|
||||
S.Index = Index;
|
||||
}
|
||||
|
||||
bool WinCOFFObjectWriter::ExportSymbol(const MCSymbol &Symbol,
|
||||
@ -860,10 +790,14 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
|
||||
|
||||
DenseMap<COFFSection *, int32_t> SectionIndices(
|
||||
NextPowerOf2(NumberOfSections));
|
||||
|
||||
// Assign section numbers.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
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;
|
||||
@ -914,6 +846,22 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
|
||||
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) {
|
||||
@ -1076,7 +1024,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
|
||||
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_) :
|
||||
|
@ -21,14 +21,19 @@
|
||||
.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
|
||||
// Ending in z should put the name first in the string table.
|
||||
|
||||
// /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: }
|
||||
.section s12345678; .long 1
|
||||
.section s1234567z; .long 1
|
||||
|
||||
|
||||
// Generate padding sections to increase the string table size to at least
|
||||
@ -47,20 +52,20 @@
|
||||
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
|
||||
// "s12345678\0" # of pad sections
|
||||
// "s1234567z\0" # of pad sections
|
||||
//
|
||||
// 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: }
|
||||
.section seven_digit; .long 1
|
||||
.section sevendigitx; .long 1
|
||||
|
||||
|
||||
// Generate padding sections to increase the string table size to at least
|
||||
@ -71,18 +76,18 @@ pad_sections aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
.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
|
||||
// "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
|
||||
// CHECK: Name: double_slash (2F 2F 41 41 6D 4A 61 34)
|
||||
// CHECK: Name: doubleslashv (2F 2F 41 41 6D 4A 61 34)
|
||||
// CHECK: }
|
||||
.section double_slash; .long 1
|
||||
.section doubleslashv; .long 1
|
||||
|
@ -190,7 +190,7 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
|
||||
|
||||
for (const auto &Sec : Doc.Sections)
|
||||
DotShStrtab.add(Sec->Name);
|
||||
DotShStrtab.finalize();
|
||||
DotShStrtab.finalize(StringTableBuilder::ELF);
|
||||
|
||||
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.finalize();
|
||||
DotStrtab.finalize(StringTableBuilder::ELF);
|
||||
|
||||
addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
|
||||
addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
|
||||
|
@ -9,20 +9,21 @@
|
||||
|
||||
#include "llvm/MC/StringTableBuilder.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include <string>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(StringTableBuilderTest, Basic) {
|
||||
TEST(StringTableBuilderTest, BasicELF) {
|
||||
StringTableBuilder B;
|
||||
|
||||
B.add("foo");
|
||||
B.add("bar");
|
||||
B.add("foobar");
|
||||
|
||||
B.finalize();
|
||||
B.finalize(StringTableBuilder::ELF);
|
||||
|
||||
std::string Expected;
|
||||
Expected += '\x00';
|
||||
@ -37,4 +38,34 @@ TEST(StringTableBuilderTest, Basic) {
|
||||
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"));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user