MCAssembler &Asm;
FragmentWriter &FWriter;
bool Is64Bit;
- SectionIndexMapTy &SectionIndexMap;
+ std::vector<const MCSectionELF *> &Sections;
// The symbol .symtab fragment we are writting to.
MCDataFragment *SymtabF;
public:
SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter, bool Is64Bit,
- SectionIndexMapTy &SectionIndexMap,
+ std::vector<const MCSectionELF *> &Sections,
MCDataFragment *SymtabF);
void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size,
uint8_t other, uint32_t shndx, bool Reserved);
};
-struct ELFRelocationEntry {
- uint64_t Offset; // Where is the relocation.
- const MCSymbol *Symbol; // The symbol to relocate with.
- unsigned Type; // The type of the relocation.
- uint64_t Addend; // The addend to use.
-
- ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type,
- uint64_t Addend)
- : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {}
-};
-
class ELFObjectWriter : public MCObjectWriter {
FragmentWriter FWriter;
bool Used, bool Renamed);
static bool isLocal(const MCSymbolData &Data, bool isUsedInReloc);
static bool IsELFMetaDataSection(const MCSectionData &SD);
- static uint64_t DataSectionSize(const MCSectionData &SD);
- static uint64_t GetSectionFileSize(const MCAsmLayout &Layout,
- const MCSectionData &SD);
- static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout,
- const MCSectionData &SD);
- void WriteDataSectionData(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCSectionELF &Section);
+ void writeDataSectionData(MCAssembler &Asm, const MCAsmLayout &Layout,
+ const MCSectionData &SD);
/// Helper struct for containing some precomputed information on symbols.
struct ELFSymbolData {
}
public:
- ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &OS,
+ ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS,
bool IsLittleEndian)
: MCObjectWriter(OS, IsLittleEndian), FWriter(IsLittleEndian),
TargetObjectWriter(MOTW), NeedsGOT(false) {}
MCObjectWriter::reset();
}
- virtual ~ELFObjectWriter();
+ ~ELFObjectWriter() override;
void WriteWord(uint64_t W) {
if (is64Bit())
FWriter.write(F, Value);
}
- void WriteHeader(const MCAssembler &Asm,
- uint64_t SectionHeaderOffset,
- unsigned NumberOfSections);
+ void writeHeader(const MCAssembler &Asm);
void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
const MCAsmLayout &Layout);
void WriteSymbolTable(MCDataFragment *SymtabF, MCAssembler &Asm,
const MCAsmLayout &Layout,
- SectionIndexMapTy &SectionIndexMap);
+ std::vector<const MCSectionELF *> &Sections);
bool shouldRelocateWithSymbol(const MCAssembler &Asm,
const MCSymbolRefExpr *RefA,
uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm,
const MCSymbol *S);
- // Map from a group section to the signature symbol
- typedef DenseMap<const MCSectionELF*, const MCSymbol*> GroupMapTy;
- // Map from a signature symbol to the group section
- typedef DenseMap<const MCSymbol*, const MCSectionELF*> RevGroupMapTy;
- // Map from a section to its offset
- typedef DenseMap<const MCSectionELF*, uint64_t> SectionOffsetMapTy;
+ // 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;
/// Compute the symbol table data
///
const SectionIndexMapTy &SectionIndexMap,
const RevGroupMapTy &RevGroupMap);
- void computeIndexMap(MCAssembler &Asm, SectionIndexMapTy &SectionIndexMap);
+ void maybeAddToGroup(MCAssembler &Asm,
+ ArrayRef<const MCSectionELF *> Sections,
+ const RevGroupMapTy &RevGroupMap,
+ const MCSectionELF &Section, unsigned Index);
+
+ void computeIndexMap(MCAssembler &Asm,
+ std::vector<const MCSectionELF *> &Sections,
+ 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,
- SectionIndexMapTy &SectionIndexMap);
+ 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,
- GroupMapTy &GroupMap, RevGroupMapTy &RevGroupMap,
+ void createIndexedSections(MCAssembler &Asm, const MCAsmLayout &Layout,
+ RevGroupMapTy &RevGroupMap,
+ std::vector<const MCSectionELF *> &Sections,
SectionIndexMapTy &SectionIndexMap);
void ExecutePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) override;
- void writeSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap,
- const MCAsmLayout &Layout,
+ void writeSectionHeader(ArrayRef<const MCSectionELF *> Sections,
+ MCAssembler &Asm, const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap,
- const SectionOffsetMapTy &SectionOffsetMap);
-
- void ComputeSectionOrder(MCAssembler &Asm,
- std::vector<const MCSectionELF*> &Sections);
+ const SectionOffsetsTy &SectionOffsets);
void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
uint64_t Address, uint64_t Offset,
bool
IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
const MCSymbolData &DataA,
- const MCSymbolData *DataB,
const MCFragment &FB,
bool InSet,
bool IsPCRel) const override;
&Asm.getOrCreateSectionData(*SymtabShndxSection);
SymtabShndxSD->setAlignment(4);
ShndxF = new MCDataFragment(SymtabShndxSD);
- unsigned Index = SectionIndexMap.size() + 1;
- SectionIndexMap[SymtabShndxSection] = Index;
+ Sections.push_back(SymtabShndxSection);
for (unsigned I = 0; I < NumWritten; ++I)
write(*ShndxF, uint32_t(0));
FWriter.write(F, Value);
}
-SymbolTableWriter::SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter,
- bool Is64Bit,
- SectionIndexMapTy &SectionIndexMap,
- MCDataFragment *SymtabF)
- : Asm(Asm), FWriter(FWriter), Is64Bit(Is64Bit),
- SectionIndexMap(SectionIndexMap), SymtabF(SymtabF), ShndxF(nullptr),
- NumWritten(0) {}
+SymbolTableWriter::SymbolTableWriter(
+ MCAssembler &Asm, FragmentWriter &FWriter, bool Is64Bit,
+ 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,
uint64_t size, uint8_t other,
{}
// Emit the ELF header.
-void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
- uint64_t SectionHeaderOffset,
- unsigned NumberOfSections) {
+void ELFObjectWriter::writeHeader(const MCAssembler &Asm) {
// ELF Header
// ----------
//
// emitWord method behaves differently for ELF32 and ELF64, writing
// 4 bytes in the former and 8 in the latter.
- Write8(0x7f); // e_ident[EI_MAG0]
- Write8('E'); // e_ident[EI_MAG1]
- Write8('L'); // e_ident[EI_MAG2]
- Write8('F'); // e_ident[EI_MAG3]
+ WriteBytes(ELF::ElfMagic); // e_ident[EI_MAG0] to e_ident[EI_MAG3]
Write8(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
Write32(ELF::EV_CURRENT); // e_version
WriteWord(0); // e_entry, no entry point in .o file
WriteWord(0); // e_phoff, no program header for .o
- WriteWord(SectionHeaderOffset); // e_shoff = sec hdr table off in bytes
+ WriteWord(0); // e_shoff = sec hdr table off in bytes
// e_flags = whatever the target wants
Write32(Asm.getELFHeaderEFlags());
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,
MSD.SectionIndex, IsReserved);
}
-void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
- MCAssembler &Asm,
- const MCAsmLayout &Layout,
- SectionIndexMapTy &SectionIndexMap) {
+void ELFObjectWriter::WriteSymbolTable(
+ MCDataFragment *SymtabF, MCAssembler &Asm, const MCAsmLayout &Layout,
+ std::vector<const MCSectionELF *> &Sections) {
// The string table must be emitted first because we need the index
// into the string table for all the symbol names.
// FIXME: Make sure the start of the symbol table is aligned.
- SymbolTableWriter Writer(Asm, FWriter, is64Bit(), SectionIndexMap, SymtabF);
+ SymbolTableWriter Writer(Asm, FWriter, is64Bit(), Sections, SymtabF);
// The first entry is the undefined symbol entry.
Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
return nullptr;
}
+// True if the assembler knows nothing about the final value of the symbol.
+// This doesn't cover the comdat issues, since in those cases the assembler
+// can at least know that all symbols in the section will move together.
static bool isWeak(const MCSymbolData &D) {
- return D.getFlags() & ELF_STB_Weak || MCELF::GetType(D) == ELF::STT_GNU_IFUNC;
+ if (MCELF::GetType(D) == ELF::STT_GNU_IFUNC)
+ return true;
+
+ switch (MCELF::GetBinding(D)) {
+ default:
+ llvm_unreachable("Unknown binding");
+ case ELF::STB_LOCAL:
+ return false;
+ case ELF::STB_GLOBAL:
+ return false;
+ case ELF::STB_WEAK:
+ case ELF::STB_GNU_UNIQUE:
+ return true;
+ }
}
void ELFObjectWriter::RecordRelocation(MCAssembler &Asm,
return true;
}
-void ELFObjectWriter::computeIndexMap(MCAssembler &Asm,
- SectionIndexMapTy &SectionIndexMap) {
- unsigned Index = 1;
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(it->getSection());
- if (Section.getType() != ELF::SHT_GROUP)
- continue;
- SectionIndexMap[&Section] = Index++;
- }
+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 = Sections[RevGroupMap.lookup(Sym) - 1];
+ MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
+ // FIXME: we could use the previous fragment
+ MCDataFragment *F = new MCDataFragment(&Data);
+ write(*F, Index);
+}
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionData &SD = *it;
+void ELFObjectWriter::computeIndexMap(
+ MCAssembler &Asm, std::vector<const MCSectionELF *> &Sections,
+ SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap) {
+ 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;
- SectionIndexMap[&Section] = Index++;
- if (MCSectionData *RelSD = createRelocationSection(Asm, SD)) {
- const MCSectionELF *RelSection =
- static_cast<const MCSectionELF *>(&RelSD->getSection());
- SectionIndexMap[RelSection] = Index++;
- }
+ Sections.push_back(&Section);
+ unsigned Index = Sections.size();
+ SectionIndexMap[&Section] = 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 =
WriteWord(EntrySize); // sh_entsize
}
-// ELF doesn't require relocations to be in any order. We sort by the r_offset,
-// just to match gnu as for easier comparison. The use type is an arbitrary way
-// of making the sort deterministic.
-static int cmpRel(const ELFRelocationEntry *AP, const ELFRelocationEntry *BP) {
- const ELFRelocationEntry &A = *AP;
- const ELFRelocationEntry &B = *BP;
- if (A.Offset != B.Offset)
- return B.Offset - A.Offset;
- if (B.Type != A.Type)
- return A.Type - B.Type;
- //llvm_unreachable("ELFRelocs might be unstable!");
- return 0;
-}
-
-static void sortRelocs(const MCAssembler &Asm,
- std::vector<ELFRelocationEntry> &Relocs) {
- array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel);
-}
-
void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm,
MCDataFragment *F,
const MCSectionData *SD) {
std::vector<ELFRelocationEntry> &Relocs = Relocations[SD];
- sortRelocs(Asm, Relocs);
+ // Sort the relocation entries. Most targets just sort by Offset, but some
+ // (e.g., MIPS) have additional constraints.
+ TargetObjectWriter->sortRelocs(Asm, Relocs);
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
const ELFRelocationEntry &Entry = Relocs[e - i - 1];
}
}
+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, SectionIndexMapTy &SectionIndexMap) {
+ 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 = SectionIndexMap.size() + 1;
- SectionIndexMap[ShstrtabSection] = ShstrtabIndex;
-
+ // Symbol table
const MCSectionELF *SymtabSection =
Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
EntrySize, "");
MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
SymtabSD.setAlignment(is64Bit() ? 8 : 4);
- SymbolTableIndex = SectionIndexMap.size() + 1;
- SectionIndexMap[SymtabSection] = SymbolTableIndex;
-
- const MCSectionELF *StrtabSection;
- StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
- MCSectionData &StrtabSD = Asm.getOrCreateSectionData(*StrtabSection);
- StrtabSD.setAlignment(1);
- StringTableIndex = SectionIndexMap.size() + 1;
- SectionIndexMap[StrtabSection] = StringTableIndex;
-
- // Symbol table
+ SymbolTableIndex = Sections.size() + 1;
+ Sections.push_back(SymtabSection);
F = new MCDataFragment(&SymtabSD);
- WriteSymbolTable(F, Asm, Layout, SectionIndexMap);
-
- 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());
+ WriteSymbolTable(F, Asm, Layout, Sections);
}
void ELFObjectWriter::createIndexedSections(
- MCAssembler &Asm, MCAsmLayout &Layout, GroupMapTy &GroupMap,
- RevGroupMapTy &RevGroupMap, SectionIndexMapTy &SectionIndexMap) {
+ 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 (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end();
- it != ie; ++it) {
+ for (const MCSectionData &SD : Asm) {
const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(it->getSection());
+ static_cast<const MCSectionELF &>(SD.getSection());
if (!(Section.getFlags() & ELF::SHF_GROUP))
continue;
const MCSymbol *SignatureSymbol = Section.getGroup();
Asm.getOrCreateSymbolData(*SignatureSymbol);
- const MCSectionELF *&Group = RevGroupMap[SignatureSymbol];
- if (!Group) {
- Group = Ctx.CreateELFGroupSection();
+ unsigned &GroupIdx = RevGroupMap[SignatureSymbol];
+ if (!GroupIdx) {
+ const MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol);
+ Sections.push_back(Group);
+ GroupIdx = Sections.size();
+
MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
Data.setAlignment(4);
MCDataFragment *F = new MCDataFragment(&Data);
write(*F, uint32_t(ELF::GRP_COMDAT));
}
- GroupMap[Group] = SignatureSymbol;
}
- computeIndexMap(Asm, SectionIndexMap);
-
- // Add sections to the groups
- for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end();
- it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(it->getSection());
- if (!(Section.getFlags() & ELF::SHF_GROUP))
- continue;
- const MCSectionELF *Group = RevGroupMap[Section.getGroup()];
- MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
- // FIXME: we could use the previous fragment
- MCDataFragment *F = new MCDataFragment(&Data);
- uint32_t Index = SectionIndexMap.lookup(&Section);
- write(*F, Index);
- }
+ computeIndexMap(Asm, Sections, SectionIndexMap, RevGroupMap);
}
void ELFObjectWriter::writeSection(MCAssembler &Asm,
!SD.getSection().isVirtualSection();
}
-uint64_t ELFObjectWriter::DataSectionSize(const MCSectionData &SD) {
- uint64_t Ret = 0;
- for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e;
- ++i) {
- const MCFragment &F = *i;
- assert(F.getKind() == MCFragment::FT_Data);
- Ret += cast<MCDataFragment>(F).getContents().size();
- }
- return Ret;
-}
-
-uint64_t ELFObjectWriter::GetSectionFileSize(const MCAsmLayout &Layout,
- const MCSectionData &SD) {
- if (IsELFMetaDataSection(SD))
- return DataSectionSize(SD);
- return Layout.getSectionFileSize(&SD);
-}
-
-uint64_t ELFObjectWriter::GetSectionAddressSize(const MCAsmLayout &Layout,
- const MCSectionData &SD) {
- if (IsELFMetaDataSection(SD))
- return DataSectionSize(SD);
- return Layout.getSectionAddressSize(&SD);
-}
-
-void ELFObjectWriter::WriteDataSectionData(MCAssembler &Asm,
+void ELFObjectWriter::writeDataSectionData(MCAssembler &Asm,
const MCAsmLayout &Layout,
- const MCSectionELF &Section) {
- const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
-
- uint64_t Padding = OffsetToAlignment(OS.tell(), SD.getAlignment());
- WriteZeros(Padding);
-
+ const MCSectionData &SD) {
if (IsELFMetaDataSection(SD)) {
for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e;
++i) {
}
void ELFObjectWriter::writeSectionHeader(
- MCAssembler &Asm, const GroupMapTy &GroupMap, const MCAsmLayout &Layout,
- const SectionIndexMapTy &SectionIndexMap,
- const SectionOffsetMapTy &SectionOffsetMap) {
- const unsigned NumSections = Asm.size() + 1;
-
- std::vector<const MCSectionELF*> Sections;
- Sections.resize(NumSections - 1);
-
- for (SectionIndexMapTy::const_iterator i=
- SectionIndexMap.begin(), e = SectionIndexMap.end(); i != e; ++i) {
- const std::pair<const MCSectionELF*, uint32_t> &p = *i;
- Sections[p.second - 1] = p.first;
- }
+ ArrayRef<const MCSectionELF *> Sections, MCAssembler &Asm,
+ const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap,
+ const SectionOffsetsTy &SectionOffsets) {
+ const unsigned NumSections = Asm.size();
// Null section first.
uint64_t FirstSectionSize =
- NumSections >= ELF::SHN_LORESERVE ? NumSections : 0;
- uint32_t FirstSectionLink =
- ShstrtabIndex >= ELF::SHN_LORESERVE ? ShstrtabIndex : 0;
- WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, FirstSectionLink, 0, 0, 0);
+ (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0;
+ WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0);
- for (unsigned i = 0; i < NumSections - 1; ++i) {
+ for (unsigned i = 0; i < NumSections; ++i) {
const MCSectionELF &Section = *Sections[i];
const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
uint32_t GroupSymbolIndex;
if (Section.getType() != ELF::SHT_GROUP)
GroupSymbolIndex = 0;
else
- GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm,
- GroupMap.lookup(&Section));
+ GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, Section.getGroup());
- uint64_t Size = GetSectionAddressSize(Layout, SD);
+ const std::pair<uint64_t, uint64_t> &Offsets = SectionOffsets[i];
+ uint64_t Size = Section.getType() == ELF::SHT_NOBITS
+ ? Layout.getSectionAddressSize(&SD)
+ : Offsets.second - Offsets.first;
- writeSection(Asm, SectionIndexMap, GroupSymbolIndex,
- SectionOffsetMap.lookup(&Section), Size, SD.getAlignment(),
- Section);
- }
-}
-
-void ELFObjectWriter::ComputeSectionOrder(MCAssembler &Asm,
- std::vector<const MCSectionELF*> &Sections) {
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(it->getSection());
- if (Section.getType() == ELF::SHT_GROUP)
- Sections.push_back(&Section);
- }
-
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(it->getSection());
- if (Section.getType() != ELF::SHT_GROUP &&
- Section.getType() != ELF::SHT_REL &&
- Section.getType() != ELF::SHT_RELA)
- Sections.push_back(&Section);
- }
-
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(it->getSection());
- if (Section.getType() == ELF::SHT_REL ||
- Section.getType() == ELF::SHT_RELA)
- Sections.push_back(&Section);
+ writeSection(Asm, SectionIndexMap, GroupSymbolIndex, Offsets.first, Size,
+ SD.getAlignment(), Section);
}
}
void ELFObjectWriter::WriteObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
- GroupMapTy GroupMap;
RevGroupMapTy RevGroupMap;
SectionIndexMapTy SectionIndexMap;
CompressDebugSections(Asm, const_cast<MCAsmLayout &>(Layout));
- createIndexedSections(Asm, const_cast<MCAsmLayout &>(Layout), GroupMap,
- RevGroupMap, SectionIndexMap);
+ std::vector<const MCSectionELF *> Sections;
+ 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),
- SectionIndexMap);
+ CreateMetadataSections(Asm, Layout, Sections);
- uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
- uint64_t HeaderSize = is64Bit() ? sizeof(ELF::Elf64_Ehdr) :
- sizeof(ELF::Elf32_Ehdr);
- uint64_t FileOff = HeaderSize;
-
- std::vector<const MCSectionELF*> Sections;
- ComputeSectionOrder(Asm, Sections);
- unsigned NumSections = Sections.size();
- SectionOffsetMapTy SectionOffsetMap;
- for (unsigned i = 0; i < NumSections; ++i) {
+ SectionOffsetsTy SectionOffsets;
- const MCSectionELF &Section = *Sections[i];
- const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
+ // Write out the ELF header ...
+ writeHeader(Asm);
- FileOff = RoundUpToAlignment(FileOff, SD.getAlignment());
+ // ... then the sections ...
+ 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);
// Remember the offset into the file for this section.
- SectionOffsetMap[&Section] = FileOff;
-
- // Get the size of the section in the output file (including padding).
- FileOff += GetSectionFileSize(Layout, SD);
+ uint64_t SecStart = OS.tell();
+ writeDataSectionData(Asm, Layout, SD);
+ uint64_t SecEnd = OS.tell();
+ SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
}
- FileOff = RoundUpToAlignment(FileOff, NaturalAlignment);
-
- const unsigned SectionHeaderOffset = FileOff;
-
- // Write out the ELF header ...
- WriteHeader(Asm, SectionHeaderOffset, NumSections + 1);
+ {
+ uint64_t SecStart = OS.tell();
+ createStringTable(Asm, Sections);
+ uint64_t SecEnd = OS.tell();
+ SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
+ }
- // ... then the sections ...
- for (unsigned i = 0; i < NumSections; ++i)
- WriteDataSectionData(Asm, Layout, *Sections[i]);
+ {
+ 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);
+ const unsigned SectionHeaderOffset = OS.tell();
+
// ... then the section header table ...
- writeSectionHeader(Asm, GroupMap, Layout, SectionIndexMap, SectionOffsetMap);
+ 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(
- const MCAssembler &Asm, const MCSymbolData &DataA,
- const MCSymbolData *DataB, const MCFragment &FB, bool InSet,
- bool IsPCRel) const {
- if (!InSet && (::isWeak(DataA) || (DataB && ::isWeak(*DataB))))
- return false;
- return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
- Asm, DataA, DataB, FB, InSet, IsPCRel);
+ const MCAssembler &Asm, const MCSymbolData &DataA, const MCFragment &FB,
+ bool InSet, bool IsPCRel) const {
+ if (IsPCRel) {
+ assert(!InSet);
+ if (::isWeak(DataA))
+ return false;
+ }
+ return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(Asm, DataA, FB,
+ InSet, IsPCRel);
}
bool ELFObjectWriter::isWeak(const MCSymbolData &SD) const {
- return ::isWeak(SD);
+ if (::isWeak(SD))
+ return true;
+
+ // It is invalid to replace a reference to a global in a comdat
+ // with a reference to a local since out of comdat references
+ // to a local are forbidden.
+ // We could try to return false for more cases, like the reference
+ // being in the same comdat or Sym being an alias to another global,
+ // but it is not clear if it is worth the effort.
+ if (MCELF::GetBinding(SD) != ELF::STB_GLOBAL)
+ return false;
+
+ const MCSymbol &Sym = SD.getSymbol();
+ if (!Sym.isInSection())
+ return false;
+
+ const auto &Sec = cast<MCSectionELF>(Sym.getSection());
+ return Sec.getGroup();
}
MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
- raw_ostream &OS,
+ raw_pwrite_stream &OS,
bool IsLittleEndian) {
return new ELFObjectWriter(MOTW, OS, IsLittleEndian);
}