Author: dim Date: Sat Jan 14 15:39:25 2017 New Revision: 312181 URL: https://svnweb.freebsd.org/changeset/base/312181
Log: Vendor import of lld release_40 branch r292009: https://llvm.org/svn/llvm-project/lld/branches/release_40@292009 Added: vendor/lld/dist/test/COFF/Inputs/pdb1.yaml vendor/lld/dist/test/COFF/Inputs/pdb2.yaml vendor/lld/dist/test/ELF/Inputs/relocation-copy-relro.s (contents, props changed) vendor/lld/dist/test/ELF/Inputs/unknown-reloc.s (contents, props changed) vendor/lld/dist/test/ELF/incompatible-section-types2.s (contents, props changed) vendor/lld/dist/test/ELF/merge-section-types.s (contents, props changed) vendor/lld/dist/test/ELF/relocation-copy-relro.s (contents, props changed) vendor/lld/dist/test/ELF/relocation-none-i686.test vendor/lld/dist/test/ELF/unknown-reloc.s (contents, props changed) vendor/lld/dist/test/ELF/version-script-anonymous-local.s (contents, props changed) Deleted: vendor/lld/dist/test/COFF/dumppdb.test Modified: vendor/lld/dist/CMakeLists.txt vendor/lld/dist/COFF/PDB.cpp vendor/lld/dist/ELF/Driver.cpp vendor/lld/dist/ELF/Error.cpp vendor/lld/dist/ELF/Error.h vendor/lld/dist/ELF/InputFiles.cpp vendor/lld/dist/ELF/InputSection.cpp vendor/lld/dist/ELF/InputSection.h vendor/lld/dist/ELF/LinkerScript.cpp vendor/lld/dist/ELF/OutputSections.cpp vendor/lld/dist/ELF/OutputSections.h vendor/lld/dist/ELF/Relocations.cpp vendor/lld/dist/ELF/SymbolTable.cpp vendor/lld/dist/ELF/Symbols.cpp vendor/lld/dist/ELF/Symbols.h vendor/lld/dist/ELF/SyntheticSections.cpp vendor/lld/dist/ELF/Target.cpp vendor/lld/dist/ELF/Writer.cpp vendor/lld/dist/test/COFF/pdb.test vendor/lld/dist/test/ELF/Inputs/copy-rel-pie.s vendor/lld/dist/test/ELF/aarch64-condb-reloc.s vendor/lld/dist/test/ELF/aarch64-gnu-ifunc-plt.s vendor/lld/dist/test/ELF/aarch64-tstbr14-reloc.s vendor/lld/dist/test/ELF/amdgpu-relocs.s vendor/lld/dist/test/ELF/arm-abs32-dyn.s vendor/lld/dist/test/ELF/arm-exidx-shared.s vendor/lld/dist/test/ELF/arm-fpic-got.s vendor/lld/dist/test/ELF/arm-gnu-ifunc-plt.s vendor/lld/dist/test/ELF/arm-pie-relative.s vendor/lld/dist/test/ELF/arm-plt-reloc.s vendor/lld/dist/test/ELF/arm-thumb-interwork-shared.s vendor/lld/dist/test/ELF/arm-thumb-plt-reloc.s vendor/lld/dist/test/ELF/arm-tls-norelax-gd-ie.s vendor/lld/dist/test/ELF/arm-tls-norelax-gd-le.s vendor/lld/dist/test/ELF/arm-tls-norelax-ie-le.s vendor/lld/dist/test/ELF/arm-tls-norelax-ld-le.s vendor/lld/dist/test/ELF/basic-mips.s vendor/lld/dist/test/ELF/basic.s vendor/lld/dist/test/ELF/basic64be.s vendor/lld/dist/test/ELF/combrelocs.s vendor/lld/dist/test/ELF/copy-rel-pie.s vendor/lld/dist/test/ELF/dynamic-reloc-index.s vendor/lld/dist/test/ELF/dynamic-reloc.s vendor/lld/dist/test/ELF/format-binary.test vendor/lld/dist/test/ELF/gnu-ifunc-plt-i386.s vendor/lld/dist/test/ELF/gnu-ifunc-plt.s vendor/lld/dist/test/ELF/gnu-ifunc-shared.s vendor/lld/dist/test/ELF/got-aarch64.s vendor/lld/dist/test/ELF/got-plt-header.s vendor/lld/dist/test/ELF/gotpc-relax-nopic.s vendor/lld/dist/test/ELF/i386-merge.s vendor/lld/dist/test/ELF/incompatible-section-types.s vendor/lld/dist/test/ELF/invalid/invalid-relocation-x64.s vendor/lld/dist/test/ELF/linkerscript/orphan.s vendor/lld/dist/test/ELF/linkerscript/repsection-symbol.s vendor/lld/dist/test/ELF/linkerscript/sort-non-script.s vendor/lld/dist/test/ELF/lto/undefined-puts.ll vendor/lld/dist/test/ELF/lto/visibility.ll vendor/lld/dist/test/ELF/mips-26.s vendor/lld/dist/test/ELF/mips-32.s vendor/lld/dist/test/ELF/mips-64-disp.s vendor/lld/dist/test/ELF/mips-64-got.s vendor/lld/dist/test/ELF/mips-64.s vendor/lld/dist/test/ELF/mips-dynamic.s vendor/lld/dist/test/ELF/mips-got-and-copy.s vendor/lld/dist/test/ELF/mips-got-extsym.s vendor/lld/dist/test/ELF/mips-got-hilo.s vendor/lld/dist/test/ELF/mips-got-redundant.s vendor/lld/dist/test/ELF/mips-got-relocs.s vendor/lld/dist/test/ELF/mips-got-weak.s vendor/lld/dist/test/ELF/mips-got16.s vendor/lld/dist/test/ELF/mips-gp-ext.s vendor/lld/dist/test/ELF/mips-gp-lowest.s vendor/lld/dist/test/ELF/mips-hilo-gp-disp.s vendor/lld/dist/test/ELF/mips-hilo.s vendor/lld/dist/test/ELF/mips-options.s vendor/lld/dist/test/ELF/mips-pc-relocs.s vendor/lld/dist/test/ELF/mips-plt-r6.s vendor/lld/dist/test/ELF/mips-tls-64.s vendor/lld/dist/test/ELF/mips-tls-static-64.s vendor/lld/dist/test/ELF/mips-tls-static.s vendor/lld/dist/test/ELF/mips-tls.s vendor/lld/dist/test/ELF/mips-xgot-order.s vendor/lld/dist/test/ELF/plt-aarch64.s vendor/lld/dist/test/ELF/plt-i686.s vendor/lld/dist/test/ELF/plt.s vendor/lld/dist/test/ELF/ppc64-relocs.s vendor/lld/dist/test/ELF/ppc64-shared-rel-toc.s vendor/lld/dist/test/ELF/ppc64-toc-restore.s vendor/lld/dist/test/ELF/rel-offset.s vendor/lld/dist/test/ELF/relative-dynamic-reloc-pie.s vendor/lld/dist/test/ELF/relative-dynamic-reloc-ppc64.s vendor/lld/dist/test/ELF/relative-dynamic-reloc.s vendor/lld/dist/test/ELF/relocation-copy-flags.s vendor/lld/dist/test/ELF/relocation-i686.s vendor/lld/dist/test/ELF/relocation-non-alloc.s vendor/lld/dist/test/ELF/relocation.s vendor/lld/dist/test/ELF/section-layout.s vendor/lld/dist/test/ELF/section-name.s vendor/lld/dist/test/ELF/sort-norosegment.s vendor/lld/dist/test/ELF/startstop.s vendor/lld/dist/test/ELF/synthetic-got.s vendor/lld/dist/test/ELF/tls-dynamic-i686.s vendor/lld/dist/test/ELF/tls-dynamic.s vendor/lld/dist/test/ELF/tls-offset.s vendor/lld/dist/test/ELF/undef-with-plt-addr.s vendor/lld/dist/test/ELF/undefined-versioned-symbol.s vendor/lld/dist/test/ELF/x86-64-tls-gd-local.s Modified: vendor/lld/dist/CMakeLists.txt ============================================================================== --- vendor/lld/dist/CMakeLists.txt Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/CMakeLists.txt Sat Jan 14 15:39:25 2017 (r312181) @@ -12,6 +12,7 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRE endif() execute_process(COMMAND "${LLVM_CONFIG_PATH}" "--obj-root" "--includedir" + "--cmakedir" RESULT_VARIABLE HAD_ERROR OUTPUT_VARIABLE LLVM_CONFIG_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -23,12 +24,12 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRE list(GET LLVM_CONFIG_OUTPUT 0 OBJ_ROOT) list(GET LLVM_CONFIG_OUTPUT 1 MAIN_INCLUDE_DIR) + list(GET LLVM_CONFIG_OUTPUT 2 LLVM_CMAKE_PATH) set(LLVM_OBJ_ROOT ${OBJ_ROOT} CACHE PATH "path to LLVM build tree") set(LLVM_MAIN_INCLUDE_DIR ${MAIN_INCLUDE_DIR} CACHE PATH "path to llvm/include") file(TO_CMAKE_PATH ${LLVM_OBJ_ROOT} LLVM_BINARY_DIR) - set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") if(NOT EXISTS "${LLVM_CMAKE_PATH}/LLVMConfig.cmake") message(FATAL_ERROR "LLVMConfig.cmake not found") Modified: vendor/lld/dist/COFF/PDB.cpp ============================================================================== --- vendor/lld/dist/COFF/PDB.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/COFF/PDB.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -14,8 +14,12 @@ #include "SymbolTable.h" #include "Symbols.h" #include "llvm/DebugInfo/CodeView/CVDebugRecord.h" +#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/SymbolDumper.h" -#include "llvm/DebugInfo/CodeView/TypeDumper.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" +#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/DebugInfo/MSF/ByteStream.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" @@ -61,44 +65,75 @@ static SectionChunk *findByName(std::vec return nullptr; } -static ArrayRef<uint8_t> getDebugT(ObjectFile *File) { - SectionChunk *Sec = findByName(File->getDebugChunks(), ".debug$T"); +static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) { + SectionChunk *Sec = findByName(File->getDebugChunks(), SecName); if (!Sec) return {}; // First 4 bytes are section magic. ArrayRef<uint8_t> Data = Sec->getContents(); if (Data.size() < 4) - fatal(".debug$T too short"); + fatal(SecName + " too short"); if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC) - fatal(".debug$T has an invalid magic"); + fatal(SecName + " has an invalid magic"); return Data.slice(4); } +// Merge .debug$T sections and returns it. +static std::vector<uint8_t> mergeDebugT(SymbolTable *Symtab) { + ScopedPrinter W(outs()); + + // Visit all .debug$T sections to add them to Builder. + codeview::TypeTableBuilder Builder(BAlloc); + for (ObjectFile *File : Symtab->ObjectFiles) { + ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); + if (Data.empty()) + continue; + + msf::ByteStream Stream(Data); + codeview::CVTypeArray Types; + msf::StreamReader Reader(Stream); + if (auto EC = Reader.readArray(Types, Reader.getLength())) + fatal(EC, "Reader::readArray failed"); + if (!codeview::mergeTypeStreams(Builder, Types)) + fatal("codeview::mergeTypeStreams failed"); + } + + // Construct section contents. + std::vector<uint8_t> V; + Builder.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Rec) { + V.insert(V.end(), Rec.begin(), Rec.end()); + }); + return V; +} + static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) { - ArrayRef<uint8_t> Data = getDebugT(File); + ListScope LS(W, "DebugT"); + ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); if (Data.empty()) return; - msf::ByteStream Stream(Data); - CVTypeDumper TypeDumper(&W, false); - if (auto EC = TypeDumper.dump(Data)) + TypeDatabase TDB; + TypeDumpVisitor TDV(TDB, &W, false); + CVTypeDumper TypeDumper(TDB); + if (auto EC = TypeDumper.dump(Data, TDV)) fatal(EC, "CVTypeDumper::dump failed"); } static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) { - SectionChunk *Sec = findByName(File->getDebugChunks(), ".debug$S"); - if (!Sec) + ListScope LS(W, "DebugS"); + ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$S"); + if (Data.empty()) return; - msf::ByteStream Stream(Sec->getContents()); + msf::ByteStream Stream(Data); CVSymbolArray Symbols; msf::StreamReader Reader(Stream); if (auto EC = Reader.readArray(Symbols, Reader.getLength())) fatal(EC, "StreamReader.readArray<CVSymbolArray> failed"); - CVTypeDumper TypeDumper(&W, false); - CVSymbolDumper SymbolDumper(W, TypeDumper, nullptr, false); + TypeDatabase TDB; + CVSymbolDumper SymbolDumper(W, TDB, nullptr, false); if (auto EC = SymbolDumper.dump(Symbols)) fatal(EC, "CVSymbolDumper::dump failed"); } @@ -113,21 +148,15 @@ static void dumpCodeView(SymbolTable *Sy } } -static void addTypeInfo(SymbolTable *Symtab, - pdb::TpiStreamBuilder &TpiBuilder) { - for (ObjectFile *File : Symtab->ObjectFiles) { - ArrayRef<uint8_t> Data = getDebugT(File); - if (Data.empty()) - continue; - - msf::ByteStream Stream(Data); - codeview::CVTypeArray Records; - msf::StreamReader Reader(Stream); - if (auto EC = Reader.readArray(Records, Reader.getLength())) - fatal(EC, "Reader.readArray failed"); - for (const codeview::CVType &Rec : Records) - TpiBuilder.addTypeRecord(Rec); - } +static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, + ArrayRef<uint8_t> Data) { + msf::ByteStream Stream(Data); + codeview::CVTypeArray Records; + msf::StreamReader Reader(Stream); + if (auto EC = Reader.readArray(Records, Reader.getLength())) + fatal(EC, "Reader.readArray failed"); + for (const codeview::CVType &Rec : Records) + TpiBuilder.addTypeRecord(Rec); } // Creates a PDB file. @@ -162,8 +191,11 @@ void coff::createPDB(StringRef Path, Sym // Add an empty TPI stream. auto &TpiBuilder = Builder.getTpiBuilder(); TpiBuilder.setVersionHeader(pdb::PdbTpiV80); - if (Config->DebugPdb) - addTypeInfo(Symtab, TpiBuilder); + std::vector<uint8_t> TpiData; + if (Config->DebugPdb) { + TpiData = mergeDebugT(Symtab); + addTypeInfo(TpiBuilder, TpiData); + } // Add an empty IPI stream. auto &IpiBuilder = Builder.getIpiBuilder(); Modified: vendor/lld/dist/ELF/Driver.cpp ============================================================================== --- vendor/lld/dist/ELF/Driver.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/Driver.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -24,6 +24,7 @@ #include "lld/Driver/Driver.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Object/Decompressor.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Path.h" #include "llvm/Support/TarWriter.h" @@ -815,7 +816,7 @@ template <class ELFT> void LinkerDriver: [](InputSectionBase<ELFT> *S) { if (!S->Live) return; - if (S->isCompressed()) + if (Decompressor::isCompressedELFSection(S->Flags, S->Name)) S->uncompress(); if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(S)) MS->splitIntoPieces(); Modified: vendor/lld/dist/ELF/Error.cpp ============================================================================== --- vendor/lld/dist/ELF/Error.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/Error.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -103,4 +103,8 @@ void elf::fatal(std::error_code EC, cons fatal(Prefix + ": " + EC.message()); } +void elf::fatal(Error &E, const Twine &Prefix) { + fatal(Prefix + ": " + llvm::toString(std::move(E))); +} + } // namespace lld Modified: vendor/lld/dist/ELF/Error.h ============================================================================== --- vendor/lld/dist/ELF/Error.h Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/Error.h Sat Jan 14 15:39:25 2017 (r312181) @@ -44,6 +44,7 @@ void error(std::error_code EC, const Twi LLVM_ATTRIBUTE_NORETURN void exitLld(int Val); LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix); +LLVM_ATTRIBUTE_NORETURN void fatal(Error &E, const Twine &Prefix); // check() functions are convenient functions to strip errors // from error-or-value objects. @@ -55,11 +56,7 @@ template <class T> T check(ErrorOr<T> E) template <class T> T check(Expected<T> E) { if (!E) - handleAllErrors(std::move(E.takeError()), - [](llvm::ErrorInfoBase &EIB) -> Error { - fatal(EIB.message()); - return Error::success(); - }); + fatal(llvm::toString(E.takeError())); return std::move(*E); } Modified: vendor/lld/dist/ELF/InputFiles.cpp ============================================================================== --- vendor/lld/dist/ELF/InputFiles.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/InputFiles.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -857,8 +857,8 @@ template <class ELFT> void BinaryFile::p StringRef EndName = Saver.save(Twine(Filename) + "_end"); StringRef SizeName = Saver.save(Twine(Filename) + "_size"); - auto *Section = - make<InputSection<ELFT>>(SHF_ALLOC, SHT_PROGBITS, 8, Data, ".data"); + auto *Section = make<InputSection<ELFT>>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, + 8, Data, ".data"); Sections.push_back(Section); elf::Symtab<ELFT>::X->addRegular(StartName, STV_DEFAULT, STT_OBJECT, 0, 0, Modified: vendor/lld/dist/ELF/InputSection.cpp ============================================================================== --- vendor/lld/dist/ELF/InputSection.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/InputSection.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -19,6 +19,7 @@ #include "SyntheticSections.h" #include "Target.h" #include "Thunks.h" +#include "llvm/Object/Decompressor.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" #include <mutex> @@ -35,7 +36,10 @@ using namespace lld::elf; // Returns a string to construct an error message. template <class ELFT> std::string lld::toString(const InputSectionBase<ELFT> *Sec) { - return (Sec->getFile()->getName() + ":(" + Sec->Name + ")").str(); + // File can be absent if section is synthetic. + std::string FileName = + Sec->getFile() ? Sec->getFile()->getName() : "<internal>"; + return (FileName + ":(" + Sec->Name + ")").str(); } template <class ELFT> @@ -102,11 +106,6 @@ template <class ELFT> size_t InputSectio return Data.size(); } -// Returns a string for an error message. -template <class SectionT> static std::string getName(SectionT *Sec) { - return (Sec->getFile()->getName() + ":(" + Sec->Name + ")").str(); -} - template <class ELFT> typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const { switch (kind()) { @@ -128,71 +127,23 @@ typename ELFT::uint InputSectionBase<ELF llvm_unreachable("invalid section kind"); } -template <class ELFT> bool InputSectionBase<ELFT>::isCompressed() const { - return (Flags & SHF_COMPRESSED) || Name.startswith(".zdebug"); -} - -// Returns compressed data and its size when uncompressed. -template <class ELFT> -std::pair<ArrayRef<uint8_t>, uint64_t> -InputSectionBase<ELFT>::getElfCompressedData(ArrayRef<uint8_t> Data) { - // Compressed section with Elf_Chdr is the ELF standard. - if (Data.size() < sizeof(Elf_Chdr)) - fatal(toString(this) + ": corrupted compressed section"); - auto *Hdr = reinterpret_cast<const Elf_Chdr *>(Data.data()); - if (Hdr->ch_type != ELFCOMPRESS_ZLIB) - fatal(toString(this) + ": unsupported compression type"); - return {Data.slice(sizeof(*Hdr)), Hdr->ch_size}; -} - -// Returns compressed data and its size when uncompressed. -template <class ELFT> -std::pair<ArrayRef<uint8_t>, uint64_t> -InputSectionBase<ELFT>::getRawCompressedData(ArrayRef<uint8_t> Data) { - // Compressed sections without Elf_Chdr header contain this header - // instead. This is a GNU extension. - struct ZlibHeader { - char Magic[4]; // Should be "ZLIB" - char Size[8]; // Uncompressed size in big-endian - }; - - if (Data.size() < sizeof(ZlibHeader)) - fatal(toString(this) + ": corrupted compressed section"); - auto *Hdr = reinterpret_cast<const ZlibHeader *>(Data.data()); - if (memcmp(Hdr->Magic, "ZLIB", 4)) - fatal(toString(this) + ": broken ZLIB-compressed section"); - return {Data.slice(sizeof(*Hdr)), read64be(Hdr->Size)}; -} - // Uncompress section contents. Note that this function is called // from parallel_for_each, so it must be thread-safe. template <class ELFT> void InputSectionBase<ELFT>::uncompress() { - if (!zlib::isAvailable()) - fatal(toString(this) + - ": build lld with zlib to enable compressed sections support"); - - // This section is compressed. Here we decompress it. Ideally, all - // compressed sections have SHF_COMPRESSED bit and their contents - // start with headers of Elf_Chdr type. However, sections whose - // names start with ".zdebug_" don't have the bit and contains a raw - // ZLIB-compressed data (which is a bad thing because section names - // shouldn't be significant in ELF.) We need to be able to read both. - ArrayRef<uint8_t> Buf; // Compressed data - size_t Size; // Uncompressed size - if (Flags & SHF_COMPRESSED) - std::tie(Buf, Size) = getElfCompressedData(Data); - else - std::tie(Buf, Size) = getRawCompressedData(Data); + Decompressor Decompressor = check(Decompressor::create( + Name, toStringRef(Data), ELFT::TargetEndianness == llvm::support::little, + ELFT::Is64Bits)); - // Uncompress Buf. + size_t Size = Decompressor.getDecompressedSize(); char *OutputBuf; { static std::mutex Mu; std::lock_guard<std::mutex> Lock(Mu); OutputBuf = BAlloc.Allocate<char>(Size); } - if (zlib::uncompress(toStringRef(Buf), OutputBuf, Size) != zlib::StatusOK) - fatal(toString(this) + ": error while uncompressing section"); + + if (Error E = Decompressor.decompress({OutputBuf, Size})) + fatal(E, toString(this)); Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size); } Modified: vendor/lld/dist/ELF/InputSection.h ============================================================================== --- vendor/lld/dist/ELF/InputSection.h Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/InputSection.h Sat Jan 14 15:39:25 2017 (r312181) @@ -138,22 +138,12 @@ public: // section. uintX_t getOffset(uintX_t Offset) const; - // ELF supports ZLIB-compressed section. - // Returns true if the section is compressed. - bool isCompressed() const; void uncompress(); // Returns a source location string. Used to construct an error message. std::string getLocation(uintX_t Offset); void relocate(uint8_t *Buf, uint8_t *BufEnd); - -private: - std::pair<ArrayRef<uint8_t>, uint64_t> - getElfCompressedData(ArrayRef<uint8_t> Data); - - std::pair<ArrayRef<uint8_t>, uint64_t> - getRawCompressedData(ArrayRef<uint8_t> Data); }; // SectionPiece represents a piece of splittable section contents. Modified: vendor/lld/dist/ELF/LinkerScript.cpp ============================================================================== --- vendor/lld/dist/ELF/LinkerScript.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/LinkerScript.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -1014,6 +1014,7 @@ private: void readAnonymousDeclaration(); void readVersionDeclaration(StringRef VerStr); std::vector<SymbolVersion> readSymbols(); + void readLocals(); ScriptConfiguration &Opt = *ScriptConfig; bool IsUnderSysroot; @@ -1861,17 +1862,22 @@ void ScriptParser::readAnonymousDeclarat if (consume("global:") || peek() != "local:") Config->VersionScriptGlobals = readSymbols(); - // Next, read local symbols. - if (consume("local:")) { - if (consume("*")) { + readLocals(); + expect("}"); + expect(";"); +} + +void ScriptParser::readLocals() { + if (!consume("local:")) + return; + std::vector<SymbolVersion> Locals = readSymbols(); + for (SymbolVersion V : Locals) { + if (V.Name == "*") { Config->DefaultSymbolVersion = VER_NDX_LOCAL; - expect(";"); - } else { - setError("local symbol list for anonymous version is not supported"); + continue; } + Config->VersionScriptLocals.push_back(V); } - expect("}"); - expect(";"); } // Reads a list of symbols, e.g. "VerStr { global: foo; bar; local: *; };". @@ -1885,16 +1891,7 @@ void ScriptParser::readVersionDeclaratio if (consume("global:") || peek() != "local:") Config->VersionDefinitions.back().Globals = readSymbols(); - // Read local symbols. - if (consume("local:")) { - if (consume("*")) { - Config->DefaultSymbolVersion = VER_NDX_LOCAL; - expect(";"); - } else { - for (SymbolVersion V : readSymbols()) - Config->VersionScriptLocals.push_back(V); - } - } + readLocals(); expect("}"); // Each version may have a parent version. For example, "Ver2" Modified: vendor/lld/dist/ELF/OutputSections.cpp ============================================================================== --- vendor/lld/dist/ELF/OutputSections.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/OutputSections.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -636,7 +636,12 @@ OutputSectionFactory<ELFT>::create(const if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(C->Flags)) error("Section has flags incompatible with others with the same name " + toString(C)); - if (Sec->Type != C->Type) + // Convert notbits to progbits if they are mixed. This happens is some + // linker scripts. + if (Sec->Type == SHT_NOBITS && C->Type == SHT_PROGBITS) + Sec->Type = SHT_PROGBITS; + if (Sec->Type != C->Type && + !(Sec->Type == SHT_PROGBITS && C->Type == SHT_NOBITS)) error("Section has different type from others with the same name " + toString(C)); Sec->Flags |= Flags; Modified: vendor/lld/dist/ELF/OutputSections.h ============================================================================== --- vendor/lld/dist/ELF/OutputSections.h Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/OutputSections.h Sat Jan 14 15:39:25 2017 (r312181) @@ -206,6 +206,7 @@ template <class ELFT> struct Out { static uint8_t First; static EhOutputSection<ELFT> *EhFrame; static OutputSection<ELFT> *Bss; + static OutputSection<ELFT> *BssRelRo; static OutputSectionBase *Opd; static uint8_t *OpdBuf; static PhdrEntry *TlsPhdr; @@ -252,6 +253,7 @@ template <class ELFT> uint64_t getHeader template <class ELFT> uint8_t Out<ELFT>::First; template <class ELFT> EhOutputSection<ELFT> *Out<ELFT>::EhFrame; template <class ELFT> OutputSection<ELFT> *Out<ELFT>::Bss; +template <class ELFT> OutputSection<ELFT> *Out<ELFT>::BssRelRo; template <class ELFT> OutputSectionBase *Out<ELFT>::Opd; template <class ELFT> uint8_t *Out<ELFT>::OpdBuf; template <class ELFT> PhdrEntry *Out<ELFT>::TlsPhdr; Modified: vendor/lld/dist/ELF/Relocations.cpp ============================================================================== --- vendor/lld/dist/ELF/Relocations.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/Relocations.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -399,7 +399,21 @@ template <class ELFT> static uint32_t ge return 1 << TrailingZeros; } -// Reserve space in .bss for copy relocation. +template <class ELFT> static bool isReadOnly(SharedSymbol<ELFT> *SS) { + typedef typename ELFT::uint uintX_t; + typedef typename ELFT::Phdr Elf_Phdr; + + // Determine if the symbol is read-only by scanning the DSO's program headers. + uintX_t Value = SS->Sym.st_value; + for (const Elf_Phdr &Phdr : check(SS->file()->getObj().program_headers())) + if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) && + !(Phdr.p_flags & ELF::PF_W) && Value >= Phdr.p_vaddr && + Value < Phdr.p_vaddr + Phdr.p_memsz) + return true; + return false; +} + +// Reserve space in .bss or .bss.rel.ro for copy relocation. template <class ELFT> static void addCopyRelSymbol(SharedSymbol<ELFT> *SS) { typedef typename ELFT::uint uintX_t; typedef typename ELFT::Sym Elf_Sym; @@ -409,10 +423,16 @@ template <class ELFT> static void addCop if (SymSize == 0) fatal("cannot create a copy relocation for symbol " + toString(*SS)); + // See if this symbol is in a read-only segment. If so, preserve the symbol's + // memory protection by reserving space in the .bss.rel.ro section. + bool IsReadOnly = isReadOnly(SS); + OutputSection<ELFT> *CopySec = + IsReadOnly ? Out<ELFT>::BssRelRo : Out<ELFT>::Bss; + uintX_t Alignment = getAlignment(SS); - uintX_t Off = alignTo(Out<ELFT>::Bss->Size, Alignment); - Out<ELFT>::Bss->Size = Off + SymSize; - Out<ELFT>::Bss->updateAlignment(Alignment); + uintX_t Off = alignTo(CopySec->Size, Alignment); + CopySec->Size = Off + SymSize; + CopySec->updateAlignment(Alignment); uintX_t Shndx = SS->Sym.st_shndx; uintX_t Value = SS->Sym.st_value; // Look through the DSO's dynamic symbol table for aliases and create a @@ -425,12 +445,12 @@ template <class ELFT> static void addCop Symtab<ELFT>::X->find(check(S.getName(SS->file()->getStringTable())))); if (!Alias) continue; - Alias->OffsetInBss = Off; + Alias->CopyIsInBssRelRo = IsReadOnly; + Alias->CopyOffset = Off; Alias->NeedsCopyOrPltAddr = true; Alias->symbol()->IsUsedInRegularObj = true; } - In<ELFT>::RelaDyn->addReloc( - {Target->CopyRel, Out<ELFT>::Bss, SS->OffsetInBss, false, SS, 0}); + In<ELFT>::RelaDyn->addReloc({Target->CopyRel, CopySec, Off, false, SS, 0}); } template <class ELFT> Modified: vendor/lld/dist/ELF/SymbolTable.cpp ============================================================================== --- vendor/lld/dist/ELF/SymbolTable.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/SymbolTable.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -605,19 +605,16 @@ SymbolTable<ELFT>::findAllByVersion(Symb // If there's only one anonymous version definition in a version // script file, the script does not actually define any symbol version, -// but just specifies symbols visibilities. We assume that the script was -// in the form of { global: foo; bar; local *; }. So, local is default. -// In this function, we make specified symbols global. +// but just specifies symbols visibilities. template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() { - for (SymbolVersion &Ver : Config->VersionScriptGlobals) { - if (Ver.HasWildcard) { - for (SymbolBody *B : findAllByVersion(Ver)) - B->symbol()->VersionId = VER_NDX_GLOBAL; - continue; - } - for (SymbolBody *B : findByVersion(Ver)) - B->symbol()->VersionId = VER_NDX_GLOBAL; - } + for (SymbolVersion &Ver : Config->VersionScriptGlobals) + assignExactVersion(Ver, VER_NDX_GLOBAL, "global"); + for (SymbolVersion &Ver : Config->VersionScriptGlobals) + assignWildcardVersion(Ver, VER_NDX_GLOBAL); + for (SymbolVersion &Ver : Config->VersionScriptLocals) + assignExactVersion(Ver, VER_NDX_LOCAL, "local"); + for (SymbolVersion &Ver : Config->VersionScriptLocals) + assignWildcardVersion(Ver, VER_NDX_LOCAL); } // Set symbol versions to symbols. This function handles patterns @@ -673,10 +670,7 @@ template <class ELFT> void SymbolTable<E Sym->body()->parseSymbolVersion(); // Handle edge cases first. - if (!Config->VersionScriptGlobals.empty()) { - handleAnonymousVersion(); - return; - } + handleAnonymousVersion(); if (Config->VersionDefinitions.empty()) return; @@ -687,8 +681,6 @@ template <class ELFT> void SymbolTable<E // First, we assign versions to exact matching symbols, // i.e. version definitions not containing any glob meta-characters. - for (SymbolVersion &Ver : Config->VersionScriptLocals) - assignExactVersion(Ver, VER_NDX_LOCAL, "local"); for (VersionDefinition &V : Config->VersionDefinitions) for (SymbolVersion &Ver : V.Globals) assignExactVersion(Ver, V.Id, V.Name); @@ -697,8 +689,6 @@ template <class ELFT> void SymbolTable<E // i.e. version definitions containing glob meta-characters. // Note that because the last match takes precedence over previous matches, // we iterate over the definitions in the reverse order. - for (SymbolVersion &Ver : Config->VersionScriptLocals) - assignWildcardVersion(Ver, VER_NDX_LOCAL); for (VersionDefinition &V : llvm::reverse(Config->VersionDefinitions)) for (SymbolVersion &Ver : V.Globals) assignWildcardVersion(Ver, V.Id); Modified: vendor/lld/dist/ELF/Symbols.cpp ============================================================================== --- vendor/lld/dist/ELF/Symbols.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/Symbols.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -81,7 +81,7 @@ static typename ELFT::uint getSymVA(cons return 0; if (SS.isFunc()) return Body.getPltVA<ELFT>(); - return Out<ELFT>::Bss->Addr + SS.OffsetInBss; + return SS.getBssSectionForCopy()->Addr + SS.CopyOffset; } case SymbolBody::UndefinedKind: return 0; @@ -97,7 +97,8 @@ SymbolBody::SymbolBody(Kind K, StringRef uint8_t Type) : SymbolKind(K), NeedsCopyOrPltAddr(false), IsLocal(IsLocal), IsInGlobalMipsGot(false), Is32BitMipsGot(false), IsInIplt(false), - IsInIgot(false), Type(Type), StOther(StOther), Name(Name) {} + IsInIgot(false), CopyIsInBssRelRo(false), Type(Type), StOther(StOther), + Name(Name) {} // Returns true if a symbol can be replaced at load-time by a symbol // with the same name defined in other ELF executable or DSO. @@ -245,6 +246,12 @@ Undefined<ELFT>::Undefined(StringRefZ Na this->File = File; } +template <typename ELFT> +OutputSection<ELFT> *SharedSymbol<ELFT>::getBssSectionForCopy() const { + assert(needsCopy()); + return CopyIsInBssRelRo ? Out<ELFT>::BssRelRo : Out<ELFT>::Bss; +} + DefinedCommon::DefinedCommon(StringRef Name, uint64_t Size, uint64_t Alignment, uint8_t StOther, uint8_t Type, InputFile *File) : Defined(SymbolBody::DefinedCommonKind, Name, /*IsLocal=*/false, StOther, @@ -287,10 +294,22 @@ InputFile *LazyObject::fetch() { return createObjectFile(MBRef); } -bool Symbol::includeInDynsym() const { +uint8_t Symbol::computeBinding() const { + if (Config->Relocatable) + return Binding; if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) + return STB_LOCAL; + if (VersionId == VER_NDX_LOCAL && !body()->isUndefined()) + return STB_LOCAL; + if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE) + return STB_GLOBAL; + return Binding; +} + +bool Symbol::includeInDynsym() const { + if (computeBinding() == STB_LOCAL) return false; - return (ExportDynamic && VersionId != VER_NDX_LOCAL) || body()->isShared() || + return ExportDynamic || body()->isShared() || (body()->isUndefined() && Config->Shared); } @@ -366,6 +385,11 @@ template class elf::Undefined<ELF32BE>; template class elf::Undefined<ELF64LE>; template class elf::Undefined<ELF64BE>; +template class elf::SharedSymbol<ELF32LE>; +template class elf::SharedSymbol<ELF32BE>; +template class elf::SharedSymbol<ELF64LE>; +template class elf::SharedSymbol<ELF64BE>; + template class elf::DefinedRegular<ELF32LE>; template class elf::DefinedRegular<ELF32BE>; template class elf::DefinedRegular<ELF64LE>; Modified: vendor/lld/dist/ELF/Symbols.h ============================================================================== --- vendor/lld/dist/ELF/Symbols.h Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/Symbols.h Sat Jan 14 15:39:25 2017 (r312181) @@ -123,6 +123,11 @@ public: // True if this symbol is in the Igot sub-section of the .got.plt or .got. unsigned IsInIgot : 1; + // True if this is a shared symbol in a read-only segment which requires a + // copy relocation. This causes space for the symbol to be allocated in the + // .bss.rel.ro section. + unsigned CopyIsInBssRelRo : 1; + // The following fields have the same meaning as the ELF symbol attributes. uint8_t Type; // symbol type uint8_t StOther; // st_other field value @@ -282,13 +287,15 @@ public: // This field is a pointer to the symbol's version definition. const Elf_Verdef *Verdef; - // OffsetInBss is significant only when needsCopy() is true. - uintX_t OffsetInBss = 0; + // CopyOffset is significant only when needsCopy() is true. + uintX_t CopyOffset = 0; // If non-null the symbol has a Thunk that may be used as an alternative // destination for callers of this Symbol. Thunk<ELFT> *ThunkData = nullptr; bool needsCopy() const { return this->NeedsCopyOrPltAddr && !this->isFunc(); } + + OutputSection<ELFT> *getBssSectionForCopy() const; }; // This class represents a symbol defined in an archive file. It is @@ -413,6 +420,7 @@ struct Symbol { unsigned InVersionScript : 1; bool includeInDynsym() const; + uint8_t computeBinding() const; bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } // This field is used to store the Symbol's SymbolBody. This instantiation of Modified: vendor/lld/dist/ELF/SyntheticSections.cpp ============================================================================== --- vendor/lld/dist/ELF/SyntheticSections.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/SyntheticSections.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -1060,18 +1060,6 @@ static bool sortMipsSymbols(const Symbol return L->GotIndex < R->GotIndex; } -static uint8_t getSymbolBinding(SymbolBody *Body) { - Symbol *S = Body->symbol(); - if (Config->Relocatable) - return S->Binding; - uint8_t Visibility = S->Visibility; - if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) - return STB_LOCAL; - if (Config->NoGnuUnique && S->Binding == STB_GNU_UNIQUE) - return STB_GLOBAL; - return S->Binding; -} - template <class ELFT> void SymbolTableSection<ELFT>::finalize() { this->OutSec->Link = this->Link = StrTabSec.OutSec->SectionIndex; this->OutSec->Info = this->Info = NumLocals + 1; @@ -1085,11 +1073,12 @@ template <class ELFT> void SymbolTableSe } if (!StrTabSec.isDynamic()) { - std::stable_sort(Symbols.begin(), Symbols.end(), - [](const SymbolTableEntry &L, const SymbolTableEntry &R) { - return getSymbolBinding(L.Symbol) == STB_LOCAL && - getSymbolBinding(R.Symbol) != STB_LOCAL; - }); + std::stable_sort( + Symbols.begin(), Symbols.end(), + [](const SymbolTableEntry &L, const SymbolTableEntry &R) { + return L.Symbol->symbol()->computeBinding() == STB_LOCAL && + R.Symbol->symbol()->computeBinding() != STB_LOCAL; + }); return; } if (In<ELFT>::GnuHashTab) @@ -1159,7 +1148,7 @@ void SymbolTableSection<ELFT>::writeGlob uint8_t Type = Body->Type; uintX_t Size = Body->getSize<ELFT>(); - ESym->setBindingAndType(getSymbolBinding(Body), Type); + ESym->setBindingAndType(Body->symbol()->computeBinding(), Type); ESym->st_size = Size; ESym->st_name = StrOff; ESym->setVisibility(Body->symbol()->Visibility); @@ -1201,10 +1190,12 @@ SymbolTableSection<ELFT>::getOutputSecti } case SymbolBody::DefinedCommonKind: return In<ELFT>::Common->OutSec; - case SymbolBody::SharedKind: - if (cast<SharedSymbol<ELFT>>(Sym)->needsCopy()) - return Out<ELFT>::Bss; + case SymbolBody::SharedKind: { + auto &SS = cast<SharedSymbol<ELFT>>(*Sym); + if (SS.needsCopy()) + return SS.getBssSectionForCopy(); break; + } case SymbolBody::UndefinedKind: case SymbolBody::LazyArchiveKind: case SymbolBody::LazyObjectKind: Modified: vendor/lld/dist/ELF/Target.cpp ============================================================================== --- vendor/lld/dist/ELF/Target.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/Target.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -356,7 +356,9 @@ X86TargetInfo::X86TargetInfo() { RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const { switch (Type) { - default: + case R_386_16: + case R_386_32: + case R_386_TLS_LDO_32: return R_ABS; case R_386_TLS_GD: return R_TLSGD; @@ -381,6 +383,12 @@ RelExpr X86TargetInfo::getRelExpr(uint32 return R_TLS; case R_386_TLS_LE_32: return R_NEG_TLS; + case R_386_NONE: + return R_HINT; + default: + error("do not know how to handle relocation '" + toString(Type) + "' (" + + Twine(Type) + ")"); + return R_HINT; } } @@ -623,7 +631,11 @@ template <class ELFT> RelExpr X86_64TargetInfo<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S) const { switch (Type) { - default: + case R_X86_64_32: + case R_X86_64_32S: + case R_X86_64_64: + case R_X86_64_DTPOFF32: + case R_X86_64_DTPOFF64: return R_ABS; case R_X86_64_TPOFF32: return R_TLS; @@ -649,6 +661,10 @@ RelExpr X86_64TargetInfo<ELFT>::getRelEx return R_GOT_PC; case R_X86_64_NONE: return R_HINT; + default: + error("do not know how to handle relocation '" + toString(Type) + "' (" + + Twine(Type) + ")"); + return R_HINT; } } @@ -870,7 +886,7 @@ void X86_64TargetInfo<ELFT>::relocateOne write64le(Loc, Val); break; default: - error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + llvm_unreachable("unexpected relocation"); } } Modified: vendor/lld/dist/ELF/Writer.cpp ============================================================================== --- vendor/lld/dist/ELF/Writer.cpp Sat Jan 14 15:39:18 2017 (r312180) +++ vendor/lld/dist/ELF/Writer.cpp Sat Jan 14 15:39:25 2017 (r312181) @@ -250,6 +250,8 @@ template <class ELFT> void Writer<ELFT>: // Create singleton output sections. Out<ELFT>::Bss = make<OutputSection<ELFT>>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); + Out<ELFT>::BssRelRo = make<OutputSection<ELFT>>(".bss.rel.ro", SHT_NOBITS, + SHF_ALLOC | SHF_WRITE); In<ELFT>::DynStrTab = make<StringTableSection<ELFT>>(".dynstr", true); In<ELFT>::Dynamic = make<DynamicSection<ELFT>>(); Out<ELFT>::EhFrame = make<EhOutputSection<ELFT>>(); @@ -498,6 +500,8 @@ template <class ELFT> bool elf::isRelroS return true; if (In<ELFT>::MipsGot && Sec == In<ELFT>::MipsGot->OutSec) return true; + if (Sec == Out<ELFT>::BssRelRo) + return true; StringRef S = Sec->getName(); return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" || S == ".eh_frame" || S == ".openbsd.randomdata"; @@ -557,30 +561,38 @@ static bool compareSectionsNonScript(con // If we got here we know that both A and B are in the same PT_LOAD. - // The TLS initialization block needs to be a single contiguous block in a R/W - // PT_LOAD, so stick TLS sections directly before R/W sections. The TLS NOBITS - // sections are placed here as they don't take up virtual address space in the - // PT_LOAD. bool AIsTls = A->Flags & SHF_TLS; bool BIsTls = B->Flags & SHF_TLS; - if (AIsTls != BIsTls) - return AIsTls; - - // The next requirement we have is to put nobits sections last. The - // reason is that the only thing the dynamic linker will see about - // them is a p_memsz that is larger than p_filesz. Seeing that it - // zeros the end of the PT_LOAD, so that has to correspond to the - // nobits sections. bool AIsNoBits = A->Type == SHT_NOBITS; bool BIsNoBits = B->Type == SHT_NOBITS; - if (AIsNoBits != BIsNoBits) - return BIsNoBits; - // We place RelRo section before plain r/w ones. + // The first requirement we have is to put (non-TLS) nobits sections last. The + // reason is that the only thing the dynamic linker will see about them is a + // p_memsz that is larger than p_filesz. Seeing that it zeros the end of the + // PT_LOAD, so that has to correspond to the nobits sections. + bool AIsNonTlsNoBits = AIsNoBits && !AIsTls; + bool BIsNonTlsNoBits = BIsNoBits && !BIsTls; + if (AIsNonTlsNoBits != BIsNonTlsNoBits) + return BIsNonTlsNoBits; + + // We place nobits RelRo sections before plain r/w ones, and non-nobits RelRo + // sections after r/w ones, so that the RelRo sections are contiguous. bool AIsRelRo = isRelroSection<ELFT>(A); bool BIsRelRo = isRelroSection<ELFT>(B); if (AIsRelRo != BIsRelRo) - return AIsRelRo; + return AIsNonTlsNoBits ? AIsRelRo : BIsRelRo; + + // The TLS initialization block needs to be a single contiguous block in a R/W + // PT_LOAD, so stick TLS sections directly before the other RelRo R/W + // sections. The TLS NOBITS sections are placed here as they don't take up + // virtual address space in the PT_LOAD. + if (AIsTls != BIsTls) + return AIsTls; + + // Within the TLS initialization block, the non-nobits sections need to appear + // first. + if (AIsNoBits != BIsNoBits) + return BIsNoBits; // Some architectures have additional ordering restrictions for sections // within the same PT_LOAD. @@ -1071,6 +1083,8 @@ template <class ELFT> void Writer<ELFT>: template <class ELFT> void Writer<ELFT>::addPredefinedSections() { if (Out<ELFT>::Bss->Size > 0) OutputSections.push_back(Out<ELFT>::Bss); + if (Out<ELFT>::BssRelRo->Size > 0) + OutputSections.push_back(Out<ELFT>::BssRelRo); auto OS = dyn_cast_or_null<OutputSection<ELFT>>(findSection(".ARM.exidx")); if (OS && !OS->Sections.empty() && !Config->Relocatable) @@ -1272,8 +1286,9 @@ void Writer<ELFT>::addPtArmExid(std::vec Phdrs.push_back(ARMExidx); } -// The first section of each PT_LOAD and the first section after PT_GNU_RELRO -// have to be page aligned so that the dynamic linker can set the permissions. +// The first section of each PT_LOAD, the first section in PT_GNU_RELRO and the +// first section after PT_GNU_RELRO have to be page aligned so that the dynamic +// linker can set the permissions. template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { for (const PhdrEntry &P : Phdrs) if (P.p_type == PT_LOAD && P.First) @@ -1282,6 +1297,8 @@ template <class ELFT> void Writer<ELFT>: for (const PhdrEntry &P : Phdrs) { if (P.p_type != PT_GNU_RELRO) continue; + if (P.First) + P.First->PageAlign = true; // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we // have to align it to a page. auto End = OutputSections.end(); @@ -1635,10 +1652,12 @@ static void unlinkAsync(StringRef Path) // Path as a new file. If we do that in a different thread, the new // thread can remove the new file. SmallString<128> TempPath; - if (auto EC = sys::fs::createUniqueFile(Path + "tmp%%%%%%%%", TempPath)) - fatal(EC, "createUniqueFile failed"); - if (auto EC = sys::fs::rename(Path, TempPath)) - fatal(EC, "rename failed"); + if (sys::fs::createUniqueFile(Path + "tmp%%%%%%%%", TempPath)) + return; + if (sys::fs::rename(Path, TempPath)) { + sys::fs::remove(TempPath); + return; + } // Remove TempPath in background. std::thread([=] { ::remove(TempPath.str().str().c_str()); }).detach(); Added: vendor/lld/dist/test/COFF/Inputs/pdb1.yaml ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/lld/dist/test/COFF/Inputs/pdb1.yaml Sat Jan 14 15:39:25 2017 (r312181) @@ -0,0 +1,172 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .drectve + Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] + Alignment: 1 + SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D45532220 + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + SectionData: 04000000F1000000580000001A00011100000000443A5C625C72657434322D6D61696E2E6F626A003A003C1100600000D00013000000F259000013000000F25900004D6963726F736F667420285229204F7074696D697A696E6720436F6D70696C657200F10000004E0000002A0047110000000000000000000000000E000000040000000900000005100000000000000000006D61696E001C001210280000000000000000000000000000000000000000000042110002004F110000F20000002000000000000000000000000E0000000000000001000000140000000000000002000080F400000018000000010000001001C538722F63570DF6705DDE06FE96E5D10000F30000001300000000643A5C625C72657434322D6D61696E2E630000F10000000800000006004C110E100000 + Relocations: + - VirtualAddress: 140 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 144 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 196 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 200 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - Name: '.debug$T' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + SectionData: 0400000006000112000000000E0008107400000000000000001000000A000210011000000C0001000A00011201000000000000000E0008107400000000000000031000001200011600000000041000006D61696E00F3F2F10E0001160000000001100000666F6F000E00051600000000443A5C6200F3F2F12200051600000000433A5C767331345C56435C42494E5C616D6436345C636C2E6578650002010516000000002D5A37202D63202D4D54202D49433A5C767331345C56435C494E434C554445202D49433A5C767331345C56435C41544C4D46435C494E434C554445202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C31305C696E636C7564655C31302E302E31303135302E305C7563727422202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C4E4554465853444B5C342E365C696E636C7564655C756D22202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C382E315C696E636C7564655C73686172656422000A0004160100000009100000820005160A100000202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C382E315C696E636C7564655C 756D22202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C382E315C696E636C7564655C77696E727422202D5443202D5800F3F2F1160005160000000072657434322D6D61696E2E6300F3F2F11600051600000000443A5C625C76633134302E70646200F11A000316050007100000081000000C1000000D1000000B100000F2F1 + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 4883EC28E8000000004883C428C3 + Relocations: + - VirtualAddress: 5 + SymbolName: foo + Type: IMAGE_REL_AMD64_REL32 + - Name: .xdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0104010004420000' + - Name: .pdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '000000000E00000000000000' + Relocations: + - VirtualAddress: 0 *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"