[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
This commit is contained in:
Colden Cullen 2018-01-31 17:48:04 +00:00
parent 790baeed37
commit b9b6ed9ae6
2 changed files with 42 additions and 20 deletions

View File

@ -107,10 +107,11 @@ public:
/// If the object does not use a type server PDB (compiled with /Z7), we merge /// 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 /// all the type and item records from the .debug$S stream and fill in the
/// caller-provided ObjectIndexMap. /// caller-provided ObjectIndexMap.
const CVIndexMap &mergeDebugT(ObjFile *File, CVIndexMap &ObjectIndexMap); Expected<const CVIndexMap&> mergeDebugT(ObjFile *File,
CVIndexMap &ObjectIndexMap);
const CVIndexMap &maybeMergeTypeServerPDB(ObjFile *File, Expected<const CVIndexMap&> maybeMergeTypeServerPDB(ObjFile *File,
TypeServer2Record &TS); TypeServer2Record &TS);
/// Add the section map and section contributions to the PDB. /// Add the section map and section contributions to the PDB.
void addSections(ArrayRef<OutputSection *> OutputSections, void addSections(ArrayRef<OutputSection *> OutputSections,
@ -151,6 +152,10 @@ private:
/// Type index mappings of type server PDBs that we've loaded so far. /// Type index mappings of type server PDBs that we've loaded so far.
std::map<GUID, CVIndexMap> TypeServerIndexMappings; 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 @@ maybeReadTypeServerRecord(CVTypeArray &Types) {
return std::move(TS); return std::move(TS);
} }
const CVIndexMap &PDBLinker::mergeDebugT(ObjFile *File, Expected<const CVIndexMap&> PDBLinker::mergeDebugT(ObjFile *File,
CVIndexMap &ObjectIndexMap) { CVIndexMap &ObjectIndexMap) {
ScopedTimer T(TypeMergingTimer); ScopedTimer T(TypeMergingTimer);
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
@ -317,11 +322,19 @@ tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) {
return std::move(NS); return std::move(NS);
} }
const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, Expected<const CVIndexMap&> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File,
TypeServer2Record &TS) { 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::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. // index mapping if we have it.
auto Insertion = TypeServerIndexMappings.insert({TS.getGuid(), CVIndexMap()}); auto Insertion = TypeServerIndexMappings.insert({TSId, CVIndexMap()});
CVIndexMap &IndexMap = Insertion.first->second; CVIndexMap &IndexMap = Insertion.first->second;
if (!Insertion.second) if (!Insertion.second)
return IndexMap; return IndexMap;
@ -332,18 +345,21 @@ const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjFile *File,
// Check for a PDB at: // Check for a PDB at:
// 1. The given file path // 1. The given file path
// 2. Next to the object file or archive file // 2. Next to the object file or archive file
auto ExpectedSession = tryToLoadPDB(TS.getGuid(), TS.getName()); auto ExpectedSession = tryToLoadPDB(TSId, TSPath);
if (!ExpectedSession) { if (!ExpectedSession) {
consumeError(ExpectedSession.takeError()); consumeError(ExpectedSession.takeError());
StringRef LocalPath = StringRef LocalPath =
!File->ParentName.empty() ? File->ParentName : File->getName(); !File->ParentName.empty() ? File->ParentName : File->getName();
SmallString<128> Path = sys::path::parent_path(LocalPath); SmallString<128> Path = sys::path::parent_path(LocalPath);
sys::path::append( sys::path::append(
Path, sys::path::filename(TS.getName(), sys::path::Style::windows)); Path, sys::path::filename(TSPath, sys::path::Style::windows));
ExpectedSession = tryToLoadPDB(TS.getGuid(), Path); ExpectedSession = tryToLoadPDB(TSId, Path);
}
if (auto E = ExpectedSession.takeError()) {
TypeServerIndexMappings.erase(TSId);
MissingTypeServerPDBs.emplace(TSId);
return std::move(E);
} }
if (auto E = ExpectedSession.takeError())
fatal("Type server PDB was not found: " + toString(std::move(E)));
auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream(); auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream();
if (auto E = ExpectedTpi.takeError()) if (auto E = ExpectedTpi.takeError())
@ -764,7 +780,16 @@ void PDBLinker::addObjFile(ObjFile *File) {
// the PDB first, so that we can get the map from object file type and item // the PDB first, so that we can get the map from object file type and item
// indices to PDB type and item indices. // indices to PDB type and item indices.
CVIndexMap ObjectIndexMap; 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); ScopedTimer T(SymbolMergingTimer);

View File

@ -1,13 +1,10 @@
# This is an object compiled with /Zi (see the LF_TYPESERVER2 record) without an # 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. # 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: 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 was not found
--- !COFF --- !COFF
header: header: