X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FELFObjectWriter.cpp;h=e6552beefd01bea53398306e9711ffc4b7698c22;hb=d2b0d84d0fd44db1eaaa30fcd6d7e5af4cb062a0;hp=7d15f17684efa8897c6b920a83decdc9294c3e87;hpb=569f382a463eb5cf279fd972aa9f2fcbc1b6c07d;p=oota-llvm.git diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 7d15f17684e..e6552beefd0 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -21,7 +21,6 @@ #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCObjectWriter.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; @@ -74,8 +74,6 @@ class ELFObjectWriter : public MCObjectWriter { 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 MCSymbol &Symbol, bool IsUsedInReloc, - bool IsSignature); /// Helper struct for containing some precomputed information on symbols. struct ELFSymbolData { @@ -100,8 +98,6 @@ class ELFObjectWriter : public MCObjectWriter { /// The target specific ELF writer instance. std::unique_ptr TargetObjectWriter; - SmallPtrSet UsedInReloc; - SmallPtrSet WeakrefUsedInReloc; DenseMap Renames; llvm::DenseMap> @@ -111,7 +107,9 @@ class ELFObjectWriter : public MCObjectWriter { /// @name Symbol Table Data /// @{ - StringTableBuilder StrTabBuilder; + BumpPtrAllocator Alloc; + StringSaver VersionSymSaver{Alloc}; + StringTableBuilder StrTabBuilder{StringTableBuilder::ELF}; /// @} @@ -121,8 +119,6 @@ class ELFObjectWriter : public MCObjectWriter { unsigned StringTableIndex; // This holds the .symtab section index. unsigned SymbolTableIndex; - // This holds the .symtab_shndx section index. - unsigned SymtabShndxSectionIndex = 0; // Sections in the order they are to be output in the section table. std::vector SectionTable; @@ -138,14 +134,14 @@ 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) {} void reset() override { - UsedInReloc.clear(); - WeakrefUsedInReloc.clear(); Renames.clear(); Relocations.clear(); StrTabBuilder.clear(); @@ -157,16 +153,16 @@ 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); @@ -183,7 +179,7 @@ class ELFObjectWriter : public MCObjectWriter { 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; @@ -206,10 +202,10 @@ class ELFObjectWriter : public MCObjectWriter { const MCSectionELF *createStringTable(MCContext &Ctx); - void ExecutePostLayoutBinding(MCAssembler &Asm, + void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; - void writeSectionHeader(const MCAssembler &Asm, const MCAsmLayout &Layout, + void writeSectionHeader(const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, const SectionOffsetsTy &SectionOffsets); @@ -223,7 +219,7 @@ 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, @@ -231,13 +227,18 @@ class ELFObjectWriter : public MCObjectWriter { bool isWeak(const MCSymbol &Sym) const override; - void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; + 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); StrTabBuilder.add(Sec->getSectionName()); @@ -314,47 +315,47 @@ 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(StringTableIndex < ELF::SHN_LORESERVE); - Write16(StringTableIndex); + write16(StringTableIndex); } uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym, @@ -372,7 +373,7 @@ uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym, 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. @@ -449,9 +450,6 @@ void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex, ELFSymbolData &MSD, const MCAsmLayout &Layout) { const auto &Symbol = cast(*MSD.Symbol); - assert((!Symbol.getFragment() || - (Symbol.getFragment()->getParent() == &Symbol.getSection())) && - "The symbol's section doesn't match the fragment's symbol"); const MCSymbolELF *Base = cast_or_null(Layout.getBaseSymbol(Symbol)); @@ -465,13 +463,12 @@ void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer, if (Base) { 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 = Symbol.getVisibility(); - uint8_t Other = Symbol.getOther() << (ELF_STO_Shift - ELF_STV_Shift); - Other |= Visibility; + uint8_t Other = Symbol.getOther() | Visibility; uint64_t Value = SymbolValue(*MSD.Symbol, Layout); uint64_t Size = 0; @@ -593,25 +590,6 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, 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. @@ -632,7 +610,7 @@ static bool isWeak(const MCSymbolELF &Sym) { } } -void ELFObjectWriter::RecordRelocation(MCAssembler &Asm, +void ELFObjectWriter::recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, @@ -652,28 +630,36 @@ 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().reportFatalError( + if (IsPCRel) { + Asm.getContext().reportError( Fixup.getLoc(), "No relocation available to represent this relative expression"); + return; + } const auto &SymB = cast(RefB->getSymbol()); - if (SymB.isUndefined()) - Asm.getContext().reportFatalError( + 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().reportFatalError( + if (&SecB != &FixupSection) { + Asm.getContext().reportError( Fixup.getLoc(), "Cannot represent a difference across sections"); + return; + } - if (::isWeak(SymB)) - Asm.getContext().reportFatalError( + if (::isWeak(SymB)) { + Asm.getContext().reportError( Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol"); + return; + } uint64_t SymBOffset = Layout.getSymbolOffset(SymB); uint64_t K = SymBOffset - FixupOffset; @@ -685,6 +671,17 @@ void ELFObjectWriter::RecordRelocation(MCAssembler &Asm, const MCSymbolRefExpr *RefA = Target.getSymA(); 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, SymA, C, Type); if (!RelocateWithSymbol && SymA && !SymA->isUndefined()) @@ -704,6 +701,8 @@ void ELFObjectWriter::RecordRelocation(MCAssembler &Asm, auto *ELFSec = cast_or_null(SecA); const auto *SectionSymbol = ELFSec ? cast(ELFSec->getBeginSymbol()) : nullptr; + if (SectionSymbol) + SectionSymbol->setUsedInReloc(); ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend); Relocations[&FixupSection].push_back(Rec); return; @@ -713,10 +712,10 @@ void ELFObjectWriter::RecordRelocation(MCAssembler &Asm, 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); @@ -740,40 +739,22 @@ 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 = Symbol.getBinding() == ELF::STB_GLOBAL; - if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal) + if (Symbol.isUndefined() && !Symbol.isBindingSet()) return false; - if (Symbol.getType() == ELF::STT_SECTION) - return true; - if (Symbol.isTemporary()) return false; - return true; -} - -bool ELFObjectWriter::isLocal(const MCSymbol &Symbol, bool IsUsedInReloc, - bool IsSignature) { - if (Symbol.isExternal()) - return false; - - if (Symbol.isDefined()) - return true; - - if (IsUsedInReloc) + if (Symbol.getType() == ELF::STT_SECTION) return false; - return IsSignature; + return true; } void ELFObjectWriter::computeSymbolTable( @@ -790,11 +771,8 @@ void ELFObjectWriter::computeSymbolTable( SymtabSection->setAlignment(is64Bit() ? 8 : 4); SymbolTableIndex = addToSectionTable(SymtabSection); - uint64_t Padding = - OffsetToAlignment(OS.tell(), SymtabSection->getAlignment()); - WriteZeros(Padding); - - uint64_t SecStart = OS.tell(); + 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); @@ -806,22 +784,24 @@ void ELFObjectWriter::computeSymbolTable( bool HasLargeSectionIndex = false; for (const MCSymbol &S : Asm.symbols()) { const auto &Symbol = cast(S); - bool Used = UsedInReloc.count(&Symbol); - bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol); - bool isSignature = RevGroupMap.count(&Symbol); + bool Used = Symbol.isUsedInReloc(); + bool WeakrefUsed = Symbol.isWeakrefUsedInReloc(); + bool isSignature = Symbol.isSignature(); if (!isInSymtab(Layout, Symbol, Used || WeakrefUsed || isSignature, Renames.count(&Symbol))) continue; + if (Symbol.isTemporary() && Symbol.isUndefined()) { + Ctx.reportError(SMLoc(), "Undefined temporary symbol"); + continue; + } + ELFSymbolData MSD; MSD.Symbol = cast(&Symbol); - // Undefined symbols are global, but this is the first place we - // are able to set it. - bool Local = isLocal(Symbol, Used, isSignature); - if (!Local && Symbol.getBinding() == ELF::STB_LOCAL) - Symbol.setBinding(ELF::STB_GLOBAL); + bool Local = Symbol.getBinding() == ELF::STB_LOCAL; + assert(Local || !Symbol.isTemporary()); if (Symbol.isAbsolute()) { MSD.SectionIndex = ELF::SHN_ABS; @@ -836,8 +816,6 @@ void ELFObjectWriter::computeSymbolTable( } else { MSD.SectionIndex = ELF::SHN_UNDEF; } - if (!Used && WeakrefUsed) - Symbol.setBinding(ELF::STB_WEAK); } else { const MCSectionELF &Section = static_cast(Symbol.getSection()); @@ -871,24 +849,26 @@ 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 (Symbol.getType() != ELF::STT_SECTION) - MSD.Name = StrTabBuilder.add(Name); + if (Symbol.getType() != ELF::STT_SECTION) { + MSD.Name = Name; + StrTabBuilder.add(Name); + } if (Local) LocalSymbolData.push_back(MSD); @@ -896,6 +876,9 @@ void ELFObjectWriter::computeSymbolTable( ExternalSymbolData.push_back(MSD); } + // This holds the .symtab_shndx section index. + unsigned SymtabShndxSectionIndex = 0; + if (HasLargeSectionIndex) { MCSectionELF *SymtabShndxSection = Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, ""); @@ -907,7 +890,7 @@ void ELFObjectWriter::computeSymbolTable( for (const std::string &Name : FileNames) StrTabBuilder.add(Name); - StrTabBuilder.finalize(StringTableBuilder::ELF); + StrTabBuilder.finalize(); for (const std::string &Name : FileNames) Writer.writeSymbol(StrTabBuilder.getOffset(Name), @@ -940,7 +923,7 @@ void ELFObjectWriter::computeSymbolTable( assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL); } - uint64_t SecEnd = OS.tell(); + uint64_t SecEnd = getStream().tell(); SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd); ArrayRef ShndxIndexes = Writer.getShndxIndexes(); @@ -950,12 +933,12 @@ void ELFObjectWriter::computeSymbolTable( } assert(SymtabShndxSectionIndex != 0); - SecStart = OS.tell(); + SecStart = getStream().tell(); const MCSectionELF *SymtabShndxSection = SectionTable[SymtabShndxSectionIndex - 1]; for (uint32_t Index : ShndxIndexes) write(Index); - SecEnd = OS.tell(); + SecEnd = getStream().tell(); SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd); } @@ -986,31 +969,6 @@ ELFObjectWriter::createRelocationSection(MCContext &Ctx, return RelaSection; } -static SmallVector -getUncompressedData(const MCAsmLayout &Layout, - const MCSection::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. @@ -1045,27 +1003,29 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, return; } - // Gather the uncompressed data from all the fragments. - const MCSection::FragmentListType &Fragments = Section.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(&Section, Layout); + getStream() << UncompressedData; return; } if (!prependCompressionHeader(UncompressedData.size(), CompressedContents)) { - Asm.writeSectionData(&Section, 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, @@ -1074,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 } @@ -1090,8 +1050,13 @@ 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) { @@ -1129,7 +1094,7 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm, const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) { const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1]; - OS << StrTabBuilder.data(); + getStream() << StrTabBuilder.data(); return StrtabSection; } @@ -1183,8 +1148,7 @@ void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, } void ELFObjectWriter::writeSectionHeader( - const MCAssembler &Asm, const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, + const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, const SectionOffsetsTy &SectionOffsets) { const unsigned NumSections = SectionTable.size(); @@ -1214,7 +1178,7 @@ void ELFObjectWriter::writeSectionHeader( } } -void ELFObjectWriter::WriteObject(MCAssembler &Asm, +void ELFObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { MCContext &Ctx = Asm.getContext(); MCSectionELF *StrtabSection = @@ -1236,16 +1200,15 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, for (MCSection &Sec : Asm) { MCSectionELF &Section = static_cast(Sec); - uint64_t Padding = OffsetToAlignment(OS.tell(), Section.getAlignment()); - WriteZeros(Padding); + align(Section.getAlignment()); // Remember the offset into the file for this section. - uint64_t SecStart = OS.tell(); + uint64_t SecStart = getStream().tell(); - const MCSymbol *SignatureSymbol = Section.getGroup(); + const MCSymbolELF *SignatureSymbol = Section.getGroup(); writeSectionData(Asm, Section, Layout); - uint64_t SecEnd = OS.tell(); + uint64_t SecEnd = getStream().tell(); SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd); MCSectionELF *RelSection = createRelocationSection(Ctx, Section); @@ -1259,9 +1222,11 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, 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); @@ -1272,11 +1237,10 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, } for (MCSectionELF *Group : Groups) { - uint64_t Padding = OffsetToAlignment(OS.tell(), Group->getAlignment()); - WriteZeros(Padding); + align(Group->getAlignment()); // Remember the offset into the file for this section. - uint64_t SecStart = OS.tell(); + uint64_t SecStart = getStream().tell(); const MCSymbol *SignatureSymbol = Group->getGroup(); assert(SignatureSymbol); @@ -1286,7 +1250,7 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, write(SecIndex); } - uint64_t SecEnd = OS.tell(); + uint64_t SecEnd = getStream().tell(); SectionOffsets[Group] = std::make_pair(SecStart, SecEnd); } @@ -1294,33 +1258,31 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets); for (MCSectionELF *RelSection : Relocations) { - uint64_t Padding = OffsetToAlignment(OS.tell(), RelSection->getAlignment()); - WriteZeros(Padding); + align(RelSection->getAlignment()); // Remember the offset into the file for this section. - uint64_t SecStart = OS.tell(); + uint64_t SecStart = getStream().tell(); writeRelocations(Asm, *RelSection->getAssociatedSection()); - uint64_t SecEnd = OS.tell(); + uint64_t SecEnd = getStream().tell(); SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd); } { - uint64_t SecStart = OS.tell(); + uint64_t SecStart = getStream().tell(); const MCSectionELF *Sec = createStringTable(Ctx); - uint64_t SecEnd = OS.tell(); + 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 @@ -1333,22 +1295,22 @@ 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( +bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB, bool InSet, bool IsPCRel) const { const auto &SymA = cast(SA); @@ -1357,7 +1319,7 @@ bool ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( if (::isWeak(SymA)) return false; } - return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB, + return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB, InSet, IsPCRel); }