[LLD][COFF] Cleanup error messages / add more coverage tests
- Log the reason for a PDB or precompiled-OBJ load failure
- Properly handle out-of-date PDB or precompiled-OBJ signature by displaying a corresponding error
- Slightly change behavior on PDB failure: any subsequent load attempt from another OBJ would result in the same error message being logged
- Slightly change behavior on PDB failure: retry with filename only if previous error was ENOENT ("no such file or directory")
- Tests: a. for native PDB errors; b. cover all the cases above
Differential Revision: https://reviews.llvm.org/D51559
llvm-svn: 341825
diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp
index 08cde6f..bb6d246 100644
--- a/lld/COFF/PDB.cpp
+++ b/lld/COFF/PDB.cpp
@@ -165,7 +165,7 @@
/// List of TypeServer PDBs which cannot be loaded.
/// Cached to prevent repeated load attempts.
- std::set<GUID> MissingTypeServerPDBs;
+ std::map<GUID, std::string> MissingTypeServerPDBs;
};
}
@@ -326,21 +326,22 @@
// 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::PDBError>(
- pdb::pdb_error_code::type_server_not_found, TSPath);
+ return make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date);
return std::move(NS);
}
Expected<const CVIndexMap&> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File,
TypeServer2Record &TS) {
- const GUID& TSId = TS.getGuid();
+ 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::PDBError>(
- pdb::pdb_error_code::type_server_not_found, TSPath);
+ auto PrevErr = MissingTypeServerPDBs.find(TSId);
+ if (PrevErr != MissingTypeServerPDBs.end())
+ return createFileError(
+ TSPath, std::move(make_error<StringError>(PrevErr->second,
+ inconvertibleErrorCode())));
// Second, check if we already loaded a PDB with this GUID. Return the type
// index mapping if we have it.
@@ -355,20 +356,37 @@
// Check for a PDB at:
// 1. The given file path
// 2. Next to the object file or archive file
- 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(TSPath, sys::path::Style::windows));
- ExpectedSession = tryToLoadPDB(TSId, Path);
- }
+ auto ExpectedSession = handleExpected(
+ tryToLoadPDB(TSId, TSPath),
+ [&]() {
+ StringRef LocalPath =
+ !File->ParentName.empty() ? File->ParentName : File->getName();
+ SmallString<128> Path = sys::path::parent_path(LocalPath);
+ sys::path::append(
+ Path, sys::path::filename(TSPath, sys::path::Style::windows));
+ return tryToLoadPDB(TSId, Path);
+ },
+ [&](std::unique_ptr<ECError> 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);
- MissingTypeServerPDBs.emplace(TSId);
- return std::move(E);
+
+ // 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;
+ auto It = MissingTypeServerPDBs.emplace(TSId, S.str());
+
+ return createFileError(TSPath, std::move(E));
}
pdb::NativeSession *Session = ExpectedSession->get();
@@ -837,8 +855,10 @@
// 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()));
+ auto FileName = sys::path::filename(Path);
+ warn("Cannot use debug info for '" + FileName + "'\n" +
+ ">>> failed to load reference " +
+ StringRef(toString(IndexMapResult.takeError())));
return;
}