1 //===-- llvm/Debuginfod/Debuginfod.h - Debuginfod client --------*- C++ -*-===//
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 several declarations for the debuginfod client and
11 /// server. The client functions are getDefaultDebuginfodUrls,
12 /// getCachedOrDownloadArtifact, and several convenience functions for specific
13 /// artifact types: getCachedOrDownloadSource, getCachedOrDownloadExecutable,
14 /// and getCachedOrDownloadDebuginfo. For the server, this file declares the
15 /// DebuginfodLogEntry and DebuginfodServer structs, as well as the
16 /// DebuginfodLog, DebuginfodCollection classes.
17 ///
18 //===----------------------------------------------------------------------===//
19 
20 #ifndef LLVM_DEBUGINFOD_DEBUGINFOD_H
21 #define LLVM_DEBUGINFOD_DEBUGINFOD_H
22 
23 #include "HTTPServer.h"
24 
25 #include "llvm/ADT/StringMap.h"
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/Object/BuildID.h"
28 #include "llvm/Support/Error.h"
29 #include "llvm/Support/MemoryBuffer.h"
30 #include "llvm/Support/Mutex.h"
31 #include "llvm/Support/RWMutex.h"
32 #include "llvm/Support/Timer.h"
33 
34 #include <chrono>
35 #include <condition_variable>
36 #include <optional>
37 #include <queue>
38 
39 namespace llvm {
40 
41 /// Returns false if a debuginfod lookup can be determined to have no chance of
42 /// succeeding.
43 bool canUseDebuginfod();
44 
45 /// Finds default array of Debuginfod server URLs by checking DEBUGINFOD_URLS
46 /// environment variable.
47 SmallVector<StringRef> getDefaultDebuginfodUrls();
48 
49 /// Sets the list of debuginfod server URLs to query. This overrides the
50 /// environment variable DEBUGINFOD_URLS.
51 void setDefaultDebuginfodUrls(const SmallVector<StringRef> &URLs);
52 
53 /// Finds a default local file caching directory for the debuginfod client,
54 /// first checking DEBUGINFOD_CACHE_PATH.
55 Expected<std::string> getDefaultDebuginfodCacheDirectory();
56 
57 /// Finds a default timeout for debuginfod HTTP requests. Checks
58 /// DEBUGINFOD_TIMEOUT environment variable, default is 90 seconds (90000 ms).
59 std::chrono::milliseconds getDefaultDebuginfodTimeout();
60 
61 /// Fetches a specified source file by searching the default local cache
62 /// directory and server URLs.
63 Expected<std::string> getCachedOrDownloadSource(object::BuildIDRef ID,
64                                                 StringRef SourceFilePath);
65 
66 /// Fetches an executable by searching the default local cache directory and
67 /// server URLs.
68 Expected<std::string> getCachedOrDownloadExecutable(object::BuildIDRef ID);
69 
70 /// Fetches a debug binary by searching the default local cache directory and
71 /// server URLs.
72 Expected<std::string> getCachedOrDownloadDebuginfo(object::BuildIDRef ID);
73 
74 /// Fetches any debuginfod artifact using the default local cache directory and
75 /// server URLs.
76 Expected<std::string> getCachedOrDownloadArtifact(StringRef UniqueKey,
77                                                   StringRef UrlPath);
78 
79 /// Fetches any debuginfod artifact using the specified local cache directory,
80 /// server URLs, and request timeout (in milliseconds). If the artifact is
81 /// found, uses the UniqueKey for the local cache file.
82 Expected<std::string> getCachedOrDownloadArtifact(
83     StringRef UniqueKey, StringRef UrlPath, StringRef CacheDirectoryPath,
84     ArrayRef<StringRef> DebuginfodUrls, std::chrono::milliseconds Timeout);
85 
86 class ThreadPool;
87 
88 struct DebuginfodLogEntry {
89   std::string Message;
90   DebuginfodLogEntry() = default;
91   DebuginfodLogEntry(const Twine &Message);
92 };
93 
94 class DebuginfodLog {
95   std::mutex QueueMutex;
96   std::condition_variable QueueCondition;
97   std::queue<DebuginfodLogEntry> LogEntryQueue;
98 
99 public:
100   // Adds a log entry to end of the queue.
101   void push(DebuginfodLogEntry Entry);
102   // Adds a log entry to end of the queue.
103   void push(const Twine &Message);
104   // Blocks until there are log entries in the queue, then pops and returns the
105   // first one.
106   DebuginfodLogEntry pop();
107 };
108 
109 /// Tracks a collection of debuginfod artifacts on the local filesystem.
110 class DebuginfodCollection {
111   SmallVector<std::string, 1> Paths;
112   sys::RWMutex BinariesMutex;
113   StringMap<std::string> Binaries;
114   sys::RWMutex DebugBinariesMutex;
115   StringMap<std::string> DebugBinaries;
116   Error findBinaries(StringRef Path);
117   Expected<std::optional<std::string>> getDebugBinaryPath(object::BuildIDRef);
118   Expected<std::optional<std::string>> getBinaryPath(object::BuildIDRef);
119   // If the collection has not been updated since MinInterval, call update() and
120   // return true. Otherwise return false. If update returns an error, return the
121   // error.
122   Expected<bool> updateIfStale();
123   DebuginfodLog &Log;
124   ThreadPool &Pool;
125   Timer UpdateTimer;
126   sys::Mutex UpdateMutex;
127 
128   // Minimum update interval, in seconds, for on-demand updates triggered when a
129   // build-id is not found.
130   double MinInterval;
131 
132 public:
133   DebuginfodCollection(ArrayRef<StringRef> Paths, DebuginfodLog &Log,
134                        ThreadPool &Pool, double MinInterval);
135   Error update();
136   Error updateForever(std::chrono::milliseconds Interval);
137   Expected<std::string> findDebugBinaryPath(object::BuildIDRef);
138   Expected<std::string> findBinaryPath(object::BuildIDRef);
139 };
140 
141 struct DebuginfodServer {
142   HTTPServer Server;
143   DebuginfodLog &Log;
144   DebuginfodCollection &Collection;
145   DebuginfodServer(DebuginfodLog &Log, DebuginfodCollection &Collection);
146 };
147 
148 } // end namespace llvm
149 
150 #endif
151