1*36f01909SNoah Shutty //===-- llvm-debuginfod.cpp - federating debuginfod server ----------------===//
2*36f01909SNoah Shutty //
3*36f01909SNoah Shutty // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*36f01909SNoah Shutty // See https://llvm.org/LICENSE.txt for license information.
5*36f01909SNoah Shutty // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*36f01909SNoah Shutty //
7*36f01909SNoah Shutty //===----------------------------------------------------------------------===//
8*36f01909SNoah Shutty ///
9*36f01909SNoah Shutty /// \file
10*36f01909SNoah Shutty /// This file contains the llvm-debuginfod tool, which serves the debuginfod
11*36f01909SNoah Shutty /// protocol over HTTP. The tool periodically scans zero or more filesystem
12*36f01909SNoah Shutty /// directories for ELF binaries to serve, and federates requests for unknown
13*36f01909SNoah Shutty /// build IDs to the debuginfod servers set in the DEBUGINFOD_URLS environment
14*36f01909SNoah Shutty /// variable.
15*36f01909SNoah Shutty ///
16*36f01909SNoah Shutty //===----------------------------------------------------------------------===//
17*36f01909SNoah Shutty 
18*36f01909SNoah Shutty #include "llvm/Debuginfod/Debuginfod.h"
19*36f01909SNoah Shutty #include "llvm/Debuginfod/HTTPClient.h"
20*36f01909SNoah Shutty #include "llvm/Support/CommandLine.h"
21*36f01909SNoah Shutty #include "llvm/Support/InitLLVM.h"
22*36f01909SNoah Shutty #include "llvm/Support/ThreadPool.h"
23*36f01909SNoah Shutty 
24*36f01909SNoah Shutty using namespace llvm;
25*36f01909SNoah Shutty 
26*36f01909SNoah Shutty cl::OptionCategory DebuginfodCategory("llvm-debuginfod Options");
27*36f01909SNoah Shutty 
28*36f01909SNoah Shutty static cl::list<std::string> ScanPaths(cl::Positional,
29*36f01909SNoah Shutty                                        cl::desc("<Directories to scan>"),
30*36f01909SNoah Shutty                                        cl::cat(DebuginfodCategory));
31*36f01909SNoah Shutty 
32*36f01909SNoah Shutty static cl::opt<unsigned>
33*36f01909SNoah Shutty     Port("p", cl::init(0),
34*36f01909SNoah Shutty          cl::desc("Port to listen on. Set to 0 to bind to any available port."),
35*36f01909SNoah Shutty          cl::cat(DebuginfodCategory));
36*36f01909SNoah Shutty 
37*36f01909SNoah Shutty static cl::opt<std::string>
38*36f01909SNoah Shutty     HostInterface("i", cl::init("0.0.0.0"),
39*36f01909SNoah Shutty                   cl::desc("Host interface to bind to."),
40*36f01909SNoah Shutty                   cl::cat(DebuginfodCategory));
41*36f01909SNoah Shutty 
42*36f01909SNoah Shutty static cl::opt<int>
43*36f01909SNoah Shutty     ScanInterval("t", cl::init(300),
44*36f01909SNoah Shutty                  cl::desc("Number of seconds to wait between subsequent "
45*36f01909SNoah Shutty                           "automated scans of the filesystem."),
46*36f01909SNoah Shutty                  cl::cat(DebuginfodCategory));
47*36f01909SNoah Shutty 
48*36f01909SNoah Shutty static cl::opt<double> MinInterval(
49*36f01909SNoah Shutty     "m", cl::init(10),
50*36f01909SNoah Shutty     cl::desc(
51*36f01909SNoah Shutty         "Minimum number of seconds to wait before an on-demand update can be "
52*36f01909SNoah Shutty         "triggered by a request for a buildid which is not in the collection."),
53*36f01909SNoah Shutty     cl::cat(DebuginfodCategory));
54*36f01909SNoah Shutty 
55*36f01909SNoah Shutty static cl::opt<size_t>
56*36f01909SNoah Shutty     MaxConcurrency("c", cl::init(0),
57*36f01909SNoah Shutty                    cl::desc("Maximum number of files to scan concurrently. If "
58*36f01909SNoah Shutty                             "0, use the hardware concurrency."),
59*36f01909SNoah Shutty                    cl::cat(DebuginfodCategory));
60*36f01909SNoah Shutty 
61*36f01909SNoah Shutty static cl::opt<bool> VerboseLogging("v", cl::init(false),
62*36f01909SNoah Shutty                                     cl::desc("Enable verbose logging."),
63*36f01909SNoah Shutty                                     cl::cat(DebuginfodCategory));
64*36f01909SNoah Shutty 
65*36f01909SNoah Shutty ExitOnError ExitOnErr;
66*36f01909SNoah Shutty 
67*36f01909SNoah Shutty int main(int argc, char **argv) {
68*36f01909SNoah Shutty   InitLLVM X(argc, argv);
69*36f01909SNoah Shutty   HTTPClient::initialize();
70*36f01909SNoah Shutty   cl::HideUnrelatedOptions({&DebuginfodCategory});
71*36f01909SNoah Shutty   cl::ParseCommandLineOptions(argc, argv);
72*36f01909SNoah Shutty 
73*36f01909SNoah Shutty   SmallVector<StringRef, 1> Paths;
74*36f01909SNoah Shutty   for (const std::string &Path : ScanPaths)
75*36f01909SNoah Shutty     Paths.push_back(Path);
76*36f01909SNoah Shutty 
77*36f01909SNoah Shutty   ThreadPool Pool(hardware_concurrency(MaxConcurrency));
78*36f01909SNoah Shutty   DebuginfodLog Log;
79*36f01909SNoah Shutty   DebuginfodCollection Collection(Paths, Log, Pool, MinInterval);
80*36f01909SNoah Shutty   DebuginfodServer Server(Log, Collection);
81*36f01909SNoah Shutty 
82*36f01909SNoah Shutty   if (!Port)
83*36f01909SNoah Shutty     Port = ExitOnErr(Server.Server.bind(HostInterface.c_str()));
84*36f01909SNoah Shutty   else
85*36f01909SNoah Shutty     ExitOnErr(Server.Server.bind(Port, HostInterface.c_str()));
86*36f01909SNoah Shutty 
87*36f01909SNoah Shutty   Log.push("Listening on port " + Twine(Port).str());
88*36f01909SNoah Shutty 
89*36f01909SNoah Shutty   Pool.async([&]() { ExitOnErr(Server.Server.listen()); });
90*36f01909SNoah Shutty   Pool.async([&]() {
91*36f01909SNoah Shutty     while (1) {
92*36f01909SNoah Shutty       DebuginfodLogEntry Entry = Log.pop();
93*36f01909SNoah Shutty       if (VerboseLogging) {
94*36f01909SNoah Shutty         outs() << Entry.Message << "\n";
95*36f01909SNoah Shutty         outs().flush();
96*36f01909SNoah Shutty       }
97*36f01909SNoah Shutty     }
98*36f01909SNoah Shutty   });
99*36f01909SNoah Shutty   if (Paths.size())
100*36f01909SNoah Shutty     ExitOnErr(Collection.updateForever(std::chrono::seconds(ScanInterval)));
101*36f01909SNoah Shutty   Pool.wait();
102*36f01909SNoah Shutty   llvm_unreachable("The ThreadPool should never finish running its tasks.");
103*36f01909SNoah Shutty }
104