llvm-project/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp
Daniel Thornburgh e61d89efd7 [NFC] [Object] Create library to fetch debug info by build ID.
This creates a library for fetching debug info by build ID, whether
locally or remotely via debuginfod. The functionality was refactored
out of existing code in the Symboliize library. Existing utilities
were refactored to use this library.

Reviewed By: phosek

Differential Revision: https://reviews.llvm.org/D132504
2022-09-28 13:35:35 -07:00

128 lines
4.8 KiB
C++

//===-- llvm-debuginfod-find.cpp - Simple CLI for libdebuginfod-client ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the llvm-debuginfod-find tool. This tool
/// queries the debuginfod servers in the DEBUGINFOD_URLS environment
/// variable (delimited by space (" ")) for the executable,
/// debuginfo, or specified source file of the binary matching the
/// given build-id.
///
//===----------------------------------------------------------------------===//
#include "llvm/Debuginfod/BuildIDFetcher.h"
#include "llvm/Debuginfod/Debuginfod.h"
#include "llvm/Debuginfod/HTTPClient.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
using namespace llvm;
cl::OptionCategory DebuginfodFindCategory("llvm-debuginfod-find Options");
cl::opt<std::string> InputBuildID(cl::Positional, cl::Required,
cl::desc("<input build_id>"), cl::init("-"),
cl::cat(DebuginfodFindCategory));
static cl::opt<bool>
FetchExecutable("executable", cl::init(false),
cl::desc("If set, fetch a binary file associated with this "
"build id, containing the executable sections."),
cl::cat(DebuginfodFindCategory));
static cl::opt<bool>
FetchDebuginfo("debuginfo", cl::init(false),
cl::desc("If set, fetch a binary file associated with this "
"build id, containing the debuginfo sections."),
cl::cat(DebuginfodFindCategory));
static cl::opt<std::string> FetchSource(
"source", cl::init(""),
cl::desc("Fetch a source file associated with this build id, which is at "
"this relative path relative to the compilation directory."),
cl::cat(DebuginfodFindCategory));
static cl::opt<bool>
DumpToStdout("dump", cl::init(false),
cl::desc("If set, dumps the contents of the fetched artifact "
"to standard output. Otherwise, dumps the absolute "
"path to the cached artifact on disk."),
cl::cat(DebuginfodFindCategory));
static cl::list<std::string> DebugFileDirectory(
"debug-file-directory",
cl::desc("Path to directory where to look for debug files."),
cl::cat(DebuginfodFindCategory));
[[noreturn]] static void helpExit() {
errs() << "Must specify exactly one of --executable, "
"--source=/path/to/file, or --debuginfo.";
exit(1);
}
ExitOnError ExitOnErr;
static std::string fetchDebugInfo(object::BuildIDRef BuildID);
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
HTTPClient::initialize();
cl::HideUnrelatedOptions({&DebuginfodFindCategory});
cl::ParseCommandLineOptions(
argc, argv,
"llvm-debuginfod-find: Fetch debuginfod artifacts\n\n"
"This program is a frontend to the debuginfod client library. The cache "
"directory, request timeout (in seconds), and debuginfod server urls are "
"set by these environment variables:\n"
"DEBUGINFOD_CACHE_PATH (default set by sys::path::cache_directory)\n"
"DEBUGINFOD_TIMEOUT (defaults to 90s)\n"
"DEBUGINFOD_URLS=[comma separated URLs] (defaults to empty)\n");
if (FetchExecutable + FetchDebuginfo + (FetchSource != "") != 1)
helpExit();
std::string IDString;
if (!tryGetFromHex(InputBuildID, IDString)) {
errs() << "Build ID " << InputBuildID << " is not a hex string.\n";
exit(1);
}
object::BuildID ID(IDString.begin(), IDString.end());
std::string Path;
if (FetchSource != "")
Path = ExitOnErr(getCachedOrDownloadSource(ID, FetchSource));
else if (FetchExecutable)
Path = ExitOnErr(getCachedOrDownloadExecutable(ID));
else if (FetchDebuginfo)
Path = fetchDebugInfo(ID);
else
llvm_unreachable("We have already checked that exactly one of the above "
"conditions is true.");
if (DumpToStdout) {
// Print the contents of the artifact.
ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(
Path, /*IsText=*/false, /*RequiresNullTerminator=*/false);
ExitOnErr(errorCodeToError(Buf.getError()));
outs() << Buf.get()->getBuffer();
} else
// Print the path to the cached artifact file.
outs() << Path << "\n";
}
// Find a debug file in local build ID directories and via debuginfod.
std::string fetchDebugInfo(object::BuildIDRef BuildID) {
if (Optional<std::string> Path =
DebuginfodFetcher(DebugFileDirectory).fetch(BuildID))
return *Path;
errs() << "Build ID " << llvm::toHex(BuildID, /*Lowercase=*/true)
<< " could not be found.";
exit(1);
}