LLVM  14.0.0git
Debuginfod.cpp
Go to the documentation of this file.
1 //===-- llvm/Debuginfod/Debuginfod.cpp - Debuginfod client library --------===//
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 ///
11 /// This file defines the fetchInfo function, which retrieves
12 /// any of the three supported artifact types: (executable, debuginfo, source
13 /// file) associated with a build-id from debuginfod servers. If a source file
14 /// is to be fetched, its absolute path must be specified in the Description
15 /// argument to fetchInfo.
16 ///
17 //===----------------------------------------------------------------------===//
18 
20 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Support/Caching.h"
24 #include "llvm/Support/Error.h"
26 #include "llvm/Support/xxhash.h"
27 
28 namespace llvm {
29 static std::string uniqueKey(llvm::StringRef S) { return utostr(xxHash64(S)); }
30 
31 // Returns a binary BuildID as a normalized hex string.
32 // Uses lowercase for compatibility with common debuginfod servers.
33 static std::string buildIDToString(BuildIDRef ID) {
34  return llvm::toHex(ID, /*LowerCase=*/true);
35 }
36 
38  const char *DebuginfodUrlsEnv = std::getenv("DEBUGINFOD_URLS");
39  if (DebuginfodUrlsEnv == nullptr)
40  return SmallVector<StringRef>();
41 
42  SmallVector<StringRef> DebuginfodUrls;
43  StringRef(DebuginfodUrlsEnv).split(DebuginfodUrls, " ");
44  return DebuginfodUrls;
45 }
46 
48  if (const char *CacheDirectoryEnv = std::getenv("DEBUGINFOD_CACHE_PATH"))
49  return CacheDirectoryEnv;
50 
51  SmallString<64> CacheDirectory;
52  if (!sys::path::cache_directory(CacheDirectory))
53  return createStringError(
54  errc::io_error, "Unable to determine appropriate cache directory.");
55  sys::path::append(CacheDirectory, "llvm-debuginfod", "client");
56  return std::string(CacheDirectory);
57 }
58 
59 std::chrono::milliseconds getDefaultDebuginfodTimeout() {
60  long Timeout;
61  const char *DebuginfodTimeoutEnv = std::getenv("DEBUGINFOD_TIMEOUT");
62  if (DebuginfodTimeoutEnv &&
63  to_integer(StringRef(DebuginfodTimeoutEnv).trim(), Timeout, 10))
64  return std::chrono::milliseconds(Timeout * 1000);
65 
66  return std::chrono::milliseconds(90 * 1000);
67 }
68 
69 /// The following functions fetch a debuginfod artifact to a file in a local
70 /// cache and return the cached file path. They first search the local cache,
71 /// followed by the debuginfod servers.
72 
74  StringRef SourceFilePath) {
75  SmallString<64> UrlPath;
76  sys::path::append(UrlPath, sys::path::Style::posix, "buildid",
77  buildIDToString(ID), "source",
78  sys::path::convert_to_slash(SourceFilePath));
79  return getCachedOrDownloadArtifact(uniqueKey(UrlPath), UrlPath);
80 }
81 
83  SmallString<64> UrlPath;
84  sys::path::append(UrlPath, sys::path::Style::posix, "buildid",
85  buildIDToString(ID), "executable");
86  return getCachedOrDownloadArtifact(uniqueKey(UrlPath), UrlPath);
87 }
88 
90  SmallString<64> UrlPath;
91  sys::path::append(UrlPath, sys::path::Style::posix, "buildid",
92  buildIDToString(ID), "debuginfo");
93  return getCachedOrDownloadArtifact(uniqueKey(UrlPath), UrlPath);
94 }
95 
96 // General fetching function.
98  StringRef UrlPath) {
99  SmallString<10> CacheDir;
100 
102  if (!CacheDirOrErr)
103  return CacheDirOrErr.takeError();
104  CacheDir = *CacheDirOrErr;
105 
106  Expected<SmallVector<StringRef>> DebuginfodUrlsOrErr =
108  if (!DebuginfodUrlsOrErr)
109  return DebuginfodUrlsOrErr.takeError();
110  SmallVector<StringRef> &DebuginfodUrls = *DebuginfodUrlsOrErr;
111  return getCachedOrDownloadArtifact(UniqueKey, UrlPath, CacheDir,
112  DebuginfodUrls,
114 }
115 
117  StringRef UniqueKey, StringRef UrlPath, StringRef CacheDirectoryPath,
118  ArrayRef<StringRef> DebuginfodUrls, std::chrono::milliseconds Timeout) {
119  SmallString<64> AbsCachedArtifactPath;
120  sys::path::append(AbsCachedArtifactPath, CacheDirectoryPath,
121  "llvmcache-" + UniqueKey);
122 
123  Expected<FileCache> CacheOrErr =
124  localCache("Debuginfod-client", ".debuginfod-client", CacheDirectoryPath);
125  if (!CacheOrErr)
126  return CacheOrErr.takeError();
127 
128  FileCache Cache = *CacheOrErr;
129  // We choose an arbitrary Task parameter as we do not make use of it.
130  unsigned Task = 0;
131  Expected<AddStreamFn> CacheAddStreamOrErr = Cache(Task, UniqueKey);
132  if (!CacheAddStreamOrErr)
133  return CacheAddStreamOrErr.takeError();
134  AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
135  if (!CacheAddStream)
136  return std::string(AbsCachedArtifactPath);
137  // The artifact was not found in the local cache, query the debuginfod
138  // servers.
141  "No working HTTP client is available.");
142 
144  return createStringError(
146  "A working HTTP client is available, but it is not initialized. To "
147  "allow Debuginfod to make HTTP requests, call HTTPClient::initialize() "
148  "at the beginning of main.");
149 
150  HTTPClient Client;
151  Client.setTimeout(Timeout);
152  for (StringRef ServerUrl : DebuginfodUrls) {
153  SmallString<64> ArtifactUrl;
154  sys::path::append(ArtifactUrl, sys::path::Style::posix, ServerUrl, UrlPath);
155 
156  Expected<HTTPResponseBuffer> ResponseOrErr = Client.get(ArtifactUrl);
157  if (!ResponseOrErr)
158  return ResponseOrErr.takeError();
159 
160  HTTPResponseBuffer &Response = *ResponseOrErr;
161  if (Response.Code != 200)
162  continue;
163 
164  // We have retrieved the artifact from this server, and now add it to the
165  // file cache.
167  CacheAddStream(Task);
168  if (!FileStreamOrErr)
169  return FileStreamOrErr.takeError();
170  std::unique_ptr<CachedFileStream> &FileStream = *FileStreamOrErr;
171  if (!Response.Body)
172  return createStringError(
173  errc::io_error, "Unallocated MemoryBuffer in HTTPResponseBuffer.");
174 
175  *FileStream->OS << StringRef(Response.Body->getBufferStart(),
176  Response.Body->getBufferSize());
177 
178  // Return the path to the artifact on disk.
179  return std::string(AbsCachedArtifactPath);
180  }
181 
182  return createStringError(errc::argument_out_of_domain, "build id not found");
183 }
184 } // namespace llvm
llvm::FileCache
std::function< Expected< AddStreamFn >(unsigned Task, StringRef Key)> FileCache
This is the type of a file cache.
Definition: Caching.h:56
llvm::HTTPClient
A reusable client that can perform HTTPRequests through a network socket.
Definition: HTTPClient.h:79
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::buildIDToString
static std::string buildIDToString(BuildIDRef ID)
Definition: Debuginfod.cpp:33
llvm::sys::path::Style::posix
@ posix
StringRef.h
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1177
llvm::HTTPClient::IsInitialized
static bool IsInitialized
Definition: HTTPClient.h:88
llvm::sys::path::convert_to_slash
std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
Definition: Path.cpp:569
llvm::AddStreamFn
std::function< Expected< std::unique_ptr< CachedFileStream > >(unsigned Task)> AddStreamFn
This type defines the callback to add a file that is generated on the fly.
Definition: Caching.h:42
Error.h
HTTPClient.h
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::getDefaultDebuginfodTimeout
std::chrono::milliseconds getDefaultDebuginfodTimeout()
Finds a default timeout for debuginfod HTTP requests.
Definition: Debuginfod.cpp:59
llvm::sys::path::cache_directory
bool cache_directory(SmallVectorImpl< char > &result)
Get the directory where installed packages should put their machine-local cache, e....
llvm::sys::path::append
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:457
Caching.h
CachePruning.h
llvm::uniqueKey
static std::string uniqueKey(llvm::StringRef S)
Definition: Debuginfod.cpp:29
llvm::errc::argument_out_of_domain
@ argument_out_of_domain
llvm::StringRef::split
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:748
llvm::getCachedOrDownloadArtifact
Expected< std::string > getCachedOrDownloadArtifact(StringRef UniqueKey, StringRef UrlPath)
Fetches any debuginfod artifact using the default local cache directory and server URLs.
Definition: Debuginfod.cpp:97
llvm::localCache
Expected< FileCache > localCache(Twine CacheNameRef, Twine TempFilePrefixRef, Twine CacheDirectoryPathRef, AddBufferFn AddBuffer=[](size_t Task, std::unique_ptr< MemoryBuffer > MB) { })
Create a local file system cache which uses the given cache name, temporary file prefix,...
Definition: Caching.cpp:29
llvm::SmallString< 64 >
llvm::HTTPResponseBuffer::Body
std::unique_ptr< WritableMemoryBuffer > Body
Definition: HTTPClient.h:57
Debuginfod.h
llvm::symbolize::toHex
static std::string toHex(uint64_t V)
Definition: DIPrinter.cpp:276
llvm::HTTPClient::isAvailable
static bool isAvailable()
Returns true only if LLVM has been compiled with a working HTTPClient.
Definition: HTTPClient.cpp:203
llvm::HTTPClient::setTimeout
void setTimeout(std::chrono::milliseconds Timeout)
Sets the timeout for the entire request, in milliseconds.
Definition: HTTPClient.cpp:209
llvm::getDefaultDebuginfodCacheDirectory
Expected< std::string > getDefaultDebuginfodCacheDirectory()
Finds a default local file caching directory for the debuginfod client, first checking DEBUGINFOD_CAC...
Definition: Debuginfod.cpp:47
llvm::getCachedOrDownloadExecutable
Expected< std::string > getCachedOrDownloadExecutable(BuildIDRef ID)
Fetches an executable by searching the default local cache directory and server URLs.
Definition: Debuginfod.cpp:82
xxhash.h
FileUtilities.h
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::HTTPResponseBuffer::Code
unsigned Code
Definition: HTTPClient.h:56
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::HTTPClient::get
Expected< HTTPResponseBuffer > get(StringRef Url)
Performs an HTTPRequest with the default configuration to make a GET request to the given Url.
Definition: HTTPClient.cpp:90
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1241
llvm::getDefaultDebuginfodUrls
Expected< SmallVector< StringRef > > getDefaultDebuginfodUrls()
Finds default array of Debuginfod server URLs by checking DEBUGINFOD_URLS environment variable.
Definition: Debuginfod.cpp:37
llvm::errc::io_error
@ io_error
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:599
llvm::getCachedOrDownloadSource
Expected< std::string > getCachedOrDownloadSource(BuildIDRef ID, StringRef SourceFilePath)
Fetches a specified source file by searching the default local cache directory and server URLs.
Definition: Debuginfod.cpp:73
llvm::getCachedOrDownloadDebuginfo
Expected< std::string > getCachedOrDownloadDebuginfo(BuildIDRef ID)
Fetches a debug binary by searching the default local cache directory and server URLs.
Definition: Debuginfod.cpp:89
llvm::HTTPResponseBuffer
An HTTP response status code bundled with a buffer to store the body.
Definition: HTTPClient.h:55
llvm::xxHash64
uint64_t xxHash64(llvm::StringRef Data)
Definition: xxhash.cpp:71
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38