X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FELFObjectWriter.cpp;h=13a3ddbb46218f8cd325acfd34e8f2050002fcee;hb=a19abeb7abaa80b946c593164a08c3d230183a95;hp=4577f0130ed65ae6c0205d7d4c63ab0c3cf4e19e;hpb=90ce9f70e23495dc234ff85d4097203dc2efadcc;p=oota-llvm.git diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 4577f0130ed..13a3ddbb462 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -31,8 +31,8 @@ #include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/Endian.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include using namespace llvm; @@ -41,68 +41,35 @@ using namespace llvm; #define DEBUG_TYPE "reloc-info" namespace { -class FragmentWriter { - bool IsLittleEndian; - -public: - FragmentWriter(bool IsLittleEndian); - template void write(MCDataFragment &F, T Val); -}; typedef DenseMap SectionIndexMapTy; +class ELFObjectWriter; + class SymbolTableWriter { - MCAssembler &Asm; - FragmentWriter &FWriter; + ELFObjectWriter &EWriter; bool Is64Bit; - SectionIndexMapTy &SectionIndexMap; - - // The symbol .symtab fragment we are writting to. - MCDataFragment *SymtabF; - // .symtab_shndx fragment we are writting to. - MCDataFragment *ShndxF; + // indexes we are going to write to .symtab_shndx. + std::vector ShndxIndexes; // The numbel of symbols written so far. unsigned NumWritten; void createSymtabShndx(); - template void write(MCDataFragment &F, T Value); + template void write(T Value); public: - SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter, bool Is64Bit, - SectionIndexMapTy &SectionIndexMap, - MCDataFragment *SymtabF); + SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit); 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. - bool UseSymbol; // Relocate with a symbol, not the section. - union { - const MCSymbol *Symbol; // The symbol to relocate with. - const MCSectionData *Section; // The section 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), UseSymbol(true), Symbol(Symbol), Type(Type), - Addend(Addend) {} - - ELFRelocationEntry(uint64_t Offset, const MCSectionData *Section, - unsigned Type, uint64_t Addend) - : Offset(Offset), UseSymbol(false), Section(Section), Type(Type), - Addend(Addend) {} + ArrayRef getShndxIndexes() const { return ShndxIndexes; } }; class ELFObjectWriter : public MCObjectWriter { - FragmentWriter FWriter; - protected: static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); @@ -112,23 +79,11 @@ class ELFObjectWriter : public MCObjectWriter { 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); - - /*static bool isFixupKindX86RIPRel(unsigned Kind) { - return Kind == X86::reloc_riprel_4byte || - Kind == X86::reloc_riprel_4byte_movq_load; - }*/ - - /// ELFSymbolData - Helper struct for containing some precomputed - /// information on symbols. + + void writeDataSectionData(MCAssembler &Asm, const MCAsmLayout &Layout, + const MCSectionData &SD); + + /// Helper struct for containing some precomputed information on symbols. struct ELFSymbolData { MCSymbolData *SymbolData; uint64_t StringIndex; @@ -137,6 +92,14 @@ class ELFObjectWriter : public MCObjectWriter { // Support lexicographic sorting. bool operator<(const ELFSymbolData &RHS) const { + unsigned LHSType = MCELF::GetType(*SymbolData); + unsigned RHSType = MCELF::GetType(*RHS.SymbolData); + if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION) + return false; + if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION) + return true; + if (LHSType == ELF::STT_SECTION && RHSType == ELF::STT_SECTION) + return SectionIndex < RHS.SectionIndex; return Name < RHS.Name; } }; @@ -187,12 +150,26 @@ class ELFObjectWriter : public MCObjectWriter { } 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(OS, IsLittleEndian), TargetObjectWriter(MOTW), + NeedsGOT(false) {} + + void reset() override { + UsedInReloc.clear(); + WeakrefUsedInReloc.clear(); + Renames.clear(); + Relocations.clear(); + ShStrTabBuilder.clear(); + StrTabBuilder.clear(); + FileSymbolData.clear(); + LocalSymbolData.clear(); + ExternalSymbolData.clear(); + UndefinedSymbolData.clear(); + MCObjectWriter::reset(); + } - virtual ~ELFObjectWriter(); + ~ELFObjectWriter() override; void WriteWord(uint64_t W) { if (is64Bit()) @@ -201,27 +178,33 @@ class ELFObjectWriter : public MCObjectWriter { Write32(W); } - template void write(MCDataFragment &F, T Value) { - FWriter.write(F, Value); + template void write(T Val) { + if (IsLittleEndian) + support::endian::Writer(OS).write(Val); + else + support::endian::Writer(OS).write(Val); } - void WriteHeader(const MCAssembler &Asm, - uint64_t SectionDataSize, - unsigned NumberOfSections); + template void write(MCDataFragment &F, T Value); + + 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); + // Start and end offset of each section + typedef std::vector> SectionOffsetsTy; + + void WriteSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, + std::vector &Sections, + SectionOffsetsTy &SectionOffsets); bool shouldRelocateWithSymbol(const MCAssembler &Asm, const MCSymbolRefExpr *RefA, const MCSymbolData *SD, uint64_t C, unsigned Type) const; - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) override; @@ -229,60 +212,54 @@ class ELFObjectWriter : public MCObjectWriter { uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, const MCSymbol *S); - // Map from a group section to the signature symbol - typedef DenseMap GroupMapTy; - // Map from a signature symbol to the group section - typedef DenseMap RevGroupMapTy; - // Map from a section to the section with the relocations - typedef DenseMap RelMapTy; - // Map from a section to its offset - typedef DenseMap SectionOffsetMapTy; + // Map from a signature symbol to the group section index + typedef DenseMap RevGroupMapTy; /// Compute the symbol table data /// /// \param Asm - The assembler. /// \param SectionIndexMap - Maps a section to its index. /// \param RevGroupMap - Maps a signature symbol to the group section. - /// \param NumRegularSections - Number of non-relocation sections. void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, - const RevGroupMapTy &RevGroupMap, - unsigned NumRegularSections); + const RevGroupMapTy &RevGroupMap); - void ComputeIndexMap(MCAssembler &Asm, + void maybeAddToGroup(MCAssembler &Asm, + ArrayRef Sections, + const RevGroupMapTy &RevGroupMap, + const MCSectionELF &Section, unsigned Index); + + void computeIndexMap(MCAssembler &Asm, + std::vector &Sections, SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap); + const RevGroupMapTy &RevGroupMap); - void CreateRelocationSections(MCAssembler &Asm, MCAsmLayout &Layout, - RelMapTy &RelMap); + void createRelocationSection(MCAssembler &Asm, const MCSectionData &SD); void CompressDebugSections(MCAssembler &Asm, MCAsmLayout &Layout); - void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout, - const RelMapTy &RelMap); + void WriteRelocations(MCAssembler &Asm, const MCAsmLayout &Layout); - void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, - SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap); + void + createSectionHeaderStringTable(MCAssembler &Asm, + std::vector &Sections); + void createStringTable(MCAssembler &Asm, + std::vector &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, + void createIndexedSections(MCAssembler &Asm, const MCAsmLayout &Layout, RevGroupMapTy &RevGroupMap, - SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap); + std::vector &Sections, + SectionIndexMapTy &SectionIndexMap); void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; - void WriteSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap, - const MCAsmLayout &Layout, + void writeSectionHeader(ArrayRef Sections, + MCAssembler &Asm, const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, - const SectionOffsetMapTy &SectionOffsetMap); - - void ComputeSectionOrder(MCAssembler &Asm, - std::vector &Sections); + const SectionOffsetsTy &SectionOffsets); void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, uint64_t Address, uint64_t Offset, @@ -300,8 +277,10 @@ class ELFObjectWriter : public MCObjectWriter { bool InSet, bool IsPCRel) const override; + bool isWeak(const MCSymbolData &SD) const override; + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; - void WriteSection(MCAssembler &Asm, + void writeSection(MCAssembler &Asm, const SectionIndexMapTy &SectionIndexMap, uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size, uint64_t Alignment, @@ -309,10 +288,7 @@ class ELFObjectWriter : public MCObjectWriter { }; } -FragmentWriter::FragmentWriter(bool IsLittleEndian) - : IsLittleEndian(IsLittleEndian) {} - -template void FragmentWriter::write(MCDataFragment &F, T Val) { +template void ELFObjectWriter::write(MCDataFragment &F, T Val) { if (IsLittleEndian) Val = support::endian::byte_swap(Val); else @@ -322,36 +298,18 @@ template void FragmentWriter::write(MCDataFragment &F, T Val) { } void SymbolTableWriter::createSymtabShndx() { - if (ShndxF) + if (!ShndxIndexes.empty()) return; - MCContext &Ctx = Asm.getContext(); - const MCSectionELF *SymtabShndxSection = - Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, - SectionKind::getReadOnly(), 4, ""); - MCSectionData *SymtabShndxSD = - &Asm.getOrCreateSectionData(*SymtabShndxSection); - SymtabShndxSD->setAlignment(4); - ShndxF = new MCDataFragment(SymtabShndxSD); - unsigned Index = SectionIndexMap.size() + 1; - SectionIndexMap[SymtabShndxSection] = Index; - - for (unsigned I = 0; I < NumWritten; ++I) - write(*ShndxF, uint32_t(0)); + ShndxIndexes.resize(NumWritten); } -template -void SymbolTableWriter::write(MCDataFragment &F, T Value) { - FWriter.write(F, Value); +template void SymbolTableWriter::write(T Value) { + EWriter.write(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(ELFObjectWriter &EWriter, bool Is64Bit) + : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {} void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size, uint8_t other, @@ -361,31 +319,29 @@ void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value, if (LargeIndex) createSymtabShndx(); - if (ShndxF) { + if (!ShndxIndexes.empty()) { if (LargeIndex) - write(*ShndxF, shndx); + ShndxIndexes.push_back(shndx); else - write(*ShndxF, uint32_t(0)); + ShndxIndexes.push_back(0); } uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx; - raw_svector_ostream OS(SymtabF->getContents()); - if (Is64Bit) { - write(*SymtabF, name); // st_name - write(*SymtabF, info); // st_info - write(*SymtabF, other); // st_other - write(*SymtabF, Index); // st_shndx - write(*SymtabF, value); // st_value - write(*SymtabF, size); // st_size + write(name); // st_name + write(info); // st_info + write(other); // st_other + write(Index); // st_shndx + write(value); // st_value + write(size); // st_size } else { - write(*SymtabF, name); // st_name - write(*SymtabF, uint32_t(value)); // st_value - write(*SymtabF, uint32_t(size)); // st_size - write(*SymtabF, info); // st_info - write(*SymtabF, other); // st_other - write(*SymtabF, Index); // st_shndx + write(name); // st_name + write(uint32_t(value)); // st_value + write(uint32_t(size)); // st_size + write(info); // st_info + write(other); // st_other + write(Index); // st_shndx } ++NumWritten; @@ -423,9 +379,7 @@ ELFObjectWriter::~ELFObjectWriter() {} // Emit the ELF header. -void ELFObjectWriter::WriteHeader(const MCAssembler &Asm, - uint64_t SectionDataSize, - unsigned NumberOfSections) { +void ELFObjectWriter::writeHeader(const MCAssembler &Asm) { // ELF Header // ---------- // @@ -434,10 +388,7 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm, // 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] @@ -458,8 +409,7 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm, 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(SectionDataSize + (is64Bit() ? sizeof(ELF::Elf64_Ehdr) : - sizeof(ELF::Elf32_Ehdr))); // 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()); @@ -474,16 +424,11 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm, 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, @@ -614,7 +559,7 @@ void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, if (ESize) { int64_t Res; - if (!ESize->EvaluateAsAbsolute(Res, Layout)) + if (!ESize->evaluateKnownAbsolute(Res, Layout)) report_fatal_error("Size expression must be absolute."); Size = Res; } @@ -624,16 +569,32 @@ void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, MSD.SectionIndex, IsReserved); } -void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, - MCAssembler &Asm, - const MCAsmLayout &Layout, - SectionIndexMapTy &SectionIndexMap) { +void ELFObjectWriter::WriteSymbolTable( + MCAssembler &Asm, const MCAsmLayout &Layout, + std::vector &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 // into the string table for all the symbol names. - // FIXME: Make sure the start of the symbol table is aligned. + SymbolTableWriter Writer(*this, is64Bit()); + + uint64_t Padding = OffsetToAlignment(OS.tell(), SymtabSD.getAlignment()); + WriteZeros(Padding); - SymbolTableWriter Writer(Asm, FWriter, is64Bit(), SectionIndexMap, SymtabF); + uint64_t SecStart = OS.tell(); // The first entry is the undefined symbol entry. Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); @@ -651,22 +612,6 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, WriteSymbol(Writer, MSD, Layout); } - // Write out a symbol table entry for each regular section. - for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; - ++i) { - const MCSectionELF &Section = - static_cast(i->getSection()); - if (Section.getType() == ELF::SHT_RELA || - Section.getType() == ELF::SHT_REL || - Section.getType() == ELF::SHT_STRTAB || - Section.getType() == ELF::SHT_SYMTAB || - Section.getType() == ELF::SHT_SYMTAB_SHNDX) - continue; - Writer.writeSymbol(0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT, - SectionIndexMap.lookup(&Section), false); - LastLocalSymbolIndex++; - } - for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) { ELFSymbolData &MSD = ExternalSymbolData[i]; MCSymbolData &Data = *MSD.SymbolData; @@ -685,6 +630,25 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) LastLocalSymbolIndex++; } + + uint64_t SecEnd = OS.tell(); + SectionOffsets.push_back(std::make_pair(SecStart, SecEnd)); + + ArrayRef 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 @@ -807,13 +771,31 @@ static const MCSymbol *getWeakRef(const MCSymbolRefExpr &Ref) { return nullptr; } -void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, +// 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) { + 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, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) { + const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { const MCSectionData *FixupSection = Fragment->getParent(); uint64_t C = Target.getConstant(); uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); @@ -849,6 +831,10 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, Fixup.getLoc(), "Cannot represent a difference across sections"); const MCSymbolData &SymBD = Asm.getSymbolData(SymB); + if (::isWeak(SymBD)) + Asm.getContext().FatalError( + Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol"); + uint64_t SymBOffset = Layout.getSymbolOffset(&SymBD); uint64_t K = SymBOffset - FixupOffset; IsPCRel = true; @@ -882,8 +868,11 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, if (!RelocateWithSymbol) { const MCSection *SecA = (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr; - const MCSectionData *SecAD = SecA ? &Asm.getSectionData(*SecA) : nullptr; - ELFRelocationEntry Rec(FixupOffset, SecAD, Type, Addend); + auto *ELFSec = cast_or_null(SecA); + MCSymbol *SectionSymbol = + ELFSec ? Asm.getContext().getOrCreateSectionSymbol(*ELFSec) + : nullptr; + ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend); Relocations[FixupSection].push_back(Rec); return; } @@ -961,39 +950,41 @@ bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isUsedInReloc) { return true; } -void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm, - SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap) { - unsigned Index = 1; - for (MCAssembler::iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it) { - const MCSectionELF &Section = - static_cast(it->getSection()); - if (Section.getType() != ELF::SHT_GROUP) - continue; - SectionIndexMap[&Section] = Index++; - } +void ELFObjectWriter::maybeAddToGroup(MCAssembler &Asm, + ArrayRef 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) { +void ELFObjectWriter::computeIndexMap( + MCAssembler &Asm, std::vector &Sections, + SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap) { + for (const MCSectionData &SD : Asm) { const MCSectionELF &Section = - static_cast(it->getSection()); - if (Section.getType() == ELF::SHT_GROUP || - Section.getType() == ELF::SHT_REL || - Section.getType() == ELF::SHT_RELA) + static_cast(SD.getSection()); + if (Section.getType() == ELF::SHT_GROUP) continue; - SectionIndexMap[&Section] = Index++; - const MCSectionELF *RelSection = RelMap.lookup(&Section); - if (RelSection) - SectionIndexMap[RelSection] = Index++; + Sections.push_back(&Section); + unsigned Index = Sections.size(); + SectionIndexMap[&Section] = Index; + maybeAddToGroup(Asm, Sections, RevGroupMap, Section, Index); + createRelocationSection(Asm, SD); } } -void -ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, - const RevGroupMapTy &RevGroupMap, - unsigned NumRegularSections) { +void ELFObjectWriter::computeSymbolTable( + MCAssembler &Asm, const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, + const RevGroupMapTy &RevGroupMap) { // FIXME: Is this the correct place to do this? // FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed? if (NeedsGOT) { @@ -1038,7 +1029,7 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, 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) @@ -1050,18 +1041,48 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, assert(MSD.SectionIndex && "Invalid section index!"); } - // The @@@ in symbol version is replaced with @ in undefined symbols and - // @@ in defined ones. + // The @@@ in symbol version is replaced with @ in undefined symbols and @@ + // in defined ones. + // + // FIXME: All name handling should be done before we get to the writer, + // including dealing with GNU-style version suffixes. Fixing this isn't + // trivial. + // + // We thus have to be careful to not perform the symbol version replacement + // blindly: + // + // The ELF format is used on Windows by the MCJIT engine. Thus, on + // Windows, the ELFObjectWriter can encounter symbols mangled using the MS + // Visual Studio C++ name mangling scheme. Symbols mangled using the MSVC + // C++ name mangling can legally have "@@@" as a sub-string. In that case, + // the EFLObjectWriter should not interpret the "@@@" sub-string as + // specifying GNU-style symbol versioning. The ELFObjectWriter therefore + // checks for the MSVC C++ name mangling prefix which is either "?", "@?", + // "__imp_?" or "__imp_@?". + // + // It would have been interesting to perform the MS mangling prefix check + // only when the target triple is of the form *-pc-windows-elf. But, it + // seems that this information is not easily accessible from the + // ELFObjectWriter. StringRef Name = Symbol.getName(); - SmallString<32> Buf; - size_t Pos = Name.find("@@@"); - if (Pos != StringRef::npos) { - Buf += Name.substr(0, Pos); - unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1; - Buf += Name.substr(Pos + Skip); - Name = Buf; + if (!Name.startswith("?") && !Name.startswith("@?") && + !Name.startswith("__imp_?") && !Name.startswith("__imp_@?")) { + // This symbol isn't following the MSVC C++ name mangling convention. We + // can thus safely interpret the @@@ in symbol names as specifying symbol + // versioning. + SmallString<32> Buf; + size_t Pos = Name.find("@@@"); + if (Pos != StringRef::npos) { + Buf += Name.substr(0, Pos); + unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1; + Buf += Name.substr(Pos + Skip); + Name = Buf; + } } - MSD.Name = StrTabBuilder.add(Name); + + // Sections have their own string table + if (MCELF::GetType(SD) != ELF::STT_SECTION) + MSD.Name = StrTabBuilder.add(Name); if (MSD.SectionIndex == ELF::SHN_UNDEF) UndefinedSymbolData.push_back(MSD); @@ -1079,9 +1100,11 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, 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) + for (ELFSymbolData &MSD : LocalSymbolData) + MSD.StringIndex = MCELF::GetType(*MSD.SymbolData) == ELF::STT_SECTION + ? 0 + : StrTabBuilder.getOffset(MSD.Name); + for (ELFSymbolData &MSD : ExternalSymbolData) MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name); for (ELFSymbolData& MSD : UndefinedSymbolData) MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name); @@ -1097,56 +1120,43 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) LocalSymbolData[i].SymbolData->setIndex(Index++); - Index += NumRegularSections; - for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) ExternalSymbolData[i].SymbolData->setIndex(Index++); for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) UndefinedSymbolData[i].SymbolData->setIndex(Index++); } -void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm, - MCAsmLayout &Layout, - RelMapTy &RelMap) { - for (MCAssembler::const_iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it) { - const MCSectionData &SD = *it; - if (Relocations[&SD].empty()) - continue; +void ELFObjectWriter::createRelocationSection(MCAssembler &Asm, + const MCSectionData &SD) { + if (Relocations[&SD].empty()) + return; - MCContext &Ctx = Asm.getContext(); - const MCSectionELF &Section = - static_cast(SD.getSection()); + MCContext &Ctx = Asm.getContext(); + const MCSectionELF &Section = + static_cast(SD.getSection()); - const StringRef SectionName = Section.getSectionName(); - std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel"; - RelaSectionName += SectionName; + const StringRef SectionName = Section.getSectionName(); + std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel"; + RelaSectionName += SectionName; - unsigned EntrySize; - if (hasRelocationAddend()) - EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela); - else - EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); + unsigned EntrySize; + if (hasRelocationAddend()) + EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela); + else + EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); - unsigned Flags = 0; - StringRef Group = ""; - if (Section.getFlags() & ELF::SHF_GROUP) { - Flags = ELF::SHF_GROUP; - Group = Section.getGroup()->getName(); - } + unsigned Flags = 0; + if (Section.getFlags() & ELF::SHF_GROUP) + Flags = ELF::SHF_GROUP; - const MCSectionELF *RelaSection = - Ctx.getELFSection(RelaSectionName, hasRelocationAddend() ? - ELF::SHT_RELA : ELF::SHT_REL, Flags, - SectionKind::getReadOnly(), - EntrySize, Group); - RelMap[&Section] = RelaSection; - Asm.getOrCreateSectionData(*RelaSection); - } + const MCSectionELF *RelaSection = Ctx.createELFRelSection( + RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL, + Flags, EntrySize, Section.getGroup(), &Section); + Asm.getOrCreateSectionData(*RelaSection); } static SmallVector -getUncompressedData(MCAsmLayout &Layout, +getUncompressedData(const MCAsmLayout &Layout, MCSectionData::FragmentListType &Fragments) { SmallVector UncompressedData; for (const MCFragment &F : Fragments) { @@ -1176,7 +1186,7 @@ getUncompressedData(MCAsmLayout &Layout, static bool prependCompressionHeader(uint64_t Size, SmallVectorImpl &CompressedContents) { - static const StringRef Magic = "ZLIB"; + const StringRef Magic = "ZLIB"; if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size()) return false; if (sys::IsLittleEndianHost) @@ -1193,7 +1203,7 @@ prependCompressionHeader(uint64_t Size, // 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 -getCompressedFragment(MCAsmLayout &Layout, +getCompressedFragment(const MCAsmLayout &Layout, MCSectionData::FragmentListType &Fragments) { std::unique_ptr CompressedFragment(new MCDataFragment()); @@ -1290,22 +1300,23 @@ void ELFObjectWriter::CompressDebugSections(MCAssembler &Asm, } } -void ELFObjectWriter::WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout, - const RelMapTy &RelMap) { - for (MCAssembler::const_iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it) { - const MCSectionData &SD = *it; - const MCSectionELF &Section = - static_cast(SD.getSection()); +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 = + static_cast(RelSD.getSection()); - const MCSectionELF *RelaSection = RelMap.lookup(&Section); - if (!RelaSection) + unsigned Type = RelSection.getType(); + if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) continue; - MCSectionData &RelaSD = Asm.getOrCreateSectionData(*RelaSection); - RelaSD.setAlignment(is64Bit() ? 8 : 4); - MCDataFragment *F = new MCDataFragment(&RelaSD); - WriteRelocationsFragment(Asm, F, &*it); + const MCSectionELF *Section = RelSection.getAssociatedSection(); + MCSectionData &SD = Asm.getOrCreateSectionData(*Section); + RelSD.setAlignment(is64Bit() ? 8 : 4); + + MCDataFragment *F = new MCDataFragment(&RelSD); + WriteRelocationsFragment(Asm, F, &SD); } } @@ -1327,45 +1338,19 @@ void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, 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!"); -} - -static void sortRelocs(const MCAssembler &Asm, - std::vector &Relocs) { - array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel); -} - void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F, const MCSectionData *SD) { std::vector &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]; - - unsigned Index; - if (Entry.UseSymbol) { - Index = getSymbolIndexInSymbolTable(Asm, Entry.Symbol); - } else { - const MCSectionData *Sec = Entry.Section; - if (Sec) - Index = Sec->getOrdinal() + FileSymbolData.size() + - LocalSymbolData.size() + 1; - else - Index = 0; - } + unsigned Index = + Entry.Symbol ? getSymbolIndexInSymbolTable(Asm, Entry.Symbol) : 0; if (is64Bit()) { write(*F, Entry.Offset); @@ -1396,110 +1381,70 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, } } -void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, - MCAsmLayout &Layout, - SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap) { - MCContext &Ctx = Asm.getContext(); - MCDataFragment *F; +void ELFObjectWriter::createSectionHeaderStringTable( + MCAssembler &Asm, std::vector &Sections) { + const MCSectionELF *ShstrtabSection = Sections[ShstrtabIndex - 1]; - unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32; + Asm.getOrCreateSectionData(*ShstrtabSection); - // We construct .shstrtab, .symtab and .strtab in this order to match gnu as. - const MCSectionELF *ShstrtabSection = - Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0, - SectionKind::getReadOnly()); - MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection); - ShstrtabSD.setAlignment(1); - - const MCSectionELF *SymtabSection = - Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, - SectionKind::getReadOnly(), - EntrySize, ""); - MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection); - SymtabSD.setAlignment(is64Bit() ? 8 : 4); - - const MCSectionELF *StrtabSection; - StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0, - SectionKind::getReadOnly()); - MCSectionData &StrtabSD = Asm.getOrCreateSectionData(*StrtabSection); - StrtabSD.setAlignment(1); - - ComputeIndexMap(Asm, SectionIndexMap, RelMap); - - ShstrtabIndex = SectionIndexMap.lookup(ShstrtabSection); - SymbolTableIndex = SectionIndexMap.lookup(SymtabSection); - StringTableIndex = SectionIndexMap.lookup(StrtabSection); - - // Symbol table - 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) { + for (MCSectionData &SD : Asm) { const MCSectionELF &Section = - static_cast(it->getSection()); + static_cast(SD.getSection()); ShStrTabBuilder.add(Section.getSectionName()); } ShStrTabBuilder.finalize(StringTableBuilder::ELF); - F->getContents().append(ShStrTabBuilder.data().begin(), - ShStrTabBuilder.data().end()); + OS << ShStrTabBuilder.data(); +} + +void ELFObjectWriter::createStringTable( + MCAssembler &Asm, std::vector &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::CreateIndexedSections(MCAssembler &Asm, - MCAsmLayout &Layout, - GroupMapTy &GroupMap, - RevGroupMapTy &RevGroupMap, - SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap) { +void ELFObjectWriter::createIndexedSections( + MCAssembler &Asm, const MCAsmLayout &Layout, RevGroupMapTy &RevGroupMap, + std::vector &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(it->getSection()); + static_cast(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, RelMap); - - // Add sections to the groups - for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); - it != ie; ++it) { - const MCSectionELF &Section = - static_cast(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, +void ELFObjectWriter::writeSection(MCAssembler &Asm, const SectionIndexMapTy &SectionIndexMap, uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size, @@ -1509,30 +1454,19 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, uint64_t sh_info = 0; switch(Section.getType()) { + default: + // Nothing to do. + break; + case ELF::SHT_DYNAMIC: sh_link = ShStrTabBuilder.getOffset(Section.getSectionName()); - sh_info = 0; break; case ELF::SHT_REL: case ELF::SHT_RELA: { - const MCSectionELF *SymtabSection; - const MCSectionELF *InfoSection; - SymtabSection = Asm.getContext().getELFSection(".symtab", ELF::SHT_SYMTAB, - 0, - SectionKind::getReadOnly()); - sh_link = SectionIndexMap.lookup(SymtabSection); + sh_link = SymbolTableIndex; assert(sh_link && ".symtab not found"); - - // Remove ".rel" and ".rela" prefixes. - unsigned SecNameLen = (Section.getType() == ELF::SHT_REL) ? 4 : 5; - StringRef SectionName = Section.getSectionName().substr(SecNameLen); - StringRef GroupName = - Section.getGroup() ? Section.getGroup()->getName() : ""; - - InfoSection = Asm.getContext().getELFSection(SectionName, ELF::SHT_PROGBITS, - 0, SectionKind::getReadOnly(), - 0, GroupName); + const MCSectionELF *InfoSection = Section.getAssociatedSection(); sh_info = SectionIndexMap.lookup(InfoSection); break; } @@ -1547,49 +1481,15 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, sh_link = SymbolTableIndex; break; - case ELF::SHT_PROGBITS: - case ELF::SHT_STRTAB: - case ELF::SHT_NOBITS: - case ELF::SHT_NOTE: - case ELF::SHT_NULL: - case ELF::SHT_ARM_ATTRIBUTES: - case ELF::SHT_INIT_ARRAY: - case ELF::SHT_FINI_ARRAY: - case ELF::SHT_PREINIT_ARRAY: - case ELF::SHT_X86_64_UNWIND: - case ELF::SHT_MIPS_REGINFO: - case ELF::SHT_MIPS_OPTIONS: - case ELF::SHT_MIPS_ABIFLAGS: - // Nothing to do. - break; - case ELF::SHT_GROUP: sh_link = SymbolTableIndex; sh_info = GroupSymbolIndex; break; - - default: - llvm_unreachable("FIXME: sh_type value not supported!"); } if (TargetObjectWriter->getEMachine() == ELF::EM_ARM && - Section.getType() == ELF::SHT_ARM_EXIDX) { - StringRef SecName(Section.getSectionName()); - if (SecName == ".ARM.exidx") { - sh_link = SectionIndexMap.lookup( - Asm.getContext().getELFSection(".text", - ELF::SHT_PROGBITS, - ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, - SectionKind::getText())); - } else if (SecName.startswith(".ARM.exidx")) { - StringRef GroupName = - Section.getGroup() ? Section.getGroup()->getName() : ""; - sh_link = SectionIndexMap.lookup(Asm.getContext().getELFSection( - SecName.substr(sizeof(".ARM.exidx") - 1), ELF::SHT_PROGBITS, - ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, SectionKind::getText(), 0, - GroupName)); - } - } + Section.getType() == ELF::SHT_ARM_EXIDX) + sh_link = SectionIndexMap.lookup(Section.getAssociatedSection()); WriteSecHdrEntry(ShStrTabBuilder.getOffset(Section.getSectionName()), Section.getType(), @@ -1602,39 +1502,9 @@ bool ELFObjectWriter::IsELFMetaDataSection(const MCSectionData &SD) { !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(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) { @@ -1647,186 +1517,156 @@ void ELFObjectWriter::WriteDataSectionData(MCAssembler &Asm, } } -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 Sections; - Sections.resize(NumSections - 1); - - for (SectionIndexMapTy::const_iterator i= - SectionIndexMap.begin(), e = SectionIndexMap.end(); i != e; ++i) { - const std::pair &p = *i; - Sections[p.second - 1] = p.first; - } +void ELFObjectWriter::writeSectionHeader( + ArrayRef 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 &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, + writeSection(Asm, SectionIndexMap, GroupSymbolIndex, Offsets.first, Size, SD.getAlignment(), Section); } } -void ELFObjectWriter::ComputeSectionOrder(MCAssembler &Asm, - std::vector &Sections) { - for (MCAssembler::iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it) { - const MCSectionELF &Section = - static_cast(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(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(it->getSection()); - if (Section.getType() == ELF::SHT_REL || - Section.getType() == ELF::SHT_RELA) - Sections.push_back(&Section); - } -} - void ELFObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { - GroupMapTy GroupMap; RevGroupMapTy RevGroupMap; SectionIndexMapTy SectionIndexMap; - unsigned NumUserSections = Asm.size(); - CompressDebugSections(Asm, const_cast(Layout)); - - DenseMap RelMap; - CreateRelocationSections(Asm, const_cast(Layout), RelMap); - - const unsigned NumUserAndRelocSections = Asm.size(); - CreateIndexedSections(Asm, const_cast(Layout), GroupMap, - RevGroupMap, SectionIndexMap, RelMap); - const unsigned AllSections = Asm.size(); - const unsigned NumIndexedSections = AllSections - NumUserAndRelocSections; - - unsigned NumRegularSections = NumUserSections + NumIndexedSections; + std::vector Sections; + createIndexedSections(Asm, Layout, RevGroupMap, Sections, SectionIndexMap); // Compute symbol table information. - computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, - NumRegularSections); + computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap); - WriteRelocations(Asm, const_cast(Layout), RelMap); + WriteRelocations(Asm, Layout); - CreateMetadataSections(const_cast(Asm), - const_cast(Layout), - SectionIndexMap, - RelMap); - uint64_t NaturalAlignment = is64Bit() ? 8 : 4; - uint64_t HeaderSize = is64Bit() ? sizeof(ELF::Elf64_Ehdr) : - sizeof(ELF::Elf32_Ehdr); - uint64_t FileOff = HeaderSize; - - std::vector Sections; - ComputeSectionOrder(Asm, Sections); - unsigned NumSections = Sections.size(); - SectionOffsetMapTy SectionOffsetMap; - for (unsigned i = 0; i < NumRegularSections + 1; ++i) { - const MCSectionELF &Section = *Sections[i]; - const MCSectionData &SD = Asm.getOrCreateSectionData(Section); + SectionOffsetsTy SectionOffsets; - FileOff = RoundUpToAlignment(FileOff, SD.getAlignment()); + // Write out the ELF header ... + writeHeader(Asm); - // Remember the offset into the file for this section. - SectionOffsetMap[&Section] = FileOff; + // ... 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); - // Get the size of the section in the output file (including padding). - FileOff += GetSectionFileSize(Layout, SD); + // Remember the offset into the file for this section. + 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 - HeaderSize; - - uint64_t SectionHeaderEntrySize = is64Bit() ? - sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr); - FileOff += (NumSections + 1) * SectionHeaderEntrySize; - - for (unsigned i = NumRegularSections + 1; i < NumSections; ++i) { - const MCSectionELF &Section = *Sections[i]; - const MCSectionData &SD = Asm.getOrCreateSectionData(Section); - - FileOff = RoundUpToAlignment(FileOff, SD.getAlignment()); - - // Remember the offset into the file for this section. - SectionOffsetMap[&Section] = FileOff; + WriteSymbolTable(Asm, Layout, Sections, SectionOffsets); - // Get the size of the section in the output file (including padding). - FileOff += GetSectionFileSize(Layout, SD); + { + uint64_t SecStart = OS.tell(); + createStringTable(Asm, Sections); + uint64_t SecEnd = OS.tell(); + SectionOffsets.push_back(std::make_pair(SecStart, SecEnd)); } - // Write out the ELF header ... - WriteHeader(Asm, SectionHeaderOffset, NumSections + 1); - - // ... then the regular sections ... - // + because of .shstrtab - for (unsigned i = 0; i < NumRegularSections + 1; ++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(&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(&Val), sizeof(Val), + offsetof(ELF::Elf32_Ehdr, e_shoff)); + NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum); + } + OS.pwrite(reinterpret_cast(&NumSections), sizeof(NumSections), + NumSectionsOffset); +} - // ... and then the remaining sections ... - for (unsigned i = NumRegularSections + 1; i < NumSections; ++i) - WriteDataSectionData(Asm, Layout, *Sections[i]); +bool ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( + 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::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, - bool IsPCRel) const { - if (DataA.getFlags() & ELF_STB_Weak || MCELF::GetType(DataA) == ELF::STT_GNU_IFUNC) +bool ELFObjectWriter::isWeak(const MCSymbolData &SD) const { + 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; - return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( - Asm, DataA, FB,InSet, IsPCRel); + + const MCSymbol &Sym = SD.getSymbol(); + if (!Sym.isInSection()) + return false; + + const auto &Sec = cast(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); }