forked from OSchip/llvm-project
[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:
parent
790baeed37
commit
b9b6ed9ae6
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue