//===-- 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/ADT/StringExtras.h" #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 InputBuildID(cl::Positional, cl::Required, cl::desc(""), cl::init("-"), cl::cat(DebuginfodFindCategory)); static cl::opt 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 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 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 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 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> 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 (std::optional Path = DebuginfodFetcher(DebugFileDirectory).fetch(BuildID)) return *Path; errs() << "Build ID " << llvm::toHex(BuildID, /*Lowercase=*/true) << " could not be found.\n"; exit(1); }