57 return llvm::toHex(
ID,
true);
65 const char *DebuginfodUrlsEnv = std::getenv(
"DEBUGINFOD_URLS");
66 if (DebuginfodUrlsEnv ==
nullptr)
71 return DebuginfodUrls;
77 if (
const char *CacheDirectoryEnv = std::getenv(
"DEBUGINFOD_CACHE_PATH"))
78 return CacheDirectoryEnv;
83 errc::io_error,
"Unable to determine appropriate cache directory.");
85 return std::string(CacheDirectory);
90 const char *DebuginfodTimeoutEnv = std::getenv(
"DEBUGINFOD_TIMEOUT");
91 if (DebuginfodTimeoutEnv &&
92 to_integer(
StringRef(DebuginfodTimeoutEnv).trim(), Timeout, 10))
93 return std::chrono::milliseconds(Timeout * 1000);
95 return std::chrono::milliseconds(90 * 1000);
133 CacheDir = *CacheDirOrErr;
144class StreamedHTTPResponseHandler :
public HTTPResponseHandler {
145 using CreateStreamFn =
146 std::function<Expected<std::unique_ptr<CachedFileStream>>()>;
147 CreateStreamFn CreateStream;
149 std::unique_ptr<CachedFileStream> FileStream;
152 StreamedHTTPResponseHandler(CreateStreamFn CreateStream, HTTPClient &Client)
153 : CreateStream(CreateStream), Client(Client) {}
154 virtual ~StreamedHTTPResponseHandler() =
default;
156 Error handleBodyChunk(StringRef BodyChunk)
override;
161Error StreamedHTTPResponseHandler::handleBodyChunk(StringRef BodyChunk) {
163 unsigned Code = Client.responseCode();
164 if (Code && Code != 200)
166 Expected<std::unique_ptr<CachedFileStream>> FileStreamOrError =
168 if (!FileStreamOrError)
169 return FileStreamOrError.takeError();
170 FileStream = std::move(*FileStreamOrError);
172 *FileStream->OS << BodyChunk;
183 return all_of(
Name, [](
char C) {
return llvm::isPrint(
C) &&
C !=
' '; }) &&
184 all_of(
Value, [](
char C) {
return llvm::isPrint(
C) ||
C ==
'\t'; });
188 const char *Filename = getenv(
"DEBUGINFOD_HEADERS_FILE");
198 for (
StringRef Line : llvm::split((*HeadersFile)->getBuffer(),
'\n')) {
200 if (!Line.empty() && Line.back() ==
'\r')
201 Line = Line.drop_back();
203 if (!
all_of(Line, llvm::isSpace))
205 <<
"could not parse debuginfod header: " << Filename <<
':'
206 << LineNumber <<
'\n';
219 "llvmcache-" + UniqueKey);
222 localCache(
"Debuginfod-client",
".debuginfod-client", CacheDirectoryPath);
230 if (!CacheAddStreamOrErr)
232 AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
234 return std::string(AbsCachedArtifactPath);
239 "No working HTTP client is available.");
244 "A working HTTP client is available, but it is not initialized. To "
245 "allow Debuginfod to make HTTP requests, call HTTPClient::initialize() "
246 "at the beginning of main.");
250 for (
StringRef ServerUrl : DebuginfodUrls) {
257 StreamedHTTPResponseHandler Handler(
258 [&]() {
return CacheAddStream(Task,
""); }, Client);
263 return std::move(Err);
266 if (Code && Code != 200)
272 if (!PruningPolicyOrErr)
274 pruneCache(CacheDirectoryPath, *PruningPolicyOrErr);
277 return std::string(AbsCachedArtifactPath);
284 : Message(Message.str()) {}
292 std::lock_guard<std::mutex> Guard(QueueMutex);
293 LogEntryQueue.push(Entry);
295 QueueCondition.notify_one();
300 std::unique_lock<std::mutex> Guard(QueueMutex);
302 QueueCondition.wait(Guard, [&] {
return !LogEntryQueue.empty(); });
304 std::lock_guard<std::mutex> Guard(QueueMutex);
305 if (!LogEntryQueue.size())
316 : Log(Log), Pool(Pool), MinInterval(MinInterval) {
322 std::lock_guard<sys::Mutex> Guard(UpdateMutex);
326 for (
const std::string &Path : Paths) {
327 Log.
push(
"Updating binaries at path " + Path);
328 if (
Error Err = findBinaries(Path))
331 Log.
push(
"Updated collection");
342 if (Time < MinInterval)
345 return std::move(Err);
353 std::this_thread::sleep_for(
Interval);
375Error DebuginfodCollection::findBinaries(StringRef Path) {
377 sys::fs::recursive_directory_iterator
I(Twine(Path), EC),
E;
378 std::mutex IteratorMutex;
379 ThreadPoolTaskGroup IteratorGroup(Pool);
380 for (
unsigned WorkerIndex = 0; WorkerIndex < Pool.
getThreadCount();
382 IteratorGroup.async([&,
this]() ->
void {
383 std::string FilePath;
387 std::lock_guard<std::mutex> Guard(IteratorMutex);
392 FilePath =
I->path();
400 Expected<object::OwningBinary<object::Binary>> BinOrErr =
407 object::Binary *
Bin = std::move(BinOrErr.get().getBinary());
408 if (!
Bin->isObject())
412 object::ELFObjectFileBase *
Object =
413 dyn_cast<object::ELFObjectFileBase>(
Bin);
422 if (
Object->hasDebugInfo()) {
423 std::lock_guard<sys::RWMutex> DebugBinariesGuard(DebugBinariesMutex);
424 (void)DebugBinaries.
try_emplace(IDString, std::move(FilePath));
426 std::lock_guard<sys::RWMutex> BinariesGuard(BinariesMutex);
427 (void)Binaries.
try_emplace(IDString, std::move(FilePath));
432 IteratorGroup.wait();
433 std::unique_lock<std::mutex> Guard(IteratorMutex);
439Expected<std::optional<std::string>>
440DebuginfodCollection::getBinaryPath(BuildIDRef
ID) {
442 std::shared_lock<sys::RWMutex> Guard(BinariesMutex);
444 if (Loc != Binaries.
end()) {
445 std::string
Path = Loc->getValue();
451Expected<std::optional<std::string>>
452DebuginfodCollection::getDebugBinaryPath(BuildIDRef
ID) {
454 std::shared_lock<sys::RWMutex> Guard(DebugBinariesMutex);
456 if (Loc != DebugBinaries.
end()) {
457 std::string
Path = Loc->getValue();
469 std::optional<std::string> Path = *PathOrErr;
476 PathOrErr = getBinaryPath(
ID);
500 std::optional<std::string> Path = *PathOrErr;
507 PathOrErr = getBinaryPath(
ID);
522 : Log(Log), Collection(Collection) {
525 Log.push("GET " + Request.UrlPath);
526 std::string IDString;
527 if (!tryGetFromHex(Request.UrlPathMatches[0], IDString)) {
529 {404,
"text/plain",
"Build ID is not a hex string\n"});
534 if (
Error Err = PathOrErr.takeError()) {
535 consumeError(std::move(Err));
536 Request.setResponse({404,
"text/plain",
"Build ID not found\n"});
542 Server.get(R
"(/buildid/(.*)/executable)", [&](HTTPServerRequest Request) {
543 Log.push("GET " + Request.UrlPath);
544 std::string IDString;
545 if (!tryGetFromHex(Request.UrlPathMatches[0], IDString)) {
547 {404,
"text/plain",
"Build ID is not a hex string\n"});
550 object::BuildID ID(IDString.begin(), IDString.end());
551 Expected<std::string> PathOrErr = Collection.findBinaryPath(ID);
552 if (Error Err = PathOrErr.takeError()) {
553 consumeError(std::move(Err));
554 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 ...
Tracks a collection of debuginfod artifacts on the local filesystem.
DebuginfodCollection(ArrayRef< StringRef > Paths, DebuginfodLog &Log, ThreadPool &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.
Interval Class - An Interval is a set of nodes defined such that every node in the interval has all o...
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.
A ThreadPool for asynchronous parallel execution on a defined number of threads.
unsigned getThreadCount() const
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.
static std::string uniqueKey(llvm::StringRef S)
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.
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::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)
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.
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()
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.