FWriter.write(F, Value);
}
- void WriteHeader(const MCAssembler &Asm,
- unsigned NumberOfSections);
+ void writeHeader(const MCAssembler &Asm);
void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
const MCAsmLayout &Layout);
uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm,
const MCSymbol *S);
- // Map from a signature symbol to the group section
- typedef DenseMap<const MCSymbol*, const MCSectionELF*> RevGroupMapTy;
+ // Map from a signature symbol to the group section index
+ typedef DenseMap<const MCSymbol *, unsigned> RevGroupMapTy;
// Start and end offset of each section
typedef std::vector<std::pair<uint64_t, uint64_t>> SectionOffsetsTy;
const SectionIndexMapTy &SectionIndexMap,
const RevGroupMapTy &RevGroupMap);
- void maybeAddToGroup(MCAssembler &Asm, const RevGroupMapTy &RevGroupMap,
+ void maybeAddToGroup(MCAssembler &Asm,
+ ArrayRef<const MCSectionELF *> Sections,
+ const RevGroupMapTy &RevGroupMap,
const MCSectionELF &Section, unsigned Index);
void computeIndexMap(MCAssembler &Asm,
SectionIndexMapTy &SectionIndexMap,
const RevGroupMapTy &RevGroupMap);
- MCSectionData *createRelocationSection(MCAssembler &Asm,
- const MCSectionData &SD);
+ void createRelocationSection(MCAssembler &Asm, const MCSectionData &SD);
void CompressDebugSections(MCAssembler &Asm, MCAsmLayout &Layout);
- void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout);
+ void WriteRelocations(MCAssembler &Asm, const MCAsmLayout &Layout);
- void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout,
+ void
+ createSectionHeaderStringTable(MCAssembler &Asm,
+ std::vector<const MCSectionELF *> &Sections);
+ void createStringTable(MCAssembler &Asm,
+ 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
// those are the .note.GNU-stack section and the group sections.
- void createIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout,
+ void createIndexedSections(MCAssembler &Asm, const MCAsmLayout &Layout,
RevGroupMapTy &RevGroupMap,
std::vector<const MCSectionELF *> &Sections,
SectionIndexMapTy &SectionIndexMap);
{}
// Emit the ELF header.
-void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
- unsigned NumberOfSections) {
+void ELFObjectWriter::writeHeader(const MCAssembler &Asm) {
// ELF Header
// ----------
//
Write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
// e_shnum = # of section header ents
- if (NumberOfSections >= ELF::SHN_LORESERVE)
- Write16(ELF::SHN_UNDEF);
- else
- Write16(NumberOfSections);
+ Write16(0);
// e_shstrndx = Section # of '.shstrtab'
- if (ShstrtabIndex >= ELF::SHN_LORESERVE)
- Write16(ELF::SHN_XINDEX);
- else
- Write16(ShstrtabIndex);
+ assert(ShstrtabIndex < ELF::SHN_LORESERVE);
+ Write16(ShstrtabIndex);
}
uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data,
}
void ELFObjectWriter::maybeAddToGroup(MCAssembler &Asm,
+ ArrayRef<const MCSectionELF *> Sections,
const RevGroupMapTy &RevGroupMap,
const MCSectionELF &Section,
unsigned Index) {
const MCSymbol *Sym = Section.getGroup();
if (!Sym)
return;
- const MCSectionELF *Group = RevGroupMap.lookup(Sym);
+ const MCSectionELF *Group = Sections[RevGroupMap.lookup(Sym) - 1];
MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
// FIXME: we could use the previous fragment
MCDataFragment *F = new MCDataFragment(&Data);
void ELFObjectWriter::computeIndexMap(
MCAssembler &Asm, std::vector<const MCSectionELF *> &Sections,
SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap) {
- std::vector<const MCSectionELF *> RelSections;
for (const MCSectionData &SD : Asm) {
const MCSectionELF &Section =
static_cast<const MCSectionELF &>(SD.getSection());
- if (Section.getType() == ELF::SHT_GROUP ||
- Section.getType() == ELF::SHT_REL ||
- Section.getType() == ELF::SHT_RELA)
+ if (Section.getType() == ELF::SHT_GROUP)
continue;
Sections.push_back(&Section);
unsigned Index = Sections.size();
SectionIndexMap[&Section] = Index;
- maybeAddToGroup(Asm, RevGroupMap, Section, Index);
-
- if (MCSectionData *RelSD = createRelocationSection(Asm, SD)) {
- const MCSectionELF *RelSection =
- static_cast<const MCSectionELF *>(&RelSD->getSection());
- RelSections.push_back(RelSection);
- }
- }
-
- // Put relocation sections close together. The linker reads them
- // first, so this improves cache locality.
- for (const MCSectionELF *Sec : RelSections) {
- Sections.push_back(Sec);
- unsigned Index = Sections.size();
- maybeAddToGroup(Asm, RevGroupMap, *Sec, Index);
+ maybeAddToGroup(Asm, Sections, RevGroupMap, Section, Index);
+ createRelocationSection(Asm, SD);
}
}
MSD.SectionIndex = ELF::SHN_COMMON;
} else if (BaseSymbol->isUndefined()) {
if (isSignature && !Used)
- MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap.lookup(&Symbol));
+ MSD.SectionIndex = RevGroupMap.lookup(&Symbol);
else
MSD.SectionIndex = ELF::SHN_UNDEF;
if (!Used && WeakrefUsed)
UndefinedSymbolData[i].SymbolData->setIndex(Index++);
}
-MCSectionData *
-ELFObjectWriter::createRelocationSection(MCAssembler &Asm,
- const MCSectionData &SD) {
+void ELFObjectWriter::createRelocationSection(MCAssembler &Asm,
+ const MCSectionData &SD) {
if (Relocations[&SD].empty())
- return nullptr;
+ return;
MCContext &Ctx = Asm.getContext();
const MCSectionELF &Section =
const MCSectionELF *RelaSection = Ctx.createELFRelSection(
RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL,
Flags, EntrySize, Section.getGroup(), &Section);
- return &Asm.getOrCreateSectionData(*RelaSection);
+ Asm.getOrCreateSectionData(*RelaSection);
}
static SmallVector<char, 128>
-getUncompressedData(MCAsmLayout &Layout,
+getUncompressedData(const MCAsmLayout &Layout,
MCSectionData::FragmentListType &Fragments) {
SmallVector<char, 128> UncompressedData;
for (const MCFragment &F : Fragments) {
// Return a single fragment containing the compressed contents of the whole
// section. Null if the section was not compressed for any reason.
static std::unique_ptr<MCDataFragment>
-getCompressedFragment(MCAsmLayout &Layout,
+getCompressedFragment(const MCAsmLayout &Layout,
MCSectionData::FragmentListType &Fragments) {
std::unique_ptr<MCDataFragment> CompressedFragment(new MCDataFragment());
}
}
-void ELFObjectWriter::WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) {
+void ELFObjectWriter::WriteRelocations(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) {
MCSectionData &RelSD = *it;
const MCSectionELF &RelSection =
}
}
+void ELFObjectWriter::createSectionHeaderStringTable(
+ MCAssembler &Asm, std::vector<const MCSectionELF *> &Sections) {
+ const MCSectionELF *ShstrtabSection = Sections[ShstrtabIndex - 1];
+
+ Asm.getOrCreateSectionData(*ShstrtabSection);
+
+ for (MCSectionData &SD : Asm) {
+ const MCSectionELF &Section =
+ static_cast<const MCSectionELF &>(SD.getSection());
+ ShStrTabBuilder.add(Section.getSectionName());
+ }
+ ShStrTabBuilder.finalize(StringTableBuilder::ELF);
+ OS << ShStrTabBuilder.data();
+}
+
+void ELFObjectWriter::createStringTable(
+ MCAssembler &Asm, std::vector<const MCSectionELF *> &Sections) {
+ MCContext &Ctx = Asm.getContext();
+ const MCSectionELF *StrtabSection =
+ Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
+ Asm.getOrCreateSectionData(*StrtabSection);
+ Sections.push_back(StrtabSection);
+ StringTableIndex = Sections.size();
+ OS << StrTabBuilder.data();
+}
+
void ELFObjectWriter::CreateMetadataSections(
- MCAssembler &Asm, MCAsmLayout &Layout,
+ 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;
- // We construct .shstrtab, .symtab and .strtab in this order to match gnu as.
- const MCSectionELF *ShstrtabSection =
- Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0);
- MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection);
- ShstrtabSD.setAlignment(1);
- ShstrtabIndex = Sections.size() + 1;
- Sections.push_back(ShstrtabSection);
-
+ // Symbol table
const MCSectionELF *SymtabSection =
Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
EntrySize, "");
SymtabSD.setAlignment(is64Bit() ? 8 : 4);
SymbolTableIndex = Sections.size() + 1;
Sections.push_back(SymtabSection);
-
- const MCSectionELF *StrtabSection;
- StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
- MCSectionData &StrtabSD = Asm.getOrCreateSectionData(*StrtabSection);
- StrtabSD.setAlignment(1);
- StringTableIndex = Sections.size() + 1;
- Sections.push_back(StrtabSection);
-
- // Symbol table
F = new MCDataFragment(&SymtabSD);
WriteSymbolTable(F, Asm, Layout, Sections);
-
- F = new MCDataFragment(&StrtabSD);
- F->getContents().append(StrTabBuilder.data().begin(),
- StrTabBuilder.data().end());
-
- F = new MCDataFragment(&ShstrtabSD);
-
- // Section header string table.
- for (auto it = Asm.begin(), ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(it->getSection());
- ShStrTabBuilder.add(Section.getSectionName());
- }
- ShStrTabBuilder.finalize(StringTableBuilder::ELF);
- F->getContents().append(ShStrTabBuilder.data().begin(),
- ShStrTabBuilder.data().end());
}
void ELFObjectWriter::createIndexedSections(
- MCAssembler &Asm, MCAsmLayout &Layout, RevGroupMapTy &RevGroupMap,
+ MCAssembler &Asm, const MCAsmLayout &Layout, RevGroupMapTy &RevGroupMap,
std::vector<const MCSectionELF *> &Sections,
SectionIndexMapTy &SectionIndexMap) {
MCContext &Ctx = Asm.getContext();
+ const MCSectionELF *ShstrtabSection =
+ Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0);
+ Sections.push_back(ShstrtabSection);
+ ShstrtabIndex = Sections.size();
+ assert(ShstrtabIndex == 1);
+
// Build the groups
for (const MCSectionData &SD : Asm) {
const MCSectionELF &Section =
const MCSymbol *SignatureSymbol = Section.getGroup();
Asm.getOrCreateSymbolData(*SignatureSymbol);
- const MCSectionELF *&Group = RevGroupMap[SignatureSymbol];
- if (!Group) {
- Group = Ctx.createELFGroupSection(SignatureSymbol);
+ unsigned &GroupIdx = RevGroupMap[SignatureSymbol];
+ if (!GroupIdx) {
+ const MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol);
Sections.push_back(Group);
- SectionIndexMap[Group] = Sections.size();
+ GroupIdx = Sections.size();
MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
Data.setAlignment(4);
// Null section first.
uint64_t FirstSectionSize =
(NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0;
- uint32_t FirstSectionLink =
- ShstrtabIndex >= ELF::SHN_LORESERVE ? ShstrtabIndex : 0;
- WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, FirstSectionLink, 0, 0, 0);
+ WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0);
for (unsigned i = 0; i < NumSections; ++i) {
const MCSectionELF &Section = *Sections[i];
CompressDebugSections(Asm, const_cast<MCAsmLayout &>(Layout));
std::vector<const MCSectionELF *> Sections;
- createIndexedSections(Asm, const_cast<MCAsmLayout &>(Layout), RevGroupMap,
- Sections, SectionIndexMap);
+ createIndexedSections(Asm, Layout, RevGroupMap, Sections, SectionIndexMap);
// Compute symbol table information.
computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap);
- WriteRelocations(Asm, const_cast<MCAsmLayout &>(Layout));
+ WriteRelocations(Asm, Layout);
- CreateMetadataSections(const_cast<MCAssembler &>(Asm),
- const_cast<MCAsmLayout &>(Layout), Sections);
+ CreateMetadataSections(Asm, Layout, Sections);
- unsigned NumSections = Asm.size();
SectionOffsetsTy SectionOffsets;
// Write out the ELF header ...
- WriteHeader(Asm, NumSections + 1);
+ writeHeader(Asm);
// ... then the sections ...
- for (const MCSectionELF *Section : Sections) {
- const MCSectionData &SD = Asm.getOrCreateSectionData(*Section);
+ SectionOffsets.push_back(std::make_pair(0, 0));
+ for (auto I = ++Sections.begin(), E = Sections.end(); I != E; ++I) {
+ const MCSectionData &SD = Asm.getOrCreateSectionData(**I);
uint64_t Padding = OffsetToAlignment(OS.tell(), SD.getAlignment());
WriteZeros(Padding);
SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
}
+ {
+ uint64_t SecStart = OS.tell();
+ createStringTable(Asm, Sections);
+ uint64_t SecEnd = OS.tell();
+ SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
+ }
+
+ {
+ uint64_t SecStart = OS.tell();
+ createSectionHeaderStringTable(Asm, Sections);
+ uint64_t SecEnd = OS.tell();
+ SectionOffsets[0] = std::make_pair(SecStart, SecEnd);
+ }
+
uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
uint64_t Padding = OffsetToAlignment(OS.tell(), NaturalAlignment);
WriteZeros(Padding);
// ... then the section header table ...
writeSectionHeader(Sections, Asm, Layout, SectionIndexMap, SectionOffsets);
+ uint16_t NumSections = (Sections.size() + 1 >= ELF::SHN_LORESERVE)
+ ? ELF::SHN_UNDEF
+ : Sections.size() + 1;
+ if (sys::IsLittleEndianHost != IsLittleEndian)
+ sys::swapByteOrder(NumSections);
+ unsigned NumSectionsOffset;
+
if (is64Bit()) {
uint64_t Val = SectionHeaderOffset;
if (sys::IsLittleEndianHost != IsLittleEndian)
sys::swapByteOrder(Val);
OS.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
offsetof(ELF::Elf64_Ehdr, e_shoff));
+ NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
} else {
uint32_t Val = SectionHeaderOffset;
if (sys::IsLittleEndianHost != IsLittleEndian)
sys::swapByteOrder(Val);
OS.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
offsetof(ELF::Elf32_Ehdr, e_shoff));
+ NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
}
+ OS.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),
+ NumSectionsOffset);
}
bool ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(