X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FELFObjectWriter.cpp;h=e6552beefd01bea53398306e9711ffc4b7698c22;hb=d2b0d84d0fd44db1eaaa30fcd6d7e5af4cb062a0;hp=670e06e22c808e2c95da3dc9e57e3cec5e3aa0e4;hpb=9e6378de5744088759f92a7503c7ca81d815c05d;p=oota-llvm.git diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 670e06e22c8..e6552beefd0 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/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" @@ -34,6 +33,7 @@ #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/StringSaver.h" #include using namespace llvm; @@ -71,23 +71,20 @@ public: class ELFObjectWriter : public MCObjectWriter { 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); /// 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) @@ -101,28 +98,21 @@ class ELFObjectWriter : public MCObjectWriter { /// The target specific ELF writer instance. std::unique_ptr TargetObjectWriter; - SmallPtrSet UsedInReloc; - SmallPtrSet WeakrefUsedInReloc; - DenseMap Renames; + DenseMap Renames; llvm::DenseMap> Relocations; - StringTableBuilder ShStrTabBuilder; /// @} /// @name Symbol Table Data /// @{ - StringTableBuilder StrTabBuilder; - std::vector FileSymbolData; - std::vector LocalSymbolData; - std::vector ExternalSymbolData; - std::vector UndefinedSymbolData; + BumpPtrAllocator Alloc; + StringSaver VersionSymSaver{Alloc}; + StringTableBuilder StrTabBuilder{StringTableBuilder::ELF}; /// @} - bool NeedsGOT; - // This holds the symbol table index of the last local symbol. unsigned LastLocalSymbolIndex; // This holds the .strtab section index. @@ -130,8 +120,6 @@ class ELFObjectWriter : public MCObjectWriter { // This holds the .symtab section index. unsigned SymbolTableIndex; - unsigned ShstrtabIndex; - // Sections in the order they are to be output in the section table. std::vector SectionTable; unsigned addToSectionTable(const MCSectionELF *Sec); @@ -146,24 +134,17 @@ class ELFObjectWriter : public MCObjectWriter { return TargetObjectWriter->GetRelocType(Target, Fixup, IsPCRel); } + void align(unsigned Alignment); + public: ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS, bool IsLittleEndian) - : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW), - NeedsGOT(false) {} + : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} void reset() override { - UsedInReloc.clear(); - WeakrefUsedInReloc.clear(); Renames.clear(); Relocations.clear(); - ShStrTabBuilder.clear(); StrTabBuilder.clear(); - FileSymbolData.clear(); - LocalSymbolData.clear(); - ExternalSymbolData.clear(); - UndefinedSymbolData.clear(); - NeedsGOT = false; SectionTable.clear(); MCObjectWriter::reset(); } @@ -172,43 +153,37 @@ class ELFObjectWriter : public MCObjectWriter { void WriteWord(uint64_t W) { if (is64Bit()) - Write64(W); + write64(W); else - Write32(W); + write32(W); } template void write(T Val) { if (IsLittleEndian) - support::endian::Writer(OS).write(Val); + support::endian::Writer(getStream()).write(Val); else - support::endian::Writer(OS).write(Val); + support::endian::Writer(getStream()).write(Val); } 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); // Start and end offset of each section typedef std::map> SectionOffsetsTy; - void WriteSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, - SectionOffsetsTy &SectionOffsets); - 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(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 signature symbol to the group section index typedef DenseMap RevGroupMapTy; @@ -219,22 +194,22 @@ class ELFObjectWriter : public MCObjectWriter { /// \param RevGroupMap - Maps a signature symbol to the group section. void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, - const RevGroupMapTy &RevGroupMap); + const RevGroupMapTy &RevGroupMap, + SectionOffsetsTy &SectionOffsets); - const MCSectionELF *createRelocationSection(MCAssembler &Asm, - const MCSectionELF &Sec); + MCSectionELF *createRelocationSection(MCContext &Ctx, + const MCSectionELF &Sec); - const MCSectionELF *createSectionHeaderStringTable(); const MCSectionELF *createStringTable(MCContext &Ctx); - void ExecutePostLayoutBinding(MCAssembler &Asm, + void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; - void writeSectionHeader(MCAssembler &Asm, const MCAsmLayout &Layout, + void writeSectionHeader(const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, const SectionOffsetsTy &SectionOffsets); - void writeSectionData(const MCAssembler &Asm, const MCSectionData &SD, + void writeSectionData(const MCAssembler &Asm, MCSection &Sec, const MCAsmLayout &Layout); void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, @@ -244,26 +219,29 @@ class ELFObjectWriter : public MCObjectWriter { void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec); - bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB, bool InSet, bool IsPCRel) const override; - bool isWeak(const MCSymbolData &SD) const override; + bool isWeak(const MCSymbol &Sym) 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); }; } +void ELFObjectWriter::align(unsigned Alignment) { + uint64_t Padding = OffsetToAlignment(getStream().tell(), Alignment); + WriteZeros(Padding); +} + unsigned ELFObjectWriter::addToSectionTable(const MCSectionELF *Sec) { SectionTable.push_back(Sec); - ShStrTabBuilder.add(Sec->getSectionName()); + StrTabBuilder.add(Sec->getSectionName()); return SectionTable.size(); } @@ -324,27 +302,6 @@ 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() {} @@ -358,80 +315,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. - WriteBytes(ELF::ElfMagic); // e_ident[EI_MAG0] to 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(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 - Write16(0); + write16(0); // e_shstrndx = Section # of '.shstrtab' - assert(ShstrtabIndex < ELF::SHN_LORESERVE); - 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 (const MCSymbol &Alias : Asm.symbols()) { - MCSymbolData &OriginalData = Alias.getData(); - + for (const MCSymbol &A : Asm.symbols()) { + const auto &Alias = cast(A); // Not an alias. if (!Alias.isVariable()) continue; auto *Ref = dyn_cast(Alias.getVariableValue()); if (!Ref) continue; - const MCSymbol &Symbol = Ref->getSymbol(); - MCSymbolData &SD = Asm.getSymbolData(Symbol); + const auto &Symbol = cast(Ref->getSymbol()); StringRef AliasName = Alias.getName(); size_t Pos = AliasName.find('@'); @@ -440,8 +395,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("@@@")) @@ -491,41 +446,36 @@ 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())) && - "The symbol's section doesn't match the fragment's symbol"); - const MCSymbol *Base = Layout.getBaseSymbol(OrigData.getSymbol()); + const auto &Symbol = cast(*MSD.Symbol); + const MCSymbolELF *Base = + cast_or_null(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; @@ -535,88 +485,8 @@ void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, } // Write out the symbol table entry - Writer.writeSymbol(MSD.StringIndex, Info, Value, Size, Other, - MSD.SectionIndex, IsReserved); -} - -void ELFObjectWriter::WriteSymbolTable(MCAssembler &Asm, - const MCAsmLayout &Layout, - 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 = addToSectionTable(SymtabSection); - - // The string table must be emitted first because we need the index - // into the string table for all the symbol names. - - SymbolTableWriter Writer(*this, is64Bit()); - - uint64_t Padding = OffsetToAlignment(OS.tell(), SymtabSD.getAlignment()); - WriteZeros(Padding); - - uint64_t SecStart = OS.tell(); - - // 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++; - } - - uint64_t SecEnd = OS.tell(); - SectionOffsets[SymtabSection] = 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, ""); - addToSectionTable(SymtabShndxSection); - MCSectionData *SymtabShndxSD = - &Asm.getOrCreateSectionData(*SymtabShndxSection); - SymtabShndxSD->setAlignment(4); - for (uint32_t Index : ShndxIndexes) - write(Index); - SecEnd = OS.tell(); - SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd); + Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex, + IsReserved); } // It is always valid to create a relocation with a symbol. It is preferable @@ -624,9 +494,9 @@ void ELFObjectWriter::WriteSymbolTable(MCAssembler &Asm, // 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(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) @@ -661,11 +531,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"); @@ -689,7 +559,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(Sym.getSection()); + auto &Sec = cast(Sym->getSection()); unsigned Flags = Sec.getFlags(); if (Flags & ELF::SHF_MERGE) { if (C != 0) @@ -712,41 +582,22 @@ 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(Expr); - if (!Inner) - return nullptr; - - if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) - return &Inner->getSymbol(); - return nullptr; -} - // True if the assembler knows nothing about the final value of the symbol. // This doesn't cover the comdat issues, since in those cases the assembler // can at least know that all symbols in the section will move together. -static bool isWeak(const MCSymbolData &D) { - if (MCELF::GetType(D) == ELF::STT_GNU_IFUNC) +static bool isWeak(const MCSymbolELF &Sym) { + if (Sym.getType() == ELF::STT_GNU_IFUNC) return true; - switch (MCELF::GetBinding(D)) { + switch (Sym.getBinding()) { default: llvm_unreachable("Unknown binding"); case ELF::STB_LOCAL: @@ -759,14 +610,12 @@ static bool isWeak(const MCSymbolData &D) { } } -void ELFObjectWriter::RecordRelocation(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 *FixupSectionD = Fragment->getParent(); - const MCSectionELF &FixupSection = - cast(FixupSectionD->getSection()); + const MCSectionELF &FixupSection = cast(*Fragment->getParent()); uint64_t C = Target.getConstant(); uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); @@ -781,31 +630,38 @@ void ELFObjectWriter::RecordRelocation(MCAssembler &Asm, // In general, ELF has no relocations for -B. It can only represent (A + C) // 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( + if (IsPCRel) { + Asm.getContext().reportError( Fixup.getLoc(), "No relocation available to represent this relative expression"); + return; + } - const MCSymbol &SymB = RefB->getSymbol(); + const auto &SymB = cast(RefB->getSymbol()); - if (SymB.isUndefined()) - Asm.getContext().FatalError( + if (SymB.isUndefined()) { + Asm.getContext().reportError( Fixup.getLoc(), Twine("symbol '") + SymB.getName() + "' can not be undefined in a subtraction expression"); + return; + } assert(!SymB.isAbsolute() && "Should have been folded"); const MCSection &SecB = SymB.getSection(); - if (&SecB != &FixupSection) - Asm.getContext().FatalError( + if (&SecB != &FixupSection) { + Asm.getContext().reportError( Fixup.getLoc(), "Cannot represent a difference across sections"); + return; + } - const MCSymbolData &SymBD = Asm.getSymbolData(SymB); - if (::isWeak(SymBD)) - Asm.getContext().FatalError( + if (::isWeak(SymB)) { + Asm.getContext().reportError( Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol"); + return; + } - uint64_t SymBOffset = Layout.getSymbolOffset(&SymBD); + uint64_t SymBOffset = Layout.getSymbolOffset(SymB); uint64_t K = SymBOffset - FixupOffset; IsPCRel = true; C -= K; @@ -813,13 +669,23 @@ void ELFObjectWriter::RecordRelocation(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(&RefA->getSymbol()) : nullptr; + + bool ViaWeakRef = false; + if (SymA && SymA->isVariable()) { + const MCExpr *Expr = SymA->getVariableValue(); + if (const auto *Inner = dyn_cast(Expr)) { + if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) { + SymA = cast(&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()) { @@ -829,50 +695,36 @@ void ELFObjectWriter::RecordRelocation(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(SecA); - MCSymbol *SectionSymbol = - ELFSec ? Asm.getContext().getOrCreateSectionSymbol(*ELFSec) - : nullptr; + const auto *SectionSymbol = + ELFSec ? cast(ELFSec->getBeginSymbol()) : nullptr; + if (SectionSymbol) + SectionSymbol->setUsedInReloc(); ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend); 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); 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(Expr)) { @@ -887,34 +739,19 @@ 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; @@ -922,62 +759,70 @@ bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isUsedInReloc) { 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) { - 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); - } + const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap, + SectionOffsetsTy &SectionOffsets) { + MCContext &Ctx = Asm.getContext(); + SymbolTableWriter Writer(*this, is64Bit()); - // Add the data for the symbols. - for (const MCSymbol &Symbol : Asm.symbols()) { - MCSymbolData &SD = Symbol.getData(); + // 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); + + align(SymtabSection->getAlignment()); + uint64_t SecStart = getStream().tell(); + + // 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 LocalSymbolData; + std::vector 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(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); + if (Symbol.isTemporary() && Symbol.isUndefined()) { + Ctx.reportError(SMLoc(), "Undefined temporary symbol"); + continue; } - if (!BaseSymbol) { + ELFSymbolData MSD; + MSD.Symbol = cast(&Symbol); + + bool Local = Symbol.getBinding() == ELF::STB_LOCAL; + assert(Local || !Symbol.isTemporary()); + + 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) + } else if (Symbol.isUndefined()) { + if (isSignature && !Used) { MSD.SectionIndex = RevGroupMap.lookup(&Symbol); - else + 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(BaseSymbol->getSection()); + static_cast(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 @@ @@ -1004,74 +849,105 @@ void ELFObjectWriter::computeSymbolTable( // seems that this information is not easily accessible from the // ELFObjectWriter. StringRef Name = Symbol.getName(); + SmallString<32> 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; + Name = VersionSymSaver.save(Buf.c_str()); } } // Sections have their own string table - if (MCELF::GetType(SD) != ELF::STT_SECTION) - MSD.Name = StrTabBuilder.add(Name); + if (Symbol.getType() != ELF::STT_SECTION) { + MSD.Name = 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); + // This holds the .symtab_shndx section index. + unsigned SymtabShndxSectionIndex = 0; + + 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 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(); - 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); + } + + // Write the symbol table entries. + LastLocalSymbolIndex = Index; + + 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); + } + + uint64_t SecEnd = getStream().tell(); + SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd); + + ArrayRef ShndxIndexes = Writer.getShndxIndexes(); + if (ShndxIndexes.empty()) { + assert(SymtabShndxSectionIndex == 0); + return; + } + assert(SymtabShndxSectionIndex != 0); + + SecStart = getStream().tell(); + const MCSectionELF *SymtabShndxSection = + SectionTable[SymtabShndxSectionIndex - 1]; + for (uint32_t Index : ShndxIndexes) + write(Index); + SecEnd = getStream().tell(); + SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd); } -const MCSectionELF * -ELFObjectWriter::createRelocationSection(MCAssembler &Asm, +MCSectionELF * +ELFObjectWriter::createRelocationSection(MCContext &Ctx, const MCSectionELF &Sec) { if (Relocations[&Sec].empty()) return nullptr; - MCContext &Ctx = Asm.getContext(); const StringRef SectionName = Sec.getSectionName(); std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel"; RelaSectionName += SectionName; @@ -1086,39 +962,13 @@ ELFObjectWriter::createRelocationSection(MCAssembler &Asm, if (Sec.getFlags() & ELF::SHF_GROUP) Flags = ELF::SHF_GROUP; - const MCSectionELF *RelaSection = Ctx.createELFRelSection( + MCSectionELF *RelaSection = Ctx.createELFRelSection( RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL, Flags, EntrySize, Sec.getGroup(), &Sec); - MCSectionData &RelSD = Asm.getOrCreateSectionData(*RelaSection); - RelSD.setAlignment(is64Bit() ? 8 : 4); + RelaSection->setAlignment(is64Bit() ? 8 : 4); return RelaSection; } -static SmallVector -getUncompressedData(const MCAsmLayout &Layout, - const MCSectionData::FragmentListType &Fragments) { - SmallVector UncompressedData; - for (const MCFragment &F : Fragments) { - const SmallVectorImpl *Contents; - switch (F.getKind()) { - case MCFragment::FT_Data: - Contents = &cast(F).getContents(); - break; - case MCFragment::FT_Dwarf: - Contents = &cast(F).getContents(); - break; - case MCFragment::FT_DwarfFrame: - Contents = &cast(F).getContents(); - break; - default: - llvm_unreachable( - "Not expecting any other fragment types in a debug_* section"); - } - UncompressedData.append(Contents->begin(), Contents->end()); - } - return UncompressedData; -} - // Include the debug info compression header: // "ZLIB" followed by 8 bytes representing the uncompressed size of the section, // useful for consumers to preallocate a buffer to decompress into. @@ -1139,11 +989,9 @@ prependCompressionHeader(uint64_t Size, return true; } -void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, - const MCSectionData &SD, +void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, const MCAsmLayout &Layout) { - const MCSectionELF &Section = - static_cast(SD.getSection()); + MCSectionELF &Section = static_cast(Sec); StringRef SectionName = Section.getSectionName(); // Compressing debug_frame requires handling alignment fragments which is @@ -1151,31 +999,33 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, // for writing to arbitrary buffers) for little benefit. if (!Asm.getContext().getAsmInfo()->compressDebugSections() || !SectionName.startswith(".debug_") || SectionName == ".debug_frame") { - Asm.writeSectionData(&SD, Layout); + Asm.writeSectionData(&Section, Layout); return; } - // Gather the uncompressed data from all the fragments. - const MCSectionData::FragmentListType &Fragments = SD.getFragmentList(); - SmallVector UncompressedData = - getUncompressedData(Layout, Fragments); + SmallVector UncompressedData; + raw_svector_ostream VecOS(UncompressedData); + raw_pwrite_stream &OldStream = getStream(); + setStream(VecOS); + Asm.writeSectionData(&Section, Layout); + setStream(OldStream); SmallVector CompressedContents; zlib::Status Success = zlib::compress( StringRef(UncompressedData.data(), UncompressedData.size()), CompressedContents); if (Success != zlib::StatusOK) { - Asm.writeSectionData(&SD, Layout); + getStream() << UncompressedData; return; } if (!prependCompressionHeader(UncompressedData.size(), CompressedContents)) { - Asm.writeSectionData(&SD, Layout); + getStream() << UncompressedData; return; } Asm.getContext().renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str()); - OS << CompressedContents; + getStream() << CompressedContents; } void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, @@ -1184,14 +1034,14 @@ 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 } @@ -1200,14 +1050,18 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec) { std::vector &Relocs = Relocations[&Sec]; - // Sort the relocation entries. Most targets just sort by Offset, but some - // (e.g., MIPS) have additional constraints. + // We record relocations by pushing to the end of a vector. Reverse the vector + // to get the relocations in the order they were created. + // In most cases that is not important, but it can be for special sections + // (.eh_frame) or specific relocations (TLS optimizations on SystemZ). + std::reverse(Relocs.begin(), Relocs.end()); + + // Sort the relocation entries. MIPS needs this. 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(Entry.Offset); @@ -1238,27 +1092,15 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm, } } -const MCSectionELF *ELFObjectWriter::createSectionHeaderStringTable() { - const MCSectionELF *ShstrtabSection = SectionTable[ShstrtabIndex - 1]; - ShStrTabBuilder.finalize(StringTableBuilder::ELF); - OS << ShStrTabBuilder.data(); - return ShstrtabSection; -} - const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) { - const MCSectionELF *StrtabSection = - Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0); - StringTableIndex = addToSectionTable(StrtabSection); - OS << StrTabBuilder.data(); + const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1]; + getStream() << 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; @@ -1299,15 +1141,14 @@ void ELFObjectWriter::writeSection(MCAssembler &Asm, Section.getType() == ELF::SHT_ARM_EXIDX) sh_link = SectionIndexMap.lookup(Section.getAssociatedSection()); - WriteSecHdrEntry(ShStrTabBuilder.getOffset(Section.getSectionName()), - Section.getType(), - Section.getFlags(), 0, Offset, Size, sh_link, sh_info, - Alignment, Section.getEntrySize()); + 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 MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, + const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, const SectionOffsetsTy &SectionOffsets) { const unsigned NumSections = SectionTable.size(); @@ -1317,30 +1158,32 @@ void ELFObjectWriter::writeSectionHeader( WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0); for (const MCSectionELF *Section : SectionTable) { - const MCSectionData &SD = Asm.getOrCreateSectionData(*Section); uint32_t GroupSymbolIndex; unsigned Type = Section->getType(); if (Type != ELF::SHT_GROUP) GroupSymbolIndex = 0; else - GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, Section->getGroup()); + GroupSymbolIndex = Section->getGroup()->getIndex(); const std::pair &Offsets = SectionOffsets.find(Section)->second; - uint64_t Size = Type == ELF::SHT_NOBITS ? Layout.getSectionAddressSize(&SD) - : Offsets.second - Offsets.first; + uint64_t Size; + if (Type == ELF::SHT_NOBITS) + Size = Layout.getSectionAddressSize(Section); + else + Size = Offsets.second - Offsets.first; - writeSection(Asm, SectionIndexMap, GroupSymbolIndex, Offsets.first, Size, - SD.getAlignment(), *Section); + writeSection(SectionIndexMap, GroupSymbolIndex, Offsets.first, Size, + *Section); } } -void ELFObjectWriter::WriteObject(MCAssembler &Asm, +void ELFObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { MCContext &Ctx = Asm.getContext(); - const MCSectionELF *ShstrtabSection = - Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0); - ShstrtabIndex = addToSectionTable(ShstrtabSection); + MCSectionELF *StrtabSection = + Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0); + StringTableIndex = addToSectionTable(StrtabSection); RevGroupMapTy RevGroupMap; SectionIndexMapTy SectionIndexMap; @@ -1352,94 +1195,94 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, // ... then the sections ... SectionOffsetsTy SectionOffsets; - bool ComputedSymtab = false; - for (const MCSectionData &SD : Asm) { - const MCSectionELF &Section = - static_cast(SD.getSection()); + std::vector Groups; + std::vector Relocations; + for (MCSection &Sec : Asm) { + MCSectionELF &Section = static_cast(Sec); - uint64_t Padding = OffsetToAlignment(OS.tell(), SD.getAlignment()); - WriteZeros(Padding); + align(Section.getAlignment()); // Remember the offset into the file for this section. - uint64_t SecStart = OS.tell(); - - const MCSymbol *SignatureSymbol = Section.getGroup(); - unsigned Type = Section.getType(); - if (Type == ELF::SHT_GROUP) { - assert(SignatureSymbol); - write(uint32_t(ELF::GRP_COMDAT)); - for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) { - uint32_t SecIndex = SectionIndexMap.lookup(Member); - write(SecIndex); - } - } else if (Type == ELF::SHT_REL || Type == ELF::SHT_RELA) { - if (!ComputedSymtab) { - // Compute symbol table information. - computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap); - ComputedSymtab = true; - } - writeRelocations(Asm, *Section.getAssociatedSection()); - } else { - writeSectionData(Asm, SD, Layout); - } + uint64_t SecStart = getStream().tell(); - uint64_t SecEnd = OS.tell(); - SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd); + const MCSymbolELF *SignatureSymbol = Section.getGroup(); + writeSectionData(Asm, Section, Layout); - if (Type == ELF::SHT_GROUP || Type == ELF::SHT_REL || Type == ELF::SHT_RELA) - continue; + uint64_t SecEnd = getStream().tell(); + SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd); - const MCSectionELF *RelSection = createRelocationSection(Asm, Section); + MCSectionELF *RelSection = createRelocationSection(Ctx, Section); if (SignatureSymbol) { - Asm.getOrCreateSymbolData(*SignatureSymbol); + Asm.registerSymbol(*SignatureSymbol); unsigned &GroupIdx = RevGroupMap[SignatureSymbol]; if (!GroupIdx) { - const MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol); + MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol); GroupIdx = addToSectionTable(Group); - MCSectionData *GroupD = &Asm.getOrCreateSectionData(*Group); - GroupD->setAlignment(4); + Group->setAlignment(4); + Groups.push_back(Group); } - GroupMembers[SignatureSymbol].push_back(&Section); + std::vector &Members = + GroupMembers[SignatureSymbol]; + Members.push_back(&Section); if (RelSection) - GroupMembers[SignatureSymbol].push_back(RelSection); + Members.push_back(RelSection); } SectionIndexMap[&Section] = addToSectionTable(&Section); - if (RelSection) + if (RelSection) { SectionIndexMap[RelSection] = addToSectionTable(RelSection); + Relocations.push_back(RelSection); + } } - if (!ComputedSymtab) { - // Compute symbol table information. - computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap); - ComputedSymtab = true; + for (MCSectionELF *Group : Groups) { + align(Group->getAlignment()); + + // Remember the offset into the file for this section. + uint64_t SecStart = getStream().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); + } + + uint64_t SecEnd = getStream().tell(); + SectionOffsets[Group] = std::make_pair(SecStart, SecEnd); } - WriteSymbolTable(Asm, Layout, SectionOffsets); + // Compute symbol table information. + computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets); - { - uint64_t SecStart = OS.tell(); - const MCSectionELF *Sec = createStringTable(Ctx); - uint64_t SecEnd = OS.tell(); - SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd); + for (MCSectionELF *RelSection : Relocations) { + align(RelSection->getAlignment()); + + // Remember the offset into the file for this section. + uint64_t SecStart = getStream().tell(); + + writeRelocations(Asm, *RelSection->getAssociatedSection()); + + uint64_t SecEnd = getStream().tell(); + SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd); } { - uint64_t SecStart = OS.tell(); - const MCSectionELF *Sec = createSectionHeaderStringTable(); - uint64_t SecEnd = OS.tell(); + uint64_t SecStart = getStream().tell(); + const MCSectionELF *Sec = createStringTable(Ctx); + uint64_t SecEnd = getStream().tell(); SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd); } uint64_t NaturalAlignment = is64Bit() ? 8 : 4; - uint64_t Padding = OffsetToAlignment(OS.tell(), NaturalAlignment); - WriteZeros(Padding); + align(NaturalAlignment); - const unsigned SectionHeaderOffset = OS.tell(); + const unsigned SectionHeaderOffset = getStream().tell(); // ... then the section header table ... - writeSectionHeader(Asm, Layout, SectionIndexMap, SectionOffsets); + writeSectionHeader(Layout, SectionIndexMap, SectionOffsets); uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE) ? (uint16_t)ELF::SHN_UNDEF @@ -1452,35 +1295,37 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, uint64_t Val = SectionHeaderOffset; if (sys::IsLittleEndianHost != IsLittleEndian) sys::swapByteOrder(Val); - OS.pwrite(reinterpret_cast(&Val), sizeof(Val), - offsetof(ELF::Elf64_Ehdr, e_shoff)); + getStream().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)); + getStream().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); + getStream().pwrite(reinterpret_cast(&NumSections), + sizeof(NumSections), NumSectionsOffset); } -bool ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( - const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB, +bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( + const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB, bool InSet, bool IsPCRel) const { + const auto &SymA = cast(SA); if (IsPCRel) { assert(!InSet); - if (::isWeak(SymA.getData())) + if (::isWeak(SymA)) return false; } - return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB, + return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB, InSet, IsPCRel); } -bool ELFObjectWriter::isWeak(const MCSymbolData &SD) const { - if (::isWeak(SD)) +bool ELFObjectWriter::isWeak(const MCSymbol &S) const { + const auto &Sym = cast(S); + if (::isWeak(Sym)) return true; // It is invalid to replace a reference to a global in a comdat @@ -1489,10 +1334,9 @@ bool ELFObjectWriter::isWeak(const MCSymbolData &SD) const { // 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) + if (Sym.getBinding() != ELF::STB_GLOBAL) return false; - const MCSymbol &Sym = SD.getSymbol(); if (!Sym.isInSection()) return false;