brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 7b85166 Raw
158 lines · cpp
1//===-- llvm-debuginfod.cpp - federating debuginfod server ----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file contains the llvm-debuginfod tool, which serves the debuginfod11/// protocol over HTTP. The tool periodically scans zero or more filesystem12/// directories for ELF binaries to serve, and federates requests for unknown13/// build IDs to the debuginfod servers set in the DEBUGINFOD_URLS environment14/// variable.15///16//===----------------------------------------------------------------------===//17 18#include "llvm/ADT/StringExtras.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/Debuginfod/Debuginfod.h"21#include "llvm/Debuginfod/HTTPClient.h"22#include "llvm/Option/ArgList.h"23#include "llvm/Option/Option.h"24#include "llvm/Support/CommandLine.h"25#include "llvm/Support/LLVMDriver.h"26#include "llvm/Support/ThreadPool.h"27 28using namespace llvm;29 30// Command-line option boilerplate.31namespace {32enum ID {33  OPT_INVALID = 0, // This is not an option ID.34#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),35#include "Opts.inc"36#undef OPTION37};38 39#define OPTTABLE_STR_TABLE_CODE40#include "Opts.inc"41#undef OPTTABLE_STR_TABLE_CODE42 43#define OPTTABLE_PREFIXES_TABLE_CODE44#include "Opts.inc"45#undef OPTTABLE_PREFIXES_TABLE_CODE46 47using namespace llvm::opt;48static constexpr opt::OptTable::Info InfoTable[] = {49#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),50#include "Opts.inc"51#undef OPTION52};53 54class DebuginfodOptTable : public opt::GenericOptTable {55public:56  DebuginfodOptTable()57      : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {}58};59} // end anonymous namespace60 61// Options62static unsigned Port;63static std::string HostInterface;64static int ScanInterval;65static double MinInterval;66static size_t MaxConcurrency;67static bool VerboseLogging;68static std::vector<std::string> ScanPaths;69 70ExitOnError ExitOnErr;71 72template <typename T>73static void parseIntArg(const opt::InputArgList &Args, int ID, T &Value,74                        T Default) {75  if (const opt::Arg *A = Args.getLastArg(ID)) {76    StringRef V(A->getValue());77    if (!llvm::to_integer(V, Value, 0)) {78      errs() << A->getSpelling() + ": expected an integer, but got '" + V + "'";79      exit(1);80    }81  } else {82    Value = Default;83  }84}85 86static void parseArgs(int argc, char **argv) {87  DebuginfodOptTable Tbl;88  llvm::StringRef ToolName = argv[0];89  llvm::BumpPtrAllocator A;90  llvm::StringSaver Saver{A};91  opt::InputArgList Args =92      Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {93        llvm::errs() << Msg << '\n';94        std::exit(1);95      });96 97  if (Args.hasArg(OPT_help)) {98    Tbl.printHelp(llvm::outs(),99                  "llvm-debuginfod [options] <Directories to scan>",100                  ToolName.str().c_str());101    std::exit(0);102  }103 104  VerboseLogging = Args.hasArg(OPT_verbose_logging);105  ScanPaths = Args.getAllArgValues(OPT_INPUT);106 107  parseIntArg(Args, OPT_port, Port, 0u);108  parseIntArg(Args, OPT_scan_interval, ScanInterval, 300);109  parseIntArg(Args, OPT_max_concurrency, MaxConcurrency, size_t(0));110 111  if (const opt::Arg *A = Args.getLastArg(OPT_min_interval)) {112    StringRef V(A->getValue());113    if (!llvm::to_float(V, MinInterval)) {114      errs() << A->getSpelling() + ": expected a number, but got '" + V + "'";115      exit(1);116    }117  } else {118    MinInterval = 10.0;119  }120 121  HostInterface = Args.getLastArgValue(OPT_host_interface, "0.0.0.0");122}123 124int llvm_debuginfod_main(int argc, char **argv, const llvm::ToolContext &) {125  HTTPClient::initialize();126  parseArgs(argc, argv);127 128  SmallVector<StringRef, 1> Paths;129  llvm::append_range(Paths, ScanPaths);130 131  DefaultThreadPool Pool(hardware_concurrency(MaxConcurrency));132  DebuginfodLog Log;133  DebuginfodCollection Collection(Paths, Log, Pool, MinInterval);134  DebuginfodServer Server(Log, Collection);135 136  if (!Port)137    Port = ExitOnErr(Server.Server.bind(HostInterface.c_str()));138  else139    ExitOnErr(Server.Server.bind(Port, HostInterface.c_str()));140 141  Log.push("Listening on port " + Twine(Port).str());142 143  Pool.async([&]() { ExitOnErr(Server.Server.listen()); });144  Pool.async([&]() {145    while (true) {146      DebuginfodLogEntry Entry = Log.pop();147      if (VerboseLogging) {148        outs() << Entry.Message << "\n";149        outs().flush();150      }151    }152  });153  if (Paths.size())154    ExitOnErr(Collection.updateForever(std::chrono::seconds(ScanInterval)));155  Pool.wait();156  llvm_unreachable("The ThreadPool should never finish running its tasks.");157}158