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