Index: vendor/lld/dist-release_80/COFF/PDB.cpp =================================================================== --- vendor/lld/dist-release_80/COFF/PDB.cpp (revision 344172) +++ vendor/lld/dist-release_80/COFF/PDB.cpp (revision 344173) @@ -1,1765 +1,1771 @@ //===- PDB.cpp ------------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "PDB.h" #include "Chunks.h" #include "Config.h" #include "Driver.h" #include "SymbolTable.h" #include "Symbols.h" #include "Writer.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Timer.h" #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/RecordName.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.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/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/GSIStreamBuilder.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/TpiHashing.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/Object/CVDebugRecord.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Errc.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/JamCRC.h" #include "llvm/Support/Parallel.h" #include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" #include using namespace lld; using namespace lld::coff; using namespace llvm; using namespace llvm::codeview; using llvm::object::coff_section; static ExitOnError ExitOnErr; static Timer TotalPdbLinkTimer("PDB Emission (Cumulative)", Timer::root()); static Timer AddObjectsTimer("Add Objects", TotalPdbLinkTimer); static Timer TypeMergingTimer("Type Merging", AddObjectsTimer); static Timer SymbolMergingTimer("Symbol Merging", AddObjectsTimer); static Timer GlobalsLayoutTimer("Globals Stream Layout", TotalPdbLinkTimer); static Timer TpiStreamLayoutTimer("TPI Stream Layout", TotalPdbLinkTimer); static Timer DiskCommitTimer("Commit to Disk", TotalPdbLinkTimer); namespace { /// Map from type index and item index in a type server PDB to the /// corresponding index in the destination PDB. struct CVIndexMap { SmallVector TPIMap; SmallVector IPIMap; bool IsTypeServerMap = false; bool IsPrecompiledTypeMap = false; }; class DebugSHandler; class PDBLinker { friend DebugSHandler; public: PDBLinker(SymbolTable *Symtab) : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc), IDTable(Alloc), GlobalTypeTable(Alloc), GlobalIDTable(Alloc) { // This isn't strictly necessary, but link.exe usually puts an empty string // as the first "valid" string in the string table, so we do the same in // order to maintain as much byte-for-byte compatibility as possible. PDBStrTab.insert(""); } /// Emit the basic PDB structure: initial streams, headers, etc. void initialize(llvm::codeview::DebugInfo *BuildId); /// Add natvis files specified on the command line. void addNatvisFiles(); /// Link CodeView from each object file in the symbol table into the PDB. void addObjectsToPDB(); /// Link CodeView from a single object file into the target (output) PDB. /// When a precompiled headers object is linked, its TPI map might be provided /// externally. void addObjFile(ObjFile *File, CVIndexMap *ExternIndexMap = nullptr); /// 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. Expected mergeDebugT(ObjFile *File, CVIndexMap *ObjectIndexMap); /// Reads and makes available a PDB. Expected maybeMergeTypeServerPDB(ObjFile *File, const CVType &FirstType); /// Merges a precompiled headers TPI map into the current TPI map. The /// precompiled headers object will also be loaded and remapped in the /// process. Expected mergeInPrecompHeaderObj(ObjFile *File, const CVType &FirstType, CVIndexMap *ObjectIndexMap); /// Reads and makes available a precompiled headers object. /// /// This is a requirement for objects compiled with cl.exe /Yu. In that /// case, the referenced object (which was compiled with /Yc) has to be loaded /// first. This is mainly because the current object's TPI stream has external /// references to the precompiled headers object. /// /// If the precompiled headers object was already loaded, this function will /// simply return its (remapped) TPI map. Expected aquirePrecompObj(ObjFile *File, PrecompRecord Precomp); /// Adds a precompiled headers object signature -> TPI mapping. std::pair registerPrecompiledHeaders(uint32_t Signature); void mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap, std::vector &StringTableRefs, BinaryStreamRef SymData); /// Add the section map and section contributions to the PDB. void addSections(ArrayRef OutputSections, ArrayRef SectionTable); /// Get the type table or the global type table if /DEBUG:GHASH is enabled. TypeCollection &getTypeTable() { if (Config->DebugGHashes) return GlobalTypeTable; return TypeTable; } /// Get the ID table or the global ID table if /DEBUG:GHASH is enabled. TypeCollection &getIDTable() { if (Config->DebugGHashes) return GlobalIDTable; return IDTable; } /// Write the PDB to disk and store the Guid generated for it in *Guid. void commit(codeview::GUID *Guid); private: BumpPtrAllocator Alloc; SymbolTable *Symtab; pdb::PDBFileBuilder Builder; /// Type records that will go into the PDB TPI stream. MergingTypeTableBuilder TypeTable; /// Item records that will go into the PDB IPI stream. MergingTypeTableBuilder IDTable; /// Type records that will go into the PDB TPI stream (for /DEBUG:GHASH) GlobalTypeTableBuilder GlobalTypeTable; /// Item records that will go into the PDB IPI stream (for /DEBUG:GHASH) GlobalTypeTableBuilder GlobalIDTable; /// PDBs use a single global string table for filenames in the file checksum /// table. DebugStringTableSubsection PDBStrTab; llvm::SmallString<128> NativePath; /// A list of other PDBs which are loaded during the linking process and which /// we need to keep around since the linking operation may reference pointers /// inside of these PDBs. llvm::SmallVector, 2> LoadedPDBs; std::vector SectionMap; /// Type index mappings of type server PDBs that we've loaded so far. std::map TypeServerIndexMappings; /// Type index mappings of precompiled objects type map that we've loaded so /// far. std::map PrecompTypeIndexMappings; /// List of TypeServer PDBs which cannot be loaded. /// Cached to prevent repeated load attempts. std::map MissingTypeServerPDBs; }; class DebugSHandler { PDBLinker &Linker; /// The object file whose .debug$S sections we're processing. ObjFile &File; /// The result of merging type indices. const CVIndexMap &IndexMap; /// The DEBUG_S_STRINGTABLE subsection. These strings are referred to by /// index from other records in the .debug$S section. All of these strings /// need to be added to the global PDB string table, and all references to /// these strings need to have their indices re-written to refer to the /// global PDB string table. DebugStringTableSubsectionRef CVStrTab; /// The DEBUG_S_FILECHKSMS subsection. As above, these are referred to /// by other records in the .debug$S section and need to be merged into the /// PDB. DebugChecksumsSubsectionRef Checksums; /// The DEBUG_S_FRAMEDATA subsection(s). There can be more than one of /// these and they need not appear in any specific order. However, they /// contain string table references which need to be re-written, so we /// collect them all here and re-write them after all subsections have been /// discovered and processed. std::vector NewFpoFrames; /// Pointers to raw memory that we determine have string table references /// that need to be re-written. We first process all .debug$S subsections /// to ensure that we can handle subsections written in any order, building /// up this list as we go. At the end, we use the string table (which must /// have been discovered by now else it is an error) to re-write these /// references. std::vector StringTableReferences; public: DebugSHandler(PDBLinker &Linker, ObjFile &File, const CVIndexMap &IndexMap) : Linker(Linker), File(File), IndexMap(IndexMap) {} void handleDebugS(lld::coff::SectionChunk &DebugS); void finish(); }; } // Visual Studio's debugger requires absolute paths in various places in the // PDB to work without additional configuration: // https://docs.microsoft.com/en-us/visualstudio/debugger/debug-source-files-common-properties-solution-property-pages-dialog-box static void pdbMakeAbsolute(SmallVectorImpl &FileName) { // The default behavior is to produce paths that are valid within the context // of the machine that you perform the link on. If the linker is running on // a POSIX system, we will output absolute POSIX paths. If the linker is // running on a Windows system, we will output absolute Windows paths. If the // user desires any other kind of behavior, they should explicitly pass // /pdbsourcepath, in which case we will treat the exact string the user // passed in as the gospel and not normalize, canonicalize it. if (sys::path::is_absolute(FileName, sys::path::Style::windows) || sys::path::is_absolute(FileName, sys::path::Style::posix)) return; // It's not absolute in any path syntax. Relative paths necessarily refer to // the local file system, so we can make it native without ending up with a // nonsensical path. - sys::path::native(FileName); if (Config->PDBSourcePath.empty()) { + sys::path::native(FileName); sys::fs::make_absolute(FileName); return; } - // Only apply native and dot removal to the relative file path. We want to - // leave the path the user specified untouched since we assume they specified - // it for a reason. - sys::path::remove_dots(FileName, /*remove_dot_dots=*/true); + // Try to guess whether /PDBSOURCEPATH is a unix path or a windows path. + // Since PDB's are more of a Windows thing, we make this conservative and only + // decide that it's a unix path if we're fairly certain. Specifically, if + // it starts with a forward slash. SmallString<128> AbsoluteFileName = Config->PDBSourcePath; - sys::path::append(AbsoluteFileName, FileName); + sys::path::Style GuessedStyle = AbsoluteFileName.startswith("/") + ? sys::path::Style::posix + : sys::path::Style::windows; + sys::path::append(AbsoluteFileName, GuessedStyle, FileName); + sys::path::native(AbsoluteFileName, GuessedStyle); + sys::path::remove_dots(AbsoluteFileName, true, GuessedStyle); + FileName = std::move(AbsoluteFileName); } static SectionChunk *findByName(ArrayRef Sections, StringRef Name) { for (SectionChunk *C : Sections) if (C->getSectionName() == Name) return C; return nullptr; } static ArrayRef consumeDebugMagic(ArrayRef Data, StringRef SecName) { // First 4 bytes are section magic. if (Data.size() < 4) fatal(SecName + " too short"); if (support::endian::read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC) fatal(SecName + " has an invalid magic"); return Data.slice(4); } static ArrayRef getDebugSection(ObjFile *File, StringRef SecName) { if (SectionChunk *Sec = findByName(File->getDebugChunks(), SecName)) return consumeDebugMagic(Sec->getContents(), SecName); return {}; } // A COFF .debug$H section is currently a clang extension. This function checks // if a .debug$H section is in a format that we expect / understand, so that we // can ignore any sections which are coincidentally also named .debug$H but do // not contain a format we recognize. static bool canUseDebugH(ArrayRef DebugH) { if (DebugH.size() < sizeof(object::debug_h_header)) return false; auto *Header = reinterpret_cast(DebugH.data()); DebugH = DebugH.drop_front(sizeof(object::debug_h_header)); return Header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC && Header->Version == 0 && Header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1_8) && (DebugH.size() % 8 == 0); } static Optional> getDebugH(ObjFile *File) { SectionChunk *Sec = findByName(File->getDebugChunks(), ".debug$H"); if (!Sec) return llvm::None; ArrayRef Contents = Sec->getContents(); if (!canUseDebugH(Contents)) return None; return Contents; } static ArrayRef getHashesFromDebugH(ArrayRef DebugH) { assert(canUseDebugH(DebugH)); DebugH = DebugH.drop_front(sizeof(object::debug_h_header)); uint32_t Count = DebugH.size() / sizeof(GloballyHashedType); return {reinterpret_cast(DebugH.data()), Count}; } static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, TypeCollection &TypeTable) { // Start the TPI or IPI stream header. TpiBuilder.setVersionHeader(pdb::PdbTpiV80); // Flatten the in memory type table and hash each type. TypeTable.ForEachRecord([&](TypeIndex TI, const CVType &Type) { auto Hash = pdb::hashTypeRecord(Type); if (auto E = Hash.takeError()) fatal("type hashing error"); TpiBuilder.addTypeRecord(Type.RecordData, *Hash); }); } // OBJs usually start their symbol stream with a S_OBJNAME record. This record // also contains the signature/key of the current PCH session. The signature // must be same for all objects which depend on the precompiled object. // Recompiling the precompiled headers will generate a new PCH key and thus // invalidate all the dependent objects. static uint32_t extractPCHSignature(ObjFile *File) { auto DbgIt = find_if(File->getDebugChunks(), [](SectionChunk *C) { return C->getSectionName() == ".debug$S"; }); if (!DbgIt) return 0; ArrayRef Contents = consumeDebugMagic((*DbgIt)->getContents(), ".debug$S"); DebugSubsectionArray Subsections; BinaryStreamReader Reader(Contents, support::little); ExitOnErr(Reader.readArray(Subsections, Contents.size())); for (const DebugSubsectionRecord &SS : Subsections) { if (SS.kind() != DebugSubsectionKind::Symbols) continue; // If it's there, the S_OBJNAME record shall come first in the stream. Expected Sym = readSymbolFromStream(SS.getRecordData(), 0); if (!Sym) { consumeError(Sym.takeError()); continue; } if (auto ObjName = SymbolDeserializer::deserializeAs(Sym.get())) return ObjName->Signature; } return 0; } Expected PDBLinker::mergeDebugT(ObjFile *File, CVIndexMap *ObjectIndexMap) { ScopedTimer T(TypeMergingTimer); bool IsPrecompiledHeader = false; ArrayRef Data = getDebugSection(File, ".debug$T"); if (Data.empty()) { // Try again, Microsoft precompiled headers use .debug$P instead of // .debug$T Data = getDebugSection(File, ".debug$P"); IsPrecompiledHeader = true; } if (Data.empty()) return *ObjectIndexMap; // no debug info // Precompiled headers objects need to save the index map for further // reference by other objects which use the precompiled headers. if (IsPrecompiledHeader) { uint32_t PCHSignature = extractPCHSignature(File); if (PCHSignature == 0) fatal("No signature found for the precompiled headers OBJ (" + File->getName() + ")"); // When a precompiled headers object comes first on the command-line, we // update the mapping here. Otherwise, if an object referencing the // precompiled headers object comes first, the mapping is created in // aquirePrecompObj(), thus we would skip this block. if (!ObjectIndexMap->IsPrecompiledTypeMap) { auto R = registerPrecompiledHeaders(PCHSignature); if (R.second) fatal( "A precompiled headers OBJ with the same signature was already " "provided! (" + File->getName() + ")"); ObjectIndexMap = &R.first; } } BinaryByteStream Stream(Data, support::little); CVTypeArray Types; BinaryStreamReader Reader(Stream); if (auto EC = Reader.readArray(Types, Reader.getLength())) fatal("Reader::readArray failed: " + toString(std::move(EC))); auto FirstType = Types.begin(); if (FirstType == Types.end()) return *ObjectIndexMap; if (FirstType->kind() == LF_TYPESERVER2) { // Look through type servers. If we've already seen this type server, // don't merge any type information. return maybeMergeTypeServerPDB(File, *FirstType); } else if (FirstType->kind() == LF_PRECOMP) { // This object was compiled with /Yu, so process the corresponding // precompiled headers object (/Yc) first. Some type indices in the current // object are referencing data in the precompiled headers object, so we need // both to be loaded. auto E = mergeInPrecompHeaderObj(File, *FirstType, ObjectIndexMap); if (!E) return E.takeError(); // Drop LF_PRECOMP record from the input stream, as it needs to be replaced // with the precompiled headers object type stream. // Note that we can't just call Types.drop_front(), as we explicitly want to // rebase the stream. Types.setUnderlyingStream( Types.getUnderlyingStream().drop_front(FirstType->RecordData.size())); } // Fill in the temporary, caller-provided ObjectIndexMap. if (Config->DebugGHashes) { ArrayRef Hashes; std::vector OwnedHashes; if (Optional> DebugH = getDebugH(File)) Hashes = getHashesFromDebugH(*DebugH); else { OwnedHashes = GloballyHashedType::hashTypes(Types); Hashes = OwnedHashes; } if (auto Err = mergeTypeAndIdRecords(GlobalIDTable, GlobalTypeTable, ObjectIndexMap->TPIMap, Types, Hashes, File->PCHSignature)) fatal("codeview::mergeTypeAndIdRecords failed: " + toString(std::move(Err))); } else { if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable, ObjectIndexMap->TPIMap, Types, File->PCHSignature)) fatal("codeview::mergeTypeAndIdRecords failed: " + toString(std::move(Err))); } return *ObjectIndexMap; } static Expected> tryToLoadPDB(const codeview::GUID &GuidFromObj, StringRef TSPath) { // Ensure the file exists before anything else. We want to return ENOENT, // "file not found", even if the path points to a removable device (in which // case the return message would be EAGAIN, "resource unavailable try again") if (!llvm::sys::fs::exists(TSPath)) return errorCodeToError(std::error_code(ENOENT, std::generic_category())); ErrorOr> MBOrErr = MemoryBuffer::getFile( TSPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false); if (!MBOrErr) return errorCodeToError(MBOrErr.getError()); std::unique_ptr ThisSession; if (auto EC = pdb::NativeSession::createFromPdb( MemoryBuffer::getMemBuffer(Driver->takeBuffer(std::move(*MBOrErr)), /*RequiresNullTerminator=*/false), ThisSession)) return std::move(EC); std::unique_ptr NS( static_cast(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::pdb_error_code::signature_out_of_date); return std::move(NS); } Expected PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, const CVType &FirstType) { TypeServer2Record TS; if (auto EC = TypeDeserializer::deserializeAs(const_cast(FirstType), TS)) fatal("error reading record: " + toString(std::move(EC))); const codeview::GUID &TSId = TS.getGuid(); StringRef TSPath = TS.getName(); // First, check if the PDB has previously failed to load. auto PrevErr = MissingTypeServerPDBs.find(TSId); if (PrevErr != MissingTypeServerPDBs.end()) return createFileError( TSPath, make_error(PrevErr->second, inconvertibleErrorCode())); // Second, check if we already loaded a PDB with this GUID. Return the type // index mapping if we have it. auto Insertion = TypeServerIndexMappings.insert({TSId, 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 = handleExpected( tryToLoadPDB(TSId, TSPath), [&]() { StringRef LocalPath = !File->ParentName.empty() ? File->ParentName : File->getName(); SmallString<128> Path = sys::path::parent_path(LocalPath); // Currently, type server PDBs are only created by cl, which only runs // on Windows, so we can assume type server paths are Windows style. sys::path::append( Path, sys::path::filename(TSPath, sys::path::Style::windows)); return tryToLoadPDB(TSId, Path); }, [&](std::unique_ptr EC) -> Error { auto SysErr = EC->convertToErrorCode(); // Only re-try loading if the previous error was "No such file or // directory" if (SysErr.category() == std::generic_category() && SysErr.value() == ENOENT) return Error::success(); return Error(std::move(EC)); }); if (auto E = ExpectedSession.takeError()) { TypeServerIndexMappings.erase(TSId); // Flatten the error to a string, for later display, if the error occurs // again on the same PDB. std::string ErrMsg; raw_string_ostream S(ErrMsg); S << E; MissingTypeServerPDBs.emplace(TSId, S.str()); return createFileError(TSPath, std::move(E)); } pdb::NativeSession *Session = ExpectedSession->get(); // Keep a strong reference to this PDB, so that it's safe to hold pointers // into the file. LoadedPDBs.push_back(std::move(*ExpectedSession)); auto ExpectedTpi = Session->getPDBFile().getPDBTpiStream(); if (auto E = ExpectedTpi.takeError()) fatal("Type server does not have TPI stream: " + toString(std::move(E))); auto ExpectedIpi = Session->getPDBFile().getPDBIpiStream(); if (auto E = ExpectedIpi.takeError()) fatal("Type server does not have TPI stream: " + toString(std::move(E))); if (Config->DebugGHashes) { // PDBs do not actually store global hashes, so when merging a type server // PDB we have to synthesize global hashes. To do this, we first synthesize // global hashes for the TPI stream, since it is independent, then we // synthesize hashes for the IPI stream, using the hashes for the TPI stream // as inputs. auto TpiHashes = GloballyHashedType::hashTypes(ExpectedTpi->typeArray()); auto IpiHashes = GloballyHashedType::hashIds(ExpectedIpi->typeArray(), TpiHashes); Optional EndPrecomp; // Merge TPI first, because the IPI stream will reference type indices. if (auto Err = mergeTypeRecords(GlobalTypeTable, IndexMap.TPIMap, ExpectedTpi->typeArray(), TpiHashes, EndPrecomp)) fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err))); // Merge IPI. if (auto Err = mergeIdRecords(GlobalIDTable, IndexMap.TPIMap, IndexMap.IPIMap, ExpectedIpi->typeArray(), IpiHashes)) fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err))); } else { // Merge TPI first, because the IPI stream will reference type indices. if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap, ExpectedTpi->typeArray())) fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err))); // Merge IPI. if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap, ExpectedIpi->typeArray())) fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err))); } return IndexMap; } Expected PDBLinker::mergeInPrecompHeaderObj(ObjFile *File, const CVType &FirstType, CVIndexMap *ObjectIndexMap) { PrecompRecord Precomp; if (auto EC = TypeDeserializer::deserializeAs(const_cast(FirstType), Precomp)) fatal("error reading record: " + toString(std::move(EC))); auto E = aquirePrecompObj(File, Precomp); if (!E) return E.takeError(); const CVIndexMap &PrecompIndexMap = *E; assert(PrecompIndexMap.IsPrecompiledTypeMap); if (PrecompIndexMap.TPIMap.empty()) return PrecompIndexMap; assert(Precomp.getStartTypeIndex() == TypeIndex::FirstNonSimpleIndex); assert(Precomp.getTypesCount() <= PrecompIndexMap.TPIMap.size()); // Use the previously remapped index map from the precompiled headers. ObjectIndexMap->TPIMap.append(PrecompIndexMap.TPIMap.begin(), PrecompIndexMap.TPIMap.begin() + Precomp.getTypesCount()); return *ObjectIndexMap; } static bool equals_path(StringRef path1, StringRef path2) { #if defined(_WIN32) return path1.equals_lower(path2); #else return path1.equals(path2); #endif } // Find by name an OBJ provided on the command line static ObjFile *findObjByName(StringRef FileNameOnly) { SmallString<128> CurrentPath; for (ObjFile *F : ObjFile::Instances) { StringRef CurrentFileName = sys::path::filename(F->getName()); // Compare based solely on the file name (link.exe behavior) if (equals_path(CurrentFileName, FileNameOnly)) return F; } return nullptr; } std::pair PDBLinker::registerPrecompiledHeaders(uint32_t Signature) { auto Insertion = PrecompTypeIndexMappings.insert({Signature, CVIndexMap()}); CVIndexMap &IndexMap = Insertion.first->second; if (!Insertion.second) return {IndexMap, true}; // Mark this map as a precompiled types map. IndexMap.IsPrecompiledTypeMap = true; return {IndexMap, false}; } Expected PDBLinker::aquirePrecompObj(ObjFile *File, PrecompRecord Precomp) { // First, check if we already loaded the precompiled headers object with this // signature. Return the type index mapping if we've already seen it. auto R = registerPrecompiledHeaders(Precomp.getSignature()); if (R.second) return R.first; CVIndexMap &IndexMap = R.first; // Cross-compile warning: given that Clang doesn't generate LF_PRECOMP // records, we assume the OBJ comes from a Windows build of cl.exe. Thusly, // the paths embedded in the OBJs are in the Windows format. SmallString<128> PrecompFileName = sys::path::filename( Precomp.getPrecompFilePath(), sys::path::Style::windows); // link.exe requires that a precompiled headers object must always be provided // on the command-line, even if that's not necessary. auto PrecompFile = findObjByName(PrecompFileName); if (!PrecompFile) return createFileError( PrecompFileName.str(), make_error(pdb::pdb_error_code::external_cmdline_ref)); addObjFile(PrecompFile, &IndexMap); if (!PrecompFile->PCHSignature) fatal(PrecompFile->getName() + " is not a precompiled headers object"); if (Precomp.getSignature() != PrecompFile->PCHSignature.getValueOr(0)) return createFileError( Precomp.getPrecompFilePath().str(), make_error(pdb::pdb_error_code::signature_out_of_date)); return IndexMap; } static bool remapTypeIndex(TypeIndex &TI, ArrayRef TypeIndexMap) { if (TI.isSimple()) return true; if (TI.toArrayIndex() >= TypeIndexMap.size()) return false; TI = TypeIndexMap[TI.toArrayIndex()]; return true; } static void remapTypesInSymbolRecord(ObjFile *File, SymbolKind SymKind, MutableArrayRef RecordBytes, const CVIndexMap &IndexMap, ArrayRef TypeRefs) { MutableArrayRef Contents = RecordBytes.drop_front(sizeof(RecordPrefix)); 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 TypeOrItemMap = IndexMap.TPIMap; bool IsItemIndex = Ref.Kind == TiRefKind::IndexRef; if (IsItemIndex && IndexMap.IsTypeServerMap) TypeOrItemMap = IndexMap.IPIMap; MutableArrayRef TIs( reinterpret_cast(Contents.data() + Ref.Offset), Ref.Count); for (TypeIndex &TI : TIs) { if (!remapTypeIndex(TI, TypeOrItemMap)) { log("ignoring symbol record of kind 0x" + utohexstr(SymKind) + " in " + File->getName() + " with bad " + (IsItemIndex ? "item" : "type") + " index 0x" + utohexstr(TI.getIndex())); TI = TypeIndex(SimpleTypeKind::NotTranslated); continue; } } } } static void recordStringTableReferenceAtOffset(MutableArrayRef Contents, uint32_t Offset, std::vector &StrTableRefs) { Contents = Contents.drop_front(Offset).take_front(sizeof(support::ulittle32_t)); ulittle32_t *Index = reinterpret_cast(Contents.data()); StrTableRefs.push_back(Index); } static void recordStringTableReferences(SymbolKind Kind, MutableArrayRef Contents, std::vector &StrTableRefs) { // For now we only handle S_FILESTATIC, but we may need the same logic for // S_DEFRANGE and S_DEFRANGE_SUBFIELD. However, I cannot seem to generate any // PDBs that contain these types of records, so because of the uncertainty // they are omitted here until we can prove that it's necessary. switch (Kind) { case SymbolKind::S_FILESTATIC: // FileStaticSym::ModFileOffset recordStringTableReferenceAtOffset(Contents, 8, StrTableRefs); break; case SymbolKind::S_DEFRANGE: case SymbolKind::S_DEFRANGE_SUBFIELD: log("Not fixing up string table reference in S_DEFRANGE / " "S_DEFRANGE_SUBFIELD record"); break; default: break; } } static SymbolKind symbolKind(ArrayRef RecordData) { const RecordPrefix *Prefix = reinterpret_cast(RecordData.data()); return static_cast(uint16_t(Prefix->RecordKind)); } /// MSVC translates S_PROC_ID_END to S_END, and S_[LG]PROC32_ID to S_[LG]PROC32 static void translateIdSymbols(MutableArrayRef &RecordData, TypeCollection &IDTable) { RecordPrefix *Prefix = reinterpret_cast(RecordData.data()); SymbolKind Kind = symbolKind(RecordData); if (Kind == SymbolKind::S_PROC_ID_END) { Prefix->RecordKind = SymbolKind::S_END; return; } // In an object file, GPROC32_ID has an embedded reference which refers to the // single object file type index namespace. This has already been translated // to the PDB file's ID stream index space, but we need to convert this to a // symbol that refers to the type stream index space. So we remap again from // ID index space to type index space. if (Kind == SymbolKind::S_GPROC32_ID || Kind == SymbolKind::S_LPROC32_ID) { SmallVector Refs; auto Content = RecordData.drop_front(sizeof(RecordPrefix)); CVSymbol Sym(Kind, RecordData); discoverTypeIndicesInSymbol(Sym, Refs); assert(Refs.size() == 1); assert(Refs.front().Count == 1); TypeIndex *TI = reinterpret_cast(Content.data() + Refs[0].Offset); // `TI` is the index of a FuncIdRecord or MemberFuncIdRecord which lives in // the IPI stream, whose `FunctionType` member refers to the TPI stream. // Note that LF_FUNC_ID and LF_MEMFUNC_ID have the same record layout, and // in both cases we just need the second type index. if (!TI->isSimple() && !TI->isNoneType()) { CVType FuncIdData = IDTable.getType(*TI); SmallVector Indices; discoverTypeIndices(FuncIdData, Indices); assert(Indices.size() == 2); *TI = Indices[1]; } Kind = (Kind == SymbolKind::S_GPROC32_ID) ? SymbolKind::S_GPROC32 : SymbolKind::S_LPROC32; Prefix->RecordKind = uint16_t(Kind); } } /// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned. /// The object file may not be aligned. static MutableArrayRef copyAndAlignSymbol(const CVSymbol &Sym, MutableArrayRef &AlignedMem) { size_t Size = alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb)); assert(Size >= 4 && "record too short"); assert(Size <= MaxRecordLength && "record too long"); assert(AlignedMem.size() >= Size && "didn't preallocate enough"); // Copy the symbol record and zero out any padding bytes. MutableArrayRef NewData = AlignedMem.take_front(Size); AlignedMem = AlignedMem.drop_front(Size); memcpy(NewData.data(), Sym.data().data(), Sym.length()); memset(NewData.data() + Sym.length(), 0, Size - Sym.length()); // Update the record prefix length. It should point to the beginning of the // next record. auto *Prefix = reinterpret_cast(NewData.data()); Prefix->RecordLen = Size - 2; return NewData; } struct ScopeRecord { ulittle32_t PtrParent; ulittle32_t PtrEnd; }; struct SymbolScope { ScopeRecord *OpeningRecord; uint32_t ScopeOffset; }; static void scopeStackOpen(SmallVectorImpl &Stack, uint32_t CurOffset, CVSymbol &Sym) { assert(symbolOpensScope(Sym.kind())); SymbolScope S; S.ScopeOffset = CurOffset; S.OpeningRecord = const_cast( reinterpret_cast(Sym.content().data())); S.OpeningRecord->PtrParent = Stack.empty() ? 0 : Stack.back().ScopeOffset; Stack.push_back(S); } static void scopeStackClose(SmallVectorImpl &Stack, uint32_t CurOffset, ObjFile *File) { if (Stack.empty()) { warn("symbol scopes are not balanced in " + File->getName()); return; } SymbolScope S = Stack.pop_back_val(); S.OpeningRecord->PtrEnd = CurOffset; } static bool symbolGoesInModuleStream(const CVSymbol &Sym, bool IsGlobalScope) { switch (Sym.kind()) { case SymbolKind::S_GDATA32: case SymbolKind::S_CONSTANT: // We really should not be seeing S_PROCREF and S_LPROCREF in the first place // since they are synthesized by the linker in response to S_GPROC32 and // S_LPROC32, but if we do see them, don't put them in the module stream I // guess. case SymbolKind::S_PROCREF: case SymbolKind::S_LPROCREF: return false; // S_UDT records go in the module stream if it is not a global S_UDT. case SymbolKind::S_UDT: return !IsGlobalScope; // S_GDATA32 does not go in the module stream, but S_LDATA32 does. case SymbolKind::S_LDATA32: default: return true; } } static bool symbolGoesInGlobalsStream(const CVSymbol &Sym, bool IsGlobalScope) { switch (Sym.kind()) { case SymbolKind::S_CONSTANT: case SymbolKind::S_GDATA32: // S_LDATA32 goes in both the module stream and the globals stream. case SymbolKind::S_LDATA32: case SymbolKind::S_GPROC32: case SymbolKind::S_LPROC32: // We really should not be seeing S_PROCREF and S_LPROCREF in the first place // since they are synthesized by the linker in response to S_GPROC32 and // S_LPROC32, but if we do see them, copy them straight through. case SymbolKind::S_PROCREF: case SymbolKind::S_LPROCREF: return true; // S_UDT records go in the globals stream if it is a global S_UDT. case SymbolKind::S_UDT: return IsGlobalScope; default: return false; } } static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, uint16_t ModIndex, unsigned SymOffset, const CVSymbol &Sym) { switch (Sym.kind()) { case SymbolKind::S_CONSTANT: case SymbolKind::S_UDT: case SymbolKind::S_GDATA32: case SymbolKind::S_LDATA32: case SymbolKind::S_PROCREF: case SymbolKind::S_LPROCREF: Builder.addGlobalSymbol(Sym); break; case SymbolKind::S_GPROC32: case SymbolKind::S_LPROC32: { SymbolRecordKind K = SymbolRecordKind::ProcRefSym; if (Sym.kind() == SymbolKind::S_LPROC32) K = SymbolRecordKind::LocalProcRef; ProcRefSym PS(K); PS.Module = ModIndex; // For some reason, MSVC seems to add one to this value. ++PS.Module; PS.Name = getSymbolName(Sym); PS.SumName = 0; PS.SymOffset = SymOffset; Builder.addGlobalSymbol(PS); break; } default: llvm_unreachable("Invalid symbol kind!"); } } void PDBLinker::mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap, std::vector &StringTableRefs, BinaryStreamRef SymData) { ArrayRef SymsBuffer; cantFail(SymData.readBytes(0, SymData.getLength(), SymsBuffer)); SmallVector Scopes; // Iterate every symbol to check if any need to be realigned, and if so, how // much space we need to allocate for them. bool NeedsRealignment = false; unsigned TotalRealignedSize = 0; auto EC = forEachCodeViewRecord( SymsBuffer, [&](CVSymbol Sym) -> llvm::Error { unsigned RealignedSize = alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb)); NeedsRealignment |= RealignedSize != Sym.length(); TotalRealignedSize += RealignedSize; return Error::success(); }); // If any of the symbol record lengths was corrupt, ignore them all, warn // about it, and move on. if (EC) { warn("corrupt symbol records in " + File->getName()); consumeError(std::move(EC)); return; } // If any symbol needed realignment, allocate enough contiguous memory for // them all. Typically symbol subsections are small enough that this will not // cause fragmentation. MutableArrayRef AlignedSymbolMem; if (NeedsRealignment) { void *AlignedData = Alloc.Allocate(TotalRealignedSize, alignOf(CodeViewContainer::Pdb)); AlignedSymbolMem = makeMutableArrayRef( reinterpret_cast(AlignedData), TotalRealignedSize); } // Iterate again, this time doing the real work. unsigned CurSymOffset = File->ModuleDBI->getNextSymbolOffset(); ArrayRef BulkSymbols; cantFail(forEachCodeViewRecord( SymsBuffer, [&](CVSymbol Sym) -> llvm::Error { // Align the record if required. MutableArrayRef RecordBytes; if (NeedsRealignment) { RecordBytes = copyAndAlignSymbol(Sym, AlignedSymbolMem); Sym = CVSymbol(Sym.kind(), RecordBytes); } else { // Otherwise, we can actually mutate the symbol directly, since we // copied it to apply relocations. RecordBytes = makeMutableArrayRef( const_cast(Sym.data().data()), Sym.length()); } // Discover type index references in the record. Skip it if we don't // know where they are. SmallVector TypeRefs; if (!discoverTypeIndicesInSymbol(Sym, TypeRefs)) { log("ignoring unknown symbol record with kind 0x" + utohexstr(Sym.kind())); return Error::success(); } // Re-map all the type index references. remapTypesInSymbolRecord(File, Sym.kind(), RecordBytes, IndexMap, TypeRefs); // An object file may have S_xxx_ID symbols, but these get converted to // "real" symbols in a PDB. translateIdSymbols(RecordBytes, getIDTable()); Sym = CVSymbol(symbolKind(RecordBytes), RecordBytes); // If this record refers to an offset in the object file's string table, // add that item to the global PDB string table and re-write the index. recordStringTableReferences(Sym.kind(), RecordBytes, StringTableRefs); // Fill in "Parent" and "End" fields by maintaining a stack of scopes. if (symbolOpensScope(Sym.kind())) scopeStackOpen(Scopes, CurSymOffset, Sym); else if (symbolEndsScope(Sym.kind())) scopeStackClose(Scopes, CurSymOffset, File); // Add the symbol to the globals stream if necessary. Do this before // adding the symbol to the module since we may need to get the next // symbol offset, and writing to the module's symbol stream will update // that offset. if (symbolGoesInGlobalsStream(Sym, Scopes.empty())) addGlobalSymbol(Builder.getGsiBuilder(), File->ModuleDBI->getModuleIndex(), CurSymOffset, Sym); if (symbolGoesInModuleStream(Sym, Scopes.empty())) { // Add symbols to the module in bulk. If this symbol is contiguous // with the previous run of symbols to add, combine the ranges. If // not, close the previous range of symbols and start a new one. if (Sym.data().data() == BulkSymbols.end()) { BulkSymbols = makeArrayRef(BulkSymbols.data(), BulkSymbols.size() + Sym.length()); } else { File->ModuleDBI->addSymbolsInBulk(BulkSymbols); BulkSymbols = RecordBytes; } CurSymOffset += Sym.length(); } return Error::success(); })); // Add any remaining symbols we've accumulated. File->ModuleDBI->addSymbolsInBulk(BulkSymbols); } // Allocate memory for a .debug$S / .debug$F section and relocate it. static ArrayRef relocateDebugChunk(BumpPtrAllocator &Alloc, SectionChunk &DebugChunk) { uint8_t *Buffer = Alloc.Allocate(DebugChunk.getSize()); assert(DebugChunk.OutputSectionOff == 0 && "debug sections should not be in output sections"); DebugChunk.readRelocTargets(); DebugChunk.writeTo(Buffer); return makeArrayRef(Buffer, DebugChunk.getSize()); } static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) { OutputSection *OS = C->getOutputSection(); pdb::SectionContrib SC; memset(&SC, 0, sizeof(SC)); SC.ISect = OS->SectionIndex; SC.Off = C->getRVA() - OS->getRVA(); SC.Size = C->getSize(); if (auto *SecChunk = dyn_cast(C)) { SC.Characteristics = SecChunk->Header->Characteristics; SC.Imod = SecChunk->File->ModuleDBI->getModuleIndex(); ArrayRef Contents = SecChunk->getContents(); JamCRC CRC(0); ArrayRef CharContents = makeArrayRef( reinterpret_cast(Contents.data()), Contents.size()); CRC.update(CharContents); SC.DataCrc = CRC.getCRC(); } else { SC.Characteristics = OS->Header.Characteristics; // FIXME: When we start creating DBI for import libraries, use those here. SC.Imod = Modi; } SC.RelocCrc = 0; // FIXME return SC; } static uint32_t translateStringTableIndex(uint32_t ObjIndex, const DebugStringTableSubsectionRef &ObjStrTable, DebugStringTableSubsection &PdbStrTable) { auto ExpectedString = ObjStrTable.getString(ObjIndex); if (!ExpectedString) { warn("Invalid string table reference"); consumeError(ExpectedString.takeError()); return 0; } return PdbStrTable.insert(*ExpectedString); } void DebugSHandler::handleDebugS(lld::coff::SectionChunk &DebugS) { DebugSubsectionArray Subsections; ArrayRef RelocatedDebugContents = consumeDebugMagic( relocateDebugChunk(Linker.Alloc, DebugS), DebugS.getSectionName()); BinaryStreamReader Reader(RelocatedDebugContents, support::little); ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size())); for (const DebugSubsectionRecord &SS : Subsections) { switch (SS.kind()) { case DebugSubsectionKind::StringTable: { assert(!CVStrTab.valid() && "Encountered multiple string table subsections!"); ExitOnErr(CVStrTab.initialize(SS.getRecordData())); break; } case DebugSubsectionKind::FileChecksums: assert(!Checksums.valid() && "Encountered multiple checksum subsections!"); 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::FrameData: { // We need to re-write string table indices here, so save off all // frame data subsections until we've processed the entire list of // subsections so that we can be sure we have the string table. DebugFrameDataSubsectionRef FDS; ExitOnErr(FDS.initialize(SS.getRecordData())); NewFpoFrames.push_back(std::move(FDS)); break; } case DebugSubsectionKind::Symbols: { Linker.mergeSymbolRecords(&File, IndexMap, StringTableReferences, SS.getRecordData()); break; } default: // FIXME: Process the rest of the subsections. break; } } } void DebugSHandler::finish() { pdb::DbiStreamBuilder &DbiBuilder = Linker.Builder.getDbiBuilder(); // We should have seen all debug subsections across the entire object file now // which means that if a StringTable subsection and Checksums subsection were // present, now is the time to handle them. if (!CVStrTab.valid()) { if (Checksums.valid()) fatal(".debug$S sections with a checksums subsection must also contain a " "string table subsection"); if (!StringTableReferences.empty()) warn("No StringTable subsection was encountered, but there are string " "table references"); return; } // Rewrite string table indices in the Fpo Data and symbol records to refer to // the global PDB string table instead of the object file string table. for (DebugFrameDataSubsectionRef &FDS : NewFpoFrames) { const ulittle32_t *Reloc = FDS.getRelocPtr(); for (codeview::FrameData FD : FDS) { FD.RvaStart += *Reloc; FD.FrameFunc = translateStringTableIndex(FD.FrameFunc, CVStrTab, Linker.PDBStrTab); DbiBuilder.addNewFpoData(FD); } } for (ulittle32_t *Ref : StringTableReferences) *Ref = translateStringTableIndex(*Ref, CVStrTab, Linker.PDBStrTab); // 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. auto NewChecksums = make_unique(Linker.PDBStrTab); for (FileChecksumEntry &FC : Checksums) { SmallString<128> FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset)); pdbMakeAbsolute(FileName); ExitOnErr(Linker.Builder.getDbiBuilder().addModuleSourceFile( *File.ModuleDBI, FileName)); NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum); } File.ModuleDBI->addDebugSubsection(std::move(NewChecksums)); } void PDBLinker::addObjFile(ObjFile *File, CVIndexMap *ExternIndexMap) { if (File->wasProcessedForPDB()) return; // 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(); pdbMakeAbsolute(Path); StringRef Name = InArchive ? File->getName() : StringRef(Path); pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); File->ModuleDBI = &ExitOnErr(DbiBuilder.addModuleInfo(Name)); File->ModuleDBI->setObjFileName(Path); auto Chunks = File->getChunks(); uint32_t Modi = File->ModuleDBI->getModuleIndex(); for (Chunk *C : Chunks) { auto *SecChunk = dyn_cast(C); if (!SecChunk || !SecChunk->Live) continue; pdb::SectionContrib SC = createSectionContrib(SecChunk, Modi); File->ModuleDBI->setFirstSectionContrib(SC); break; } // 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; auto IndexMapResult = mergeDebugT(File, ExternIndexMap ? ExternIndexMap : &ObjectIndexMap); // If the .debug$T sections fail to merge, assume there is no debug info. if (!IndexMapResult) { if (!Config->WarnDebugInfoUnusable) { consumeError(IndexMapResult.takeError()); return; } StringRef FileName = sys::path::filename(Path); warn("Cannot use debug info for '" + FileName + "' [LNK4099]\n" + ">>> failed to load reference " + StringRef(toString(IndexMapResult.takeError()))); return; } ScopedTimer T(SymbolMergingTimer); DebugSHandler DSH(*this, *File, *IndexMapResult); // Now do all live .debug$S and .debug$F sections. for (SectionChunk *DebugChunk : File->getDebugChunks()) { if (!DebugChunk->Live || DebugChunk->getSize() == 0) continue; if (DebugChunk->getSectionName() == ".debug$S") { DSH.handleDebugS(*DebugChunk); continue; } if (DebugChunk->getSectionName() == ".debug$F") { ArrayRef RelocatedDebugContents = relocateDebugChunk(Alloc, *DebugChunk); FixedStreamArray FpoRecords; BinaryStreamReader Reader(RelocatedDebugContents, support::little); uint32_t Count = RelocatedDebugContents.size() / sizeof(object::FpoData); ExitOnErr(Reader.readArray(FpoRecords, Count)); // These are already relocated and don't refer to the string table, so we // can just copy it. for (const object::FpoData &FD : FpoRecords) DbiBuilder.addOldFpoData(FD); continue; } } // Do any post-processing now that all .debug$S sections have been processed. DSH.finish(); } static PublicSym32 createPublic(Defined *Def) { PublicSym32 Pub(SymbolKind::S_PUB32); Pub.Name = Def->getName(); if (auto *D = dyn_cast(Def)) { if (D->getCOFFSymbol().isFunctionDefinition()) Pub.Flags = PublicSymFlags::Function; } else if (isa(Def)) { Pub.Flags = PublicSymFlags::Function; } OutputSection *OS = Def->getChunk()->getOutputSection(); assert(OS && "all publics should be in final image"); Pub.Offset = Def->getRVA() - OS->getRVA(); Pub.Segment = OS->SectionIndex; return Pub; } // Add all object files to the PDB. Merge .debug$T sections into IpiData and // TpiData. void PDBLinker::addObjectsToPDB() { ScopedTimer T1(AddObjectsTimer); for (ObjFile *File : ObjFile::Instances) addObjFile(File); Builder.getStringTableBuilder().setStrings(PDBStrTab); T1.stop(); // Construct TPI and IPI stream contents. ScopedTimer T2(TpiStreamLayoutTimer); addTypeInfo(Builder.getTpiBuilder(), getTypeTable()); addTypeInfo(Builder.getIpiBuilder(), getIDTable()); T2.stop(); ScopedTimer T3(GlobalsLayoutTimer); // Compute the public and global symbols. auto &GsiBuilder = Builder.getGsiBuilder(); std::vector Publics; Symtab->forEachSymbol([&Publics](Symbol *S) { // Only emit defined, live symbols that have a chunk. auto *Def = dyn_cast(S); if (Def && Def->isLive() && Def->getChunk()) Publics.push_back(createPublic(Def)); }); if (!Publics.empty()) { // Sort the public symbols and add them to the stream. sort(parallel::par, Publics.begin(), Publics.end(), [](const PublicSym32 &L, const PublicSym32 &R) { return L.Name < R.Name; }); for (const PublicSym32 &Pub : Publics) GsiBuilder.addPublicSymbol(Pub); } } void PDBLinker::addNatvisFiles() { for (StringRef File : Config->NatvisFiles) { ErrorOr> DataOrErr = MemoryBuffer::getFile(File); if (!DataOrErr) { warn("Cannot open input file: " + File); continue; } Builder.addInjectedSource(File, std::move(*DataOrErr)); } } static codeview::CPUType toCodeViewMachine(COFF::MachineTypes Machine) { switch (Machine) { case COFF::IMAGE_FILE_MACHINE_AMD64: return codeview::CPUType::X64; case COFF::IMAGE_FILE_MACHINE_ARM: return codeview::CPUType::ARM7; case COFF::IMAGE_FILE_MACHINE_ARM64: return codeview::CPUType::ARM64; case COFF::IMAGE_FILE_MACHINE_ARMNT: return codeview::CPUType::ARMNT; case COFF::IMAGE_FILE_MACHINE_I386: return codeview::CPUType::Intel80386; default: llvm_unreachable("Unsupported CPU Type"); } } // Mimic MSVC which surrounds arguments containing whitespace with quotes. // Double double-quotes are handled, so that the resulting string can be // executed again on the cmd-line. static std::string quote(ArrayRef Args) { std::string R; R.reserve(256); for (StringRef A : Args) { if (!R.empty()) R.push_back(' '); bool HasWS = A.find(' ') != StringRef::npos; bool HasQ = A.find('"') != StringRef::npos; if (HasWS || HasQ) R.push_back('"'); if (HasQ) { SmallVector S; A.split(S, '"'); R.append(join(S, "\"\"")); } else { R.append(A); } if (HasWS || HasQ) R.push_back('"'); } return R; } static void addCommonLinkerModuleSymbols(StringRef Path, pdb::DbiModuleDescriptorBuilder &Mod, BumpPtrAllocator &Allocator) { ObjNameSym ONS(SymbolRecordKind::ObjNameSym); Compile3Sym CS(SymbolRecordKind::Compile3Sym); EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym); ONS.Name = "* Linker *"; ONS.Signature = 0; CS.Machine = toCodeViewMachine(Config->Machine); // Interestingly, if we set the string to 0.0.0.0, then when trying to view // local variables WinDbg emits an error that private symbols are not present. // By setting this to a valid MSVC linker version string, local variables are // displayed properly. As such, even though it is not representative of // LLVM's version information, we need this for compatibility. CS.Flags = CompileSym3Flags::None; CS.VersionBackendBuild = 25019; CS.VersionBackendMajor = 14; CS.VersionBackendMinor = 10; CS.VersionBackendQFE = 0; // MSVC also sets the frontend to 0.0.0.0 since this is specifically for the // linker module (which is by definition a backend), so we don't need to do // anything here. Also, it seems we can use "LLVM Linker" for the linker name // without any problems. Only the backend version has to be hardcoded to a // magic number. CS.VersionFrontendBuild = 0; CS.VersionFrontendMajor = 0; CS.VersionFrontendMinor = 0; CS.VersionFrontendQFE = 0; CS.Version = "LLVM Linker"; CS.setLanguage(SourceLanguage::Link); ArrayRef Args = makeArrayRef(Config->Argv).drop_front(); std::string ArgStr = quote(Args); EBS.Fields.push_back("cwd"); SmallString<64> cwd; if (Config->PDBSourcePath.empty()) sys::fs::current_path(cwd); else cwd = Config->PDBSourcePath; EBS.Fields.push_back(cwd); EBS.Fields.push_back("exe"); SmallString<64> exe = Config->Argv[0]; pdbMakeAbsolute(exe); EBS.Fields.push_back(exe); EBS.Fields.push_back("pdb"); EBS.Fields.push_back(Path); EBS.Fields.push_back("cmd"); EBS.Fields.push_back(ArgStr); Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( ONS, Allocator, CodeViewContainer::Pdb)); Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( CS, Allocator, CodeViewContainer::Pdb)); Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( EBS, Allocator, CodeViewContainer::Pdb)); } static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod, OutputSection &OS, BumpPtrAllocator &Allocator) { SectionSym Sym(SymbolRecordKind::SectionSym); Sym.Alignment = 12; // 2^12 = 4KB Sym.Characteristics = OS.Header.Characteristics; Sym.Length = OS.getVirtualSize(); Sym.Name = OS.Name; Sym.Rva = OS.getRVA(); Sym.SectionNumber = OS.SectionIndex; Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( Sym, Allocator, CodeViewContainer::Pdb)); } // Creates a PDB file. void coff::createPDB(SymbolTable *Symtab, ArrayRef OutputSections, ArrayRef SectionTable, llvm::codeview::DebugInfo *BuildId) { ScopedTimer T1(TotalPdbLinkTimer); PDBLinker PDB(Symtab); PDB.initialize(BuildId); PDB.addObjectsToPDB(); PDB.addSections(OutputSections, SectionTable); PDB.addNatvisFiles(); ScopedTimer T2(DiskCommitTimer); codeview::GUID Guid; PDB.commit(&Guid); memcpy(&BuildId->PDB70.Signature, &Guid, 16); } void PDBLinker::initialize(llvm::codeview::DebugInfo *BuildId) { ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize BuildId->Signature.CVSignature = OMF::Signature::PDB70; // Signature is set to a hash of the PDB contents when the PDB is done. memset(BuildId->PDB70.Signature, 0, 16); BuildId->PDB70.Age = 1; // Create streams in MSF for predefined streams, namely // PDB, TPI, DBI and IPI. for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I) ExitOnErr(Builder.getMsfBuilder().addStream(0)); // Add an Info stream. auto &InfoBuilder = Builder.getInfoBuilder(); InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70); InfoBuilder.setHashPDBContentsToGUID(true); // Add an empty DBI stream. pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); DbiBuilder.setAge(BuildId->PDB70.Age); DbiBuilder.setVersionHeader(pdb::PdbDbiV70); DbiBuilder.setMachineType(Config->Machine); // Technically we are not link.exe 14.11, but there are known cases where // debugging tools on Windows expect Microsoft-specific version numbers or // they fail to work at all. Since we know we produce PDBs that are // compatible with LINK 14.11, we set that version number here. DbiBuilder.setBuildNumber(14, 11); } void PDBLinker::addSections(ArrayRef OutputSections, ArrayRef SectionTable) { // It's not entirely clear what this is, but the * Linker * module uses it. pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); NativePath = Config->PDBPath; pdbMakeAbsolute(NativePath); uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); LinkerModule.setPdbFilePathNI(PdbFilePathNI); addCommonLinkerModuleSymbols(NativePath, LinkerModule, Alloc); // Add section contributions. They must be ordered by ascending RVA. for (OutputSection *OS : OutputSections) { addLinkerModuleSectionSymbol(LinkerModule, *OS, Alloc); for (Chunk *C : OS->Chunks) { pdb::SectionContrib SC = createSectionContrib(C, LinkerModule.getModuleIndex()); Builder.getDbiBuilder().addSectionContrib(SC); } } // Add Section Map stream. ArrayRef Sections = { (const object::coff_section *)SectionTable.data(), SectionTable.size() / sizeof(object::coff_section)}; SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections); DbiBuilder.setSectionMap(SectionMap); // Add COFF section header stream. ExitOnErr( DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable)); } void PDBLinker::commit(codeview::GUID *Guid) { // Write to a file. ExitOnErr(Builder.commit(Config->PDBPath, Guid)); } static Expected getFileName(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) { auto Iter = Checksums.getArray().at(FileID); if (Iter == Checksums.getArray().end()) return make_error(cv_error_code::no_records); uint32_t Offset = Iter->FileNameOffset; return Strings.getString(Offset); } static uint32_t getSecrelReloc() { switch (Config->Machine) { case AMD64: return COFF::IMAGE_REL_AMD64_SECREL; case I386: return COFF::IMAGE_REL_I386_SECREL; case ARMNT: return COFF::IMAGE_REL_ARM_SECREL; case ARM64: return COFF::IMAGE_REL_ARM64_SECREL; default: llvm_unreachable("unknown machine type"); } } // Try to find a line table for the given offset Addr into the given chunk C. // If a line table was found, the line table, the string and checksum tables // that are used to interpret the line table, and the offset of Addr in the line // table are stored in the output arguments. Returns whether a line table was // found. static bool findLineTable(const SectionChunk *C, uint32_t Addr, DebugStringTableSubsectionRef &CVStrTab, DebugChecksumsSubsectionRef &Checksums, DebugLinesSubsectionRef &Lines, uint32_t &OffsetInLinetable) { ExitOnError ExitOnErr; uint32_t SecrelReloc = getSecrelReloc(); for (SectionChunk *DbgC : C->File->getDebugChunks()) { if (DbgC->getSectionName() != ".debug$S") continue; // Build a mapping of SECREL relocations in DbgC that refer to C. DenseMap Secrels; for (const coff_relocation &R : DbgC->Relocs) { if (R.Type != SecrelReloc) continue; if (auto *S = dyn_cast_or_null( C->File->getSymbols()[R.SymbolTableIndex])) if (S->getChunk() == C) Secrels[R.VirtualAddress] = S->getValue(); } ArrayRef Contents = consumeDebugMagic(DbgC->getContents(), ".debug$S"); DebugSubsectionArray Subsections; BinaryStreamReader Reader(Contents, support::little); ExitOnErr(Reader.readArray(Subsections, Contents.size())); for (const DebugSubsectionRecord &SS : Subsections) { switch (SS.kind()) { case DebugSubsectionKind::StringTable: { assert(!CVStrTab.valid() && "Encountered multiple string table subsections!"); ExitOnErr(CVStrTab.initialize(SS.getRecordData())); break; } case DebugSubsectionKind::FileChecksums: assert(!Checksums.valid() && "Encountered multiple checksum subsections!"); ExitOnErr(Checksums.initialize(SS.getRecordData())); break; case DebugSubsectionKind::Lines: { ArrayRef Bytes; auto Ref = SS.getRecordData(); ExitOnErr(Ref.readLongestContiguousChunk(0, Bytes)); size_t OffsetInDbgC = Bytes.data() - DbgC->getContents().data(); // Check whether this line table refers to C. auto I = Secrels.find(OffsetInDbgC); if (I == Secrels.end()) break; // Check whether this line table covers Addr in C. DebugLinesSubsectionRef LinesTmp; ExitOnErr(LinesTmp.initialize(BinaryStreamReader(Ref))); uint32_t OffsetInC = I->second + LinesTmp.header()->RelocOffset; if (Addr < OffsetInC || Addr >= OffsetInC + LinesTmp.header()->CodeSize) break; assert(!Lines.header() && "Encountered multiple line tables for function!"); ExitOnErr(Lines.initialize(BinaryStreamReader(Ref))); OffsetInLinetable = Addr - OffsetInC; break; } default: break; } if (CVStrTab.valid() && Checksums.valid() && Lines.header()) return true; } } return false; } // Use CodeView line tables to resolve a file and line number for the given // offset into the given chunk and return them, or {"", 0} if a line table was // not found. std::pair coff::getFileLine(const SectionChunk *C, uint32_t Addr) { ExitOnError ExitOnErr; DebugStringTableSubsectionRef CVStrTab; DebugChecksumsSubsectionRef Checksums; DebugLinesSubsectionRef Lines; uint32_t OffsetInLinetable; if (!findLineTable(C, Addr, CVStrTab, Checksums, Lines, OffsetInLinetable)) return {"", 0}; Optional NameIndex; Optional LineNumber; for (LineColumnEntry &Entry : Lines) { for (const LineNumberEntry &LN : Entry.LineNumbers) { LineInfo LI(LN.Flags); if (LN.Offset > OffsetInLinetable) { if (!NameIndex) { NameIndex = Entry.NameIndex; LineNumber = LI.getStartLine(); } StringRef Filename = ExitOnErr(getFileName(CVStrTab, Checksums, *NameIndex)); return {Filename, *LineNumber}; } NameIndex = Entry.NameIndex; LineNumber = LI.getStartLine(); } } if (!NameIndex) return {"", 0}; StringRef Filename = ExitOnErr(getFileName(CVStrTab, Checksums, *NameIndex)); return {Filename, *LineNumber}; } Index: vendor/lld/dist-release_80/ELF/Driver.cpp =================================================================== --- vendor/lld/dist-release_80/ELF/Driver.cpp (revision 344172) +++ vendor/lld/dist-release_80/ELF/Driver.cpp (revision 344173) @@ -1,1649 +1,1649 @@ //===- Driver.cpp ---------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // The driver drives the entire linking process. It is responsible for // parsing command line options and doing whatever it is instructed to do. // // One notable thing in the LLD's driver when compared to other linkers is // that the LLD's driver is agnostic on the host operating system. // Other linkers usually have implicit default values (such as a dynamic // linker path or library paths) for each host OS. // // I don't think implicit default values are useful because they are // usually explicitly specified by the compiler driver. They can even // be harmful when you are doing cross-linking. Therefore, in LLD, we // simply trust the compiler driver to pass all required options and // don't try to make effort on our side. // //===----------------------------------------------------------------------===// #include "Driver.h" #include "Config.h" #include "Filesystem.h" #include "ICF.h" #include "InputFiles.h" #include "InputSection.h" #include "LinkerScript.h" #include "MarkLive.h" #include "OutputSections.h" #include "ScriptParser.h" #include "SymbolTable.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" #include "Writer.h" #include "lld/Common/Args.h" #include "lld/Common/Driver.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "lld/Common/Strings.h" #include "lld/Common/TargetOptionsCommandFlags.h" #include "lld/Common/Threads.h" #include "lld/Common/Version.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/Path.h" #include "llvm/Support/TarWriter.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include #include using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::sys; using namespace llvm::support; using namespace lld; using namespace lld::elf; Configuration *elf::Config; LinkerDriver *elf::Driver; static void setConfigs(opt::InputArgList &Args); bool elf::link(ArrayRef Args, bool CanExitEarly, raw_ostream &Error) { errorHandler().LogName = args::getFilenameWithoutExe(Args[0]); errorHandler().ErrorLimitExceededMsg = "too many errors emitted, stopping now (use " "-error-limit=0 to see all errors)"; errorHandler().ErrorOS = &Error; errorHandler().ExitEarly = CanExitEarly; errorHandler().ColorDiagnostics = Error.has_colors(); InputSections.clear(); OutputSections.clear(); BinaryFiles.clear(); BitcodeFiles.clear(); ObjectFiles.clear(); SharedFiles.clear(); Config = make(); Driver = make(); Script = make(); Symtab = make(); Tar = nullptr; memset(&In, 0, sizeof(In)); Config->ProgName = Args[0]; Driver->main(Args); // Exit immediately if we don't need to return to the caller. // This saves time because the overhead of calling destructors // for all globally-allocated objects is not negligible. if (CanExitEarly) exitLld(errorCount() ? 1 : 0); freeArena(); return !errorCount(); } // Parses a linker -m option. static std::tuple parseEmulation(StringRef Emul) { uint8_t OSABI = 0; StringRef S = Emul; if (S.endswith("_fbsd")) { S = S.drop_back(5); OSABI = ELFOSABI_FREEBSD; } std::pair Ret = StringSwitch>(S) .Cases("aarch64elf", "aarch64linux", "aarch64_elf64_le_vec", {ELF64LEKind, EM_AARCH64}) .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM}) .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64}) .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) .Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) - .Case("elf32ppc", {ELF32BEKind, EM_PPC}) + .Cases("elf32ppc", "elf32ppclinux", {ELF32BEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) .Case("elf64lriscv", {ELF64LEKind, EM_RISCV}) .Case("elf64ppc", {ELF64BEKind, EM_PPC64}) .Case("elf64lppc", {ELF64LEKind, EM_PPC64}) .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64}) .Case("elf_i386", {ELF32LEKind, EM_386}) .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU}) .Default({ELFNoneKind, EM_NONE}); if (Ret.first == ELFNoneKind) error("unknown emulation: " + Emul); return std::make_tuple(Ret.first, Ret.second, OSABI); } // Returns slices of MB by parsing MB as an archive file. // Each slice consists of a member file in the archive. std::vector> static getArchiveMembers( MemoryBufferRef MB) { std::unique_ptr File = CHECK(Archive::create(MB), MB.getBufferIdentifier() + ": failed to parse archive"); std::vector> V; Error Err = Error::success(); bool AddToTar = File->isThin() && Tar; for (const ErrorOr &COrErr : File->children(Err)) { Archive::Child C = CHECK(COrErr, MB.getBufferIdentifier() + ": could not get the child of the archive"); MemoryBufferRef MBRef = CHECK(C.getMemoryBufferRef(), MB.getBufferIdentifier() + ": could not get the buffer for a child of the archive"); if (AddToTar) Tar->append(relativeToRoot(check(C.getFullName())), MBRef.getBuffer()); V.push_back(std::make_pair(MBRef, C.getChildOffset())); } if (Err) fatal(MB.getBufferIdentifier() + ": Archive::children failed: " + toString(std::move(Err))); // Take ownership of memory buffers created for members of thin archives. for (std::unique_ptr &MB : File->takeThinBuffers()) make>(std::move(MB)); return V; } // Opens a file and create a file object. Path has to be resolved already. void LinkerDriver::addFile(StringRef Path, bool WithLOption) { using namespace sys::fs; Optional Buffer = readFile(Path); if (!Buffer.hasValue()) return; MemoryBufferRef MBRef = *Buffer; if (Config->FormatBinary) { Files.push_back(make(MBRef)); return; } switch (identify_magic(MBRef.getBuffer())) { case file_magic::unknown: readLinkerScript(MBRef); return; case file_magic::archive: { // Handle -whole-archive. if (InWholeArchive) { for (const auto &P : getArchiveMembers(MBRef)) Files.push_back(createObjectFile(P.first, Path, P.second)); return; } std::unique_ptr File = CHECK(Archive::create(MBRef), Path + ": failed to parse archive"); // If an archive file has no symbol table, it is likely that a user // is attempting LTO and using a default ar command that doesn't // understand the LLVM bitcode file. It is a pretty common error, so // we'll handle it as if it had a symbol table. if (!File->isEmpty() && !File->hasSymbolTable()) { for (const auto &P : getArchiveMembers(MBRef)) Files.push_back(make(P.first, Path, P.second)); return; } // Handle the regular case. Files.push_back(make(std::move(File))); return; } case file_magic::elf_shared_object: if (Config->Static || Config->Relocatable) { error("attempted static link of dynamic object " + Path); return; } // DSOs usually have DT_SONAME tags in their ELF headers, and the // sonames are used to identify DSOs. But if they are missing, // they are identified by filenames. We don't know whether the new // file has a DT_SONAME or not because we haven't parsed it yet. // Here, we set the default soname for the file because we might // need it later. // // If a file was specified by -lfoo, the directory part is not // significant, as a user did not specify it. This behavior is // compatible with GNU. Files.push_back( createSharedFile(MBRef, WithLOption ? path::filename(Path) : Path)); return; case file_magic::bitcode: case file_magic::elf_relocatable: if (InLib) Files.push_back(make(MBRef, "", 0)); else Files.push_back(createObjectFile(MBRef)); break; default: error(Path + ": unknown file type"); } } // Add a given library by searching it from input search paths. void LinkerDriver::addLibrary(StringRef Name) { if (Optional Path = searchLibrary(Name)) addFile(*Path, /*WithLOption=*/true); else error("unable to find library -l" + Name); } // This function is called on startup. We need this for LTO since // LTO calls LLVM functions to compile bitcode files to native code. // Technically this can be delayed until we read bitcode files, but // we don't bother to do lazily because the initialization is fast. static void initLLVM() { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); } // Some command line options or some combinations of them are not allowed. // This function checks for such errors. static void checkOptions() { // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup // table which is a relatively new feature. if (Config->EMachine == EM_MIPS && Config->GnuHash) error("the .gnu.hash section is not compatible with the MIPS target"); if (Config->FixCortexA53Errata843419 && Config->EMachine != EM_AARCH64) error("--fix-cortex-a53-843419 is only supported on AArch64 targets"); if (Config->TocOptimize && Config->EMachine != EM_PPC64) error("--toc-optimize is only supported on the PowerPC64 target"); 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"); if (!Config->Relocatable && !Config->DefineCommon) error("-no-define-common not supported in non relocatable output"); if (Config->Relocatable) { if (Config->Shared) error("-r and -shared may not be used together"); if (Config->GcSections) error("-r and --gc-sections may not be used together"); if (Config->GdbIndex) error("-r and --gdb-index may not be used together"); if (Config->ICF != ICFLevel::None) error("-r and --icf may not be used together"); if (Config->Pie) error("-r and -pie may not be used together"); } if (Config->ExecuteOnly) { if (Config->EMachine != EM_AARCH64) error("-execute-only is only supported on AArch64 targets"); if (Config->SingleRoRx && !Script->HasSectionsCommand) error("-execute-only and -no-rosegment cannot be used together"); } } static const char *getReproduceOption(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_reproduce)) return Arg->getValue(); return getenv("LLD_REPRODUCE"); } static bool hasZOption(opt::InputArgList &Args, StringRef Key) { for (auto *Arg : Args.filtered(OPT_z)) if (Key == Arg->getValue()) return true; return false; } static bool getZFlag(opt::InputArgList &Args, StringRef K1, StringRef K2, bool Default) { for (auto *Arg : Args.filtered_reverse(OPT_z)) { if (K1 == Arg->getValue()) return true; if (K2 == Arg->getValue()) return false; } return Default; } static bool isKnownZFlag(StringRef S) { return S == "combreloc" || S == "copyreloc" || S == "defs" || S == "execstack" || S == "global" || S == "hazardplt" || S == "initfirst" || S == "interpose" || S == "keep-text-section-prefix" || S == "lazy" || S == "muldefs" || S == "nocombreloc" || S == "nocopyreloc" || S == "nodefaultlib" || S == "nodelete" || S == "nodlopen" || S == "noexecstack" || S == "nokeep-text-section-prefix" || S == "norelro" || S == "notext" || S == "now" || S == "origin" || S == "relro" || S == "retpolineplt" || S == "rodynamic" || S == "text" || S == "wxneeded" || S.startswith("max-page-size=") || S.startswith("stack-size="); } // Report an error for an unknown -z option. static void checkZOptions(opt::InputArgList &Args) { for (auto *Arg : Args.filtered(OPT_z)) if (!isKnownZFlag(Arg->getValue())) error("unknown -z value: " + StringRef(Arg->getValue())); } void LinkerDriver::main(ArrayRef ArgsArr) { ELFOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); // Interpret this flag early because error() depends on them. errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); // Handle -help if (Args.hasArg(OPT_help)) { printHelp(); return; } // Handle -v or -version. // // A note about "compatible with GNU linkers" message: this is a hack for // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and // still the newest version in March 2017) or earlier to recognize LLD as // a GNU compatible linker. As long as an output for the -v option // contains "GNU" or "with BFD", they recognize us as GNU-compatible. // // This is somewhat ugly hack, but in reality, we had no choice other // than doing this. Considering the very long release cycle of Libtool, // it is not easy to improve it to recognize LLD as a GNU compatible // linker in a timely manner. Even if we can make it, there are still a // lot of "configure" scripts out there that are generated by old version // of Libtool. We cannot convince every software developer to migrate to // the latest version and re-generate scripts. So we have this hack. if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) message(getLLDVersion() + " (compatible with GNU linkers)"); if (const char *Path = getReproduceOption(Args)) { // Note that --reproduce is a debug option so you can ignore it // if you are trying to understand the whole picture of the code. Expected> ErrOrWriter = TarWriter::create(Path, path::stem(Path)); if (ErrOrWriter) { Tar = std::move(*ErrOrWriter); Tar->append("response.txt", createResponseFile(Args)); Tar->append("version.txt", getLLDVersion() + "\n"); } else { error("--reproduce: " + toString(ErrOrWriter.takeError())); } } readConfigs(Args); checkZOptions(Args); // The behavior of -v or --version is a bit strange, but this is // needed for compatibility with GNU linkers. if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT)) return; if (Args.hasArg(OPT_version)) return; initLLVM(); createFiles(Args); if (errorCount()) return; inferMachineType(); setConfigs(Args); checkOptions(); if (errorCount()) return; switch (Config->EKind) { case ELF32LEKind: link(Args); return; case ELF32BEKind: link(Args); return; case ELF64LEKind: link(Args); return; case ELF64BEKind: link(Args); return; default: llvm_unreachable("unknown Config->EKind"); } } static std::string getRpath(opt::InputArgList &Args) { std::vector V = args::getStrings(Args, OPT_rpath); return llvm::join(V.begin(), V.end(), ":"); } // Determines what we should do if there are remaining unresolved // symbols after the name resolution. static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &Args) { UnresolvedPolicy ErrorOrWarn = Args.hasFlag(OPT_error_unresolved_symbols, OPT_warn_unresolved_symbols, true) ? UnresolvedPolicy::ReportError : UnresolvedPolicy::Warn; // Process the last of -unresolved-symbols, -no-undefined or -z defs. for (auto *Arg : llvm::reverse(Args)) { switch (Arg->getOption().getID()) { case OPT_unresolved_symbols: { StringRef S = Arg->getValue(); if (S == "ignore-all" || S == "ignore-in-object-files") return UnresolvedPolicy::Ignore; if (S == "ignore-in-shared-libs" || S == "report-all") return ErrorOrWarn; error("unknown --unresolved-symbols value: " + S); continue; } case OPT_no_undefined: return ErrorOrWarn; case OPT_z: if (StringRef(Arg->getValue()) == "defs") return ErrorOrWarn; continue; } } // -shared implies -unresolved-symbols=ignore-all because missing // symbols are likely to be resolved at runtime using other DSOs. if (Config->Shared) return UnresolvedPolicy::Ignore; return ErrorOrWarn; } static Target2Policy getTarget2(opt::InputArgList &Args) { StringRef S = Args.getLastArgValue(OPT_target2, "got-rel"); if (S == "rel") return Target2Policy::Rel; if (S == "abs") return Target2Policy::Abs; if (S == "got-rel") return Target2Policy::GotRel; error("unknown --target2 option: " + S); return Target2Policy::GotRel; } static bool isOutputFormatBinary(opt::InputArgList &Args) { StringRef S = Args.getLastArgValue(OPT_oformat, "elf"); if (S == "binary") return true; if (!S.startswith("elf")) error("unknown --oformat value: " + S); return false; } static DiscardPolicy getDiscard(opt::InputArgList &Args) { if (Args.hasArg(OPT_relocatable)) return DiscardPolicy::None; auto *Arg = Args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none); if (!Arg) return DiscardPolicy::Default; if (Arg->getOption().getID() == OPT_discard_all) return DiscardPolicy::All; if (Arg->getOption().getID() == OPT_discard_locals) return DiscardPolicy::Locals; return DiscardPolicy::None; } static StringRef getDynamicLinker(opt::InputArgList &Args) { auto *Arg = Args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker); if (!Arg || Arg->getOption().getID() == OPT_no_dynamic_linker) return ""; return Arg->getValue(); } static ICFLevel getICF(opt::InputArgList &Args) { auto *Arg = Args.getLastArg(OPT_icf_none, OPT_icf_safe, OPT_icf_all); if (!Arg || Arg->getOption().getID() == OPT_icf_none) return ICFLevel::None; if (Arg->getOption().getID() == OPT_icf_safe) return ICFLevel::Safe; return ICFLevel::All; } static StripPolicy getStrip(opt::InputArgList &Args) { if (Args.hasArg(OPT_relocatable)) return StripPolicy::None; auto *Arg = Args.getLastArg(OPT_strip_all, OPT_strip_debug); if (!Arg) return StripPolicy::None; if (Arg->getOption().getID() == OPT_strip_all) return StripPolicy::All; return StripPolicy::Debug; } static uint64_t parseSectionAddress(StringRef S, const opt::Arg &Arg) { uint64_t VA = 0; if (S.startswith("0x")) S = S.drop_front(2); if (!to_integer(S, VA, 16)) error("invalid argument: " + toString(Arg)); return VA; } static StringMap getSectionStartMap(opt::InputArgList &Args) { StringMap Ret; for (auto *Arg : Args.filtered(OPT_section_start)) { StringRef Name; StringRef Addr; std::tie(Name, Addr) = StringRef(Arg->getValue()).split('='); Ret[Name] = parseSectionAddress(Addr, *Arg); } if (auto *Arg = Args.getLastArg(OPT_Ttext)) Ret[".text"] = parseSectionAddress(Arg->getValue(), *Arg); if (auto *Arg = Args.getLastArg(OPT_Tdata)) Ret[".data"] = parseSectionAddress(Arg->getValue(), *Arg); if (auto *Arg = Args.getLastArg(OPT_Tbss)) Ret[".bss"] = parseSectionAddress(Arg->getValue(), *Arg); return Ret; } static SortSectionPolicy getSortSection(opt::InputArgList &Args) { StringRef S = Args.getLastArgValue(OPT_sort_section); if (S == "alignment") return SortSectionPolicy::Alignment; if (S == "name") return SortSectionPolicy::Name; if (!S.empty()) error("unknown --sort-section rule: " + S); return SortSectionPolicy::Default; } static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &Args) { StringRef S = Args.getLastArgValue(OPT_orphan_handling, "place"); if (S == "warn") return OrphanHandlingPolicy::Warn; if (S == "error") return OrphanHandlingPolicy::Error; if (S != "place") error("unknown --orphan-handling mode: " + S); return OrphanHandlingPolicy::Place; } // Parse --build-id or --build-id=