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 &&
113 to_integer(
StringRef(DebuginfodTimeoutEnv).trim(), Timeout, 10))
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) {}
191 virtual ~StreamedHTTPResponseHandler() =
default;
193 Error handleBodyChunk(StringRef BodyChunk)
override;
198Error StreamedHTTPResponseHandler::handleBodyChunk(StringRef BodyChunk) {
200 unsigned Code = Client.responseCode();
201 if (Code && Code != 200)
203 Expected<std::unique_ptr<CachedFileStream>> FileStreamOrError =
205 if (!FileStreamOrError)
206 return FileStreamOrError.takeError();
207 FileStream = std::move(*FileStreamOrError);
209 *FileStream->OS << BodyChunk;
220 return all_of(
Name, [](
char C) {
return llvm::isPrint(
C) &&
C !=
' '; }) &&
221 all_of(
Value, [](
char C) {
return llvm::isPrint(
C) ||
C ==
'\t'; });
225 const char *Filename = getenv(
"DEBUGINFOD_HEADERS_FILE");
235 for (
StringRef Line : llvm::split((*HeadersFile)->getBuffer(),
'\n')) {
237 if (!Line.empty() && Line.back() ==
'\r')
238 Line = Line.drop_back();
240 if (!
all_of(Line, llvm::isSpace))
242 <<
"could not parse debuginfod header: " << Filename <<
':'
243 << LineNumber <<
'\n';
256 "llvmcache-" + UniqueKey);
259 localCache(
"Debuginfod-client",
".debuginfod-client", CacheDirectoryPath);
267 if (!CacheAddStreamOrErr)
269 AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
271 return std::string(AbsCachedArtifactPath);
276 "No working HTTP client is available.");
281 "A working HTTP client is available, but it is not initialized. To "
282 "allow Debuginfod to make HTTP requests, call HTTPClient::initialize() "
283 "at the beginning of main.");
287 for (
StringRef ServerUrl : DebuginfodUrls) {
294 StreamedHTTPResponseHandler Handler(
295 [&]() {
return CacheAddStream(Task,
""); }, Client);
300 return std::move(Err);
303 if (Code && Code != 200)
309 if (!PruningPolicyOrErr)
311 pruneCache(CacheDirectoryPath, *PruningPolicyOrErr);
314 return std::string(AbsCachedArtifactPath);
321 : Message(Message.str()) {}
329 std::lock_guard<std::mutex> Guard(QueueMutex);
330 LogEntryQueue.push(Entry);
332 QueueCondition.notify_one();
337 std::unique_lock<std::mutex> Guard(QueueMutex);
339 QueueCondition.wait(Guard, [&] {
return !LogEntryQueue.empty(); });
341 std::lock_guard<std::mutex> Guard(QueueMutex);
342 if (!LogEntryQueue.size())
354 : Log(Log), Pool(Pool), MinInterval(MinInterval) {
360 std::lock_guard<sys::Mutex> Guard(UpdateMutex);
364 for (
const std::string &Path : Paths) {
365 Log.
push(
"Updating binaries at path " + Path);
366 if (
Error Err = findBinaries(Path))
369 Log.
push(
"Updated collection");
380 if (Time < MinInterval)
383 return std::move(Err);
391 std::this_thread::sleep_for(
Interval);
413Error DebuginfodCollection::findBinaries(StringRef Path) {
415 sys::fs::recursive_directory_iterator
I(Twine(Path), EC),
E;
416 std::mutex IteratorMutex;
417 ThreadPoolTaskGroup IteratorGroup(Pool);
420 IteratorGroup.async([&,
this]() ->
void {
421 std::string FilePath;
425 std::lock_guard<std::mutex> Guard(IteratorMutex);
430 FilePath =
I->path();
438 Expected<object::OwningBinary<object::Binary>> BinOrErr =
445 object::Binary *
Bin = std::move(BinOrErr.get().getBinary());
446 if (!
Bin->isObject())
450 object::ELFObjectFileBase *
Object =
451 dyn_cast<object::ELFObjectFileBase>(
Bin);
460 if (
Object->hasDebugInfo()) {
461 std::lock_guard<sys::RWMutex> DebugBinariesGuard(DebugBinariesMutex);
462 (void)DebugBinaries.
try_emplace(IDString, std::move(FilePath));
464 std::lock_guard<sys::RWMutex> BinariesGuard(BinariesMutex);
465 (void)Binaries.
try_emplace(IDString, std::move(FilePath));
470 IteratorGroup.wait();
471 std::unique_lock<std::mutex> Guard(IteratorMutex);
477Expected<std::optional<std::string>>
478DebuginfodCollection::getBinaryPath(BuildIDRef
ID) {
480 std::shared_lock<sys::RWMutex> Guard(BinariesMutex);
482 if (Loc != Binaries.
end()) {
483 std::string
Path = Loc->getValue();
489Expected<std::optional<std::string>>
490DebuginfodCollection::getDebugBinaryPath(BuildIDRef
ID) {
492 std::shared_lock<sys::RWMutex> Guard(DebugBinariesMutex);
494 if (Loc != DebugBinaries.
end()) {
495 std::string
Path = Loc->getValue();
507 std::optional<std::string> Path = *PathOrErr;
514 PathOrErr = getBinaryPath(
ID);
538 std::optional<std::string> Path = *PathOrErr;
545 PathOrErr = getBinaryPath(
ID);
560 : Log(Log), Collection(Collection) {
563 Log.push("GET " + Request.UrlPath);
564 std::string IDString;
565 if (!tryGetFromHex(Request.UrlPathMatches[0], IDString)) {
567 {404,
"text/plain",
"Build ID is not a hex string\n"});
572 if (
Error Err = PathOrErr.takeError()) {
573 consumeError(std::move(Err));
574 Request.setResponse({404,
"text/plain",
"Build ID not found\n"});
580 Server.get(R
"(/buildid/(.*)/executable)", [&](HTTPServerRequest Request) {
581 Log.push("GET " + Request.UrlPath);
582 std::string IDString;
583 if (!tryGetFromHex(Request.UrlPathMatches[0], IDString)) {
585 {404,
"text/plain",
"Build ID is not a hex string\n"});
588 object::BuildID ID(IDString.begin(), IDString.end());
589 Expected<std::string> PathOrErr = Collection.findBinaryPath(ID);
590 if (Error Err = PathOrErr.takeError()) {
591 consumeError(std::move(Err));
592 Request.setResponse({404,
"text/plain",
"Build ID not found\n"});
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.
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.
void stopTimer()
Stop the timer.
void clear()
Clear the timer state.
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 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.
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.
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
bool cache_directory(SmallVectorImpl< char > &result)
Get the directory where installed packages should put their machine-local cache, e....
std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
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.
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.
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.
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.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Expected< std::string > getCachedOrDownloadSource(object::BuildIDRef ID, StringRef SourceFilePath)
Fetches a specified source file by searching the default local cache directory and server URLs.
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.
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.
std::function< Expected< AddStreamFn >(unsigned Task, StringRef Key, const Twine &ModuleName)> FileCache
This is the type of a file cache.
void consumeError(Error Err)
Consume a Error without doing anything.
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
DebuginfodServer(DebuginfodLog &Log, DebuginfodCollection &Collection)
DebuginfodCollection & Collection
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.