
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
128 lines
4.8 KiB
C++
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);
|
|
}
|