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 /// Finds a default local file caching directory for the debuginfod client,
50 /// first checking DEBUGINFOD_CACHE_PATH.
51 Expected<std::string> getDefaultDebuginfodCacheDirectory();
52 
53 /// Finds a default timeout for debuginfod HTTP requests. Checks
54 /// DEBUGINFOD_TIMEOUT environment variable, default is 90 seconds (90000 ms).
55 std::chrono::milliseconds getDefaultDebuginfodTimeout();
56 
57 /// Fetches a specified source file by searching the default local cache
58 /// directory and server URLs.
59 Expected<std::string> getCachedOrDownloadSource(object::BuildIDRef ID,
60                                                 StringRef SourceFilePath);
61 
62 /// Fetches an executable by searching the default local cache directory and
63 /// server URLs.
64 Expected<std::string> getCachedOrDownloadExecutable(object::BuildIDRef ID);
65 
66 /// Fetches a debug binary by searching the default local cache directory and
67 /// server URLs.
68 Expected<std::string> getCachedOrDownloadDebuginfo(object::BuildIDRef ID);
69 
70 /// Fetches any debuginfod artifact using the default local cache directory and
71 /// server URLs.
72 Expected<std::string> getCachedOrDownloadArtifact(StringRef UniqueKey,
73                                                   StringRef UrlPath);
74 
75 /// Fetches any debuginfod artifact using the specified local cache directory,
76 /// server URLs, and request timeout (in milliseconds). If the artifact is
77 /// found, uses the UniqueKey for the local cache file.
78 Expected<std::string> getCachedOrDownloadArtifact(
79     StringRef UniqueKey, StringRef UrlPath, StringRef CacheDirectoryPath,
80     ArrayRef<StringRef> DebuginfodUrls, std::chrono::milliseconds Timeout);
81 
82 class ThreadPool;
83 
84 struct DebuginfodLogEntry {
85   std::string Message;
86   DebuginfodLogEntry() = default;
87   DebuginfodLogEntry(const Twine &Message);
88 };
89 
90 class DebuginfodLog {
91   std::mutex QueueMutex;
92   std::condition_variable QueueCondition;
93   std::queue<DebuginfodLogEntry> LogEntryQueue;
94 
95 public:
96   // Adds a log entry to end of the queue.
97   void push(DebuginfodLogEntry Entry);
98   // Adds a log entry to end of the queue.
99   void push(const Twine &Message);
100   // Blocks until there are log entries in the queue, then pops and returns the
101   // first one.
102   DebuginfodLogEntry pop();
103 };
104 
105 /// Tracks a collection of debuginfod artifacts on the local filesystem.
106 class DebuginfodCollection {
107   SmallVector<std::string, 1> Paths;
108   sys::RWMutex BinariesMutex;
109   StringMap<std::string> Binaries;
110   sys::RWMutex DebugBinariesMutex;
111   StringMap<std::string> DebugBinaries;
112   Error findBinaries(StringRef Path);
113   Expected<std::optional<std::string>> getDebugBinaryPath(object::BuildIDRef);
114   Expected<std::optional<std::string>> getBinaryPath(object::BuildIDRef);
115   // If the collection has not been updated since MinInterval, call update() and
116   // return true. Otherwise return false. If update returns an error, return the
117   // error.
118   Expected<bool> updateIfStale();
119   DebuginfodLog &Log;
120   ThreadPool &Pool;
121   Timer UpdateTimer;
122   sys::Mutex UpdateMutex;
123 
124   // Minimum update interval, in seconds, for on-demand updates triggered when a
125   // build-id is not found.
126   double MinInterval;
127 
128 public:
129   DebuginfodCollection(ArrayRef<StringRef> Paths, DebuginfodLog &Log,
130                        ThreadPool &Pool, double MinInterval);
131   Error update();
132   Error updateForever(std::chrono::milliseconds Interval);
133   Expected<std::string> findDebugBinaryPath(object::BuildIDRef);
134   Expected<std::string> findBinaryPath(object::BuildIDRef);
135 };
136 
137 struct DebuginfodServer {
138   HTTPServer Server;
139   DebuginfodLog &Log;
140   DebuginfodCollection &Collection;
141   DebuginfodServer(DebuginfodLog &Log, DebuginfodCollection &Collection);
142 };
143 
144 } // end namespace llvm
145 
146 #endif
147