Date: Mon, 8 May 2017 17:13:44 +0000 (UTC) From: Dimitry Andric <dim@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r317957 - in vendor/lld/dist: . COFF ELF include/lld/Core include/lld/Support lib/Core test/ELF test/ELF/Inputs test/ELF/linkerscript test/ELF/linkerscript/Inputs test/ELF/lto test/ELF/... Message-ID: <201705081713.v48HDiRV043006@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dim Date: Mon May 8 17:13:44 2017 New Revision: 317957 URL: https://svnweb.freebsd.org/changeset/base/317957 Log: Vendor import of lld trunk r302418: https://llvm.org/svn/llvm-project/lld/trunk@302418 Added: vendor/lld/dist/include/lld/Core/TaskGroup.h (contents, props changed) vendor/lld/dist/lib/Core/TaskGroup.cpp (contents, props changed) vendor/lld/dist/test/ELF/Inputs/i386-static-tls-model1.s (contents, props changed) vendor/lld/dist/test/ELF/Inputs/i386-static-tls-model2.s (contents, props changed) vendor/lld/dist/test/ELF/Inputs/i386-static-tls-model3.s (contents, props changed) vendor/lld/dist/test/ELF/Inputs/i386-static-tls-model4.s (contents, props changed) vendor/lld/dist/test/ELF/i386-static-tls-model.s (contents, props changed) vendor/lld/dist/test/ELF/linkerscript/Inputs/compress-debug-sections.s (contents, props changed) vendor/lld/dist/test/ELF/linkerscript/compress-debug-sections.s (contents, props changed) vendor/lld/dist/test/ELF/lto/Inputs/duplicated-name.ll vendor/lld/dist/test/ELF/lto/duplicated-name.ll Deleted: vendor/lld/dist/include/lld/Support/ Modified: vendor/lld/dist/CMakeLists.txt vendor/lld/dist/COFF/Chunks.h vendor/lld/dist/COFF/ICF.cpp vendor/lld/dist/COFF/PDB.cpp vendor/lld/dist/ELF/Config.h vendor/lld/dist/ELF/Driver.cpp vendor/lld/dist/ELF/InputFiles.cpp vendor/lld/dist/ELF/InputFiles.h vendor/lld/dist/ELF/LinkerScript.cpp vendor/lld/dist/ELF/LinkerScript.h vendor/lld/dist/ELF/Options.td vendor/lld/dist/ELF/OutputSections.cpp vendor/lld/dist/ELF/Relocations.cpp vendor/lld/dist/ELF/SymbolTable.cpp vendor/lld/dist/ELF/Symbols.cpp vendor/lld/dist/ELF/SyntheticSections.cpp vendor/lld/dist/ELF/Target.cpp vendor/lld/dist/ELF/Target.h vendor/lld/dist/ELF/Writer.cpp vendor/lld/dist/ELF/Writer.h vendor/lld/dist/include/lld/Core/Parallel.h vendor/lld/dist/lib/Core/CMakeLists.txt vendor/lld/dist/test/ELF/defsym.s vendor/lld/dist/test/ELF/i386-tls-ie-shared.s vendor/lld/dist/test/ELF/lto/archive-no-index.ll vendor/lld/dist/test/ELF/lto/thin-archivecollision.ll vendor/lld/dist/test/ELF/tls-dynamic-i686.s vendor/lld/dist/test/ELF/tls-offset.s vendor/lld/dist/test/ELF/tls-opt-iele-i686-nopic.s vendor/lld/dist/unittests/CoreTests/CMakeLists.txt Modified: vendor/lld/dist/CMakeLists.txt ============================================================================== --- vendor/lld/dist/CMakeLists.txt Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/CMakeLists.txt Mon May 8 17:13:44 2017 (r317957) @@ -221,3 +221,4 @@ endif() add_subdirectory(docs) add_subdirectory(COFF) add_subdirectory(ELF) + Modified: vendor/lld/dist/COFF/Chunks.h ============================================================================== --- vendor/lld/dist/COFF/Chunks.h Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/COFF/Chunks.h Mon May 8 17:13:44 2017 (r317957) @@ -201,7 +201,7 @@ private: // Used for ICF (Identical COMDAT Folding) void replace(SectionChunk *Other); - uint32_t Color[2] = {0, 0}; + uint32_t Class[2] = {0, 0}; // Sym points to a section symbol if this is a COMDAT chunk. DefinedRegular *Sym = nullptr; Modified: vendor/lld/dist/COFF/ICF.cpp ============================================================================== --- vendor/lld/dist/COFF/ICF.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/COFF/ICF.cpp Mon May 8 17:13:44 2017 (r317957) @@ -49,10 +49,10 @@ private: size_t findBoundary(size_t Begin, size_t End); - void forEachColorRange(size_t Begin, size_t End, + void forEachClassRange(size_t Begin, size_t End, std::function<void(size_t, size_t)> Fn); - void forEachColor(std::function<void(size_t, size_t)> Fn); + void forEachClass(std::function<void(size_t, size_t)> Fn); std::vector<SectionChunk *> Chunks; int Cnt = 0; @@ -85,7 +85,7 @@ bool ICF::isEligible(SectionChunk *C) { return C->isCOMDAT() && C->isLive() && Global && Executable && !Writable; } -// Split a range into smaller ranges by recoloring sections +// Split an equivalence class into smaller classes. void ICF::segregate(size_t Begin, size_t End, bool Constant) { while (Begin < End) { // Divide [Begin, End) into two. Let Mid be the start index of the @@ -101,7 +101,7 @@ void ICF::segregate(size_t Begin, size_t // Split [Begin, End) into [Begin, Mid) and [Mid, End). uint32_t Id = NextId++; for (size_t I = Begin; I < Mid; ++I) - Chunks[I]->Color[(Cnt + 1) % 2] = Id; + Chunks[I]->Class[(Cnt + 1) % 2] = Id; // If we created a group, we need to iterate the main loop again. if (Mid != End) @@ -130,7 +130,7 @@ bool ICF::equalsConstant(const SectionCh if (auto *D1 = dyn_cast<DefinedRegular>(B1)) if (auto *D2 = dyn_cast<DefinedRegular>(B2)) return D1->getValue() == D2->getValue() && - D1->getChunk()->Color[Cnt % 2] == D2->getChunk()->Color[Cnt % 2]; + D1->getChunk()->Class[Cnt % 2] == D2->getChunk()->Class[Cnt % 2]; return false; }; if (!std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq)) @@ -155,7 +155,7 @@ bool ICF::equalsVariable(const SectionCh return true; if (auto *D1 = dyn_cast<DefinedRegular>(B1)) if (auto *D2 = dyn_cast<DefinedRegular>(B2)) - return D1->getChunk()->Color[Cnt % 2] == D2->getChunk()->Color[Cnt % 2]; + return D1->getChunk()->Class[Cnt % 2] == D2->getChunk()->Class[Cnt % 2]; return false; }; return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq); @@ -163,12 +163,12 @@ bool ICF::equalsVariable(const SectionCh size_t ICF::findBoundary(size_t Begin, size_t End) { for (size_t I = Begin + 1; I < End; ++I) - if (Chunks[Begin]->Color[Cnt % 2] != Chunks[I]->Color[Cnt % 2]) + if (Chunks[Begin]->Class[Cnt % 2] != Chunks[I]->Class[Cnt % 2]) return I; return End; } -void ICF::forEachColorRange(size_t Begin, size_t End, +void ICF::forEachClassRange(size_t Begin, size_t End, std::function<void(size_t, size_t)> Fn) { if (Begin > 0) Begin = findBoundary(Begin - 1, End); @@ -180,12 +180,12 @@ void ICF::forEachColorRange(size_t Begin } } -// Call Fn on each color group. -void ICF::forEachColor(std::function<void(size_t, size_t)> Fn) { +// Call Fn on each class group. +void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) { // If the number of sections are too small to use threading, // call Fn sequentially. if (Chunks.size() < 1024) { - forEachColorRange(0, Chunks.size(), Fn); + forEachClassRange(0, Chunks.size(), Fn); return; } @@ -193,9 +193,9 @@ void ICF::forEachColor(std::function<voi size_t NumShards = 256; size_t Step = Chunks.size() / NumShards; parallel_for(size_t(0), NumShards, [&](size_t I) { - forEachColorRange(I * Step, (I + 1) * Step, Fn); + forEachClassRange(I * Step, (I + 1) * Step, Fn); }); - forEachColorRange(Step * NumShards, Chunks.size(), Fn); + forEachClassRange(Step * NumShards, Chunks.size(), Fn); } // Merge identical COMDAT sections. @@ -209,11 +209,11 @@ void ICF::run(const std::vector<Chunk *> continue; if (isEligible(SC)) { - // Set MSB to 1 to avoid collisions with non-hash colors. - SC->Color[0] = getHash(SC) | (1 << 31); + // Set MSB to 1 to avoid collisions with non-hash classs. + SC->Class[0] = getHash(SC) | (1 << 31); Chunks.push_back(SC); } else { - SC->Color[0] = NextId++; + SC->Class[0] = NextId++; } } @@ -224,25 +224,25 @@ void ICF::run(const std::vector<Chunk *> // the same group are consecutive in the vector. std::stable_sort(Chunks.begin(), Chunks.end(), [](SectionChunk *A, SectionChunk *B) { - return A->Color[0] < B->Color[0]; + return A->Class[0] < B->Class[0]; }); // Compare static contents and assign unique IDs for each static content. - forEachColor([&](size_t Begin, size_t End) { segregate(Begin, End, true); }); + forEachClass([&](size_t Begin, size_t End) { segregate(Begin, End, true); }); ++Cnt; // Split groups by comparing relocations until convergence is obtained. do { Repeat = false; - forEachColor( + forEachClass( [&](size_t Begin, size_t End) { segregate(Begin, End, false); }); ++Cnt; } while (Repeat); log("ICF needed " + Twine(Cnt) + " iterations"); - // Merge sections in the same colors. - forEachColor([&](size_t Begin, size_t End) { + // Merge sections in the same classs. + forEachClass([&](size_t Begin, size_t End) { if (End - Begin == 1) return; Modified: vendor/lld/dist/COFF/PDB.cpp ============================================================================== --- vendor/lld/dist/COFF/PDB.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/COFF/PDB.cpp Mon May 8 17:13:44 2017 (r317957) @@ -133,7 +133,7 @@ static void dumpDebugT(ScopedPrinter &W, if (Data.empty()) return; - TypeDatabase TDB; + TypeDatabase TDB(0); TypeDumpVisitor TDV(TDB, &W, false); // Use a default implementation that does not follow type servers and instead // just dumps the contents of the TypeServer2 record. @@ -154,7 +154,7 @@ static void dumpDebugS(ScopedPrinter &W, if (auto EC = Reader.readArray(Symbols, Reader.getLength())) fatal(EC, "StreamReader.readArray<CVSymbolArray> failed"); - TypeDatabase TDB; + TypeDatabase TDB(0); CVSymbolDumper SymbolDumper(W, TDB, nullptr, false); if (auto EC = SymbolDumper.dump(Symbols)) fatal(EC, "CVSymbolDumper::dump failed"); Modified: vendor/lld/dist/ELF/Config.h ============================================================================== --- vendor/lld/dist/ELF/Config.h Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/Config.h Mon May 8 17:13:44 2017 (r317957) @@ -73,6 +73,7 @@ struct VersionDefinition { // Most fields are initialized by the driver. struct Configuration { InputFile *FirstElf = nullptr; + bool HasStaticTlsModel = false; uint8_t OSABI = 0; llvm::CachePruningPolicy ThinLTOCachePolicy; llvm::StringMap<uint64_t> SectionStartMap; @@ -99,7 +100,6 @@ struct Configuration { std::vector<SymbolVersion> VersionScriptLocals; std::vector<uint8_t> BuildIdVector; bool AllowMultipleDefinition; - bool ArchiveWithoutSymbolsSeen = false; bool AsNeeded = false; bool Bsymbolic; bool BsymbolicFunctions; Modified: vendor/lld/dist/ELF/Driver.cpp ============================================================================== --- vendor/lld/dist/ELF/Driver.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/Driver.cpp Mon May 8 17:13:44 2017 (r317957) @@ -123,13 +123,13 @@ static std::tuple<ELFKind, uint16_t, uin // Returns slices of MB by parsing MB as an archive file. // Each slice consists of a member file in the archive. -std::vector<MemoryBufferRef> -static getArchiveMembers(MemoryBufferRef MB) { +std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers( + MemoryBufferRef MB) { std::unique_ptr<Archive> File = check(Archive::create(MB), MB.getBufferIdentifier() + ": failed to parse archive"); - std::vector<MemoryBufferRef> V; + std::vector<std::pair<MemoryBufferRef, uint64_t>> V; Error Err = Error::success(); for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) { Archive::Child C = @@ -139,7 +139,7 @@ static getArchiveMembers(MemoryBufferRef check(C.getMemoryBufferRef(), MB.getBufferIdentifier() + ": could not get the buffer for a child of the archive"); - V.push_back(MBRef); + V.push_back(std::make_pair(MBRef, C.getChildOffset())); } if (Err) fatal(MB.getBufferIdentifier() + ": Archive::children failed: " + @@ -152,8 +152,7 @@ static getArchiveMembers(MemoryBufferRef return V; } -// Opens and parses a file. Path has to be resolved already. -// Newly created memory buffers are owned by this driver. +// Opens a file and create a file object. Path has to be resolved already. void LinkerDriver::addFile(StringRef Path, bool WithLOption) { using namespace sys::fs; @@ -171,14 +170,31 @@ void LinkerDriver::addFile(StringRef Pat case file_magic::unknown: readLinkerScript(MBRef); return; - case file_magic::archive: + case file_magic::archive: { + // Handle -whole-archive. if (InWholeArchive) { - for (MemoryBufferRef MB : getArchiveMembers(MBRef)) - Files.push_back(createObjectFile(MB, Path)); + for (const auto &P : getArchiveMembers(MBRef)) + Files.push_back(createObjectFile(P.first, Path, P.second)); return; } - Files.push_back(make<ArchiveFile>(MBRef)); + + std::unique_ptr<Archive> File = + check(Archive::create(MBRef), Path + ": failed to parse archive"); + + // If an archive file has no symbol table, it is likely that a user + // is attempting LTO and using a default ar command that doesn't + // understand the LLVM bitcode file. It is a pretty common error, so + // we'll handle it as if it had a symbol table. + if (!File->hasSymbolTable()) { + for (const auto &P : getArchiveMembers(MBRef)) + Files.push_back(make<LazyObjectFile>(P.first, Path, P.second)); + return; + } + + // Handle the regular case. + Files.push_back(make<ArchiveFile>(std::move(File))); return; + } case file_magic::elf_shared_object: if (Config->Relocatable) { error("attempted static link of dynamic object " + Path); @@ -199,7 +215,7 @@ void LinkerDriver::addFile(StringRef Pat return; default: if (InLib) - Files.push_back(make<LazyObjectFile>(MBRef)); + Files.push_back(make<LazyObjectFile>(MBRef, "", 0)); else Files.push_back(createObjectFile(MBRef)); } Modified: vendor/lld/dist/ELF/InputFiles.cpp ============================================================================== --- vendor/lld/dist/ELF/InputFiles.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/InputFiles.cpp Mon May 8 17:13:44 2017 (r317957) @@ -596,17 +596,13 @@ SymbolBody *elf::ObjectFile<ELFT>::creat } } -template <class ELFT> void ArchiveFile::parse() { - File = check(Archive::create(MB), - MB.getBufferIdentifier() + ": failed to parse archive"); +ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File) + : InputFile(ArchiveKind, File->getMemoryBufferRef()), + File(std::move(File)) {} - // Read the symbol table to construct Lazy objects. - for (const Archive::Symbol &Sym : File->symbols()) { +template <class ELFT> void ArchiveFile::parse() { + for (const Archive::Symbol &Sym : File->symbols()) Symtab<ELFT>::X->addLazyArchive(this, Sym); - } - - if (File->symbols().begin() == File->symbols().end()) - Config->ArchiveWithoutSymbolsSeen = true; } // Returns a buffer pointing to a member file containing a given symbol. @@ -981,6 +977,13 @@ MemoryBufferRef LazyObjectFile::getBuffe return MB; } +InputFile *LazyObjectFile::fetch() { + MemoryBufferRef MBRef = getBuffer(); + if (MBRef.getBuffer().empty()) + return nullptr; + return createObjectFile(MBRef, ArchiveName, OffsetInArchive); +} + template <class ELFT> void LazyObjectFile::parse() { for (StringRef Sym : getSymbols()) Symtab<ELFT>::X->addLazyObject(Sym, *this); Modified: vendor/lld/dist/ELF/InputFiles.h ============================================================================== --- vendor/lld/dist/ELF/InputFiles.h Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/InputFiles.h Mon May 8 17:13:44 2017 (r317957) @@ -219,7 +219,11 @@ private: // archive file semantics. class LazyObjectFile : public InputFile { public: - explicit LazyObjectFile(MemoryBufferRef M) : InputFile(LazyObjectKind, M) {} + LazyObjectFile(MemoryBufferRef M, StringRef ArchiveName, + uint64_t OffsetInArchive) + : InputFile(LazyObjectKind, M), OffsetInArchive(OffsetInArchive) { + this->ArchiveName = ArchiveName; + } static bool classof(const InputFile *F) { return F->kind() == LazyObjectKind; @@ -227,6 +231,7 @@ public: template <class ELFT> void parse(); MemoryBufferRef getBuffer(); + InputFile *fetch(); private: std::vector<StringRef> getSymbols(); @@ -234,12 +239,13 @@ private: std::vector<StringRef> getBitcodeSymbols(); bool Seen = false; + uint64_t OffsetInArchive; }; // An ArchiveFile object represents a .a file. class ArchiveFile : public InputFile { public: - explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} + explicit ArchiveFile(std::unique_ptr<Archive> &&File); static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } template <class ELFT> void parse(); Modified: vendor/lld/dist/ELF/LinkerScript.cpp ============================================================================== --- vendor/lld/dist/ELF/LinkerScript.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/LinkerScript.cpp Mon May 8 17:13:44 2017 (r317957) @@ -406,27 +406,22 @@ void LinkerScript::processCommands(Outpu } // Add input sections to an output section. - unsigned Pos = 0; - for (InputSectionBase *S : V) { - // The actual offset will be computed during - // assignAddresses. For now, use the index as a very crude - // approximation so that it is at least easy for other code to - // know the section order. - cast<InputSection>(S)->OutSecOff = Pos++; + for (InputSectionBase *S : V) Factory.addInputSec(S, Cmd->Name, Cmd->Sec); + if (OutputSection *Sec = Cmd->Sec) { + assert(Sec->SectionIndex == INT_MAX); + Sec->SectionIndex = I; } } } CurOutSec = nullptr; } -void LinkerScript::fabricateDefaultCommands(bool AllocateHeader) { +void LinkerScript::fabricateDefaultCommands() { std::vector<BaseCommand *> Commands; // Define start address - uint64_t StartAddr = Config->ImageBase; - if (AllocateHeader) - StartAddr += elf::getHeaderSize(); + uint64_t StartAddr = Config->ImageBase + elf::getHeaderSize(); // The Sections with -T<section> have been sorted in order of ascending // address. We must lower StartAddr if the lowest -T<section address> as @@ -488,6 +483,11 @@ void LinkerScript::addOrphanSections(Out } else { auto *Cmd = cast<OutputSectionCommand>(*I); Factory.addInputSec(S, Name, Cmd->Sec); + if (OutputSection *Sec = Cmd->Sec) { + unsigned Index = std::distance(Opt.Commands.begin(), I); + assert(Sec->SectionIndex == INT_MAX || Sec->SectionIndex == Index); + Sec->SectionIndex = Index; + } auto *ISD = make<InputSectionDescription>(""); ISD->Sections.push_back(S); Cmd->Commands.push_back(ISD); @@ -495,17 +495,22 @@ void LinkerScript::addOrphanSections(Out } } -static bool isTbss(OutputSection *Sec) { - return (Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS; +uint64_t LinkerScript::advance(uint64_t Size, unsigned Align) { + bool IsTbss = (CurOutSec->Flags & SHF_TLS) && CurOutSec->Type == SHT_NOBITS; + uint64_t Start = IsTbss ? Dot + ThreadBssOffset : Dot; + Start = alignTo(Start, Align); + uint64_t End = Start + Size; + + if (IsTbss) + ThreadBssOffset = End - Dot; + else + Dot = End; + return End; } void LinkerScript::output(InputSection *S) { - bool IsTbss = isTbss(CurOutSec); - - uint64_t Pos = IsTbss ? Dot + ThreadBssOffset : Dot; - Pos = alignTo(Pos, S->Alignment); - S->OutSecOff = Pos - CurOutSec->Addr; - Pos += S->getSize(); + uint64_t Pos = advance(S->getSize(), S->Alignment); + S->OutSecOff = Pos - S->getSize() - CurOutSec->Addr; // Update output section size after adding each section. This is so that // SIZEOF works correctly in the case below: @@ -524,11 +529,6 @@ void LinkerScript::output(InputSection * " bytes"); } } - - if (IsTbss) - ThreadBssOffset = Pos - Dot; - else - Dot = Pos; } void LinkerScript::switchTo(OutputSection *Sec) { @@ -536,9 +536,7 @@ void LinkerScript::switchTo(OutputSectio return; CurOutSec = Sec; - - Dot = alignTo(Dot, CurOutSec->Alignment); - CurOutSec->Addr = isTbss(CurOutSec) ? Dot + ThreadBssOffset : Dot; + CurOutSec->Addr = advance(0, CurOutSec->Alignment); // If neither AT nor AT> is specified for an allocatable section, the linker // will set the LMA such that the difference between VMA and LMA for the @@ -643,6 +641,11 @@ void LinkerScript::assignOffsets(OutputS Dot = CurMemRegion->Offset; switchTo(Sec); + // We do not support custom layout for compressed debug sectons. + // At this point we already know their size and have compressed content. + if (CurOutSec->Flags & SHF_COMPRESSED) + return; + for (BaseCommand *C : Cmd->Commands) process(*C); } @@ -678,8 +681,9 @@ void LinkerScript::adjustSectionsBeforeS // consequeces and gives us a section to put the symbol in. uint64_t Flags = SHF_ALLOC; uint32_t Type = SHT_PROGBITS; - for (BaseCommand *Base : Opt.Commands) { - auto *Cmd = dyn_cast<OutputSectionCommand>(Base); + + for (int I = 0, E = Opt.Commands.size(); I != E; ++I) { + auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]); if (!Cmd) continue; if (OutputSection *Sec = Cmd->Sec) { @@ -692,6 +696,7 @@ void LinkerScript::adjustSectionsBeforeS continue; auto *OutSec = make<OutputSection>(Cmd->Name, Type, Flags); + OutSec->SectionIndex = I; OutputSections->push_back(OutSec); Cmd->Sec = OutSec; } @@ -894,6 +899,48 @@ void LinkerScript::synchronize() { } } +static bool allocateHeaders(std::vector<PhdrEntry> &Phdrs, + ArrayRef<OutputSection *> OutputSections, + uint64_t Min) { + auto FirstPTLoad = + std::find_if(Phdrs.begin(), Phdrs.end(), + [](const PhdrEntry &E) { return E.p_type == PT_LOAD; }); + if (FirstPTLoad == Phdrs.end()) + return false; + + uint64_t HeaderSize = getHeaderSize(); + if (HeaderSize <= Min || Script->hasPhdrsCommands()) { + Min = alignDown(Min - HeaderSize, Config->MaxPageSize); + Out::ElfHeader->Addr = Min; + Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size; + return true; + } + + assert(FirstPTLoad->First == Out::ElfHeader); + OutputSection *ActualFirst = nullptr; + for (OutputSection *Sec : OutputSections) { + if (Sec->FirstInPtLoad == Out::ElfHeader) { + ActualFirst = Sec; + break; + } + } + if (ActualFirst) { + for (OutputSection *Sec : OutputSections) + if (Sec->FirstInPtLoad == Out::ElfHeader) + Sec->FirstInPtLoad = ActualFirst; + FirstPTLoad->First = ActualFirst; + } else { + Phdrs.erase(FirstPTLoad); + } + + auto PhdrI = std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry &E) { + return E.p_type == PT_PHDR; + }); + if (PhdrI != Phdrs.end()) + Phdrs.erase(PhdrI); + return false; +} + void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) { // Assign addresses as instructed by linker script SECTIONS sub-commands. Dot = 0; @@ -994,12 +1041,17 @@ static void writeInt(uint8_t *Buf, uint6 llvm_unreachable("unsupported Size argument"); } -void LinkerScript::writeDataBytes(StringRef Name, uint8_t *Buf) { - int I = getSectionIndex(Name); - if (I == INT_MAX) +void LinkerScript::writeDataBytes(OutputSection *Sec, uint8_t *Buf) { + auto I = std::find_if(Opt.Commands.begin(), Opt.Commands.end(), + [=](BaseCommand *Base) { + if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) + if (Cmd->Sec == Sec) + return true; + return false; + }); + if (I == Opt.Commands.end()) return; - - auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]); + auto *Cmd = cast<OutputSectionCommand>(*I); for (BaseCommand *Base : Cmd->Commands) if (auto *Data = dyn_cast<BytesDataCommand>(Base)) writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size); @@ -1013,18 +1065,6 @@ bool LinkerScript::hasLMA(StringRef Name return false; } -// Returns the index of the given section name in linker script -// SECTIONS commands. Sections are laid out as the same order as they -// were in the script. If a given name did not appear in the script, -// it returns INT_MAX, so that it will be laid out at end of file. -int LinkerScript::getSectionIndex(StringRef Name) { - for (int I = 0, E = Opt.Commands.size(); I != E; ++I) - if (auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I])) - if (Cmd->Name == Name) - return I; - return INT_MAX; -} - ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) { if (S == ".") return {CurOutSec, Dot - CurOutSec->Addr}; Modified: vendor/lld/dist/ELF/LinkerScript.h ============================================================================== --- vendor/lld/dist/ELF/LinkerScript.h Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/LinkerScript.h Mon May 8 17:13:44 2017 (r317957) @@ -228,6 +228,7 @@ protected: MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd); void switchTo(OutputSection *Sec); + uint64_t advance(uint64_t Size, unsigned Align); void output(InputSection *Sec); void process(BaseCommand &Base); @@ -252,7 +253,7 @@ public: bool isDefined(StringRef S); std::vector<OutputSection *> *OutputSections; - void fabricateDefaultCommands(bool AllocateHeader); + void fabricateDefaultCommands(); void addOrphanSections(OutputSectionFactory &Factory); void removeEmptyCommands(); void adjustSectionsBeforeSorting(); @@ -269,9 +270,8 @@ public: void processNonSectionCommands(); void synchronize(); void assignAddresses(std::vector<PhdrEntry> &Phdrs); - int getSectionIndex(StringRef Name); - void writeDataBytes(StringRef Name, uint8_t *Buf); + void writeDataBytes(OutputSection *Sec, uint8_t *Buf); void addSymbol(SymbolAssignment *Cmd); void processCommands(OutputSectionFactory &Factory); Modified: vendor/lld/dist/ELF/Options.td ============================================================================== --- vendor/lld/dist/ELF/Options.td Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/Options.td Mon May 8 17:13:44 2017 (r317957) @@ -290,6 +290,7 @@ def alias_L__library_path: J<"library-pa def alias_define_common_d: Flag<["-"], "d">, Alias<define_common>; def alias_define_common_dc: F<"dc">, Alias<define_common>; def alias_define_common_dp: F<"dp">, Alias<define_common>; +def alias_defsym: S<"defsym">, Alias<defsym>; def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>; def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>; def alias_dynamic_list: J<"dynamic-list=">, Alias<dynamic_list>; Modified: vendor/lld/dist/ELF/OutputSections.cpp ============================================================================== --- vendor/lld/dist/ELF/OutputSections.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/OutputSections.cpp Mon May 8 17:13:44 2017 (r317957) @@ -68,7 +68,8 @@ void OutputSection::writeHeaderTo(typena OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags) : SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type, /*Info*/ 0, - /*Link*/ 0) {} + /*Link*/ 0), + SectionIndex(INT_MAX) {} static bool compareByFilePosition(InputSection *A, InputSection *B) { // Synthetic doesn't have link order dependecy, stable_sort will keep it last @@ -139,12 +140,24 @@ template <class ELFT> void OutputSection this->Info = S->OutSec->SectionIndex; } +static uint64_t updateOffset(uint64_t Off, InputSection *S) { + Off = alignTo(Off, S->Alignment); + S->OutSecOff = Off; + return Off + S->getSize(); +} + void OutputSection::addSection(InputSection *S) { assert(S->Live); Sections.push_back(S); S->OutSec = this; this->updateAlignment(S->Alignment); + // The actual offsets will be computed by assignAddresses. For now, use + // crude approximation so that it is at least easy for other code to know the + // section order. It is also used to calculate the output section size early + // for compressed debug sections. + this->Size = updateOffset(Size, S); + // If this section contains a table of fixed-size entries, sh_entsize // holds the element size. Consequently, if this contains two or more // input sections, all of them must have the same sh_entsize. However, @@ -159,11 +172,8 @@ void OutputSection::addSection(InputSect // and scan relocations to setup sections' offsets. void OutputSection::assignOffsets() { uint64_t Off = 0; - for (InputSection *S : Sections) { - Off = alignTo(Off, S->Alignment); - S->OutSecOff = Off; - Off += S->getSize(); - } + for (InputSection *S : Sections) + Off = updateOffset(Off, S); this->Size = Off; } @@ -305,7 +315,7 @@ template <class ELFT> void OutputSection // Linker scripts may have BYTE()-family commands with which you // can write arbitrary bytes to the output. Process them if any. - Script->writeDataBytes(Name, Buf); + Script->writeDataBytes(this, Buf); } static uint64_t getOutFlags(InputSectionBase *S) { Modified: vendor/lld/dist/ELF/Relocations.cpp ============================================================================== --- vendor/lld/dist/ELF/Relocations.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/Relocations.cpp Mon May 8 17:13:44 2017 (r317957) @@ -233,7 +233,7 @@ handleTlsRelocation(uint32_t Type, Symbo } // Local-Dynamic relocs can be relaxed to Local-Exec. - if (Target->isTlsLocalDynamicRel(Type) && !Config->Shared) { + if (isRelExprOneOf<R_ABS, R_TLSLD, R_TLSLD_PC>(Expr) && !Config->Shared) { C.Relocations.push_back( {R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Body}); return 1; @@ -282,7 +282,8 @@ handleTlsRelocation(uint32_t Type, Symbo // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally // defined. - if (Target->isTlsInitialExecRel(Type) && !Config->Shared && !IsPreemptible) { + if (isRelExprOneOf<R_GOT, R_GOT_FROM_END, R_GOT_PC, R_GOT_PAGE_PC>(Expr) && + !Config->Shared && !IsPreemptible) { C.Relocations.push_back( {R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Body}); return 1; @@ -694,17 +695,6 @@ static void reportUndefined(SymbolBody & warn(Msg); } else { error(Msg); - - if (Config->ArchiveWithoutSymbolsSeen) { - message("At least one archive listed no symbols in its index." - " This can happen when creating archives with a version" - " of ar that does not understand the object files in" - " the archive. For example, if you are using LLVM" - " bitcode objects (such as created by -flto), you may" - " need to use llvm-ar or GNU ar with a plugin."); - // Reset to false so that we print the message only once. - Config->ArchiveWithoutSymbolsSeen = false; - } } } Modified: vendor/lld/dist/ELF/SymbolTable.cpp ============================================================================== --- vendor/lld/dist/ELF/SymbolTable.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/SymbolTable.cpp Mon May 8 17:13:44 2017 (r317957) @@ -540,13 +540,10 @@ void SymbolTable<ELFT>::addLazyObject(St return; // See comment for addLazyArchive above. - if (S->isWeak()) { + if (S->isWeak()) replaceBody<LazyObject>(S, Name, Obj, S->body()->Type); - } else { - MemoryBufferRef MBRef = Obj.getBuffer(); - if (!MBRef.getBuffer().empty()) - addFile(createObjectFile(MBRef)); - } + else if (InputFile *F = Obj.fetch()) + addFile(F); } // Process undefined (-u) flags by loading lazy symbols named by those flags. Modified: vendor/lld/dist/ELF/Symbols.cpp ============================================================================== --- vendor/lld/dist/ELF/Symbols.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/Symbols.cpp Mon May 8 17:13:44 2017 (r317957) @@ -327,12 +327,7 @@ InputFile *LazyArchive::fetch() { return createObjectFile(MBInfo.first, file()->getName(), MBInfo.second); } -InputFile *LazyObject::fetch() { - MemoryBufferRef MBRef = file()->getBuffer(); - if (MBRef.getBuffer().empty()) - return nullptr; - return createObjectFile(MBRef); -} +InputFile *LazyObject::fetch() { return file()->fetch(); } uint8_t Symbol::computeBinding() const { if (Config->Relocatable) Modified: vendor/lld/dist/ELF/SyntheticSections.cpp ============================================================================== --- vendor/lld/dist/ELF/SyntheticSections.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/SyntheticSections.cpp Mon May 8 17:13:44 2017 (r317957) @@ -1038,6 +1038,15 @@ template <class ELFT> void DynamicSectio if (!Config->SoName.empty()) add({DT_SONAME, In<ELFT>::DynStrTab->addString(Config->SoName)}); + if (!Config->Shared && !Config->Relocatable) + add({DT_DEBUG, (uint64_t)0}); +} + +// Add remaining entries to complete .dynamic contents. +template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { + if (this->Size) + return; // Already finalized. + // Set DT_FLAGS and DT_FLAGS_1. uint32_t DtFlags = 0; uint32_t DtFlags1 = 0; @@ -1055,21 +1064,14 @@ template <class ELFT> void DynamicSectio DtFlags |= DF_ORIGIN; DtFlags1 |= DF_1_ORIGIN; } + if (Config->HasStaticTlsModel) + DtFlags |= DF_STATIC_TLS; if (DtFlags) add({DT_FLAGS, DtFlags}); if (DtFlags1) add({DT_FLAGS_1, DtFlags1}); - if (!Config->Shared && !Config->Relocatable) - add({DT_DEBUG, (uint64_t)0}); -} - -// Add remaining entries to complete .dynamic contents. -template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { - if (this->Size) - return; // Already finalized. - this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex; if (In<ELFT>::RelaDyn->OutSec->Size > 0) { bool IsRela = Config->IsRela; Modified: vendor/lld/dist/ELF/Target.cpp ============================================================================== --- vendor/lld/dist/ELF/Target.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/Target.cpp Mon May 8 17:13:44 2017 (r317957) @@ -124,8 +124,6 @@ public: int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; void writeGotPltHeader(uint8_t *Buf) const override; uint32_t getDynRel(uint32_t Type) const override; - bool isTlsLocalDynamicRel(uint32_t Type) const override; - bool isTlsInitialExecRel(uint32_t Type) const override; void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const override; void writePltHeader(uint8_t *Buf) const override; @@ -147,8 +145,6 @@ public: RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, const uint8_t *Loc) const override; bool isPicRel(uint32_t Type) const override; - bool isTlsLocalDynamicRel(uint32_t Type) const override; - bool isTlsInitialExecRel(uint32_t Type) const override; void writeGotPltHeader(uint8_t *Buf) const override; void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; void writePltHeader(uint8_t *Buf) const override; @@ -193,7 +189,6 @@ public: RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, const uint8_t *Loc) const override; bool isPicRel(uint32_t Type) const override; - bool isTlsInitialExecRel(uint32_t Type) const override; void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; void writePltHeader(uint8_t *Buf) const override; void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, @@ -303,10 +298,6 @@ bool TargetInfo::needsThunk(RelExpr Expr return false; } -bool TargetInfo::isTlsInitialExecRel(uint32_t Type) const { return false; } - -bool TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const { return false; } - void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const { writeGotPlt(Buf, S); } @@ -360,6 +351,15 @@ X86TargetInfo::X86TargetInfo() { RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S, const uint8_t *Loc) const { + // There are 4 different TLS variable models with varying degrees of + // flexibility and performance. LocalExec and InitialExec models are fast but + // less-flexible models. They cannot be used for dlopen(). If they are in use, + // we set DF_STATIC_TLS in the ELF header so that the runtime can reject such + // DSOs. + if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 || Type == R_386_TLS_IE || + Type == R_386_TLS_GOTIE) + Config->HasStaticTlsModel = true; + switch (Type) { case R_386_8: case R_386_16: @@ -451,14 +451,6 @@ uint32_t X86TargetInfo::getDynRel(uint32 return Type; } -bool X86TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const { - return Type == R_386_TLS_LDO_32 || Type == R_386_TLS_LDM; -} - -bool X86TargetInfo::isTlsInitialExecRel(uint32_t Type) const { - return Type == R_386_TLS_IE || Type == R_386_TLS_GOTIE; -} - void X86TargetInfo::writePltHeader(uint8_t *Buf) const { if (Config->Pic) { const uint8_t V[] = { @@ -772,17 +764,6 @@ bool X86_64TargetInfo<ELFT>::isPicRel(ui } template <class ELFT> -bool X86_64TargetInfo<ELFT>::isTlsInitialExecRel(uint32_t Type) const { - return Type == R_X86_64_GOTTPOFF; -} - -template <class ELFT> -bool X86_64TargetInfo<ELFT>::isTlsLocalDynamicRel(uint32_t Type) const { - return Type == R_X86_64_DTPOFF32 || Type == R_X86_64_DTPOFF64 || - Type == R_X86_64_TLSLD; -} - -template <class ELFT> void X86_64TargetInfo<ELFT>::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { // Convert @@ -1383,11 +1364,6 @@ bool AArch64TargetInfo::usesOnlyLowPageB } } -bool AArch64TargetInfo::isTlsInitialExecRel(uint32_t Type) const { - return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 || - Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC; -} - bool AArch64TargetInfo::isPicRel(uint32_t Type) const { return Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64; } Modified: vendor/lld/dist/ELF/Target.h ============================================================================== --- vendor/lld/dist/ELF/Target.h Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/Target.h Mon May 8 17:13:44 2017 (r317957) @@ -23,8 +23,6 @@ class SymbolBody; class TargetInfo { public: - virtual bool isTlsInitialExecRel(uint32_t Type) const; - virtual bool isTlsLocalDynamicRel(uint32_t Type) const; virtual bool isPicRel(uint32_t Type) const { return true; } virtual uint32_t getDynRel(uint32_t Type) const { return Type; } virtual void writeGotPltHeader(uint8_t *Buf) const {} Modified: vendor/lld/dist/ELF/Writer.cpp ============================================================================== --- vendor/lld/dist/ELF/Writer.cpp Mon May 8 17:13:41 2017 (r317956) +++ vendor/lld/dist/ELF/Writer.cpp Mon May 8 17:13:44 2017 (r317957) @@ -62,7 +62,6 @@ private: void assignFileOffsets(); void assignFileOffsetsBinary(); void setPhdrs(); - void fixHeaders(); void fixSectionAlignments(); void fixPredefinedSymbols(); void openFile(); @@ -86,7 +85,6 @@ private: uint64_t FileSize; uint64_t SectionHeaderOff; - bool AllocateHeader = true; }; } // anonymous namespace @@ -252,7 +250,7 @@ template <class ELFT> void Writer<ELFT>: } else { if (!Script->Opt.HasSections) { fixSectionAlignments(); - Script->fabricateDefaultCommands(AllocateHeader); + Script->fabricateDefaultCommands(); } Script->synchronize(); Script->assignAddresses(Phdrs); @@ -747,15 +745,12 @@ static bool compareSectionsNonScript(con // Output section ordering is determined by this function. template <class ELFT> static bool compareSections(const OutputSection *A, const OutputSection *B) { - // For now, put sections mentioned in a linker script first. - int AIndex = Script->getSectionIndex(A->Name); - int BIndex = Script->getSectionIndex(B->Name); - bool AInScript = AIndex != INT_MAX; - bool BInScript = BIndex != INT_MAX; - if (AInScript != BInScript) - return AInScript; - // If both are in the script, use that order. - if (AInScript) + // For now, put sections mentioned in a linker script + // first. Sections not on linker script will have a SectionIndex of + // INT_MAX. + int AIndex = A->SectionIndex; + int BIndex = B->SectionIndex; + if (AIndex != BIndex) return AIndex < BIndex; return compareSectionsNonScript<ELFT>(A, B); @@ -1021,9 +1016,8 @@ template <class ELFT> void Writer<ELFT>: auto I = OutputSections.begin(); auto E = OutputSections.end(); auto NonScriptI = - std::find_if(OutputSections.begin(), E, [](OutputSection *S) { - return Script->getSectionIndex(S->Name) == INT_MAX; - }); + std::find_if(OutputSections.begin(), E, + [](OutputSection *S) { return S->SectionIndex == INT_MAX; }); while (NonScriptI != E) { auto BestPos = std::max_element( I, NonScriptI, [&](OutputSection *&A, OutputSection *&B) { @@ -1176,7 +1170,7 @@ template <class ELFT> void Writer<ELFT>: if (!Config->Relocatable && !Config->OFormatBinary) { Phdrs = Script->hasPhdrsCommands() ? Script->createPhdrs() : createPhdrs(); addPtArmExid(Phdrs); - fixHeaders(); + Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); } // Dynamic section must be the last one in this list and dynamic @@ -1321,6 +1315,11 @@ template <class ELFT> std::vector<PhdrEn // Add the first PT_LOAD segment for regular output sections. uint64_t Flags = computeFlags(PF_R); PhdrEntry *Load = AddHdr(PT_LOAD, Flags); + + // Add the headers. We will remove them if they don't fit. + Load->add(Out::ElfHeader); + Load->add(Out::ProgramHeaders); + for (OutputSection *Sec : OutputSections) { if (!(Sec->Flags & SHF_ALLOC)) break; @@ -1447,64 +1446,6 @@ template <class ELFT> void Writer<ELFT>: } } -bool elf::allocateHeaders(std::vector<PhdrEntry> &Phdrs, - ArrayRef<OutputSection *> OutputSections, - uint64_t Min) { - auto FirstPTLoad = - std::find_if(Phdrs.begin(), Phdrs.end(), - [](const PhdrEntry &E) { return E.p_type == PT_LOAD; }); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705081713.v48HDiRV043006>