[LLD][PDB] Implement FIXME: Warn on missing TypeServer PDB rather than error
Summary: Instead of fatal-ing out when missing a type server PDB, insead warn and cache the miss.
Reviewers: rnk, zturner
Reviewed By: rnk
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D42188
llvm-svn: 323893
diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp
index e8395c8..0ca2587 100644
--- a/lld/COFF/PDB.cpp
+++ b/lld/COFF/PDB.cpp
@@ -107,10 +107,11 @@
/// 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(ObjFile *File, CVIndexMap &ObjectIndexMap);
+ Expected<const CVIndexMap&> mergeDebugT(ObjFile *File,
+ CVIndexMap &ObjectIndexMap);
- const CVIndexMap &maybeMergeTypeServerPDB(ObjFile *File,
- TypeServer2Record &TS);
+ Expected<const CVIndexMap&> maybeMergeTypeServerPDB(ObjFile *File,
+ TypeServer2Record &TS);
/// Add the section map and section contributions to the PDB.
void addSections(ArrayRef<OutputSection *> OutputSections,
@@ -151,6 +152,10 @@
/// Type index mappings of type server PDBs that we've loaded so far.
std::map<GUID, CVIndexMap> TypeServerIndexMappings;
+
+ /// List of TypeServer PDBs which cannot be loaded.
+ /// Cached to prevent repeated load attempts.
+ std::set<GUID> MissingTypeServerPDBs;
};
}
@@ -241,8 +246,8 @@
return std::move(TS);
}
-const CVIndexMap &PDBLinker::mergeDebugT(ObjFile *File,
- CVIndexMap &ObjectIndexMap) {
+Expected<const CVIndexMap&> PDBLinker::mergeDebugT(ObjFile *File,
+ CVIndexMap &ObjectIndexMap) {
ScopedTimer T(TypeMergingTimer);
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
@@ -317,11 +322,19 @@
return std::move(NS);
}
-const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjFile *File,
- TypeServer2Record &TS) {
- // First, check if we already loaded a PDB with this GUID. Return the type
+Expected<const CVIndexMap&> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File,
+ TypeServer2Record &TS) {
+ 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::GenericError>(
+ 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;
@@ -332,18 +345,21 @@
// 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 =
!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()) {
+ TypeServerIndexMappings.erase(TSId);
+ MissingTypeServerPDBs.emplace(TSId);
+ return std::move(E);
+ }
auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream();
if (auto E = ExpectedTpi.takeError())
@@ -764,7 +780,16 @@
// 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);
+ auto IndexMapResult = mergeDebugT(File, ObjectIndexMap);
+
+ // If the .debug$T sections fail to merge, assume there is no debug info.
+ if (!IndexMapResult) {
+ warn("Type server PDB for " + Name + " is invalid, ignoring debug info. " +
+ toString(IndexMapResult.takeError()));
+ return;
+ }
+
+ const CVIndexMap &IndexMap = *IndexMapResult;
ScopedTimer T(SymbolMergingTimer);