Write the symbol table directly to the output file.

There is no need to first accumulate it in fragments.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236157 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola
2015-04-29 21:09:32 +00:00
parent 90d98d86c2
commit 5fc3769ddc

View File

@@ -51,32 +51,29 @@ public:
typedef DenseMap<const MCSectionELF *, uint32_t> SectionIndexMapTy; typedef DenseMap<const MCSectionELF *, uint32_t> SectionIndexMapTy;
class ELFObjectWriter;
class SymbolTableWriter { class SymbolTableWriter {
MCAssembler &Asm; ELFObjectWriter &EWriter;
FragmentWriter &FWriter;
bool Is64Bit; bool Is64Bit;
std::vector<const MCSectionELF *> &Sections;
// The symbol .symtab fragment we are writting to. // indexes we are going to write to .symtab_shndx.
MCDataFragment *SymtabF; std::vector<uint32_t> ShndxIndexes;
// .symtab_shndx fragment we are writting to.
MCDataFragment *ShndxF;
// The numbel of symbols written so far. // The numbel of symbols written so far.
unsigned NumWritten; unsigned NumWritten;
void createSymtabShndx(); void createSymtabShndx();
template <typename T> void write(MCDataFragment &F, T Value); template <typename T> void write(T Value);
public: public:
SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter, bool Is64Bit, SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit);
std::vector<const MCSectionELF *> &Sections,
MCDataFragment *SymtabF);
void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size, void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size,
uint8_t other, uint32_t shndx, bool Reserved); uint8_t other, uint32_t shndx, bool Reserved);
ArrayRef<uint32_t> getShndxIndexes() const { return ShndxIndexes; }
}; };
class ELFObjectWriter : public MCObjectWriter { class ELFObjectWriter : public MCObjectWriter {
@@ -190,6 +187,13 @@ class ELFObjectWriter : public MCObjectWriter {
Write32(W); Write32(W);
} }
template <typename T> void write(T Val) {
if (IsLittleEndian)
support::endian::Writer<support::little>(OS).write(Val);
else
support::endian::Writer<support::big>(OS).write(Val);
}
template <typename T> void write(MCDataFragment &F, T Value) { template <typename T> void write(MCDataFragment &F, T Value) {
FWriter.write(F, Value); FWriter.write(F, Value);
} }
@@ -199,9 +203,12 @@ class ELFObjectWriter : public MCObjectWriter {
void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
const MCAsmLayout &Layout); const MCAsmLayout &Layout);
void WriteSymbolTable(MCDataFragment *SymtabF, MCAssembler &Asm, // Start and end offset of each section
const MCAsmLayout &Layout, typedef std::vector<std::pair<uint64_t, uint64_t>> SectionOffsetsTy;
std::vector<const MCSectionELF *> &Sections);
void WriteSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
std::vector<const MCSectionELF *> &Sections,
SectionOffsetsTy &SectionOffsets);
bool shouldRelocateWithSymbol(const MCAssembler &Asm, bool shouldRelocateWithSymbol(const MCAssembler &Asm,
const MCSymbolRefExpr *RefA, const MCSymbolRefExpr *RefA,
@@ -218,8 +225,6 @@ class ELFObjectWriter : public MCObjectWriter {
// Map from a signature symbol to the group section index // Map from a signature symbol to the group section index
typedef DenseMap<const MCSymbol *, unsigned> RevGroupMapTy; typedef DenseMap<const MCSymbol *, unsigned> RevGroupMapTy;
// Start and end offset of each section
typedef std::vector<std::pair<uint64_t, uint64_t>> SectionOffsetsTy;
/// Compute the symbol table data /// Compute the symbol table data
/// ///
@@ -251,8 +256,6 @@ class ELFObjectWriter : public MCObjectWriter {
std::vector<const MCSectionELF *> &Sections); std::vector<const MCSectionELF *> &Sections);
void createStringTable(MCAssembler &Asm, void createStringTable(MCAssembler &Asm,
std::vector<const MCSectionELF *> &Sections); std::vector<const MCSectionELF *> &Sections);
void CreateMetadataSections(MCAssembler &Asm, const MCAsmLayout &Layout,
std::vector<const MCSectionELF *> &Sections);
// Create the sections that show up in the symbol table. Currently // Create the sections that show up in the symbol table. Currently
// those are the .note.GNU-stack section and the group sections. // those are the .note.GNU-stack section and the group sections.
@@ -309,32 +312,18 @@ template <typename T> void FragmentWriter::write(MCDataFragment &F, T Val) {
} }
void SymbolTableWriter::createSymtabShndx() { void SymbolTableWriter::createSymtabShndx() {
if (ShndxF) if (!ShndxIndexes.empty())
return; return;
MCContext &Ctx = Asm.getContext(); ShndxIndexes.resize(NumWritten);
const MCSectionELF *SymtabShndxSection =
Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
MCSectionData *SymtabShndxSD =
&Asm.getOrCreateSectionData(*SymtabShndxSection);
SymtabShndxSD->setAlignment(4);
ShndxF = new MCDataFragment(SymtabShndxSD);
Sections.push_back(SymtabShndxSection);
for (unsigned I = 0; I < NumWritten; ++I)
write(*ShndxF, uint32_t(0));
} }
template <typename T> template <typename T> void SymbolTableWriter::write(T Value) {
void SymbolTableWriter::write(MCDataFragment &F, T Value) { EWriter.write(Value);
FWriter.write(F, Value);
} }
SymbolTableWriter::SymbolTableWriter( SymbolTableWriter::SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit)
MCAssembler &Asm, FragmentWriter &FWriter, bool Is64Bit, : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {}
std::vector<const MCSectionELF *> &Sections, MCDataFragment *SymtabF)
: Asm(Asm), FWriter(FWriter), Is64Bit(Is64Bit), Sections(Sections),
SymtabF(SymtabF), ShndxF(nullptr), NumWritten(0) {}
void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value, void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
uint64_t size, uint8_t other, uint64_t size, uint8_t other,
@@ -344,29 +333,29 @@ void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
if (LargeIndex) if (LargeIndex)
createSymtabShndx(); createSymtabShndx();
if (ShndxF) { if (!ShndxIndexes.empty()) {
if (LargeIndex) if (LargeIndex)
write(*ShndxF, shndx); ShndxIndexes.push_back(shndx);
else else
write(*ShndxF, uint32_t(0)); ShndxIndexes.push_back(0);
} }
uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx; uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx;
if (Is64Bit) { if (Is64Bit) {
write(*SymtabF, name); // st_name write(name); // st_name
write(*SymtabF, info); // st_info write(info); // st_info
write(*SymtabF, other); // st_other write(other); // st_other
write(*SymtabF, Index); // st_shndx write(Index); // st_shndx
write(*SymtabF, value); // st_value write(value); // st_value
write(*SymtabF, size); // st_size write(size); // st_size
} else { } else {
write(*SymtabF, name); // st_name write(name); // st_name
write(*SymtabF, uint32_t(value)); // st_value write(uint32_t(value)); // st_value
write(*SymtabF, uint32_t(size)); // st_size write(uint32_t(size)); // st_size
write(*SymtabF, info); // st_info write(info); // st_info
write(*SymtabF, other); // st_other write(other); // st_other
write(*SymtabF, Index); // st_shndx write(Index); // st_shndx
} }
++NumWritten; ++NumWritten;
@@ -595,14 +584,31 @@ void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
} }
void ELFObjectWriter::WriteSymbolTable( void ELFObjectWriter::WriteSymbolTable(
MCDataFragment *SymtabF, MCAssembler &Asm, const MCAsmLayout &Layout, MCAssembler &Asm, const MCAsmLayout &Layout,
std::vector<const MCSectionELF *> &Sections) { std::vector<const MCSectionELF *> &Sections,
SectionOffsetsTy &SectionOffsets) {
MCContext &Ctx = Asm.getContext();
unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
// Symbol table
const MCSectionELF *SymtabSection =
Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, "");
MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
SymtabSD.setAlignment(is64Bit() ? 8 : 4);
SymbolTableIndex = Sections.size() + 1;
Sections.push_back(SymtabSection);
// The string table must be emitted first because we need the index // The string table must be emitted first because we need the index
// into the string table for all the symbol names. // into the string table for all the symbol names.
// FIXME: Make sure the start of the symbol table is aligned. SymbolTableWriter Writer(*this, is64Bit());
SymbolTableWriter Writer(Asm, FWriter, is64Bit(), Sections, SymtabF); uint64_t Padding = OffsetToAlignment(OS.tell(), SymtabSD.getAlignment());
WriteZeros(Padding);
uint64_t SecStart = OS.tell();
// The first entry is the undefined symbol entry. // The first entry is the undefined symbol entry.
Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
@@ -638,6 +644,25 @@ void ELFObjectWriter::WriteSymbolTable(
if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) if (MCELF::GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++; LastLocalSymbolIndex++;
} }
uint64_t SecEnd = OS.tell();
SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
if (ShndxIndexes.empty())
return;
SecStart = OS.tell();
const MCSectionELF *SymtabShndxSection =
Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
Sections.push_back(SymtabShndxSection);
MCSectionData *SymtabShndxSD =
&Asm.getOrCreateSectionData(*SymtabShndxSection);
SymtabShndxSD->setAlignment(4);
for (uint32_t Index : ShndxIndexes)
write(Index);
SecEnd = OS.tell();
SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
} }
// It is always valid to create a relocation with a symbol. It is preferable // It is always valid to create a relocation with a symbol. It is preferable
@@ -1396,26 +1421,6 @@ void ELFObjectWriter::createStringTable(
OS << StrTabBuilder.data(); OS << StrTabBuilder.data();
} }
void ELFObjectWriter::CreateMetadataSections(
MCAssembler &Asm, const MCAsmLayout &Layout,
std::vector<const MCSectionELF *> &Sections) {
MCContext &Ctx = Asm.getContext();
MCDataFragment *F;
unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
// Symbol table
const MCSectionELF *SymtabSection =
Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
EntrySize, "");
MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
SymtabSD.setAlignment(is64Bit() ? 8 : 4);
SymbolTableIndex = Sections.size() + 1;
Sections.push_back(SymtabSection);
F = new MCDataFragment(&SymtabSD);
WriteSymbolTable(F, Asm, Layout, Sections);
}
void ELFObjectWriter::createIndexedSections( void ELFObjectWriter::createIndexedSections(
MCAssembler &Asm, const MCAsmLayout &Layout, RevGroupMapTy &RevGroupMap, MCAssembler &Asm, const MCAsmLayout &Layout, RevGroupMapTy &RevGroupMap,
std::vector<const MCSectionELF *> &Sections, std::vector<const MCSectionELF *> &Sections,
@@ -1570,7 +1575,6 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
WriteRelocations(Asm, Layout); WriteRelocations(Asm, Layout);
CreateMetadataSections(Asm, Layout, Sections);
SectionOffsetsTy SectionOffsets; SectionOffsetsTy SectionOffsets;
@@ -1591,6 +1595,8 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
SectionOffsets.push_back(std::make_pair(SecStart, SecEnd)); SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
} }
WriteSymbolTable(Asm, Layout, Sections, SectionOffsets);
{ {
uint64_t SecStart = OS.tell(); uint64_t SecStart = OS.tell();
createStringTable(Asm, Sections); createStringTable(Asm, Sections);