Date: Wed, 19 Jul 2017 07:02:58 +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: r321192 - in vendor/lld/dist: COFF ELF ELF/Arch docs test/COFF test/COFF/Inputs test/ELF test/ELF/Inputs test/ELF/invalid test/ELF/linkerscript test/ELF/lto Message-ID: <201707190702.v6J72waQ091126@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dim Date: Wed Jul 19 07:02:58 2017 New Revision: 321192 URL: https://svnweb.freebsd.org/changeset/base/321192 Log: Vendor import of lld trunk r308421: https://llvm.org/svn/llvm-project/lld/trunk@308421 Added: vendor/lld/dist/test/COFF/Inputs/default.def vendor/lld/dist/test/COFF/Inputs/extension.def vendor/lld/dist/test/COFF/Inputs/named.def vendor/lld/dist/test/COFF/Inputs/object.s (contents, props changed) vendor/lld/dist/test/COFF/Inputs/pdb-type-server-simple-a.yaml vendor/lld/dist/test/COFF/Inputs/pdb-type-server-simple-b.yaml vendor/lld/dist/test/COFF/Inputs/pdb-type-server-simple-ts.yaml vendor/lld/dist/test/COFF/implib-name.test vendor/lld/dist/test/COFF/pdb-type-server-missing.yaml vendor/lld/dist/test/COFF/pdb-type-server-simple.test vendor/lld/dist/test/COFF/reloc-discarded-dwarf.s (contents, props changed) vendor/lld/dist/test/COFF/reloc-oob.yaml vendor/lld/dist/test/ELF/Inputs/gdb-index.s (contents, props changed) vendor/lld/dist/test/ELF/filter.s (contents, props changed) vendor/lld/dist/test/ELF/linkerscript/exidx-crash.s (contents, props changed) vendor/lld/dist/test/ELF/linkerscript/got-write-offset.s (contents, props changed) vendor/lld/dist/test/ELF/map-gc-sections.s (contents, props changed) vendor/lld/dist/test/ELF/version-script-twice.s (contents, props changed) Deleted: vendor/lld/dist/test/ELF/Inputs/gdb-index-a.elf vendor/lld/dist/test/ELF/Inputs/gdb-index-b.elf vendor/lld/dist/test/ELF/Inputs/symver-archive1.s vendor/lld/dist/test/ELF/Inputs/symver-archive2.s vendor/lld/dist/test/ELF/symver-archive.s Modified: vendor/lld/dist/COFF/Chunks.cpp vendor/lld/dist/COFF/Chunks.h vendor/lld/dist/COFF/Config.h vendor/lld/dist/COFF/Driver.cpp vendor/lld/dist/COFF/PDB.cpp vendor/lld/dist/ELF/Arch/ARM.cpp vendor/lld/dist/ELF/Arch/MipsArchTree.cpp vendor/lld/dist/ELF/Config.h vendor/lld/dist/ELF/Driver.cpp vendor/lld/dist/ELF/EhFrame.h vendor/lld/dist/ELF/Filesystem.h vendor/lld/dist/ELF/GdbIndex.h vendor/lld/dist/ELF/ICF.h vendor/lld/dist/ELF/InputFiles.h vendor/lld/dist/ELF/LTO.h vendor/lld/dist/ELF/LinkerScript.cpp vendor/lld/dist/ELF/MapFile.cpp vendor/lld/dist/ELF/MapFile.h vendor/lld/dist/ELF/Memory.h vendor/lld/dist/ELF/Options.td vendor/lld/dist/ELF/OutputSections.cpp vendor/lld/dist/ELF/OutputSections.h vendor/lld/dist/ELF/Relocations.cpp vendor/lld/dist/ELF/Relocations.h vendor/lld/dist/ELF/ScriptParser.cpp vendor/lld/dist/ELF/Strings.cpp vendor/lld/dist/ELF/Strings.h 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/Threads.h vendor/lld/dist/ELF/Thunks.cpp vendor/lld/dist/ELF/Thunks.h vendor/lld/dist/ELF/Writer.cpp vendor/lld/dist/ELF/Writer.h vendor/lld/dist/docs/windows_support.rst vendor/lld/dist/test/COFF/common.test vendor/lld/dist/test/COFF/conflict.test vendor/lld/dist/test/COFF/constant.test vendor/lld/dist/test/COFF/def-export-stdcall.s vendor/lld/dist/test/COFF/delayimports32.test vendor/lld/dist/test/COFF/entry-mangled.test vendor/lld/dist/test/COFF/entrylib.ll vendor/lld/dist/test/COFF/imports.test vendor/lld/dist/test/COFF/include-lto.ll vendor/lld/dist/test/COFF/msvclto-archive.ll vendor/lld/dist/test/COFF/msvclto-order.ll vendor/lld/dist/test/COFF/msvclto.ll vendor/lld/dist/test/COFF/pdb-comdat.test vendor/lld/dist/test/COFF/pdb-lib.s vendor/lld/dist/test/COFF/pdb-symbol-types.yaml vendor/lld/dist/test/COFF/savetemps.ll vendor/lld/dist/test/COFF/thinlto-archives.ll vendor/lld/dist/test/COFF/thinlto-mangled.ll vendor/lld/dist/test/COFF/thinlto.ll vendor/lld/dist/test/ELF/Inputs/ctors_dtors_priority1.s vendor/lld/dist/test/ELF/Inputs/ctors_dtors_priority2.s vendor/lld/dist/test/ELF/Inputs/ctors_dtors_priority3.s vendor/lld/dist/test/ELF/allow-shlib-undefined.s vendor/lld/dist/test/ELF/as-needed-no-reloc.s vendor/lld/dist/test/ELF/as-needed.s vendor/lld/dist/test/ELF/auxiliary.s vendor/lld/dist/test/ELF/compressed-debug-input.s vendor/lld/dist/test/ELF/ctors_dtors_priority.s vendor/lld/dist/test/ELF/debug-gnu-pubnames.s vendor/lld/dist/test/ELF/dynamic-reloc.s vendor/lld/dist/test/ELF/gc-sections-shared.s vendor/lld/dist/test/ELF/gdb-index-empty.s vendor/lld/dist/test/ELF/gdb-index-gc-sections.s vendor/lld/dist/test/ELF/gdb-index.s vendor/lld/dist/test/ELF/i386-reloc-large-addend.s vendor/lld/dist/test/ELF/i386-reloc-range.s vendor/lld/dist/test/ELF/invalid/tls-symbol.s vendor/lld/dist/test/ELF/linkerscript/output-too-large.s vendor/lld/dist/test/ELF/lto/available-externally.ll vendor/lld/dist/test/ELF/lto/comdat2.ll vendor/lld/dist/test/ELF/lto/common2.ll vendor/lld/dist/test/ELF/lto/common3.ll vendor/lld/dist/test/ELF/lto/discard-value-names.ll vendor/lld/dist/test/ELF/lto/opt-level.ll vendor/lld/dist/test/ELF/lto/opt-remarks.ll vendor/lld/dist/test/ELF/lto/relax-relocs.ll vendor/lld/dist/test/ELF/lto/thin-archivecollision.ll vendor/lld/dist/test/ELF/lto/thinlto.ll vendor/lld/dist/test/ELF/lto/type-merge2.ll vendor/lld/dist/test/ELF/lto/unnamed-addr-comdat.ll vendor/lld/dist/test/ELF/lto/unnamed-addr-drop.ll vendor/lld/dist/test/ELF/lto/unnamed-addr.ll vendor/lld/dist/test/ELF/many-alloc-sections.s vendor/lld/dist/test/ELF/many-sections.s vendor/lld/dist/test/ELF/merge-section-types.s vendor/lld/dist/test/ELF/new-dtags.test vendor/lld/dist/test/ELF/no-obj.s vendor/lld/dist/test/ELF/no-soname.s vendor/lld/dist/test/ELF/no-symtab.s vendor/lld/dist/test/ELF/no-undefined.s vendor/lld/dist/test/ELF/pie-weak.s vendor/lld/dist/test/ELF/progname.s vendor/lld/dist/test/ELF/relative-dynamic-reloc-pie.s vendor/lld/dist/test/ELF/relative-dynamic-reloc.s vendor/lld/dist/test/ELF/relocatable-compressed-input.s vendor/lld/dist/test/ELF/relocatable-reloc.s vendor/lld/dist/test/ELF/relocatable-section-symbol.s vendor/lld/dist/test/ELF/relocatable-sections.s vendor/lld/dist/test/ELF/relocatable-tls.s vendor/lld/dist/test/ELF/relocation-shared.s vendor/lld/dist/test/ELF/shared-be.s vendor/lld/dist/test/ELF/shared.s vendor/lld/dist/test/ELF/soname.s vendor/lld/dist/test/ELF/soname2.s Modified: vendor/lld/dist/COFF/Chunks.cpp ============================================================================== --- vendor/lld/dist/COFF/Chunks.cpp Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/COFF/Chunks.cpp Wed Jul 19 07:02:58 2017 (r321192) @@ -210,7 +210,15 @@ void SectionChunk::writeTo(uint8_t *Buf) const { memcpy(Buf + OutputSectionOff, A.data(), A.size()); // Apply relocations. + size_t InputSize = getSize(); for (const coff_relocation &Rel : Relocs) { + // Check for an invalid relocation offset. This check isn't perfect, because + // we don't have the relocation size, which is only known after checking the + // machine and relocation type. As a result, a relocation may overwrite the + // beginning of the following input section. + if (Rel.VirtualAddress >= InputSize) + fatal("relocation points beyond the end of its parent section"); + uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress; // Get the output section of the symbol for this relocation. The output @@ -227,7 +235,7 @@ void SectionChunk::writeTo(uint8_t *Buf) const { // sections are not GC roots and can end up with these kinds of relocations. // Skip these relocations. if (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym)) { - if (isCodeView()) + if (isCodeView() || isDWARF()) continue; fatal("relocation against symbol in discarded section: " + Sym->getName()); Modified: vendor/lld/dist/COFF/Chunks.h ============================================================================== --- vendor/lld/dist/COFF/Chunks.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/COFF/Chunks.h Wed Jul 19 07:02:58 2017 (r321192) @@ -112,7 +112,7 @@ class Chunk { (protected) }; // A chunk corresponding a section of an input file. -class SectionChunk : public Chunk { +class SectionChunk final : public Chunk { // Identical COMDAT Folding feature accesses section internal data. friend class ICF; @@ -187,6 +187,9 @@ class SectionChunk : public Chunk { (public) bool isCodeView() const { return SectionName == ".debug" || SectionName.startswith(".debug$"); } + + // True if this is a DWARF debug info chunk. + bool isDWARF() const { return SectionName.startswith(".debug_"); } // Allow iteration over the bodies of this chunk's relocated symbols. llvm::iterator_range<symbol_iterator> symbols() const { Modified: vendor/lld/dist/COFF/Config.h ============================================================================== --- vendor/lld/dist/COFF/Config.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/COFF/Config.h Wed Jul 19 07:02:58 2017 (r321192) @@ -82,6 +82,7 @@ struct Configuration { SymbolBody *Entry = nullptr; bool NoEntry = false; std::string OutputFile; + std::string ImportName; bool ColorDiagnostics; bool DoGC = true; bool DoICF = true; Modified: vendor/lld/dist/COFF/Driver.cpp ============================================================================== --- vendor/lld/dist/COFF/Driver.cpp Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/COFF/Driver.cpp Wed Jul 19 07:02:58 2017 (r321192) @@ -429,7 +429,32 @@ static std::string getImplibPath() { return Out.str(); } -static void createImportLibrary() { +// +// The import name is caculated as the following: +// +// | LIBRARY w/ ext | LIBRARY w/o ext | no LIBRARY +// -----+----------------+---------------------+------------------ +// LINK | {value} | {value}.{.dll/.exe} | {output name} +// LIB | {value} | {value}.dll | {output name}.dll +// +static std::string getImportName(bool AsLib) { + SmallString<128> Out; + + if (Config->ImportName.empty()) { + Out.assign(sys::path::filename(Config->OutputFile)); + if (AsLib) + sys::path::replace_extension(Out, ".dll"); + } else { + Out.assign(Config->ImportName); + if (!sys::path::has_extension(Out)) + sys::path::replace_extension(Out, + (Config->DLL || AsLib) ? ".dll" : ".exe"); + } + + return Out.str(); +} + +static void createImportLibrary(bool AsLib) { std::vector<COFFShortExport> Exports; for (Export &E1 : Config->Exports) { COFFShortExport E2; @@ -444,9 +469,8 @@ static void createImportLibrary() { Exports.push_back(E2); } - std::string DLLName = sys::path::filename(Config->OutputFile); - std::string Path = getImplibPath(); - writeImportLibrary(DLLName, Path, Exports, Config->Machine); + writeImportLibrary(getImportName(AsLib), getImplibPath(), Exports, + Config->Machine); } static void parseModuleDefs(StringRef Path) { @@ -457,6 +481,7 @@ static void parseModuleDefs(StringRef Path) { if (Config->OutputFile.empty()) Config->OutputFile = Saver.save(M.OutputFile); + Config->ImportName = Saver.save(M.ImportName); if (M.ImageBase) Config->ImageBase = M.ImageBase; if (M.StackReserve) @@ -992,7 +1017,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr // Handle generation of import library from a def file. if (!Args.hasArgNoClaim(OPT_INPUT)) { fixupExports(); - createImportLibrary(); + createImportLibrary(/*AsLib=*/true); exit(0); } @@ -1117,7 +1142,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr // need to create a .lib file. if (!Config->Exports.empty() || Config->DLL) { fixupExports(); - createImportLibrary(); + createImportLibrary(/*AsLib=*/false); assignExportOrdinals(); } Modified: vendor/lld/dist/COFF/PDB.cpp ============================================================================== --- vendor/lld/dist/COFF/PDB.cpp Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/COFF/PDB.cpp Wed Jul 19 07:02:58 2017 (r321192) @@ -14,28 +14,29 @@ #include "SymbolTable.h" #include "Symbols.h" #include "llvm/DebugInfo/CodeView/CVDebugRecord.h" -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" -#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" -#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" +#include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/Object/COFF.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/Endian.h" @@ -53,8 +54,81 @@ using llvm::object::coff_section; static ExitOnError ExitOnErr; +namespace { +/// Map from type index and item index in a type server PDB to the +/// corresponding index in the destination PDB. +struct CVIndexMap { + SmallVector<TypeIndex, 0> TPIMap; + SmallVector<TypeIndex, 0> IPIMap; + bool IsTypeServerMap = false; +}; + +class PDBLinker { +public: + PDBLinker(SymbolTable *Symtab) + : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc), + IDTable(Alloc) {} + + /// Emit the basic PDB structure: initial streams, headers, etc. + void initialize(const llvm::codeview::DebugInfo *DI); + + /// Link CodeView from each object file in the symbol table into the PDB. + void addObjectsToPDB(); + + /// Link CodeView from a single object file into the PDB. + void addObjectFile(ObjectFile *File); + + /// Produce a mapping from the type and item indices used in the object + /// file to those in the destination PDB. + /// + /// If the object file uses a type server PDB (compiled with /Zi), merge TPI + /// and IPI from the type server PDB and return a map for it. Each unique type + /// server PDB is merged at most once, so this may return an existing index + /// mapping. + /// + /// If the object does not use a type server PDB (compiled with /Z7), we merge + /// all the type and item records from the .debug$S stream and fill in the + /// caller-provided ObjectIndexMap. + const CVIndexMap &mergeDebugT(ObjectFile *File, CVIndexMap &ObjectIndexMap); + + const CVIndexMap &maybeMergeTypeServerPDB(ObjectFile *File, + TypeServer2Record &TS); + + /// Add the section map and section contributions to the PDB. + void addSections(ArrayRef<uint8_t> SectionTable); + + /// Write the PDB to disk. + void commit(); + +private: + BumpPtrAllocator Alloc; + + SymbolTable *Symtab; + + pdb::PDBFileBuilder Builder; + + /// Type records that will go into the PDB TPI stream. + TypeTableBuilder TypeTable; + + /// Item records that will go into the PDB IPI stream. + TypeTableBuilder IDTable; + + /// PDBs use a single global string table for filenames in the file checksum + /// table. + DebugStringTableSubsection PDBStrTab; + + llvm::SmallString<128> NativePath; + + std::vector<pdb::SecMapEntry> SectionMap; + + /// Type index mappings of type server PDBs that we've loaded so far. + std::map<GUID, CVIndexMap> TypeServerIndexMappings; +}; +} + // Returns a list of all SectionChunks. -static void addSectionContribs(SymbolTable *Symtab, pdb::DbiStreamBuilder &DbiBuilder) { +static void addSectionContribs(SymbolTable *Symtab, + pdb::DbiStreamBuilder &DbiBuilder) { for (Chunk *C : Symtab->getChunks()) if (auto *SC = dyn_cast<SectionChunk>(C)) DbiBuilder.addSectionContrib(SC->File->ModuleDBI, SC->Header); @@ -96,26 +170,117 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuil }); } -static void mergeDebugT(ObjectFile *File, - TypeTableBuilder &IDTable, - TypeTableBuilder &TypeTable, - SmallVectorImpl<TypeIndex> &TypeIndexMap, - pdb::PDBTypeServerHandler &Handler) { +static Optional<TypeServer2Record> +maybeReadTypeServerRecord(CVTypeArray &Types) { + auto I = Types.begin(); + if (I == Types.end()) + return None; + const CVType &Type = *I; + if (Type.kind() != LF_TYPESERVER2) + return None; + TypeServer2Record TS; + if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS)) + fatal(EC, "error reading type server record"); + return std::move(TS); +} + +const CVIndexMap &PDBLinker::mergeDebugT(ObjectFile *File, + CVIndexMap &ObjectIndexMap) { ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); if (Data.empty()) - return; + return ObjectIndexMap; BinaryByteStream Stream(Data, support::little); CVTypeArray Types; BinaryStreamReader Reader(Stream); - Handler.addSearchPath(sys::path::parent_path(File->getName())); if (auto EC = Reader.readArray(Types, Reader.getLength())) fatal(EC, "Reader::readArray failed"); + + // Look through type servers. If we've already seen this type server, don't + // merge any type information. + if (Optional<TypeServer2Record> TS = maybeReadTypeServerRecord(Types)) + return maybeMergeTypeServerPDB(File, *TS); + + // This is a /Z7 object. Fill in the temporary, caller-provided + // ObjectIndexMap. if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable, - TypeIndexMap, &Handler, Types)) - fatal(Err, "codeview::mergeTypeStreams failed"); + ObjectIndexMap.TPIMap, Types)) + fatal(Err, "codeview::mergeTypeAndIdRecords failed"); + return ObjectIndexMap; } +static Expected<std::unique_ptr<pdb::NativeSession>> +tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) { + std::unique_ptr<pdb::IPDBSession> ThisSession; + if (auto EC = + pdb::loadDataForPDB(pdb::PDB_ReaderType::Native, TSPath, ThisSession)) + return std::move(EC); + + std::unique_ptr<pdb::NativeSession> NS( + static_cast<pdb::NativeSession *>(ThisSession.release())); + pdb::PDBFile &File = NS->getPDBFile(); + auto ExpectedInfo = File.getPDBInfoStream(); + // All PDB Files should have an Info stream. + if (!ExpectedInfo) + return ExpectedInfo.takeError(); + + // Just because a file with a matching name was found and it was an actual + // PDB file doesn't mean it matches. For it to match the InfoStream's GUID + // must match the GUID specified in the TypeServer2 record. + if (ExpectedInfo->getGuid() != GuidFromObj) + return make_error<pdb::GenericError>( + pdb::generic_error_code::type_server_not_found, TSPath); + + return std::move(NS); +} + +const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjectFile *File, + TypeServer2Record &TS) { + // First, check if we already loaded a PDB with this GUID. Return the type + // index mapping if we have it. + auto Insertion = TypeServerIndexMappings.insert({TS.getGuid(), CVIndexMap()}); + CVIndexMap &IndexMap = Insertion.first->second; + if (!Insertion.second) + return IndexMap; + + // Mark this map as a type server map. + IndexMap.IsTypeServerMap = true; + + // Check for a PDB at: + // 1. The given file path + // 2. Next to the object file or archive file + auto ExpectedSession = tryToLoadPDB(TS.getGuid(), TS.getName()); + if (!ExpectedSession) { + consumeError(ExpectedSession.takeError()); + StringRef LocalPath = + !File->ParentName.empty() ? File->ParentName : File->getName(); + SmallString<128> Path = sys::path::parent_path(LocalPath); + sys::path::append( + Path, sys::path::filename(TS.getName(), sys::path::Style::windows)); + ExpectedSession = tryToLoadPDB(TS.getGuid(), Path); + } + if (auto E = ExpectedSession.takeError()) + fatal(E, "Type server PDB was not found"); + + // Merge TPI first, because the IPI stream will reference type indices. + auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream(); + if (auto E = ExpectedTpi.takeError()) + fatal(E, "Type server does not have TPI stream"); + if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap, + ExpectedTpi->typeArray())) + fatal(Err, "codeview::mergeTypeRecords failed"); + + // Merge IPI. + auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream(); + if (auto E = ExpectedIpi.takeError()) + fatal(E, "Type server does not have TPI stream"); + if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap, + ExpectedIpi->typeArray())) + fatal(Err, "codeview::mergeIdRecords failed"); + + return IndexMap; +} + static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) { if (TI.isSimple()) return true; @@ -127,16 +292,22 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef<Typ static void remapTypesInSymbolRecord(ObjectFile *File, MutableArrayRef<uint8_t> Contents, - ArrayRef<TypeIndex> TypeIndexMap, + const CVIndexMap &IndexMap, ArrayRef<TiReference> TypeRefs) { for (const TiReference &Ref : TypeRefs) { unsigned ByteSize = Ref.Count * sizeof(TypeIndex); if (Contents.size() < Ref.Offset + ByteSize) fatal("symbol record too short"); + + // This can be an item index or a type index. Choose the appropriate map. + ArrayRef<TypeIndex> TypeOrItemMap = IndexMap.TPIMap; + if (Ref.Kind == TiRefKind::IndexRef && IndexMap.IsTypeServerMap) + TypeOrItemMap = IndexMap.IPIMap; + MutableArrayRef<TypeIndex> TIs( reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count); for (TypeIndex &TI : TIs) { - if (!remapTypeIndex(TI, TypeIndexMap)) { + if (!remapTypeIndex(TI, TypeOrItemMap)) { TI = TypeIndex(SimpleTypeKind::NotTranslated); log("ignoring symbol record in " + File->getName() + " with bad type index 0x" + utohexstr(TI.getIndex())); @@ -241,7 +412,7 @@ static void scopeStackClose(SmallVectorImpl<SymbolScop } static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File, - ArrayRef<TypeIndex> TypeIndexMap, + const CVIndexMap &IndexMap, BinaryStreamRef SymData) { // FIXME: Improve error recovery by warning and skipping records when // possible. @@ -264,7 +435,7 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc // Re-map all the type index references. MutableArrayRef<uint8_t> Contents = NewData.drop_front(sizeof(RecordPrefix)); - remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs); + remapTypesInSymbolRecord(File, Contents, IndexMap, TypeRefs); // Fill in "Parent" and "End" fields by maintaining a stack of scopes. CVSymbol NewSym(Sym.kind(), NewData); @@ -289,110 +460,105 @@ static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAll ".debug$S"); } -// Add all object files to the PDB. Merge .debug$T sections into IpiData and -// TpiData. -static void addObjectsToPDB(BumpPtrAllocator &Alloc, SymbolTable *Symtab, - pdb::PDBFileBuilder &Builder, - TypeTableBuilder &TypeTable, - TypeTableBuilder &IDTable) { - // Follow type servers. If the same type server is encountered more than - // once for this instance of `PDBTypeServerHandler` (for example if many - // object files reference the same TypeServer), the types from the - // TypeServer will only be visited once. - pdb::PDBTypeServerHandler Handler; +void PDBLinker::addObjectFile(ObjectFile *File) { + // Add a module descriptor for every object file. We need to put an absolute + // path to the object into the PDB. If this is a plain object, we make its + // path absolute. If it's an object in an archive, we make the archive path + // absolute. + bool InArchive = !File->ParentName.empty(); + SmallString<128> Path = InArchive ? File->ParentName : File->getName(); + sys::fs::make_absolute(Path); + sys::path::native(Path, sys::path::Style::windows); + StringRef Name = InArchive ? File->getName() : StringRef(Path); - // PDBs use a single global string table for filenames in the file checksum - // table. - auto PDBStrTab = std::make_shared<DebugStringTableSubsection>(); + File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name)); + File->ModuleDBI->setObjFileName(Path); - // Visit all .debug$T sections to add them to Builder. - for (ObjectFile *File : Symtab->ObjectFiles) { - // Add a module descriptor for every object file. We need to put an absolute - // path to the object into the PDB. If this is a plain object, we make its - // path absolute. If it's an object in an archive, we make the archive path - // absolute. - bool InArchive = !File->ParentName.empty(); - SmallString<128> Path = InArchive ? File->ParentName : File->getName(); - sys::fs::make_absolute(Path); - sys::path::native(Path, llvm::sys::path::Style::windows); - StringRef Name = InArchive ? File->getName() : StringRef(Path); + // Before we can process symbol substreams from .debug$S, we need to process + // type information, file checksums, and the string table. Add type info to + // the PDB first, so that we can get the map from object file type and item + // indices to PDB type and item indices. + CVIndexMap ObjectIndexMap; + const CVIndexMap &IndexMap = mergeDebugT(File, ObjectIndexMap); - File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name)); - File->ModuleDBI->setObjFileName(Path); + // Now do all live .debug$S sections. + for (SectionChunk *DebugChunk : File->getDebugChunks()) { + if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S") + continue; - // Before we can process symbol substreams from .debug$S, we need to process - // type information, file checksums, and the string table. Add type info to - // the PDB first, so that we can get the map from object file type and item - // indices to PDB type and item indices. - SmallVector<TypeIndex, 128> TypeIndexMap; - mergeDebugT(File, IDTable, TypeTable, TypeIndexMap, Handler); + ArrayRef<uint8_t> RelocatedDebugContents = + relocateDebugChunk(Alloc, DebugChunk); + if (RelocatedDebugContents.empty()) + continue; - // Now do all line info. - for (SectionChunk *DebugChunk : File->getDebugChunks()) { - if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S") - continue; + DebugSubsectionArray Subsections; + BinaryStreamReader Reader(RelocatedDebugContents, support::little); + ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size())); - ArrayRef<uint8_t> RelocatedDebugContents = - relocateDebugChunk(Alloc, DebugChunk); - if (RelocatedDebugContents.empty()) - continue; - - DebugSubsectionArray Subsections; - BinaryStreamReader Reader(RelocatedDebugContents, support::little); - ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size())); - - DebugStringTableSubsectionRef CVStrTab; - DebugChecksumsSubsectionRef Checksums; - for (const DebugSubsectionRecord &SS : Subsections) { - switch (SS.kind()) { - case DebugSubsectionKind::StringTable: - ExitOnErr(CVStrTab.initialize(SS.getRecordData())); - break; - case DebugSubsectionKind::FileChecksums: - ExitOnErr(Checksums.initialize(SS.getRecordData())); - break; - case DebugSubsectionKind::Lines: - // We can add the relocated line table directly to the PDB without - // modification because the file checksum offsets will stay the same. - File->ModuleDBI->addDebugSubsection(SS); - break; - case DebugSubsectionKind::Symbols: - mergeSymbolRecords(Alloc, File, TypeIndexMap, SS.getRecordData()); - break; - default: - // FIXME: Process the rest of the subsections. - break; - } + DebugStringTableSubsectionRef CVStrTab; + DebugChecksumsSubsectionRef Checksums; + for (const DebugSubsectionRecord &SS : Subsections) { + switch (SS.kind()) { + case DebugSubsectionKind::StringTable: + ExitOnErr(CVStrTab.initialize(SS.getRecordData())); + break; + case DebugSubsectionKind::FileChecksums: + ExitOnErr(Checksums.initialize(SS.getRecordData())); + break; + case DebugSubsectionKind::Lines: + // We can add the relocated line table directly to the PDB without + // modification because the file checksum offsets will stay the same. + File->ModuleDBI->addDebugSubsection(SS); + break; + case DebugSubsectionKind::Symbols: + mergeSymbolRecords(Alloc, File, IndexMap, SS.getRecordData()); + break; + default: + // FIXME: Process the rest of the subsections. + break; } + } - if (Checksums.valid()) { - // Make a new file checksum table that refers to offsets in the PDB-wide - // string table. Generally the string table subsection appears after the - // checksum table, so we have to do this after looping over all the - // subsections. - if (!CVStrTab.valid()) - fatal(".debug$S sections must have both a string table subsection " - "and a checksum subsection table or neither"); - auto NewChecksums = - make_unique<DebugChecksumsSubsection>(*PDBStrTab); - for (FileChecksumEntry &FC : Checksums) { - StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset)); - ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile( - *File->ModuleDBI, FileName)); - NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum); - } - File->ModuleDBI->addDebugSubsection(std::move(NewChecksums)); + if (Checksums.valid()) { + // Make a new file checksum table that refers to offsets in the PDB-wide + // string table. Generally the string table subsection appears after the + // checksum table, so we have to do this after looping over all the + // subsections. + if (!CVStrTab.valid()) + fatal(".debug$S sections must have both a string table subsection " + "and a checksum subsection table or neither"); + auto NewChecksums = make_unique<DebugChecksumsSubsection>(PDBStrTab); + for (FileChecksumEntry &FC : Checksums) { + StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset)); + ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(*File->ModuleDBI, + FileName)); + NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum); } + File->ModuleDBI->addDebugSubsection(std::move(NewChecksums)); } } +} - Builder.getStringTableBuilder().setStrings(*PDBStrTab); +// Add all object files to the PDB. Merge .debug$T sections into IpiData and +// TpiData. +void PDBLinker::addObjectsToPDB() { + for (ObjectFile *File : Symtab->ObjectFiles) + addObjectFile(File); + Builder.getStringTableBuilder().setStrings(PDBStrTab); + // Construct TPI stream contents. addTypeInfo(Builder.getTpiBuilder(), TypeTable); // Construct IPI stream contents. addTypeInfo(Builder.getIpiBuilder(), IDTable); + + // Add public and symbol records stream. + + // For now we don't actually write any thing useful to the publics stream, but + // the act of "getting" it also creates it lazily so that we write an empty + // stream. + (void)Builder.getPublicsBuilder(); } static void addLinkerModuleSymbols(StringRef Path, @@ -423,7 +589,7 @@ static void addLinkerModuleSymbols(StringRef Path, std::string ArgStr = llvm::join(Args, " "); EBS.Fields.push_back("cwd"); SmallString<64> cwd; - llvm::sys::fs::current_path(cwd); + sys::fs::current_path(cwd); EBS.Fields.push_back(cwd); EBS.Fields.push_back("exe"); EBS.Fields.push_back(Config->Argv[0]); @@ -442,8 +608,14 @@ static void addLinkerModuleSymbols(StringRef Path, // Creates a PDB file. void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable, const llvm::codeview::DebugInfo *DI) { - BumpPtrAllocator Alloc; - pdb::PDBFileBuilder Builder(Alloc); + PDBLinker PDB(Symtab); + PDB.initialize(DI); + PDB.addObjectsToPDB(); + PDB.addSections(SectionTable); + PDB.commit(); +} + +void PDBLinker::initialize(const llvm::codeview::DebugInfo *DI) { ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize // Create streams in MSF for predefined streams, namely @@ -455,12 +627,7 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uin auto &InfoBuilder = Builder.getInfoBuilder(); InfoBuilder.setAge(DI ? DI->PDB70.Age : 0); - llvm::SmallString<128> NativePath(Config->PDBPath.begin(), - Config->PDBPath.end()); - llvm::sys::fs::make_absolute(NativePath); - llvm::sys::path::native(NativePath, llvm::sys::path::Style::windows); - - pdb::PDB_UniqueId uuid{}; + GUID uuid{}; if (DI) memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid)); InfoBuilder.setGuid(uuid); @@ -471,32 +638,25 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uin pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); DbiBuilder.setVersionHeader(pdb::PdbDbiV70); ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {})); +} - // It's not entirely clear what this is, but the * Linker * module uses it. - uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); - - TypeTableBuilder TypeTable(BAlloc); - TypeTableBuilder IDTable(BAlloc); - addObjectsToPDB(Alloc, Symtab, Builder, TypeTable, IDTable); - - // Add public and symbol records stream. - - // For now we don't actually write any thing useful to the publics stream, but - // the act of "getting" it also creates it lazily so that we write an empty - // stream. - (void)Builder.getPublicsBuilder(); - +void PDBLinker::addSections(ArrayRef<uint8_t> SectionTable) { // Add Section Contributions. + pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); addSectionContribs(Symtab, DbiBuilder); // Add Section Map stream. ArrayRef<object::coff_section> Sections = { (const object::coff_section *)SectionTable.data(), SectionTable.size() / sizeof(object::coff_section)}; - std::vector<pdb::SecMapEntry> SectionMap = - pdb::DbiStreamBuilder::createSectionMap(Sections); + SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections); DbiBuilder.setSectionMap(SectionMap); + // It's not entirely clear what this is, but the * Linker * module uses it. + NativePath = Config->PDBPath; + sys::fs::make_absolute(NativePath); + sys::path::native(NativePath, sys::path::Style::windows); + uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); LinkerModule.setPdbFilePathNI(PdbFilePathNI); addLinkerModuleSymbols(NativePath, LinkerModule, Alloc); @@ -504,7 +664,9 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uin // Add COFF section header stream. ExitOnErr( DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable)); +} +void PDBLinker::commit() { // Write to a file. ExitOnErr(Builder.commit(Config->PDBPath)); } Modified: vendor/lld/dist/ELF/Arch/ARM.cpp ============================================================================== --- vendor/lld/dist/ELF/Arch/ARM.cpp Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/Arch/ARM.cpp Wed Jul 19 07:02:58 2017 (r321192) @@ -40,6 +40,8 @@ class ARM final : public TargetInfo { (public) void addPltHeaderSymbols(InputSectionBase *ISD) const override; bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, const SymbolBody &S) const override; + bool inBranchRange(uint32_t RelocType, uint64_t Src, + uint64_t Dst) const override; void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; }; } // namespace @@ -216,6 +218,49 @@ bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, break; } return false; +} + +bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const { + uint64_t Range; + uint64_t InstrSize; + + switch (RelocType) { + case R_ARM_PC24: + case R_ARM_PLT32: + case R_ARM_JUMP24: + case R_ARM_CALL: + Range = 0x2000000; + InstrSize = 4; + break; + case R_ARM_THM_JUMP19: + Range = 0x100000; + InstrSize = 2; + break; + case R_ARM_THM_JUMP24: + case R_ARM_THM_CALL: + Range = 0x1000000; + InstrSize = 2; + break; + default: + return true; + } + // PC at Src is 2 instructions ahead, immediate of branch is signed + if (Src > Dst) + Range -= 2 * InstrSize; + else + Range += InstrSize; + + if ((Dst & 0x1) == 0) + // Destination is ARM, if ARM caller then Src is already 4-byte aligned. + // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure + // destination will be 4 byte aligned. + Src &= ~0x3; + else + // Bit 0 == 1 denotes Thumb state, it is not part of the range + Dst &= ~0x1; + + uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src; + return Distance <= Range; } void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { Modified: vendor/lld/dist/ELF/Arch/MipsArchTree.cpp ============================================================================== --- vendor/lld/dist/ELF/Arch/MipsArchTree.cpp Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/Arch/MipsArchTree.cpp Wed Jul 19 07:02:58 2017 (r321192) @@ -37,7 +37,7 @@ struct FileFlags { StringRef Filename; uint32_t Flags; }; -} +} // namespace static StringRef getAbiName(uint32_t Flags) { switch (Flags) { @@ -337,8 +337,8 @@ uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t return NewFlag; if (compareMipsFpAbi(OldFlag, NewFlag) < 0) error("target floating point ABI '" + getMipsFpAbiName(OldFlag) + - "' is incompatible with '" + getMipsFpAbiName(NewFlag) + "': " + - FileName); + "' is incompatible with '" + getMipsFpAbiName(NewFlag) + + "': " + FileName); return OldFlag; } Modified: vendor/lld/dist/ELF/Config.h ============================================================================== --- vendor/lld/dist/ELF/Config.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/Config.h Wed Jul 19 07:02:58 2017 (r321192) @@ -99,6 +99,7 @@ struct Configuration { std::vector<VersionDefinition> VersionDefinitions; std::vector<llvm::StringRef> Argv; std::vector<llvm::StringRef> AuxiliaryList; + std::vector<llvm::StringRef> FilterList; std::vector<llvm::StringRef> SearchPaths; std::vector<llvm::StringRef> SymbolOrderingFile; std::vector<llvm::StringRef> Undefined; Modified: vendor/lld/dist/ELF/Driver.cpp ============================================================================== --- vendor/lld/dist/ELF/Driver.cpp Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/Driver.cpp Wed Jul 19 07:02:58 2017 (r321192) @@ -259,6 +259,9 @@ static void checkOptions(opt::InputArgList &Args) { if (Config->Pie && Config->Shared) error("-shared and -pie may not be used together"); + if (!Config->Shared && !Config->FilterList.empty()) + error("-F may not be used without -shared"); + if (!Config->Shared && !Config->AuxiliaryList.empty()) error("-f may not be used without -shared"); @@ -631,6 +634,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args getArg(Args, OPT_export_dynamic, OPT_no_export_dynamic, false); Config->FatalWarnings = getArg(Args, OPT_fatal_warnings, OPT_no_fatal_warnings, false); + Config->FilterList = getArgs(Args, OPT_filter); Config->Fini = Args.getLastArgValue(OPT_fini, "_fini"); Config->GcSections = getArg(Args, OPT_gc_sections, OPT_no_gc_sections, false); Config->GdbIndex = Args.hasArg(OPT_gdb_index); Modified: vendor/lld/dist/ELF/EhFrame.h ============================================================================== --- vendor/lld/dist/ELF/EhFrame.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/EhFrame.h Wed Jul 19 07:02:58 2017 (r321192) @@ -19,7 +19,7 @@ struct EhSectionPiece; template <class ELFT> size_t readEhRecordSize(InputSectionBase *S, size_t Off); template <class ELFT> uint8_t getFdeEncoding(EhSectionPiece *P); -} -} +} // namespace elf +} // namespace lld #endif Modified: vendor/lld/dist/ELF/Filesystem.h ============================================================================== --- vendor/lld/dist/ELF/Filesystem.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/Filesystem.h Wed Jul 19 07:02:58 2017 (r321192) @@ -16,7 +16,7 @@ namespace lld { namespace elf { void unlinkAsync(StringRef Path); std::error_code tryCreateFile(StringRef Path); -} -} +} // namespace elf +} // namespace lld #endif Modified: vendor/lld/dist/ELF/GdbIndex.h ============================================================================== --- vendor/lld/dist/ELF/GdbIndex.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/GdbIndex.h Wed Jul 19 07:02:58 2017 (r321192) @@ -11,8 +11,8 @@ #define LLD_ELF_GDB_INDEX_H #include "InputFiles.h" -#include "llvm/Object/ELF.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/Object/ELF.h" namespace lld { namespace elf { Modified: vendor/lld/dist/ELF/ICF.h ============================================================================== --- vendor/lld/dist/ELF/ICF.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/ICF.h Wed Jul 19 07:02:58 2017 (r321192) @@ -14,6 +14,6 @@ namespace lld { namespace elf { template <class ELFT> void doIcf(); } -} +} // namespace lld #endif Modified: vendor/lld/dist/ELF/InputFiles.h ============================================================================== --- vendor/lld/dist/ELF/InputFiles.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/InputFiles.h Wed Jul 19 07:02:58 2017 (r321192) @@ -11,8 +11,8 @@ #define LLD_ELF_INPUT_FILES_H #include "Config.h" -#include "InputSection.h" #include "Error.h" +#include "InputSection.h" #include "Symbols.h" #include "lld/Core/LLVM.h" @@ -34,7 +34,7 @@ struct DILineInfo; namespace lto { class InputFile; } -} +} // namespace llvm namespace lld { namespace elf { Modified: vendor/lld/dist/ELF/LTO.h ============================================================================== --- vendor/lld/dist/ELF/LTO.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/LTO.h Wed Jul 19 07:02:58 2017 (r321192) @@ -30,7 +30,7 @@ namespace llvm { namespace lto { class LTO; } -} +} // namespace llvm namespace lld { namespace elf { @@ -51,7 +51,7 @@ class BitcodeCompiler { (private) std::vector<SmallString<0>> Buff; std::vector<std::unique_ptr<MemoryBuffer>> Files; }; -} -} +} // namespace elf +} // namespace lld #endif Modified: vendor/lld/dist/ELF/LinkerScript.cpp ============================================================================== --- vendor/lld/dist/ELF/LinkerScript.cpp Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/LinkerScript.cpp Wed Jul 19 07:02:58 2017 (r321192) @@ -229,6 +229,19 @@ bool LinkerScript::shouldKeep(InputSectionBase *S) { return false; } +// If an input string is in the form of "foo.N" where N is a number, +// return N. Otherwise, returns 65536, which is one greater than the +// lowest priority. +static int getPriority(StringRef S) { + size_t Pos = S.rfind('.'); + if (Pos == StringRef::npos) + return 65536; + int V; + if (!to_integer(S.substr(Pos + 1), V, 10)) + return 65536; + return V; +} + // A helper function for the SORT() command. static std::function<bool(InputSectionBase *, InputSectionBase *)> getComparator(SortSectionPolicy K) { @@ -449,7 +462,7 @@ void LinkerScript::fabricateDefaultCommands() { // The Sections with -T<section> have been sorted in order of ascending // address. We must lower StartAddr if the lowest -T<section address> as // calls to setDot() must be monotonically increasing. - for (auto& KV : Config->SectionStartMap) + for (auto &KV : Config->SectionStartMap) StartAddr = std::min(StartAddr, KV.second); Commands.push_back(make<SymbolAssignment>( @@ -739,7 +752,7 @@ void LinkerScript::adjustSectionsAfterSorting() { Cmd->MemRegion = findMemoryRegion(Cmd); // Handle align (e.g. ".foo : ALIGN(16) { ... }"). if (Cmd->AlignExpr) - Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue()); + Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue()); } } @@ -1071,7 +1084,7 @@ template <class ELFT> void OutputSectionCommand::final } if ((Sec->Flags & SHF_LINK_ORDER)) { - std::sort(Sections.begin(), Sections.end(), compareByFilePosition); + std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); for (int I = 0, N = Sections.size(); I < N; ++I) *ScriptSections[I] = Sections[I]; Modified: vendor/lld/dist/ELF/MapFile.cpp ============================================================================== --- vendor/lld/dist/ELF/MapFile.cpp Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/MapFile.cpp Wed Jul 19 07:02:58 2017 (r321192) @@ -55,7 +55,7 @@ template <class ELFT> std::vector<DefinedRegular *> ge for (SymbolBody *B : File->getSymbols()) if (B->File == File && !B->isSection()) if (auto *Sym = dyn_cast<DefinedRegular>(B)) - if (Sym->Section) + if (Sym->Section && Sym->Section->Live) V.push_back(Sym); return V; } Modified: vendor/lld/dist/ELF/MapFile.h ============================================================================== --- vendor/lld/dist/ELF/MapFile.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/MapFile.h Wed Jul 19 07:02:58 2017 (r321192) @@ -17,7 +17,7 @@ namespace elf { struct OutputSectionCommand; template <class ELFT> void writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script); -} -} +} // namespace elf +} // namespace lld #endif Modified: vendor/lld/dist/ELF/Memory.h ============================================================================== --- vendor/lld/dist/ELF/Memory.h Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/Memory.h Wed Jul 19 07:02:58 2017 (r321192) @@ -61,7 +61,7 @@ inline void freeArena() { Alloc->reset(); BAlloc.Reset(); } -} -} +} // namespace elf +} // namespace lld #endif Modified: vendor/lld/dist/ELF/Options.td ============================================================================== --- vendor/lld/dist/ELF/Options.td Wed Jul 19 07:02:53 2017 (r321191) +++ vendor/lld/dist/ELF/Options.td Wed Jul 19 07:02:58 2017 (r321192) @@ -104,6 +104,8 @@ def export_dynamic_symbol: S<"export-dynamic-symbol">, def fatal_warnings: F<"fatal-warnings">, HelpText<"Treat warnings as errors">; +def filter: J<"filter=">, HelpText<"Set DT_FILTER field to the specified name">; + def fini: S<"fini">, MetaVarName<"<symbol>">, HelpText<"Specify a finalizer function">; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201707190702.v6J72waQ091126>