X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FELFObjectWriter.cpp;h=e6552beefd01bea53398306e9711ffc4b7698c22;hb=d2b0d84d0fd44db1eaaa30fcd6d7e5af4cb062a0;hp=234c350d9dc9e54fc049d2ac0effc644f295c6d6;hpb=7081f6fc99a596eccd26b8b629e3af2e8e7ca25e;p=oota-llvm.git diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 234c350d9dc..e6552beefd0 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -33,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; @@ -106,7 +107,9 @@ class ELFObjectWriter : public MCObjectWriter { /// @name Symbol Table Data /// @{ - StringTableBuilder StrTabBuilder; + BumpPtrAllocator Alloc; + StringSaver VersionSymSaver{Alloc}; + StringTableBuilder StrTabBuilder{StringTableBuilder::ELF}; /// @} @@ -116,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; @@ -159,9 +160,9 @@ class ELFObjectWriter : public MCObjectWriter { 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); @@ -231,10 +232,10 @@ class ELFObjectWriter : public MCObjectWriter { uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size, const MCSectionELF &Section); }; -} // namespace +} void ELFObjectWriter::align(unsigned Alignment) { - uint64_t Padding = OffsetToAlignment(OS.tell(), Alignment); + uint64_t Padding = OffsetToAlignment(getStream().tell(), Alignment); WriteZeros(Padding); } @@ -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)); @@ -632,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; @@ -766,7 +772,7 @@ void ELFObjectWriter::computeSymbolTable( SymbolTableIndex = addToSectionTable(SymtabSection); align(SymtabSection->getAlignment()); - uint64_t SecStart = OS.tell(); + uint64_t SecStart = getStream().tell(); // The first entry is the undefined symbol entry. Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); @@ -786,10 +792,17 @@ void ELFObjectWriter::computeSymbolTable( Renames.count(&Symbol))) continue; + if (Symbol.isTemporary() && Symbol.isUndefined()) { + Ctx.reportError(SMLoc(), "Undefined temporary symbol"); + continue; + } + 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 (Symbol.isCommon()) { @@ -836,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); @@ -861,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, ""); @@ -872,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), @@ -905,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(); @@ -915,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); } @@ -951,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. @@ -1010,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, @@ -1055,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) { @@ -1094,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; } @@ -1203,12 +1203,12 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm, align(Section.getAlignment()); // Remember the offset into the file for this section. - uint64_t SecStart = OS.tell(); + uint64_t SecStart = getStream().tell(); 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); @@ -1240,7 +1240,7 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm, 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); @@ -1250,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); } @@ -1261,25 +1261,25 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm, 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; align(NaturalAlignment); - const unsigned SectionHeaderOffset = OS.tell(); + const unsigned SectionHeaderOffset = getStream().tell(); // ... then the section header table ... writeSectionHeader(Layout, SectionIndexMap, SectionOffsets); @@ -1295,19 +1295,19 @@ 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(