[llvm] Errorize DebuginfodFetcher for inspection at call-sites (#191191)
Failure to fetch debuginfod is rarely an error, but there are cases where we want to distinguish error reasons down the line, for example in order to test connection timeouts.
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
#define LLVM_DEBUGINFOD_DIFETCHER_H
|
||||
|
||||
#include "llvm/Object/BuildID.h"
|
||||
#include <optional>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@@ -28,7 +27,7 @@ public:
|
||||
|
||||
/// Fetches the given Build ID using debuginfod and returns a local path to
|
||||
/// the resulting file.
|
||||
std::optional<std::string> fetch(object::BuildIDRef BuildID) const override;
|
||||
Expected<std::string> fetch(object::BuildIDRef BuildID) const override;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace object {
|
||||
@@ -44,7 +45,7 @@ public:
|
||||
virtual ~BuildIDFetcher() = default;
|
||||
|
||||
/// Returns the path to the debug file with the given build ID.
|
||||
virtual std::optional<std::string> fetch(BuildIDRef BuildID) const;
|
||||
virtual Expected<std::string> fetch(BuildIDRef BuildID) const;
|
||||
|
||||
private:
|
||||
const std::vector<std::string> DebugFileDirectories;
|
||||
|
||||
@@ -490,14 +490,17 @@ bool LLVMSymbolizer::getOrFindDebugBinary(const ArrayRef<uint8_t> BuildID,
|
||||
}
|
||||
if (!BIDFetcher)
|
||||
return false;
|
||||
if (std::optional<std::string> Path = BIDFetcher->fetch(BuildID)) {
|
||||
Expected<std::string> Path = BIDFetcher->fetch(BuildID);
|
||||
if (Path) {
|
||||
Result = *Path;
|
||||
auto InsertResult = BuildIDPaths.insert({BuildIDStr, Result});
|
||||
assert(InsertResult.second);
|
||||
(void)InsertResult;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Failure to fetch debuginfod is rarely an error and most users will not care
|
||||
// why this failed.
|
||||
consumeError(Path.takeError());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,17 +15,19 @@
|
||||
#include "llvm/Debuginfod/BuildIDFetcher.h"
|
||||
|
||||
#include "llvm/Debuginfod/Debuginfod.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
std::optional<std::string>
|
||||
Expected<std::string>
|
||||
DebuginfodFetcher::fetch(ArrayRef<uint8_t> BuildID) const {
|
||||
if (std::optional<std::string> Path = BuildIDFetcher::fetch(BuildID))
|
||||
return std::move(*Path);
|
||||
|
||||
Expected<std::string> PathOrErr = getCachedOrDownloadDebuginfo(BuildID);
|
||||
if (PathOrErr)
|
||||
return *PathOrErr;
|
||||
consumeError(PathOrErr.takeError());
|
||||
return std::nullopt;
|
||||
Expected<std::string> Path = BuildIDFetcher::fetch(BuildID);
|
||||
if (Path)
|
||||
return Path;
|
||||
// Most users will not care why this failed.
|
||||
assert(errorToErrorCode(Path.takeError()) ==
|
||||
std::errc::no_such_file_or_directory &&
|
||||
"BuildIDFetcher::fetch() failed in an unexpected way");
|
||||
consumeError(Path.takeError());
|
||||
return getCachedOrDownloadDebuginfo(BuildID);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "llvm/Object/BuildID.h"
|
||||
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
@@ -79,7 +80,7 @@ BuildIDRef llvm::object::getBuildID(const ObjectFile *Obj) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<std::string> BuildIDFetcher::fetch(BuildIDRef BuildID) const {
|
||||
Expected<std::string> BuildIDFetcher::fetch(BuildIDRef BuildID) const {
|
||||
auto GetDebugPath = [&](StringRef Directory) {
|
||||
SmallString<128> Path{Directory};
|
||||
sys::path::append(Path, ".build-id",
|
||||
@@ -108,5 +109,8 @@ std::optional<std::string> BuildIDFetcher::fetch(BuildIDRef BuildID) const {
|
||||
return std::string(Path);
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
return createStringError(
|
||||
make_error_code(std::errc::no_such_file_or_directory),
|
||||
"could not find debug file for build ID '" +
|
||||
llvm::toHex(BuildID, /*LowerCase=*/true) + "'");
|
||||
}
|
||||
|
||||
@@ -1106,20 +1106,18 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
|
||||
}
|
||||
|
||||
for (object::BuildIDRef BinaryID : BinaryIDsToFetch) {
|
||||
std::optional<std::string> PathOpt = BIDFetcher->fetch(BinaryID);
|
||||
if (PathOpt) {
|
||||
std::string Path = std::move(*PathOpt);
|
||||
Expected<std::string> Path = BIDFetcher->fetch(BinaryID);
|
||||
if (Path) {
|
||||
StringRef Arch = Arches.size() == 1 ? Arches.front() : StringRef();
|
||||
if (Error E = loadFromFile(Path, Arch, CompilationDir, ProfileReaderRef,
|
||||
*Coverage, DataFound))
|
||||
if (Error E = loadFromFile(*Path, Arch, CompilationDir,
|
||||
ProfileReaderRef, *Coverage, DataFound))
|
||||
return std::move(E);
|
||||
} else if (CheckBinaryIDs) {
|
||||
return createFileError(
|
||||
ProfileFilename.value(),
|
||||
createStringError(errc::no_such_file_or_directory,
|
||||
"Missing binary ID: " +
|
||||
llvm::toHex(BinaryID, /*LowerCase=*/true)));
|
||||
}
|
||||
if (CheckBinaryIDs) {
|
||||
return createFileError(ProfileFilename.value(), Path.takeError());
|
||||
}
|
||||
// Ignore error and continue.
|
||||
consumeError(Path.takeError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,6 @@ llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
|
||||
InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind,
|
||||
const object::BuildIDFetcher *BIDFetcher,
|
||||
const ArrayRef<object::BuildID> BIs) {
|
||||
std::optional<std::string> Path;
|
||||
if (BIDFetcher) {
|
||||
if (BIs.empty())
|
||||
return make_error<InstrProfError>(
|
||||
@@ -127,12 +126,18 @@ InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind,
|
||||
"unsupported profile binary correlation when there are multiple "
|
||||
"build IDs in a profile");
|
||||
|
||||
Path = BIDFetcher->fetch(BIs.front());
|
||||
if (!Path)
|
||||
Expected<std::string> Path = BIDFetcher->fetch(BIs.front());
|
||||
if (!Path) {
|
||||
// Propagate as InstrProf specific error type.
|
||||
assert(errorToErrorCode(Path.takeError()) ==
|
||||
std::errc::no_such_file_or_directory &&
|
||||
"BuildIDFetcher::fetch() failed in an unexpected way");
|
||||
consumeError(Path.takeError());
|
||||
return make_error<InstrProfError>(
|
||||
instrprof_error::unable_to_correlate_profile,
|
||||
"Missing build ID: " + llvm::toHex(BIs.front(),
|
||||
/*LowerCase=*/true));
|
||||
}
|
||||
Filename = *Path;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,10 +152,12 @@ int llvm_debuginfod_find_main(int argc, char **argv,
|
||||
|
||||
// Find a debug file in local build ID directories and via debuginfod.
|
||||
std::string fetchDebugInfo(object::BuildIDRef BuildID) {
|
||||
if (std::optional<std::string> Path =
|
||||
DebuginfodFetcher(DebugFileDirectory).fetch(BuildID))
|
||||
return *Path;
|
||||
errs() << "Build ID " << llvm::toHex(BuildID, /*Lowercase=*/true)
|
||||
Expected<std::string> PathOrErr =
|
||||
DebuginfodFetcher(DebugFileDirectory).fetch(BuildID);
|
||||
if (PathOrErr)
|
||||
return *PathOrErr;
|
||||
errs() << "Build ID " << llvm::toHex(BuildID, /*Lowercase=*/true) << ": "
|
||||
<< " could not be found.\n";
|
||||
consumeError(PathOrErr.takeError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1743,9 +1743,13 @@ fetchBinaryByBuildID(const ObjectFile &Obj) {
|
||||
object::BuildIDRef BuildID = getBuildID(&Obj);
|
||||
if (BuildID.empty())
|
||||
return std::nullopt;
|
||||
std::optional<std::string> Path = BIDFetcher->fetch(BuildID);
|
||||
if (!Path)
|
||||
Expected<std::string> Path = BIDFetcher->fetch(BuildID);
|
||||
if (!Path) {
|
||||
// Failure to fetch debuginfod is rarely an error and most users will not
|
||||
// care why this failed.
|
||||
consumeError(Path.takeError());
|
||||
return std::nullopt;
|
||||
}
|
||||
Expected<OwningBinary<Binary>> DebugBinary = createBinary(*Path);
|
||||
if (!DebugBinary) {
|
||||
reportWarning(toString(DebugBinary.takeError()), *Path);
|
||||
@@ -3841,8 +3845,10 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
|
||||
// Look up any provided build IDs, then append them to the input filenames.
|
||||
for (const opt::Arg *A : InputArgs.filtered(OBJDUMP_build_id)) {
|
||||
object::BuildID BuildID = parseBuildIDArg(A);
|
||||
std::optional<std::string> Path = BIDFetcher->fetch(BuildID);
|
||||
Expected<std::string> Path = BIDFetcher->fetch(BuildID);
|
||||
if (!Path) {
|
||||
// Most users will not care why this failed.
|
||||
consumeError(Path.takeError());
|
||||
reportCmdLineError(A->getSpelling() + ": could not find build ID '" +
|
||||
A->getValue() + "'");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user