52std::optional<SmallVector<StringRef>> DebuginfodUrls;
64 return llvm::toHex(
ID,
true);
72 std::shared_lock<llvm::sys::RWMutex> ReadGuard(UrlsMutex);
73 if (!DebuginfodUrls) {
77 std::unique_lock<llvm::sys::RWMutex> WriteGuard(UrlsMutex);
79 if (
const char *DebuginfodUrlsEnv = std::getenv(
"DEBUGINFOD_URLS")) {
81 .
split(DebuginfodUrls.value(),
" ", -1,
false);
86 return DebuginfodUrls.value();
91 std::unique_lock<llvm::sys::RWMutex> WriteGuard(UrlsMutex);
92 DebuginfodUrls = URLs;
98 if (
const char *CacheDirectoryEnv = std::getenv(
"DEBUGINFOD_CACHE_PATH"))
99 return CacheDirectoryEnv;
104 errc::io_error,
"Unable to determine appropriate cache directory.");
106 return std::string(CacheDirectory);
111 const char *DebuginfodTimeoutEnv = std::getenv(
"DEBUGINFOD_TIMEOUT");
112 if (DebuginfodTimeoutEnv &&
114 return std::chrono::milliseconds(
Timeout * 1000);
116 return std::chrono::milliseconds(90 * 1000);
129 return std::string(UrlPath);
142 return std::string(UrlPath);
154 return std::string(UrlPath);
170 CacheDir = *CacheDirOrErr;
181class StreamedHTTPResponseHandler :
public HTTPResponseHandler {
182 using CreateStreamFn =
183 std::function<Expected<std::unique_ptr<CachedFileStream>>()>;
184 CreateStreamFn CreateStream;
186 std::unique_ptr<CachedFileStream> FileStream;
189 StreamedHTTPResponseHandler(CreateStreamFn CreateStream, HTTPClient &Client)
190 : CreateStream(CreateStream), Client(Client) {}
196 virtual ~StreamedHTTPResponseHandler() =
default;
198 Error handleBodyChunk(StringRef BodyChunk)
override;
203Error StreamedHTTPResponseHandler::handleBodyChunk(StringRef BodyChunk) {
205 unsigned Code = Client.responseCode();
206 if (Code && Code != 200)
208 Expected<std::unique_ptr<CachedFileStream>> FileStreamOrError =
210 if (!FileStreamOrError)
211 return FileStreamOrError.takeError();
212 FileStream = std::move(*FileStreamOrError);
214 *FileStream->OS << BodyChunk;
218Error StreamedHTTPResponseHandler::commit() {
220 return FileStream->commit();
231 return all_of(
Name, [](
char C) {
return llvm::isPrint(
C) &&
C !=
' '; }) &&
232 all_of(
Value, [](
char C) {
return llvm::isPrint(
C) ||
C ==
'\t'; });
236 const char *Filename = getenv(
"DEBUGINFOD_HEADERS_FILE");
246 for (
StringRef Line : llvm::split((*HeadersFile)->getBuffer(),
'\n')) {
248 Line.consume_back(
"\r");
250 if (!
all_of(Line, llvm::isSpace))
252 <<
"could not parse debuginfod header: " << Filename <<
':'
253 << LineNumber <<
'\n';
266 "llvmcache-" + UniqueKey);
269 localCache(
"Debuginfod-client",
".debuginfod-client", CacheDirectoryPath);
277 if (!CacheAddStreamOrErr)
279 AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
281 return std::string(AbsCachedArtifactPath);
286 "No working HTTP client is available.");
291 "A working HTTP client is available, but it is not initialized. To "
292 "allow Debuginfod to make HTTP requests, call HTTPClient::initialize() "
293 "at the beginning of main.");
297 for (
StringRef ServerUrl : DebuginfodUrls) {
304 StreamedHTTPResponseHandler Handler(
305 [&]() {
return CacheAddStream(Task,
""); }, Client);
310 return std::move(Err);
311 if ((Err = Handler.commit()))
312 return std::move(Err);
315 if (Code && Code != 200)
321 if (!PruningPolicyOrErr)
323 pruneCache(CacheDirectoryPath, *PruningPolicyOrErr);
326 return std::string(AbsCachedArtifactPath);
333 : Message(Message.str()) {}
341 std::lock_guard<std::mutex> Guard(QueueMutex);
342 LogEntryQueue.push(Entry);
344 QueueCondition.notify_one();
349 std::unique_lock<std::mutex> Guard(QueueMutex);
351 QueueCondition.wait(Guard, [&] {
return !LogEntryQueue.empty(); });
353 std::lock_guard<std::mutex> Guard(QueueMutex);
354 if (!LogEntryQueue.size())
366 : Log(Log), Pool(Pool), MinInterval(MinInterval) {
372 std::lock_guard<sys::Mutex> Guard(UpdateMutex);
376 for (
const std::string &Path : Paths) {
377 Log.
push(
"Updating binaries at path " + Path);
378 if (
Error Err = findBinaries(Path))
381 Log.
push(
"Updated collection");
392 if (Time < MinInterval)
395 return std::move(Err);
403 std::this_thread::sleep_for(
Interval);
425Error DebuginfodCollection::findBinaries(StringRef Path) {
427 sys::fs::recursive_directory_iterator
I(Twine(Path), EC),
E;
428 std::mutex IteratorMutex;
429 ThreadPoolTaskGroup IteratorGroup(Pool);
432 IteratorGroup.async([&,
this]() ->
void {
433 std::string FilePath;
437 std::lock_guard<std::mutex> Guard(IteratorMutex);
442 FilePath =
I->path();
450 Expected<object::OwningBinary<object::Binary>> BinOrErr =
457 object::Binary *
Bin = std::move(BinOrErr.get().getBinary());
458 if (!
Bin->isObject())
462 object::ELFObjectFileBase *
Object =
463 dyn_cast<object::ELFObjectFileBase>(
Bin);
472 if (
Object->hasDebugInfo()) {
473 std::lock_guard<sys::RWMutex> DebugBinariesGuard(DebugBinariesMutex);
474 (void)DebugBinaries.
try_emplace(IDString, std::move(FilePath));
476 std::lock_guard<sys::RWMutex> BinariesGuard(BinariesMutex);
477 (void)Binaries.
try_emplace(IDString, std::move(FilePath));
482 IteratorGroup.wait();
483 std::unique_lock<std::mutex> Guard(IteratorMutex);
489Expected<std::optional<std::string>>
490DebuginfodCollection::getBinaryPath(BuildIDRef
ID) {
492 std::shared_lock<sys::RWMutex> Guard(BinariesMutex);
494 if (Loc != Binaries.
end()) {
495 std::string
Path = Loc->getValue();
501Expected<std::optional<std::string>>
502DebuginfodCollection::getDebugBinaryPath(BuildIDRef
ID) {
504 std::shared_lock<sys::RWMutex> Guard(DebugBinariesMutex);
506 if (Loc != DebugBinaries.
end()) {
507 std::string
Path = Loc->getValue();
519 std::optional<std::string> Path = *PathOrErr;
526 PathOrErr = getBinaryPath(
ID);
550 std::optional<std::string> Path = *PathOrErr;
557 PathOrErr = getBinaryPath(
ID);
576 std::string IDString;
579 {404,
"text/plain",
"Build ID is not a hex string\n"});
584 if (Error Err = PathOrErr.takeError()) {
586 Request.
setResponse({404,
"text/plain",
"Build ID not found\n"});
595 Server.get(R
"(/buildid/(.*)/executable)", [&](HTTPServerRequest Request) {
596 Log.push("GET " + Request.UrlPath);
597 std::string IDString;
598 if (!tryGetFromHex(Request.UrlPathMatches[0], IDString)) {
600 {404,
"text/plain",
"Build ID is not a hex string\n"});
605 if (Error Err = PathOrErr.takeError()) {
607 Request.setResponse({404,
"text/plain",
"Build ID not found\n"});
617Expected<DebuginfodServer>
620 if (
llvm::Error Err = Serverd.init(Log, Collection))
621 return std::move(Err);
622 return std::move(Serverd);
This file declares a library for handling Build IDs and using them to find debug info.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains several declarations for the debuginfod client and server.
This file contains the declarations of the HTTPClient library for issuing HTTP requests and handling ...
std::pair< uint64_t, uint64_t > Interval
Tracks a collection of debuginfod artifacts on the local filesystem.
DebuginfodCollection(ArrayRef< StringRef > Paths, DebuginfodLog &Log, ThreadPoolInterface &Pool, double MinInterval)
Expected< std::string > findBinaryPath(object::BuildIDRef)
Error updateForever(std::chrono::milliseconds Interval)
Expected< std::string > findDebugBinaryPath(object::BuildIDRef)
void push(DebuginfodLogEntry Entry)
Represents either an error or a value T.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
A reusable client that can perform HTTPRequests through a network socket.
static bool isAvailable()
Returns true only if LLVM has been compiled with a working HTTPClient.
static bool IsInitialized
unsigned responseCode()
Returns the last received response code or zero if none.
Error perform(const HTTPRequest &Request, HTTPResponseHandler &Handler)
Performs the Request, passing response data to the Handler.
void setTimeout(std::chrono::milliseconds Timeout)
Sets the timeout for the entire request, in milliseconds.
void setResponse(StreamingHTTPResponse Response)
SmallVector< std::string, 1 > UrlPathMatches
The elements correspond to match groups in the url path matching regex.
Error get(StringRef UrlPathPattern, HTTPRequestHandler Handler)
Registers a URL pattern routing rule.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
iterator find(StringRef Key)
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
This defines the abstract base interface for a ThreadPool allowing asynchronous parallel execution on...
virtual unsigned getMaxConcurrency() const =0
Returns the maximum number of worker this pool can eventually grow to.
double getWallTime() const
bool isRunning() const
Check if the timer is currently running.
LLVM_ABI void stopTimer()
Stop the timer.
LLVM_ABI void clear()
Clear the timer state.
LLVM_ABI void startTimer()
Start the timer running.
TimeRecord getTotalTime() const
Return the duration for which this timer has been running.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
static LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
LLVM_ABI BuildIDRef getBuildID(const ObjectFile *Obj)
Returns the build ID, if any, contained in the given object file.
ArrayRef< uint8_t > BuildIDRef
A reference to a BuildID in binary form.
LLVM_ABI Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
NodeAddr< CodeNode * > Code
LLVM_ABI bool cache_directory(SmallVectorImpl< char > &result)
Get the directory where installed packages should put their machine-local cache, e....
LLVM_ABI std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Expected< std::string > getCachedOrDownloadExecutable(object::BuildIDRef ID)
Fetches an executable by searching the default local cache directory and server URLs.
std::string getDebuginfodCacheKey(StringRef UrlPath)
Returns the cache key for a given debuginfod URL path.
LLVM_ABI uint64_t xxh3_64bits(ArrayRef< uint8_t > data)
static bool isHeader(StringRef S)
SmallVector< StringRef > getDefaultDebuginfodUrls()
Finds default array of Debuginfod server URLs by checking DEBUGINFOD_URLS environment variable.
std::string getDebuginfodSourceUrlPath(object::BuildIDRef ID, StringRef SourceFilePath)
Get the full URL path for a source request of a given BuildID and file path.
std::function< Expected< std::unique_ptr< CachedFileStream > >(unsigned Task, const Twine &ModuleName)> AddStreamFn
This type defines the callback to add a file that is generated on the fly.
Expected< std::string > getCachedOrDownloadDebuginfo(object::BuildIDRef ID)
Fetches a debug binary by searching the default local cache directory and server URLs.
static std::string buildIDToString(BuildIDRef ID)
std::string getDebuginfodExecutableUrlPath(object::BuildIDRef ID)
Get the full URL path for an executable request of a given BuildID.
LLVM_ABI Expected< CachePruningPolicy > parseCachePruningPolicy(StringRef PolicyStr)
Parse the given string as a cache pruning policy.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Expected< std::string > getCachedOrDownloadArtifact(StringRef UniqueKey, StringRef UrlPath)
Fetches any debuginfod artifact using the default local cache directory and server URLs.
std::string getDebuginfodDebuginfoUrlPath(object::BuildIDRef ID)
Get the full URL path for a debug binary request of a given BuildID.
@ Timeout
Reached timeout while waiting for the owner to release the lock.
Expected< std::string > getCachedOrDownloadSource(object::BuildIDRef ID, StringRef SourceFilePath)
Fetches a specified source file by searching the default local cache directory and server URLs.
LLVM_ABI bool pruneCache(StringRef Path, CachePruningPolicy Policy, const std::vector< std::unique_ptr< MemoryBuffer > > &Files={})
Peform pruning using the supplied policy, returns true if pruning occurred, i.e.
std::chrono::milliseconds getDefaultDebuginfodTimeout()
Finds a default timeout for debuginfod HTTP requests.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
static bool hasELFMagic(StringRef FilePath)
bool streamFile(HTTPServerRequest &Request, StringRef FilePath)
Sets the response to stream the file at FilePath, if available, and otherwise an HTTP 404 error respo...
static SmallVector< std::string, 0 > getHeaders()
void setDefaultDebuginfodUrls(const SmallVector< StringRef > &URLs)
Sets the list of debuginfod server URLs to query.
void consumeError(Error Err)
Consume a Error without doing anything.
LLVM_ABI Expected< FileCache > localCache(const Twine &CacheNameRef, const Twine &TempFilePrefixRef, const Twine &CacheDirectoryPathRef, AddBufferFn AddBuffer=[](size_t Task, const Twine &ModuleName, std::unique_ptr< MemoryBuffer > MB) {})
Create a local file system cache which uses the given cache name, temporary file prefix,...
bool canUseDebuginfod()
Returns false if a debuginfod lookup can be determined to have no chance of succeeding.
Expected< std::string > getDefaultDebuginfodCacheDirectory()
Finds a default local file caching directory for the debuginfod client, first checking DEBUGINFOD_CAC...
DebuginfodLogEntry()=default
This type represents a file cache system that manages caching of files.
A stateless description of an outbound HTTP request.
file_magic - An "enum class" enumeration of file types based on magic (the first N bytes of the file)...
@ elf_relocatable
ELF Relocatable object file.
@ elf_shared_object
ELF dynamically linked shared lib.
@ elf_executable
ELF Executable image.
@ elf_core
ELF core image.