diff options
Diffstat (limited to 'contrib/llvm/lib/MC/ELFObjectWriter.cpp')
-rw-r--r-- | contrib/llvm/lib/MC/ELFObjectWriter.cpp | 1657 |
1 files changed, 599 insertions, 1058 deletions
diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp index e2439ab..0765937 100644 --- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp @@ -21,12 +21,11 @@ #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCELF.h" -#include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Compression.h" @@ -41,94 +40,50 @@ using namespace llvm; #define DEBUG_TYPE "reloc-info" namespace { -class FragmentWriter { - bool IsLittleEndian; - -public: - FragmentWriter(bool IsLittleEndian); - template <typename T> void write(MCDataFragment &F, T Val); -}; typedef DenseMap<const MCSectionELF *, uint32_t> 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<uint32_t> ShndxIndexes; // The numbel of symbols written so far. unsigned NumWritten; void createSymtabShndx(); - template <typename T> void write(MCDataFragment &F, T Value); + template <typename T> 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. - 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) {} + ArrayRef<uint32_t> getShndxIndexes() const { return ShndxIndexes; } }; class ELFObjectWriter : public MCObjectWriter { - FragmentWriter FWriter; - - protected: - static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); - static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant); - static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout); - static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolData &Data, + static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout); + static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol, 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. + + /// Helper struct for containing some precomputed information on symbols. struct ELFSymbolData { - MCSymbolData *SymbolData; - uint64_t StringIndex; + const MCSymbolELF *Symbol; uint32_t SectionIndex; StringRef Name; // Support lexicographic sorting. bool operator<(const ELFSymbolData &RHS) const { - unsigned LHSType = MCELF::GetType(*SymbolData); - unsigned RHSType = MCELF::GetType(*RHS.SymbolData); + unsigned LHSType = Symbol->getType(); + unsigned RHSType = RHS.Symbol->getType(); if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION) return false; if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION) @@ -142,37 +97,31 @@ class ELFObjectWriter : public MCObjectWriter { /// The target specific ELF writer instance. std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter; - SmallPtrSet<const MCSymbol *, 16> UsedInReloc; - SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc; - DenseMap<const MCSymbol *, const MCSymbol *> Renames; + DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames; - llvm::DenseMap<const MCSectionData *, std::vector<ELFRelocationEntry>> - Relocations; - StringTableBuilder ShStrTabBuilder; + llvm::DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> + Relocations; /// @} /// @name Symbol Table Data /// @{ StringTableBuilder StrTabBuilder; - std::vector<uint64_t> FileSymbolData; - std::vector<ELFSymbolData> LocalSymbolData; - std::vector<ELFSymbolData> ExternalSymbolData; - std::vector<ELFSymbolData> UndefinedSymbolData; /// @} - bool NeedsGOT; - // This holds the symbol table index of the last local symbol. unsigned LastLocalSymbolIndex; // This holds the .strtab section index. unsigned StringTableIndex; // This holds the .symtab section index. unsigned SymbolTableIndex; + // This holds the .symtab_shndx section index. + unsigned SymtabShndxSectionIndex = 0; - unsigned ShstrtabIndex; - + // Sections in the order they are to be output in the section table. + std::vector<const MCSectionELF *> SectionTable; + unsigned addToSectionTable(const MCSectionELF *Sec); // TargetObjectWriter wrappers. bool is64Bit() const { return TargetObjectWriter->is64Bit(); } @@ -184,172 +133,130 @@ class ELFObjectWriter : public MCObjectWriter { return TargetObjectWriter->GetRelocType(Target, Fixup, IsPCRel); } + void align(unsigned Alignment); + 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) {} + + void reset() override { + Renames.clear(); + Relocations.clear(); + StrTabBuilder.clear(); + SectionTable.clear(); + MCObjectWriter::reset(); + } - virtual ~ELFObjectWriter(); + ~ELFObjectWriter() override; void WriteWord(uint64_t W) { if (is64Bit()) - Write64(W); + write64(W); else - Write32(W); + write32(W); } - template <typename T> void write(MCDataFragment &F, T Value) { - FWriter.write(F, Value); + template <typename T> void write(T Val) { + if (IsLittleEndian) + support::endian::Writer<support::little>(OS).write(Val); + else + support::endian::Writer<support::big>(OS).write(Val); } - void WriteHeader(const MCAssembler &Asm, - uint64_t SectionDataSize, - unsigned NumberOfSections); + void writeHeader(const MCAssembler &Asm); - void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, - const MCAsmLayout &Layout); + void writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex, + 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::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>> + SectionOffsetsTy; bool shouldRelocateWithSymbol(const MCAssembler &Asm, const MCSymbolRefExpr *RefA, - const MCSymbolData *SD, uint64_t C, + const MCSymbol *Sym, 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; - 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 the section with the relocations - typedef DenseMap<const MCSectionELF*, const MCSectionELF*> RelMapTy; - // 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; /// 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); + SectionOffsetsTy &SectionOffsets); - void ComputeIndexMap(MCAssembler &Asm, - SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap); + MCSectionELF *createRelocationSection(MCContext &Ctx, + const MCSectionELF &Sec); - void CreateRelocationSections(MCAssembler &Asm, MCAsmLayout &Layout, - RelMapTy &RelMap); + const MCSectionELF *createStringTable(MCContext &Ctx); - void CompressDebugSections(MCAssembler &Asm, MCAsmLayout &Layout); + void executePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) override; - void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout, - const RelMapTy &RelMap); + void writeSectionHeader(const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, + const SectionOffsetsTy &SectionOffsets); - void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, - SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap); + void writeSectionData(const MCAssembler &Asm, MCSection &Sec, + const MCAsmLayout &Layout); - // 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, - SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap); + void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, + uint64_t Address, uint64_t Offset, uint64_t Size, + uint32_t Link, uint32_t Info, uint64_t Alignment, + uint64_t EntrySize); - void ExecutePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout) override; + void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec); - void WriteSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap, - const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, - const SectionOffsetMapTy &SectionOffsetMap); + bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbol &SymA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const override; - void ComputeSectionOrder(MCAssembler &Asm, - std::vector<const MCSectionELF*> &Sections); + bool isWeak(const MCSymbol &Sym) const override; - void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, - uint64_t Address, uint64_t Offset, - uint64_t Size, uint32_t Link, uint32_t Info, - uint64_t Alignment, uint64_t EntrySize); - - void WriteRelocationsFragment(const MCAssembler &Asm, - MCDataFragment *F, - const MCSectionData *SD); - - bool - IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, - bool IsPCRel) const override; - - void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; - void WriteSection(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap, - uint32_t GroupSymbolIndex, - uint64_t Offset, uint64_t Size, uint64_t Alignment, + void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; + void writeSection(const SectionIndexMapTy &SectionIndexMap, + uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size, const MCSectionELF &Section); }; } -FragmentWriter::FragmentWriter(bool IsLittleEndian) - : IsLittleEndian(IsLittleEndian) {} +void ELFObjectWriter::align(unsigned Alignment) { + uint64_t Padding = OffsetToAlignment(OS.tell(), Alignment); + WriteZeros(Padding); +} -template <typename T> void FragmentWriter::write(MCDataFragment &F, T Val) { - if (IsLittleEndian) - Val = support::endian::byte_swap<T, support::little>(Val); - else - Val = support::endian::byte_swap<T, support::big>(Val); - const char *Start = (const char *)&Val; - F.getContents().append(Start, Start + sizeof(T)); +unsigned ELFObjectWriter::addToSectionTable(const MCSectionELF *Sec) { + SectionTable.push_back(Sec); + StrTabBuilder.add(Sec->getSectionName()); + return SectionTable.size(); } 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 <typename T> -void SymbolTableWriter::write(MCDataFragment &F, T Value) { - FWriter.write(F, Value); +template <typename T> 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, @@ -359,31 +266,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; @@ -396,34 +301,11 @@ bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; } -bool ELFObjectWriter::RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) { - switch (Variant) { - default: - return false; - case MCSymbolRefExpr::VK_GOT: - case MCSymbolRefExpr::VK_PLT: - case MCSymbolRefExpr::VK_GOTPCREL: - case MCSymbolRefExpr::VK_GOTOFF: - case MCSymbolRefExpr::VK_TPOFF: - case MCSymbolRefExpr::VK_TLSGD: - case MCSymbolRefExpr::VK_GOTTPOFF: - case MCSymbolRefExpr::VK_INDNTPOFF: - case MCSymbolRefExpr::VK_NTPOFF: - case MCSymbolRefExpr::VK_GOTNTPOFF: - case MCSymbolRefExpr::VK_TLSLDM: - case MCSymbolRefExpr::VK_DTPOFF: - case MCSymbolRefExpr::VK_TLSLD: - return true; - } -} - 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 // ---------- // @@ -432,89 +314,78 @@ 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] + write8(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS] // e_ident[EI_DATA] - Write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB); + write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB); - Write8(ELF::EV_CURRENT); // e_ident[EI_VERSION] + write8(ELF::EV_CURRENT); // e_ident[EI_VERSION] // e_ident[EI_OSABI] - Write8(TargetObjectWriter->getOSABI()); - Write8(0); // e_ident[EI_ABIVERSION] + write8(TargetObjectWriter->getOSABI()); + write8(0); // e_ident[EI_ABIVERSION] WriteZeros(ELF::EI_NIDENT - ELF::EI_PAD); - Write16(ELF::ET_REL); // e_type + write16(ELF::ET_REL); // e_type - Write16(TargetObjectWriter->getEMachine()); // e_machine = target + write16(TargetObjectWriter->getEMachine()); // e_machine = target - Write32(ELF::EV_CURRENT); // e_version + 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()); + write32(Asm.getELFHeaderEFlags()); // e_ehsize = ELF header size - Write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr)); + write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr)); - Write16(0); // e_phentsize = prog header entry size - Write16(0); // e_phnum = # prog header entries = 0 + write16(0); // e_phentsize = prog header entry size + write16(0); // e_phnum = # prog header entries = 0 // e_shentsize = Section header entry size - Write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr)); + 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(StringTableIndex < ELF::SHN_LORESERVE); + write16(StringTableIndex); } -uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data, +uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout) { - if (Data.isCommon() && Data.isExternal()) - return Data.getCommonAlignment(); + if (Sym.isCommon() && Sym.isExternal()) + return Sym.getCommonAlignment(); uint64_t Res; - if (!Layout.getSymbolOffset(&Data, Res)) + if (!Layout.getSymbolOffset(Sym, Res)) return 0; - if (Layout.getAssembler().isThumbFunc(&Data.getSymbol())) + if (Layout.getAssembler().isThumbFunc(&Sym)) Res |= 1; return Res; } -void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, +void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { // The presence of symbol versions causes undefined symbols and // versions declared with @@@ to be renamed. - for (MCSymbolData &OriginalData : Asm.symbols()) { - const MCSymbol &Alias = OriginalData.getSymbol(); - + for (const MCSymbol &A : Asm.symbols()) { + const auto &Alias = cast<MCSymbolELF>(A); // Not an alias. if (!Alias.isVariable()) continue; auto *Ref = dyn_cast<MCSymbolRefExpr>(Alias.getVariableValue()); if (!Ref) continue; - const MCSymbol &Symbol = Ref->getSymbol(); - MCSymbolData &SD = Asm.getSymbolData(Symbol); + const auto &Symbol = cast<MCSymbolELF>(Ref->getSymbol()); StringRef AliasName = Alias.getName(); size_t Pos = AliasName.find('@'); @@ -523,8 +394,8 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, // Aliases defined with .symvar copy the binding from the symbol they alias. // This is the first place we are able to copy this information. - OriginalData.setExternal(SD.isExternal()); - MCELF::SetBinding(OriginalData, MCELF::GetBinding(SD)); + Alias.setExternal(Symbol.isExternal()); + Alias.setBinding(Symbol.getBinding()); StringRef Rest = AliasName.substr(Pos); if (!Symbol.isUndefined() && !Rest.startswith("@@@")) @@ -574,99 +445,50 @@ static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) { return Type; } -void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, +void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer, + uint32_t StringIndex, ELFSymbolData &MSD, const MCAsmLayout &Layout) { - MCSymbolData &OrigData = *MSD.SymbolData; - assert((!OrigData.getFragment() || - (&OrigData.getFragment()->getParent()->getSection() == - &OrigData.getSymbol().getSection())) && + const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol); + assert((!Symbol.getFragment() || + (Symbol.getFragment()->getParent() == &Symbol.getSection())) && "The symbol's section doesn't match the fragment's symbol"); - const MCSymbol *Base = Layout.getBaseSymbol(OrigData.getSymbol()); + const MCSymbolELF *Base = + cast_or_null<MCSymbolELF>(Layout.getBaseSymbol(Symbol)); // This has to be in sync with when computeSymbolTable uses SHN_ABS or // SHN_COMMON. - bool IsReserved = !Base || OrigData.isCommon(); + bool IsReserved = !Base || Symbol.isCommon(); // Binding and Type share the same byte as upper and lower nibbles - uint8_t Binding = MCELF::GetBinding(OrigData); - uint8_t Type = MCELF::GetType(OrigData); - MCSymbolData *BaseSD = nullptr; + uint8_t Binding = Symbol.getBinding(); + uint8_t Type = Symbol.getType(); if (Base) { - BaseSD = &Layout.getAssembler().getSymbolData(*Base); - Type = mergeTypeForSet(Type, MCELF::GetType(*BaseSD)); + Type = mergeTypeForSet(Type, Base->getType()); } - uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); + uint8_t Info = (Binding << 4) | Type; // Other and Visibility share the same byte with Visibility using the lower // 2 bits - uint8_t Visibility = MCELF::GetVisibility(OrigData); - uint8_t Other = MCELF::getOther(OrigData) << (ELF_STO_Shift - ELF_STV_Shift); - Other |= Visibility; + uint8_t Visibility = Symbol.getVisibility(); + uint8_t Other = Symbol.getOther() | Visibility; - uint64_t Value = SymbolValue(OrigData, Layout); + uint64_t Value = SymbolValue(*MSD.Symbol, Layout); uint64_t Size = 0; - const MCExpr *ESize = OrigData.getSize(); + const MCExpr *ESize = MSD.Symbol->getSize(); if (!ESize && Base) - ESize = BaseSD->getSize(); + ESize = Base->getSize(); 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; } // Write out the symbol table entry - Writer.writeSymbol(MSD.StringIndex, Info, Value, Size, Other, - MSD.SectionIndex, IsReserved); -} - -void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, - MCAssembler &Asm, - const MCAsmLayout &Layout, - SectionIndexMapTy &SectionIndexMap) { - // 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); - - // The first entry is the undefined symbol entry. - Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); - - for (unsigned i = 0, e = FileSymbolData.size(); i != e; ++i) { - Writer.writeSymbol(FileSymbolData[i], ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, - ELF::STV_DEFAULT, ELF::SHN_ABS, true); - } - - // Write the symbol table entries. - LastLocalSymbolIndex = FileSymbolData.size() + LocalSymbolData.size() + 1; - - for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) { - ELFSymbolData &MSD = LocalSymbolData[i]; - WriteSymbol(Writer, MSD, Layout); - } - - for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) { - ELFSymbolData &MSD = ExternalSymbolData[i]; - MCSymbolData &Data = *MSD.SymbolData; - assert(((Data.getFlags() & ELF_STB_Global) || - (Data.getFlags() & ELF_STB_Weak)) && - "External symbol requires STB_GLOBAL or STB_WEAK flag"); - WriteSymbol(Writer, MSD, Layout); - if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) - LastLocalSymbolIndex++; - } - - for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) { - ELFSymbolData &MSD = UndefinedSymbolData[i]; - MCSymbolData &Data = *MSD.SymbolData; - WriteSymbol(Writer, MSD, Layout); - if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) - LastLocalSymbolIndex++; - } + Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex, + IsReserved); } // It is always valid to create a relocation with a symbol. It is preferable @@ -674,9 +496,9 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, // allows us to omit some local symbols from the symbol table. bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, const MCSymbolRefExpr *RefA, - const MCSymbolData *SD, - uint64_t C, + const MCSymbol *S, uint64_t C, unsigned Type) const { + const auto *Sym = cast_or_null<MCSymbolELF>(S); // A PCRel relocation to an absolute value has no symbol (or section). We // represent that with a relocation to a null section. if (!RefA) @@ -711,11 +533,11 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, // An undefined symbol is not in any section, so the relocation has to point // to the symbol itself. - const MCSymbol &Sym = SD->getSymbol(); - if (Sym.isUndefined()) + assert(Sym && "Expected a symbol"); + if (Sym->isUndefined()) return true; - unsigned Binding = MCELF::GetBinding(*SD); + unsigned Binding = Sym->getBinding(); switch(Binding) { default: llvm_unreachable("Invalid Binding"); @@ -739,7 +561,7 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, // If we change such a relocation to use the section, the linker would think // that it pointed to another string and subtracting 42 at runtime will // produce the wrong value. - auto &Sec = cast<MCSectionELF>(Sym.getSection()); + auto &Sec = cast<MCSectionELF>(Sym->getSection()); unsigned Flags = Sec.getFlags(); if (Flags & ELF::SHF_MERGE) { if (C != 0) @@ -762,41 +584,40 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, // bit. With a symbol that is done by just having the symbol have that bit // set, so we would lose the bit if we relocated with the section. // FIXME: We could use the section but add the bit to the relocation value. - if (Asm.isThumbFunc(&Sym)) + if (Asm.isThumbFunc(Sym)) return true; - if (TargetObjectWriter->needsRelocateWithSymbol(*SD, Type)) + if (TargetObjectWriter->needsRelocateWithSymbol(*Sym, Type)) return true; return false; } -static const MCSymbol *getWeakRef(const MCSymbolRefExpr &Ref) { - const MCSymbol &Sym = Ref.getSymbol(); - - if (Ref.getKind() == MCSymbolRefExpr::VK_WEAKREF) - return &Sym; - - if (!Sym.isVariable()) - return nullptr; - - const MCExpr *Expr = Sym.getVariableValue(); - const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr); - if (!Inner) - 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 MCSymbolELF &Sym) { + if (Sym.getType() == ELF::STT_GNU_IFUNC) + return true; - if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) - return &Inner->getSymbol(); - return nullptr; + switch (Sym.getBinding()) { + 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(const MCAssembler &Asm, +void ELFObjectWriter::recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) { - const MCSectionData *FixupSection = Fragment->getParent(); + const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { + const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent()); uint64_t C = Target.getConstant(); uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); @@ -812,26 +633,29 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, // or (A + C - R). If B = R + K and the relocation is not pcrel, we can // replace B to implement it: (A - R - K + C) if (IsPCRel) - Asm.getContext().FatalError( + Asm.getContext().reportFatalError( Fixup.getLoc(), "No relocation available to represent this relative expression"); - const MCSymbol &SymB = RefB->getSymbol(); + const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol()); if (SymB.isUndefined()) - Asm.getContext().FatalError( + Asm.getContext().reportFatalError( Fixup.getLoc(), Twine("symbol '") + SymB.getName() + "' can not be undefined in a subtraction expression"); assert(!SymB.isAbsolute() && "Should have been folded"); const MCSection &SecB = SymB.getSection(); - if (&SecB != &FixupSection->getSection()) - Asm.getContext().FatalError( + if (&SecB != &FixupSection) + Asm.getContext().reportFatalError( Fixup.getLoc(), "Cannot represent a difference across sections"); - const MCSymbolData &SymBD = Asm.getSymbolData(SymB); - uint64_t SymBOffset = Layout.getSymbolOffset(&SymBD); + if (::isWeak(SymB)) + Asm.getContext().reportFatalError( + Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol"); + + uint64_t SymBOffset = Layout.getSymbolOffset(SymB); uint64_t K = SymBOffset - FixupOffset; IsPCRel = true; C -= K; @@ -839,13 +663,23 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, // We either rejected the fixup or folded B into C at this point. const MCSymbolRefExpr *RefA = Target.getSymA(); - const MCSymbol *SymA = RefA ? &RefA->getSymbol() : nullptr; - const MCSymbolData *SymAD = SymA ? &Asm.getSymbolData(*SymA) : nullptr; + const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol()) : nullptr; + + bool ViaWeakRef = false; + if (SymA && SymA->isVariable()) { + const MCExpr *Expr = SymA->getVariableValue(); + if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) { + if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) { + SymA = cast<MCSymbolELF>(&Inner->getSymbol()); + ViaWeakRef = true; + } + } + } unsigned Type = GetRelocType(Target, Fixup, IsPCRel); - bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymAD, C, Type); + bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type); if (!RelocateWithSymbol && SymA && !SymA->isUndefined()) - C += Layout.getSymbolOffset(SymAD); + C += Layout.getSymbolOffset(*SymA); uint64_t Addend = 0; if (hasRelocationAddend()) { @@ -855,50 +689,36 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, FixedValue = C; - // FIXME: What is this!?!? - MCSymbolRefExpr::VariantKind Modifier = - RefA ? RefA->getKind() : MCSymbolRefExpr::VK_None; - if (RelocNeedsGOT(Modifier)) - NeedsGOT = true; - if (!RelocateWithSymbol) { const MCSection *SecA = (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr; auto *ELFSec = cast_or_null<MCSectionELF>(SecA); - MCSymbol *SectionSymbol = - ELFSec ? Asm.getContext().getOrCreateSectionSymbol(*ELFSec) - : nullptr; + const auto *SectionSymbol = + ELFSec ? cast<MCSymbolELF>(ELFSec->getBeginSymbol()) : nullptr; + if (SectionSymbol) + SectionSymbol->setUsedInReloc(); ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend); - Relocations[FixupSection].push_back(Rec); + Relocations[&FixupSection].push_back(Rec); return; } if (SymA) { - if (const MCSymbol *R = Renames.lookup(SymA)) + if (const MCSymbolELF *R = Renames.lookup(SymA)) SymA = R; - if (const MCSymbol *WeakRef = getWeakRef(*RefA)) - WeakrefUsedInReloc.insert(WeakRef); + if (ViaWeakRef) + SymA->setIsWeakrefUsedInReloc(); else - UsedInReloc.insert(SymA); + SymA->setUsedInReloc(); } ELFRelocationEntry Rec(FixupOffset, SymA, Type, Addend); - Relocations[FixupSection].push_back(Rec); + Relocations[&FixupSection].push_back(Rec); return; } - -uint64_t -ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm, - const MCSymbol *S) { - const MCSymbolData &SD = Asm.getSymbolData(*S); - return SD.getIndex(); -} - bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout, - const MCSymbolData &Data, bool Used, + const MCSymbolELF &Symbol, bool Used, bool Renamed) { - const MCSymbol &Symbol = Data.getSymbol(); if (Symbol.isVariable()) { const MCExpr *Expr = Symbol.getVariableValue(); if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) { @@ -913,229 +733,227 @@ bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout, if (Renamed) return false; - if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_") - return true; - - if (Symbol.isVariable()) { - const MCSymbol *Base = Layout.getBaseSymbol(Symbol); - if (Base && Base->isUndefined()) - return false; + if (Symbol.isVariable() && Symbol.isUndefined()) { + // FIXME: this is here just to diagnose the case of a var = commmon_sym. + Layout.getBaseSymbol(Symbol); + return false; } - bool IsGlobal = MCELF::GetBinding(Data) == ELF::STB_GLOBAL; - if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal) + if (Symbol.isUndefined() && !Symbol.isBindingSet()) return false; if (Symbol.isTemporary()) return false; - return true; -} - -bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isUsedInReloc) { - if (Data.isExternal()) - return false; - - const MCSymbol &Symbol = Data.getSymbol(); - if (Symbol.isDefined()) - return true; - - if (isUsedInReloc) + if (Symbol.getType() == ELF::STT_SECTION) return false; 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<const MCSectionELF &>(it->getSection()); - if (Section.getType() != ELF::SHT_GROUP) - continue; - SectionIndexMap[&Section] = Index++; - } +void ELFObjectWriter::computeSymbolTable( + MCAssembler &Asm, const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap, + SectionOffsetsTy &SectionOffsets) { + MCContext &Ctx = Asm.getContext(); + SymbolTableWriter Writer(*this, is64Bit()); - 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) - continue; - SectionIndexMap[&Section] = Index++; - const MCSectionELF *RelSection = RelMap.lookup(&Section); - if (RelSection) - SectionIndexMap[RelSection] = Index++; - } -} + // Symbol table + unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32; + MCSectionELF *SymtabSection = + Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, ""); + SymtabSection->setAlignment(is64Bit() ? 8 : 4); + SymbolTableIndex = addToSectionTable(SymtabSection); -void -ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, - const RevGroupMapTy &RevGroupMap, - unsigned NumRegularSections) { - // FIXME: Is this the correct place to do this? - // FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed? - if (NeedsGOT) { - StringRef Name = "_GLOBAL_OFFSET_TABLE_"; - MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name); - MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym); - Data.setExternal(true); - MCELF::SetBinding(Data, ELF::STB_GLOBAL); - } + align(SymtabSection->getAlignment()); + uint64_t SecStart = OS.tell(); - // Add the data for the symbols. - for (MCSymbolData &SD : Asm.symbols()) { - const MCSymbol &Symbol = SD.getSymbol(); + // The first entry is the undefined symbol entry. + Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); - bool Used = UsedInReloc.count(&Symbol); - bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol); - bool isSignature = RevGroupMap.count(&Symbol); + std::vector<ELFSymbolData> LocalSymbolData; + std::vector<ELFSymbolData> ExternalSymbolData; - if (!isInSymtab(Layout, SD, - Used || WeakrefUsed || isSignature, + // Add the data for the symbols. + bool HasLargeSectionIndex = false; + for (const MCSymbol &S : Asm.symbols()) { + const auto &Symbol = cast<MCSymbolELF>(S); + bool Used = Symbol.isUsedInReloc(); + bool WeakrefUsed = Symbol.isWeakrefUsedInReloc(); + bool isSignature = Symbol.isSignature(); + + if (!isInSymtab(Layout, Symbol, Used || WeakrefUsed || isSignature, Renames.count(&Symbol))) continue; ELFSymbolData MSD; - MSD.SymbolData = &SD; - const MCSymbol *BaseSymbol = Layout.getBaseSymbol(Symbol); - - // Undefined symbols are global, but this is the first place we - // are able to set it. - bool Local = isLocal(SD, Used); - if (!Local && MCELF::GetBinding(SD) == ELF::STB_LOCAL) { - assert(BaseSymbol); - MCSymbolData &BaseData = Asm.getSymbolData(*BaseSymbol); - MCELF::SetBinding(SD, ELF::STB_GLOBAL); - MCELF::SetBinding(BaseData, ELF::STB_GLOBAL); - } + MSD.Symbol = cast<MCSymbolELF>(&Symbol); - if (!BaseSymbol) { + bool Local = Symbol.getBinding() == ELF::STB_LOCAL; + if (Symbol.isAbsolute()) { MSD.SectionIndex = ELF::SHN_ABS; - } else if (SD.isCommon()) { + } else if (Symbol.isCommon()) { assert(!Local); MSD.SectionIndex = ELF::SHN_COMMON; - } else if (BaseSymbol->isUndefined()) { - if (isSignature && !Used) - MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap.lookup(&Symbol)); - else + } else if (Symbol.isUndefined()) { + if (isSignature && !Used) { + MSD.SectionIndex = RevGroupMap.lookup(&Symbol); + if (MSD.SectionIndex >= ELF::SHN_LORESERVE) + HasLargeSectionIndex = true; + } else { MSD.SectionIndex = ELF::SHN_UNDEF; - if (!Used && WeakrefUsed) - MCELF::SetBinding(SD, ELF::STB_WEAK); + } } else { const MCSectionELF &Section = - static_cast<const MCSectionELF&>(BaseSymbol->getSection()); + static_cast<const MCSectionELF &>(Symbol.getSection()); MSD.SectionIndex = SectionIndexMap.lookup(&Section); assert(MSD.SectionIndex && "Invalid section index!"); + if (MSD.SectionIndex >= ELF::SHN_LORESERVE) + HasLargeSectionIndex = true; } - // 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; + } } // Sections have their own string table - if (MCELF::GetType(SD) != ELF::STT_SECTION) + if (Symbol.getType() != ELF::STT_SECTION) MSD.Name = StrTabBuilder.add(Name); - if (MSD.SectionIndex == ELF::SHN_UNDEF) - UndefinedSymbolData.push_back(MSD); - else if (Local) + if (Local) LocalSymbolData.push_back(MSD); else ExternalSymbolData.push_back(MSD); } - for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i) - StrTabBuilder.add(*i); + if (HasLargeSectionIndex) { + MCSectionELF *SymtabShndxSection = + Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, ""); + SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection); + SymtabShndxSection->setAlignment(4); + } - StrTabBuilder.finalize(StringTableBuilder::ELF); + ArrayRef<std::string> FileNames = Asm.getFileNames(); + for (const std::string &Name : FileNames) + StrTabBuilder.add(Name); - for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i) - FileSymbolData.push_back(StrTabBuilder.getOffset(*i)); + StrTabBuilder.finalize(StringTableBuilder::ELF); - 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); + for (const std::string &Name : FileNames) + Writer.writeSymbol(StrTabBuilder.getOffset(Name), + ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT, + ELF::SHN_ABS, true); // Symbols are required to be in lexicographic order. array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end()); array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); - array_pod_sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end()); // Set the symbol indices. Local symbols must come before all other // symbols with non-local bindings. - unsigned Index = FileSymbolData.size() + 1; - for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) - LocalSymbolData[i].SymbolData->setIndex(Index++); - - 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++); -} + unsigned Index = FileNames.size() + 1; + + for (ELFSymbolData &MSD : LocalSymbolData) { + unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION + ? 0 + : StrTabBuilder.getOffset(MSD.Name); + MSD.Symbol->setIndex(Index++); + writeSymbol(Writer, StringIndex, MSD, Layout); + } -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; + // Write the symbol table entries. + LastLocalSymbolIndex = Index; - MCContext &Ctx = Asm.getContext(); - const MCSectionELF &Section = - static_cast<const MCSectionELF&>(SD.getSection()); + for (ELFSymbolData &MSD : ExternalSymbolData) { + unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name); + MSD.Symbol->setIndex(Index++); + writeSymbol(Writer, StringIndex, MSD, Layout); + assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL); + } - const StringRef SectionName = Section.getSectionName(); - std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel"; - RelaSectionName += SectionName; + uint64_t SecEnd = OS.tell(); + SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd); - 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); + ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes(); + if (ShndxIndexes.empty()) { + assert(SymtabShndxSectionIndex == 0); + return; + } + assert(SymtabShndxSectionIndex != 0); - unsigned Flags = 0; - StringRef Group = ""; - if (Section.getFlags() & ELF::SHF_GROUP) { - Flags = ELF::SHF_GROUP; - Group = Section.getGroup()->getName(); - } + SecStart = OS.tell(); + const MCSectionELF *SymtabShndxSection = + SectionTable[SymtabShndxSectionIndex - 1]; + for (uint32_t Index : ShndxIndexes) + write(Index); + SecEnd = OS.tell(); + SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd); +} - const MCSectionELF *RelaSection = - Ctx.getELFSection(RelaSectionName, hasRelocationAddend() ? - ELF::SHT_RELA : ELF::SHT_REL, Flags, - SectionKind::getReadOnly(), - EntrySize, Group); - RelMap[&Section] = RelaSection; - Asm.getOrCreateSectionData(*RelaSection); - } +MCSectionELF * +ELFObjectWriter::createRelocationSection(MCContext &Ctx, + const MCSectionELF &Sec) { + if (Relocations[&Sec].empty()) + return nullptr; + + const StringRef SectionName = Sec.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 Flags = 0; + if (Sec.getFlags() & ELF::SHF_GROUP) + Flags = ELF::SHF_GROUP; + + MCSectionELF *RelaSection = Ctx.createELFRelSection( + RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL, + Flags, EntrySize, Sec.getGroup(), &Sec); + RelaSection->setAlignment(is64Bit() ? 8 : 4); + return RelaSection; } static SmallVector<char, 128> -getUncompressedData(MCAsmLayout &Layout, - MCSectionData::FragmentListType &Fragments) { +getUncompressedData(const MCAsmLayout &Layout, + const MCSection::FragmentListType &Fragments) { SmallVector<char, 128> UncompressedData; for (const MCFragment &F : Fragments) { const SmallVectorImpl<char> *Contents; @@ -1164,7 +982,7 @@ getUncompressedData(MCAsmLayout &Layout, static bool prependCompressionHeader(uint64_t Size, SmallVectorImpl<char> &CompressedContents) { - static const StringRef Magic = "ZLIB"; + const StringRef Magic = "ZLIB"; if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size()) return false; if (sys::IsLittleEndianHost) @@ -1178,123 +996,41 @@ prependCompressionHeader(uint64_t Size, return true; } -// 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, - MCSectionData::FragmentListType &Fragments) { - std::unique_ptr<MCDataFragment> CompressedFragment(new MCDataFragment()); +void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, + const MCAsmLayout &Layout) { + MCSectionELF &Section = static_cast<MCSectionELF &>(Sec); + StringRef SectionName = Section.getSectionName(); + + // Compressing debug_frame requires handling alignment fragments which is + // more work (possibly generalizing MCAssembler.cpp:writeFragment to allow + // for writing to arbitrary buffers) for little benefit. + if (!Asm.getContext().getAsmInfo()->compressDebugSections() || + !SectionName.startswith(".debug_") || SectionName == ".debug_frame") { + Asm.writeSectionData(&Section, Layout); + return; + } - // Gather the uncompressed data from all the fragments, recording the - // alignment fragment, if seen, and any fixups. + // Gather the uncompressed data from all the fragments. + const MCSection::FragmentListType &Fragments = Section.getFragmentList(); SmallVector<char, 128> UncompressedData = getUncompressedData(Layout, Fragments); - SmallVectorImpl<char> &CompressedContents = CompressedFragment->getContents(); - + SmallVector<char, 128> CompressedContents; zlib::Status Success = zlib::compress( StringRef(UncompressedData.data(), UncompressedData.size()), CompressedContents); - if (Success != zlib::StatusOK) - return nullptr; - - if (!prependCompressionHeader(UncompressedData.size(), CompressedContents)) - return nullptr; - - return CompressedFragment; -} - -typedef DenseMap<const MCSectionData *, std::vector<MCSymbolData *>> -DefiningSymbolMap; - -static void UpdateSymbols(const MCAsmLayout &Layout, - const std::vector<MCSymbolData *> &Symbols, - MCFragment &NewFragment) { - for (MCSymbolData *Sym : Symbols) { - Sym->setOffset(Sym->getOffset() + - Layout.getFragmentOffset(Sym->getFragment())); - Sym->setFragment(&NewFragment); + if (Success != zlib::StatusOK) { + Asm.writeSectionData(&Section, Layout); + return; } -} -static void CompressDebugSection(MCAssembler &Asm, MCAsmLayout &Layout, - const DefiningSymbolMap &DefiningSymbols, - const MCSectionELF &Section, - MCSectionData &SD) { - StringRef SectionName = Section.getSectionName(); - MCSectionData::FragmentListType &Fragments = SD.getFragmentList(); - - std::unique_ptr<MCDataFragment> CompressedFragment = - getCompressedFragment(Layout, Fragments); - - // Leave the section as-is if the fragments could not be compressed. - if (!CompressedFragment) + if (!prependCompressionHeader(UncompressedData.size(), CompressedContents)) { + Asm.writeSectionData(&Section, Layout); return; - - // Update the fragment+offsets of any symbols referring to fragments in this - // section to refer to the new fragment. - auto I = DefiningSymbols.find(&SD); - if (I != DefiningSymbols.end()) - UpdateSymbols(Layout, I->second, *CompressedFragment); - - // Invalidate the layout for the whole section since it will have new and - // different fragments now. - Layout.invalidateFragmentsFrom(&Fragments.front()); - Fragments.clear(); - - // Complete the initialization of the new fragment - CompressedFragment->setParent(&SD); - CompressedFragment->setLayoutOrder(0); - Fragments.push_back(CompressedFragment.release()); - - // Rename from .debug_* to .zdebug_* + } Asm.getContext().renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str()); -} - -void ELFObjectWriter::CompressDebugSections(MCAssembler &Asm, - MCAsmLayout &Layout) { - if (!Asm.getContext().getAsmInfo()->compressDebugSections()) - return; - - DefiningSymbolMap DefiningSymbols; - - for (MCSymbolData &SD : Asm.symbols()) - if (MCFragment *F = SD.getFragment()) - DefiningSymbols[F->getParent()].push_back(&SD); - - for (MCSectionData &SD : Asm) { - const MCSectionELF &Section = - static_cast<const MCSectionELF &>(SD.getSection()); - StringRef SectionName = Section.getSectionName(); - - // Compressing debug_frame requires handling alignment fragments which is - // more work (possibly generalizing MCAssembler.cpp:writeFragment to allow - // for writing to arbitrary buffers) for little benefit. - if (!SectionName.startswith(".debug_") || SectionName == ".debug_frame") - continue; - - CompressDebugSection(Asm, Layout, DefiningSymbols, Section, SD); - } -} - -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<const MCSectionELF&>(SD.getSection()); - - const MCSectionELF *RelaSection = RelMap.lookup(&Section); - if (!RelaSection) - continue; - MCSectionData &RelaSD = Asm.getOrCreateSectionData(*RelaSection); - RelaSD.setAlignment(is64Bit() ? 8 : 4); - - MCDataFragment *F = new MCDataFragment(&RelaSD); - WriteRelocationsFragment(Asm, F, &*it); - } + OS << CompressedContents; } void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, @@ -1303,214 +1039,84 @@ void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint32_t Link, uint32_t Info, uint64_t Alignment, uint64_t EntrySize) { - Write32(Name); // sh_name: index into string table - Write32(Type); // sh_type + write32(Name); // sh_name: index into string table + write32(Type); // sh_type WriteWord(Flags); // sh_flags WriteWord(Address); // sh_addr WriteWord(Offset); // sh_offset WriteWord(Size); // sh_size - Write32(Link); // sh_link - Write32(Info); // sh_info + write32(Link); // sh_link + write32(Info); // sh_info WriteWord(Alignment); // sh_addralign 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<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]; +void ELFObjectWriter::writeRelocations(const MCAssembler &Asm, + const MCSectionELF &Sec) { + std::vector<ELFRelocationEntry> &Relocs = Relocations[&Sec]; - 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 = - Entry.Symbol ? getSymbolIndexInSymbolTable(Asm, Entry.Symbol) : 0; + unsigned Index = Entry.Symbol ? Entry.Symbol->getIndex() : 0; if (is64Bit()) { - write(*F, Entry.Offset); + write(Entry.Offset); if (TargetObjectWriter->isN64()) { - write(*F, uint32_t(Index)); + write(uint32_t(Index)); - write(*F, TargetObjectWriter->getRSsym(Entry.Type)); - write(*F, TargetObjectWriter->getRType3(Entry.Type)); - write(*F, TargetObjectWriter->getRType2(Entry.Type)); - write(*F, TargetObjectWriter->getRType(Entry.Type)); + write(TargetObjectWriter->getRSsym(Entry.Type)); + write(TargetObjectWriter->getRType3(Entry.Type)); + write(TargetObjectWriter->getRType2(Entry.Type)); + write(TargetObjectWriter->getRType(Entry.Type)); } else { struct ELF::Elf64_Rela ERE64; ERE64.setSymbolAndType(Index, Entry.Type); - write(*F, ERE64.r_info); + write(ERE64.r_info); } if (hasRelocationAddend()) - write(*F, Entry.Addend); + write(Entry.Addend); } else { - write(*F, uint32_t(Entry.Offset)); + write(uint32_t(Entry.Offset)); struct ELF::Elf32_Rela ERE32; ERE32.setSymbolAndType(Index, Entry.Type); - write(*F, ERE32.r_info); + write(ERE32.r_info); if (hasRelocationAddend()) - write(*F, uint32_t(Entry.Addend)); + write(uint32_t(Entry.Addend)); } } } -void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, - MCAsmLayout &Layout, - SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap) { - 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, - 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) { - 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, - GroupMapTy &GroupMap, - RevGroupMapTy &RevGroupMap, - SectionIndexMapTy &SectionIndexMap, - const RelMapTy &RelMap) { - MCContext &Ctx = Asm.getContext(); - - // Build 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 MCSymbol *SignatureSymbol = Section.getGroup(); - Asm.getOrCreateSymbolData(*SignatureSymbol); - const MCSectionELF *&Group = RevGroupMap[SignatureSymbol]; - if (!Group) { - Group = Ctx.CreateELFGroupSection(); - 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<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); - } +const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) { + const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1]; + OS << StrTabBuilder.data(); + return StrtabSection; } -void ELFObjectWriter::WriteSection(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap, - uint32_t GroupSymbolIndex, - uint64_t Offset, uint64_t Size, - uint64_t Alignment, - const MCSectionELF &Section) { +void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, + uint32_t GroupSymbolIndex, uint64_t Offset, + uint64_t Size, const MCSectionELF &Section) { uint64_t sh_link = 0; uint64_t sh_info = 0; switch(Section.getType()) { - case ELF::SHT_DYNAMIC: - sh_link = ShStrTabBuilder.getOffset(Section.getSectionName()); - sh_info = 0; + default: + // Nothing to do. break; + case ELF::SHT_DYNAMIC: + llvm_unreachable("SHT_DYNAMIC in a relocatable object"); + 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; } @@ -1525,286 +1131,221 @@ 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)); - } - } - - WriteSecHdrEntry(ShStrTabBuilder.getOffset(Section.getSectionName()), - Section.getType(), - Section.getFlags(), 0, Offset, Size, sh_link, sh_info, - Alignment, Section.getEntrySize()); -} - -bool ELFObjectWriter::IsELFMetaDataSection(const MCSectionData &SD) { - return SD.getOrdinal() == ~UINT32_C(0) && - !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); -} + Section.getType() == ELF::SHT_ARM_EXIDX) + sh_link = SectionIndexMap.lookup(Section.getAssociatedSection()); -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); - - if (IsELFMetaDataSection(SD)) { - for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e; - ++i) { - const MCFragment &F = *i; - assert(F.getKind() == MCFragment::FT_Data); - WriteBytes(cast<MCDataFragment>(F).getContents()); - } - } else { - Asm.writeSectionData(&SD, Layout); - } + WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()), + Section.getType(), Section.getFlags(), 0, Offset, Size, + sh_link, sh_info, Section.getAlignment(), + Section.getEntrySize()); } -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; - } +void ELFObjectWriter::writeSectionHeader( + const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, + const SectionOffsetsTy &SectionOffsets) { + const unsigned NumSections = SectionTable.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); - - for (unsigned i = 0; i < NumSections - 1; ++i) { - const MCSectionELF &Section = *Sections[i]; - const MCSectionData &SD = Asm.getOrCreateSectionData(Section); + (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0; + WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0); + + for (const MCSectionELF *Section : SectionTable) { uint32_t GroupSymbolIndex; - if (Section.getType() != ELF::SHT_GROUP) + unsigned Type = Section->getType(); + if (Type != ELF::SHT_GROUP) GroupSymbolIndex = 0; else - GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, - GroupMap.lookup(&Section)); - - uint64_t Size = GetSectionAddressSize(Layout, SD); - - WriteSection(Asm, SectionIndexMap, GroupSymbolIndex, - SectionOffsetMap.lookup(&Section), Size, - SD.getAlignment(), Section); - } -} + GroupSymbolIndex = Section->getGroup()->getIndex(); -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); - } + const std::pair<uint64_t, uint64_t> &Offsets = + SectionOffsets.find(Section)->second; + uint64_t Size; + if (Type == ELF::SHT_NOBITS) + Size = Layout.getSectionAddressSize(Section); + else + Size = Offsets.second - Offsets.first; - 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(SectionIndexMap, GroupSymbolIndex, Offsets.first, Size, + *Section); } } -void ELFObjectWriter::WriteObject(MCAssembler &Asm, +void ELFObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { - GroupMapTy GroupMap; + MCContext &Ctx = Asm.getContext(); + MCSectionELF *StrtabSection = + Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0); + StringTableIndex = addToSectionTable(StrtabSection); + RevGroupMapTy RevGroupMap; SectionIndexMapTy SectionIndexMap; - unsigned NumUserSections = Asm.size(); + std::map<const MCSymbol *, std::vector<const MCSectionELF *>> GroupMembers; - CompressDebugSections(Asm, const_cast<MCAsmLayout &>(Layout)); + // Write out the ELF header ... + writeHeader(Asm); - DenseMap<const MCSectionELF*, const MCSectionELF*> RelMap; - CreateRelocationSections(Asm, const_cast<MCAsmLayout&>(Layout), RelMap); + // ... then the sections ... + SectionOffsetsTy SectionOffsets; + std::vector<MCSectionELF *> Groups; + std::vector<MCSectionELF *> Relocations; + for (MCSection &Sec : Asm) { + MCSectionELF &Section = static_cast<MCSectionELF &>(Sec); - const unsigned NumUserAndRelocSections = Asm.size(); - CreateIndexedSections(Asm, const_cast<MCAsmLayout&>(Layout), GroupMap, - RevGroupMap, SectionIndexMap, RelMap); - const unsigned AllSections = Asm.size(); - const unsigned NumIndexedSections = AllSections - NumUserAndRelocSections; + align(Section.getAlignment()); - unsigned NumRegularSections = NumUserSections + NumIndexedSections; + // Remember the offset into the file for this section. + uint64_t SecStart = OS.tell(); - // Compute symbol table information. - computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, - NumRegularSections); + const MCSymbolELF *SignatureSymbol = Section.getGroup(); + writeSectionData(Asm, Section, Layout); - WriteRelocations(Asm, const_cast<MCAsmLayout&>(Layout), RelMap); + uint64_t SecEnd = OS.tell(); + SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd); - CreateMetadataSections(const_cast<MCAssembler&>(Asm), - const_cast<MCAsmLayout&>(Layout), - SectionIndexMap, - RelMap); + MCSectionELF *RelSection = createRelocationSection(Ctx, Section); - uint64_t NaturalAlignment = is64Bit() ? 8 : 4; - uint64_t HeaderSize = is64Bit() ? sizeof(ELF::Elf64_Ehdr) : - sizeof(ELF::Elf32_Ehdr); - uint64_t FileOff = HeaderSize; + if (SignatureSymbol) { + Asm.registerSymbol(*SignatureSymbol); + unsigned &GroupIdx = RevGroupMap[SignatureSymbol]; + if (!GroupIdx) { + MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol); + GroupIdx = addToSectionTable(Group); + Group->setAlignment(4); + Groups.push_back(Group); + } + std::vector<const MCSectionELF *> &Members = + GroupMembers[SignatureSymbol]; + Members.push_back(&Section); + if (RelSection) + Members.push_back(RelSection); + } - std::vector<const MCSectionELF*> 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); + SectionIndexMap[&Section] = addToSectionTable(&Section); + if (RelSection) { + SectionIndexMap[RelSection] = addToSectionTable(RelSection); + Relocations.push_back(RelSection); + } + } - FileOff = RoundUpToAlignment(FileOff, SD.getAlignment()); + for (MCSectionELF *Group : Groups) { + align(Group->getAlignment()); // Remember the offset into the file for this section. - SectionOffsetMap[&Section] = FileOff; + uint64_t SecStart = OS.tell(); + + const MCSymbol *SignatureSymbol = Group->getGroup(); + assert(SignatureSymbol); + write(uint32_t(ELF::GRP_COMDAT)); + for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) { + uint32_t SecIndex = SectionIndexMap.lookup(Member); + write(SecIndex); + } - // Get the size of the section in the output file (including padding). - FileOff += GetSectionFileSize(Layout, SD); + uint64_t SecEnd = OS.tell(); + SectionOffsets[Group] = 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); + // Compute symbol table information. + computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets); - FileOff = RoundUpToAlignment(FileOff, SD.getAlignment()); + for (MCSectionELF *RelSection : Relocations) { + align(RelSection->getAlignment()); // Remember the offset into the file for this section. - SectionOffsetMap[&Section] = FileOff; + uint64_t SecStart = OS.tell(); + + writeRelocations(Asm, *RelSection->getAssociatedSection()); - // Get the size of the section in the output file (including padding). - FileOff += GetSectionFileSize(Layout, SD); + uint64_t SecEnd = OS.tell(); + SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd); } - // Write out the ELF header ... - WriteHeader(Asm, SectionHeaderOffset, NumSections + 1); + { + uint64_t SecStart = OS.tell(); + const MCSectionELF *Sec = createStringTable(Ctx); + uint64_t SecEnd = OS.tell(); + SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd); + } - // ... then the regular sections ... - // + because of .shstrtab - for (unsigned i = 0; i < NumRegularSections + 1; ++i) - WriteDataSectionData(Asm, Layout, *Sections[i]); + uint64_t NaturalAlignment = is64Bit() ? 8 : 4; + align(NaturalAlignment); - 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(Layout, SectionIndexMap, SectionOffsets); + + uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE) + ? (uint16_t)ELF::SHN_UNDEF + : SectionTable.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); +} - // ... 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 MCSymbol &SA, const MCFragment &FB, + bool InSet, bool IsPCRel) const { + const auto &SymA = cast<MCSymbolELF>(SA); + if (IsPCRel) { + assert(!InSet); + if (::isWeak(SymA)) + return false; + } + return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, 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 MCSymbol &S) const { + const auto &Sym = cast<MCSymbolELF>(S); + if (::isWeak(Sym)) + 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 (Sym.getBinding() != ELF::STB_GLOBAL) + return false; + + if (!Sym.isInSection()) return false; - return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( - Asm, DataA, FB,InSet, IsPCRel); + + 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); } |