Index: COFF/PDB.cpp =================================================================== --- COFF/PDB.cpp +++ COFF/PDB.cpp @@ -99,7 +99,7 @@ /// caller-provided ObjectIndexMap. const CVIndexMap &mergeDebugT(ObjFile *File, CVIndexMap &ObjectIndexMap); - const CVIndexMap &maybeMergeTypeServerPDB(ObjFile *File, + Expected maybeMergeTypeServerPDB(ObjFile *File, TypeServer2Record &TS); /// Add the section map and section contributions to the PDB. @@ -141,6 +141,10 @@ /// Type index mappings of type server PDBs that we've loaded so far. std::map TypeServerIndexMappings; + + /// List of TypeServer PDBs which cannot be loaded. + /// Cached to prevent repeated load attempts. + std::set MissingTypeServerPDBs; }; } @@ -245,9 +249,16 @@ // Look through type servers. If we've already seen this type server, don't // merge any type information. - if (Optional TS = maybeReadTypeServerRecord(Types)) - return maybeMergeTypeServerPDB(File, *TS); + if (Optional TS = maybeReadTypeServerRecord(Types)) { + // If loading the PDB succeeds, the result can be returned immediately. + auto TypeServerIndexMap = maybeMergeTypeServerPDB(File, *TS); + if (TypeServerIndexMap) + return *TypeServerIndexMap; + // If the loading failed, a warning was already thrown. + consumeError(TypeServerIndexMap.takeError()); + } + // This is a /Z7 object. Fill in the temporary, caller-provided // ObjectIndexMap. if (Config->DebugGHashes) { @@ -305,11 +316,19 @@ return std::move(NS); } -const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, +Expected PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, TypeServer2Record &TS) { - // First, check if we already loaded a PDB with this GUID. Return the type + const GUID& TSId = TS.getGuid(); + StringRef TSPath = TS.getName(); + + // First, check if the PDB has previously failed to load. + if (MissingTypeServerPDBs.count(TSId)) + return make_error( + pdb::generic_error_code::type_server_not_found, TSPath); + + // Second, 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()}); + auto Insertion = TypeServerIndexMappings.insert({TSId, CVIndexMap()}); CVIndexMap &IndexMap = Insertion.first->second; if (!Insertion.second) return IndexMap; @@ -320,7 +339,7 @@ // 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()); + auto ExpectedSession = tryToLoadPDB(TSId, TSPath); if (!ExpectedSession) { consumeError(ExpectedSession.takeError()); StringRef LocalPath = @@ -327,12 +346,18 @@ !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); + Path, sys::path::filename(TSPath, sys::path::Style::windows)); + ExpectedSession = tryToLoadPDB(TSId, Path); } - if (auto E = ExpectedSession.takeError()) - fatal("Type server PDB was not found: " + toString(std::move(E))); + if (auto E = ExpectedSession.takeError()) { + warn("Type server PDB \"" + TSPath + "\" was not found: " + + toString(std::move(E))); + TypeServerIndexMappings.erase(TSId); + MissingTypeServerPDBs.emplace(TSId); + return std::move(E); + } + auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream(); if (auto E = ExpectedTpi.takeError()) fatal("Type server does not have TPI stream: " + toString(std::move(E))); Index: test/COFF/pdb-type-server-missing.yaml =================================================================== --- test/COFF/pdb-type-server-missing.yaml +++ test/COFF/pdb-type-server-missing.yaml @@ -1,13 +1,10 @@ # This is an object compiled with /Zi (see the LF_TYPESERVER2 record) without an # adjacent type server PDB. Test that LLD fails gracefully on it. -# FIXME: Ideally we'd do what MSVC does, which is to warn and drop all debug -# info in the object with the missing PDB. - # RUN: yaml2obj %s -o %t.obj -# RUN: not lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s +# RUN: lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s -# CHECK: error: Type server PDB was not found +# CHECK: warning: Type server PDB "C:\src\llvm-project\build\definitely_not_found_for_sure.pdb" was not found --- !COFF header: