From d6d113268daec774e6dfd7f2833ea4fd62dbe386 Mon Sep 17 00:00:00 2001 From: Patrick Wildt Date: Tue, 14 Mar 2017 08:08:16 +0000 Subject: Import LLVM 4.0.0 release including clang and lld. --- gnu/llvm/tools/lld/CMakeLists.txt | 1 + gnu/llvm/tools/lld/ELF/InputFiles.h | 4 -- gnu/llvm/tools/lld/ELF/InputSection.cpp | 3 +- gnu/llvm/tools/lld/ELF/LinkerScript.cpp | 7 +- gnu/llvm/tools/lld/ELF/SymbolTable.cpp | 12 +++- gnu/llvm/tools/lld/ELF/SymbolTable.h | 1 + gnu/llvm/tools/lld/ELF/Symbols.h | 1 + gnu/llvm/tools/lld/ELF/SyntheticSections.h | 15 +++-- gnu/llvm/tools/lld/ELF/Writer.cpp | 30 +++++---- gnu/llvm/tools/lld/cmake/modules/AddLLD.cmake | 34 +++++++++- gnu/llvm/tools/lld/docs/ReleaseNotes.rst | 92 +++++++++++++++++++++++---- gnu/llvm/tools/lld/docs/conf.py | 4 +- 12 files changed, 157 insertions(+), 47 deletions(-) (limited to 'gnu/llvm/tools/lld') diff --git a/gnu/llvm/tools/lld/CMakeLists.txt b/gnu/llvm/tools/lld/CMakeLists.txt index 48ac5e038cd..be424efbbd8 100644 --- a/gnu/llvm/tools/lld/CMakeLists.txt +++ b/gnu/llvm/tools/lld/CMakeLists.txt @@ -42,6 +42,7 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) include_directories("${LLVM_BINARY_DIR}/include" ${LLVM_INCLUDE_DIRS}) link_directories(${LLVM_LIBRARY_DIRS}) + set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH) diff --git a/gnu/llvm/tools/lld/ELF/InputFiles.h b/gnu/llvm/tools/lld/ELF/InputFiles.h index 73dda7b566b..95888061d87 100644 --- a/gnu/llvm/tools/lld/ELF/InputFiles.h +++ b/gnu/llvm/tools/lld/ELF/InputFiles.h @@ -180,10 +180,6 @@ public: // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations. uint32_t MipsGp0 = 0; - // The number is the offset in the string table. It will be used as the - // st_name of the symbol. - std::vector *, unsigned>> KeptLocalSyms; - // Name of source file obtained from STT_FILE symbol value, // or empty string if there is no such symbol in object file // symbol table. diff --git a/gnu/llvm/tools/lld/ELF/InputSection.cpp b/gnu/llvm/tools/lld/ELF/InputSection.cpp index 35800424837..6b1e92891b9 100644 --- a/gnu/llvm/tools/lld/ELF/InputSection.cpp +++ b/gnu/llvm/tools/lld/ELF/InputSection.cpp @@ -246,7 +246,8 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef Rels) { if (Config->Rela) P->r_addend = getAddend(Rel); P->r_offset = RelocatedSection->getOffset(Rel.r_offset); - P->setSymbolAndType(Body.DynsymIndex, Type, Config->Mips64EL); + P->setSymbolAndType(In::SymTab->getSymbolIndex(&Body), Type, + Config->Mips64EL); } } diff --git a/gnu/llvm/tools/lld/ELF/LinkerScript.cpp b/gnu/llvm/tools/lld/ELF/LinkerScript.cpp index 887ca12537a..3cc235386b8 100644 --- a/gnu/llvm/tools/lld/ELF/LinkerScript.cpp +++ b/gnu/llvm/tools/lld/ELF/LinkerScript.cpp @@ -918,12 +918,7 @@ const OutputSectionBase *LinkerScript::getSymbolSection(StringRef S) { return CurOutSec ? CurOutSec : (*OutputSections)[0]; } - if (auto *DR = dyn_cast_or_null>(Sym)) - return DR->Section ? DR->Section->OutSec : nullptr; - if (auto *DS = dyn_cast_or_null(Sym)) - return DS->Section; - - return nullptr; + return SymbolTableSection::getOutputSection(Sym); } // Returns indices of ELF headers containing specific section, identified diff --git a/gnu/llvm/tools/lld/ELF/SymbolTable.cpp b/gnu/llvm/tools/lld/ELF/SymbolTable.cpp index b3e91c9f32e..ce257933c26 100644 --- a/gnu/llvm/tools/lld/ELF/SymbolTable.cpp +++ b/gnu/llvm/tools/lld/ELF/SymbolTable.cpp @@ -140,7 +140,7 @@ template DefinedRegular *SymbolTable::addIgnored(StringRef Name, uint8_t Visibility) { SymbolBody *S = find(Name); - if (!S || !S->isUndefined()) + if (!S || S->isInCurrentDSO()) return nullptr; return addAbsolute(Name, Visibility); } @@ -283,7 +283,7 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) { if (WasInserted) return 1; SymbolBody *Body = S->body(); - if (Body->isLazy() || Body->isUndefined() || Body->isShared()) + if (Body->isLazy() || !Body->isInCurrentDSO()) return 1; if (Binding == STB_WEAK) return -1; @@ -463,6 +463,14 @@ template SymbolBody *SymbolTable::find(StringRef Name) { return SymVector[V.Idx]->body(); } +template +SymbolBody *SymbolTable::findInCurrentDSO(StringRef Name) { + if (SymbolBody *S = find(Name)) + if (S->isInCurrentDSO()) + return S; + return nullptr; +} + template void SymbolTable::addLazyArchive(ArchiveFile *F, const object::Archive::Symbol Sym) { diff --git a/gnu/llvm/tools/lld/ELF/SymbolTable.h b/gnu/llvm/tools/lld/ELF/SymbolTable.h index 1e5a335acc1..f39dbd1e2e1 100644 --- a/gnu/llvm/tools/lld/ELF/SymbolTable.h +++ b/gnu/llvm/tools/lld/ELF/SymbolTable.h @@ -82,6 +82,7 @@ public: void scanVersionScript(); SymbolBody *find(StringRef Name); + SymbolBody *findInCurrentDSO(StringRef Name); void trace(StringRef Name); void wrap(StringRef Name); diff --git a/gnu/llvm/tools/lld/ELF/Symbols.h b/gnu/llvm/tools/lld/ELF/Symbols.h index af85dc2b121..7acb89ad071 100644 --- a/gnu/llvm/tools/lld/ELF/Symbols.h +++ b/gnu/llvm/tools/lld/ELF/Symbols.h @@ -67,6 +67,7 @@ public: return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind; } bool isShared() const { return SymbolKind == SharedKind; } + bool isInCurrentDSO() const { return !isUndefined() && !isShared(); } bool isLocal() const { return IsLocal; } bool isPreemptible() const; StringRef getName() const { return Name; } diff --git a/gnu/llvm/tools/lld/ELF/SyntheticSections.h b/gnu/llvm/tools/lld/ELF/SyntheticSections.h index dfefb3821e7..df67e079ad0 100644 --- a/gnu/llvm/tools/lld/ELF/SyntheticSections.h +++ b/gnu/llvm/tools/lld/ELF/SyntheticSections.h @@ -366,23 +366,26 @@ public: void finalize() override; void writeTo(uint8_t *Buf) override; size_t getSize() const override { return getNumSymbols() * sizeof(Elf_Sym); } - void addSymbol(SymbolBody *Body); + void addGlobal(SymbolBody *Body); + void addLocal(SymbolBody *Body); StringTableSection &getStrTabSec() const { return StrTabSec; } - unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; } + unsigned getNumSymbols() const { return Symbols.size() + 1; } + size_t getSymbolIndex(SymbolBody *Body); ArrayRef getSymbols() const { return Symbols; } - unsigned NumLocals = 0; - StringTableSection &StrTabSec; + static const OutputSectionBase *getOutputSection(SymbolBody *Sym); private: void writeLocalSymbols(uint8_t *&Buf); void writeGlobalSymbols(uint8_t *Buf); - const OutputSectionBase *getOutputSection(SymbolBody *Sym); - // A vector of symbols and their string table offsets. std::vector Symbols; + + StringTableSection &StrTabSec; + + unsigned NumLocals = 0; }; // Outputs GNU Hash section. For detailed explanation see: diff --git a/gnu/llvm/tools/lld/ELF/Writer.cpp b/gnu/llvm/tools/lld/ELF/Writer.cpp index bddc42e1acf..b004a4f0d7f 100644 --- a/gnu/llvm/tools/lld/ELF/Writer.cpp +++ b/gnu/llvm/tools/lld/ELF/Writer.cpp @@ -455,11 +455,7 @@ template void Writer::copyLocalSymbols() { InputSectionBase *Sec = DR->Section; if (!shouldKeepInSymtab(Sec, B->getName(), *B)) continue; - ++In::SymTab->NumLocals; - if (Config->Relocatable) - B->DynsymIndex = In::SymTab->NumLocals; - F->KeptLocalSyms.push_back(std::make_pair( - DR, In::SymTab->StrTabSec.addString(B->getName()))); + In::SymTab->addLocal(B); } } } @@ -480,6 +476,16 @@ static int getPPC64SectionRank(StringRef SectionName) { .Default(1); } +// All sections with SHF_MIPS_GPREL flag should be grouped together +// because data in these sections is addressable with a gp relative address. +static int getMipsSectionRank(const OutputSectionBase *S) { + if ((S->Flags & SHF_MIPS_GPREL) == 0) + return 0; + if (S->getName() == ".got") + return 1; + return 2; +} + template bool elf::isRelroSection(const OutputSectionBase *Sec) { if (!Config->ZRelro) return false; @@ -498,8 +504,6 @@ template bool elf::isRelroSection(const OutputSectionBase *Sec) { return true; if (In::Got && Sec == In::Got->OutSec) return true; - if (In::MipsGot && Sec == In::MipsGot->OutSec) - return true; if (Sec == Out::BssRelRo) return true; StringRef S = Sec->getName(); @@ -599,6 +603,8 @@ static bool compareSectionsNonScript(const OutputSectionBase *A, if (Config->EMachine == EM_PPC64) return getPPC64SectionRank(A->getName()) < getPPC64SectionRank(B->getName()); + if (Config->EMachine == EM_MIPS) + return getMipsSectionRank(A) < getMipsSectionRank(B); return false; } @@ -641,7 +647,7 @@ static void addOptionalSynthetic(StringRef Name, OutputSectionBase *Sec, typename ELFT::uint Val, uint8_t StOther = STV_HIDDEN) { if (SymbolBody *S = Symtab::X->find(Name)) - if (S->isUndefined() || S->isShared()) + if (!S->isInCurrentDSO()) Symtab::X->addSynthetic(Name, Sec, Val, StOther); } @@ -661,7 +667,7 @@ static Symbol *addOptionalRegular(StringRef Name, InputSectionBase *IS, SymbolBody *S = Symtab::X->find(Name); if (!S) return nullptr; - if (!S->isUndefined() && !S->isShared()) + if (S->isInCurrentDSO()) return S->symbol(); return addRegular(Name, IS, Value); } @@ -1024,10 +1030,10 @@ template void Writer::finalizeSections() { if (!includeInSymtab(*Body)) continue; if (In::SymTab) - In::SymTab->addSymbol(Body); + In::SymTab->addGlobal(Body); if (In::DynSymTab && S->includeInDynsym()) { - In::DynSymTab->addSymbol(Body); + In::DynSymTab->addGlobal(Body); if (auto *SS = dyn_cast>(Body)) if (SS->file()->isNeeded()) In::VerNeed->addSymbol(SS); @@ -1466,7 +1472,7 @@ template void Writer::setPhdrs() { // The glibc dynamic loader rounds the size down, so we need to round up // to protect the last page. This is a no-op on FreeBSD which always // rounds up. - P.p_memsz = alignTo(P.p_memsz, Config->MaxPageSize); + P.p_memsz = alignTo(P.p_memsz, Target->PageSize); } // The TLS pointer goes after PT_TLS. At least glibc will align it, diff --git a/gnu/llvm/tools/lld/cmake/modules/AddLLD.cmake b/gnu/llvm/tools/lld/cmake/modules/AddLLD.cmake index 906b2952a94..fd1d44199ca 100644 --- a/gnu/llvm/tools/lld/cmake/modules/AddLLD.cmake +++ b/gnu/llvm/tools/lld/cmake/modules/AddLLD.cmake @@ -1,6 +1,38 @@ macro(add_lld_library name) - llvm_add_library(${name} ${ARGN}) + cmake_parse_arguments(ARG + "SHARED" + "" + "" + ${ARGN}) + if(ARG_SHARED) + set(ARG_ENABLE_SHARED SHARED) + endif() + llvm_add_library(${name} ${ARG_ENABLE_SHARED} ${ARG_UNPARSED_ARGUMENTS}) set_target_properties(${name} PROPERTIES FOLDER "lld libraries") + + if (LLD_BUILD_TOOLS) + if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR + NOT LLVM_DISTRIBUTION_COMPONENTS) + set(export_to_lldtargets EXPORT lldTargets) + set_property(GLOBAL PROPERTY LLD_HAS_EXPORTS True) + endif() + + install(TARGETS ${name} + COMPONENT ${name} + ${export_to_lldtargets} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} + RUNTIME DESTINATION bin) + + if (${ARG_SHARED} AND NOT CMAKE_CONFIGURATION_TYPES) + add_custom_target(install-${name} + DEPENDS ${name} + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=${name} + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + endif() + set_property(GLOBAL APPEND PROPERTY LLD_EXPORTS ${name}) + endif() endmacro(add_lld_library) macro(add_lld_executable name) diff --git a/gnu/llvm/tools/lld/docs/ReleaseNotes.rst b/gnu/llvm/tools/lld/docs/ReleaseNotes.rst index 8bd73db363d..07fc7dd04e7 100644 --- a/gnu/llvm/tools/lld/docs/ReleaseNotes.rst +++ b/gnu/llvm/tools/lld/docs/ReleaseNotes.rst @@ -5,31 +5,97 @@ LLD 4.0.0 Release Notes .. contents:: :local: -.. warning:: - These are in-progress notes for the upcoming LLVM 4.0.0 release. - Introduction ============ -This document contains the release notes for the LLD linker, release 4.0.0. +LLD is a linker which supports ELF (Unix), COFF (Windows) and Mach-O +(macOS). It is generally faster than the GNU BFD/gold linkers or the +MSVC linker. + +LLD is designed to be a drop-in replacement for the system linkers, so +that users don't need to change their build systems other than swapping +the linker command. + +This document contains the release notes for LLD 4.0.0. Here we describe the status of LLD, including major improvements from the previous release. All LLD releases may be downloaded from the `LLVM releases web site `_. -Non-comprehensive list of changes in this release -================================================= + +What's New in LLD 4.0? +====================== ELF Improvements ---------------- -* Initial support for LTO. +LLD provides much better compatibility with the GNU linker than before. +Now it is able to link the entire FreeBSD base system including the kernel +out of the box. We are working closely with the FreeBSD project to +make it usable as the system linker in a future release of the operating +system. -COFF Improvements ------------------ +Multi-threading performance has been improved, and multi-threading +is now enabled by default. Combined with other optimizations, LLD 4.0 +is about 1.5 times faster than LLD 3.9 when linking large programs +in our test environment. + +Other notable changes are listed below: + +* Error messages contain more information than before. If debug info + is available, the linker prints out not only the object file name + but the source location of unresolved symbols. + +* Error messages are printed in red just like Clang by default. You + can disable it by passing ``-no-color-diagnostics``. + +* LLD's version string is now embedded in a .comment section in the + result output file. You can dump it with this command: ``objdump -j -s + .comment ``. + +* The ``-Map`` option is supported. With that, you can print out section + and symbol information to a specified file. This feature is useful + for analyzing link results. -* Item 1. +* The file format for the ``-reproduce`` option has changed from cpio to + tar. -MachO Improvements ------------------- +* When creating a copy relocation for a symbol, LLD now scans the + DSO's header to see if the symbol is in a read-only segment. If so, + space for the copy relocation is reserved in .bss.rel.ro instead of + .bss. This fixes a security issue that read-only data in a DSO + becomes writable if it is copied by a copy relocation. This issue + was disclosed originally on the + `binutils mailing list `_. + +* Compressed input sections are supported. + +* ``--oformat binary``, ``--section-start``, ``-Tbss``, ``-Tdata``, + ``-Ttext``, ``-b binary``, ``-build-id=uuid``, ``-no-rosegment``, + ``-nopie``, ``-nostdlib``, ``-omagic``, ``-retain-symbols-file``, + ``-sort-section``, ``-z max-page-size`` and ``-z wxneeded`` are + supported. + +* A lot of linker script directives have been added. + +* Default image base address for x86-64 has changed from 0x10000 to + 0x200000 to make it huge-page friendly. + +* ARM port now supports GNU ifunc, the ARM C++ exceptions ABI, TLS + relocations and static linking. Problems with ``dlopen()`` on systems + using eglibc fixed. + +* MIPS port now supports input files in new R6 revision of MIPS ABIs + or N32 ABI. Generated file now contains .MIPS.abiflags section and + complete set of ELF headers flags. + +* Relocations produced by the ``-mxgot`` compiler flag is supported + for MIPS. Now it is possible to generate "large" GOT that exceeds the 64K + limit. + +COFF Improvements +----------------- -* Item 1. +* Performance on Windows has been improved by parallelizing parts of the + linker and optimizing file system operations. As a result of these + improvements, LLD 4.0 has been measured to be about 2.5 times faster + than LLD 3.9 when linking a large Chromium DLL. diff --git a/gnu/llvm/tools/lld/docs/conf.py b/gnu/llvm/tools/lld/docs/conf.py index 6faed2fc980..8abd6f4facb 100644 --- a/gnu/llvm/tools/lld/docs/conf.py +++ b/gnu/llvm/tools/lld/docs/conf.py @@ -48,9 +48,9 @@ copyright = u'2011-%d, LLVM Project' % date.today().year # built documents. # # The short X.Y version. -version = '4.0' +version = '4' # The full version, including alpha/beta/rc tags. -release = '4.0' +release = '4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -- cgit v1.2.3