LLVM 23.0.0git
LibraryScanner.cpp
Go to the documentation of this file.
1//===- LibraryScanner.cpp - Provide Library Scanning Implementation ----===//
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
11
13#include "llvm/Object/COFF.h"
14#include "llvm/Object/ELF.h"
17#include "llvm/Object/MachO.h"
20#include "llvm/Support/Error.h"
23#include "llvm/Support/Path.h"
27
28#ifdef LLVM_ON_UNIX
29#include <sys/stat.h>
30#include <unistd.h>
31#endif // LLVM_ON_UNIX
32
33#ifdef __APPLE__
34#include <sys/stat.h>
35#undef LC_LOAD_DYLIB
36#undef LC_RPATH
37#endif // __APPLE__
38
39#define DEBUG_TYPE "orc-scanner"
40
41namespace llvm::orc {
42
43void handleError(Error Err, StringRef context = "") {
44 consumeError(handleErrors(std::move(Err), [&](const ErrorInfoBase &EIB) {
45 dbgs() << "LLVM Error";
46 if (!context.empty())
47 dbgs() << " [" << context << "]";
48 dbgs() << ": " << EIB.message() << "\n";
49 }));
50}
51
53 static const llvm::Triple HostTriple(llvm::sys::getProcessTriple());
54
55 if (HostTriple.getArch() != Obj.getArch())
56 return false;
57
58 if (Obj.getTripleObjectFormat() != HostTriple.getObjectFormat())
59 return false;
60
61 return true;
62}
63
65ObjectFileLoader::loadObjectFileWithOwnership(StringRef FilePath) {
66 LLVM_DEBUG(dbgs() << "ObjectFileLoader: Attempting to open file " << FilePath
67 << "\n";);
68 if (auto ObjOrErr = object::ObjectFile::createObjectFile(FilePath)) {
69
70 LLVM_DEBUG(dbgs() << "ObjectFileLoader: Detected object file\n";);
71
72 auto OwningBin = std::move(*ObjOrErr);
73
74 if (!isArchitectureCompatible(*OwningBin.getBinary())) {
75 LLVM_DEBUG(dbgs() << "ObjectFileLoader: Incompatible architecture: "
76 << FilePath << "\n";);
78 "Incompatible object file: %s",
79 FilePath.str().c_str());
80 }
81
82 LLVM_DEBUG(dbgs() << "ObjectFileLoader: Object file is compatible\n";);
83
84 return std::move(OwningBin);
85 } else {
86#if defined(__APPLE__)
87 consumeError(ObjOrErr.takeError());
88 auto BinOrErr = object::createBinary(FilePath);
89 if (!BinOrErr) {
90 LLVM_DEBUG(dbgs() << "ObjectFileLoader: Failed to open file " << FilePath
91 << "\n";);
92 return BinOrErr.takeError();
93 }
94
95 LLVM_DEBUG(dbgs() << "ObjectFileLoader: Successfully opened file "
96 << FilePath << "\n";);
97
98 auto OwningBin = BinOrErr->takeBinary();
99 object::Binary *Bin = OwningBin.first.get();
100
101 if (Bin->isArchive()) {
103 dbgs() << "ObjectFileLoader: File is an archive, not supported: "
104 << FilePath << "\n";);
105 return createStringError(std::errc::invalid_argument,
106 "Archive files are not supported: %s",
107 FilePath.str().c_str());
108 }
109
112 dbgs() << "ObjectFileLoader: Detected Mach-O universal binary: "
113 << FilePath << "\n";);
114 for (auto ObjForArch : UB->objects()) {
115 auto ObjOrErr = ObjForArch.getAsObjectFile();
116 if (!ObjOrErr) {
117 LLVM_DEBUG(dbgs() << "ObjectFileLoader: Skipping invalid "
118 "architecture slice\n";);
119
120 consumeError(ObjOrErr.takeError());
121 continue;
122 }
123
124 std::unique_ptr<object::ObjectFile> Obj = std::move(ObjOrErr.get());
125 if (isArchitectureCompatible(*Obj)) {
127 dbgs() << "ObjectFileLoader: Found compatible object slice\n";);
128
129 return object::OwningBinary<object::ObjectFile>(
130 std::move(Obj), std::move(OwningBin.second));
131
132 } else {
133 LLVM_DEBUG(dbgs() << "ObjectFileLoader: Incompatible architecture "
134 "slice skipped\n";);
135 }
136 }
137 LLVM_DEBUG(dbgs() << "ObjectFileLoader: No compatible slices found in "
138 "universal binary\n";);
140 "No compatible object found in fat binary: %s",
141 FilePath.str().c_str());
142 }
143 return ObjOrErr.takeError();
144#else
145 LLVM_DEBUG(dbgs() << "ObjectFileLoader: Failed to open file " << FilePath
146 << "\n";);
147 return ObjOrErr.takeError();
148#endif
149 }
150
152 "Not a compatible object file : %s",
153 FilePath.str().c_str());
154}
155
156template <class ELFT>
158 if (ELFObj.getHeader().e_type != ELF::ET_DYN)
159 return false;
160
161 auto PHOrErr = ELFObj.program_headers();
162 if (!PHOrErr) {
163 consumeError(PHOrErr.takeError());
164 return true;
165 }
166
167 for (auto Phdr : *PHOrErr) {
168 if (Phdr.p_type == ELF::PT_INTERP)
169 return false;
170 }
171
172 return true;
173}
174
176 if (Obj.isELF()) {
177 if (auto *ELF32LE = dyn_cast<object::ELF32LEObjectFile>(&Obj))
178 return isELFSharedLibrary(ELF32LE->getELFFile());
179 if (auto *ELF64LE = dyn_cast<object::ELF64LEObjectFile>(&Obj))
180 return isELFSharedLibrary(ELF64LE->getELFFile());
181 if (auto *ELF32BE = dyn_cast<object::ELF32BEObjectFile>(&Obj))
182 return isELFSharedLibrary(ELF32BE->getELFFile());
183 if (auto *ELF64BE = dyn_cast<object::ELF64BEObjectFile>(&Obj))
184 return isELFSharedLibrary(ELF64BE->getELFFile());
185 } else if (Obj.isMachO()) {
188 if (!MachO) {
189 LLVM_DEBUG(dbgs() << "Failed to cast to MachOObjectFile.\n";);
190 return false;
191 }
192 LLVM_DEBUG({
193 bool Result =
194 MachO->getHeader().filetype == MachO::HeaderFileType::MH_DYLIB;
195 dbgs() << "Mach-O filetype: " << MachO->getHeader().filetype
196 << " (MH_DYLIB == " << MachO::HeaderFileType::MH_DYLIB
197 << "), shared: " << Result << "\n";
198 });
199
200 return MachO->getHeader().filetype == MachO::HeaderFileType::MH_DYLIB;
201 } else if (Obj.isCOFF()) {
203 if (!coff)
204 return false;
206 } else {
207 LLVM_DEBUG(dbgs() << "Binary is not an ObjectFile.\n";);
208 }
209
210 return false;
211}
212
214 LLVM_DEBUG(dbgs() << "Checking if path is a shared library: " << Path
215 << "\n";);
216
217 auto FileType = sys::fs::get_file_type(Path, /*Follow*/ true);
218 if (FileType != sys::fs::file_type::regular_file) {
219 LLVM_DEBUG(dbgs() << "File type is not a regular file for path: " << Path
220 << "\n";);
221 return false;
222 }
223
224 file_magic MagicCode;
225 identify_magic(Path, MagicCode);
226
227 // Skip archives.
228 if (MagicCode == file_magic::archive)
229 return false;
230
231 // Object file inspection for PE/COFF, ELF, and Mach-O
232 bool NeedsObjectInspection =
233#if defined(_WIN32)
234 (MagicCode == file_magic::pecoff_executable);
235#elif defined(__APPLE__)
240#elif defined(LLVM_ON_UNIX)
241#ifdef __CYGWIN__
242 (MagicCode == file_magic::pecoff_executable);
243#else
244 (MagicCode == file_magic::elf_shared_object);
245#endif
246#else
247#error "Unsupported platform."
248#endif
249
250 if (!NeedsObjectInspection) {
251 LLVM_DEBUG(dbgs() << "Path is not identified as a shared library: " << Path
252 << "\n";);
253 return false;
254 }
255
256 ObjectFileLoader ObjLoader(Path);
257 auto ObjOrErr = ObjLoader.getObjectFile();
258 if (!ObjOrErr) {
259 consumeError(ObjOrErr.takeError());
260 return false;
261 }
262
263 bool IsShared = isSharedLibraryObject(ObjOrErr.get());
264
265 if (IsShared && ObjCache)
266 ObjCache->insert(Path, std::move(ObjLoader));
267
268 return IsShared;
269}
270
272 SmallString<512> ExecPath(sys::fs::getMainExecutable(nullptr, nullptr));
274
275 SmallString<512> LoaderDir;
276 if (LoaderPath.empty()) {
277 LoaderDir = std::move(ExecPath);
278 } else {
279 LoaderDir = LoaderPath.str();
280 if (!sys::fs::is_directory(LoaderPath))
282 }
283
284#ifdef __APPLE__
285 Placeholders.push_back({"@loader_path", std::string(LoaderDir)});
286 Placeholders.push_back({"@executable_path", std::string(ExecPath)});
287#else
288 Placeholders.push_back({"$origin", std::string(LoaderDir)});
289#endif
290}
291
292std::optional<std::string>
294 DylibPathValidator &Validator) const {
295 for (const auto &SP : Paths) {
296 std::string Base = Subst.substitute(SP);
297
298 SmallString<512> FullPath(Base);
299 if (!PlaceholderPrefix.empty() &&
300 Stem.starts_with_insensitive(PlaceholderPrefix))
301 FullPath.append(Stem.drop_front(PlaceholderPrefix.size()));
302 else
303 sys::path::append(FullPath, Stem);
304
305 LLVM_DEBUG(dbgs() << "SearchPathResolver::resolve FullPath = " << FullPath
306 << "\n";);
307
308 if (auto Valid = Validator.validate(FullPath.str()))
309 return Valid;
310 }
311
312 return std::nullopt;
313}
314
315std::optional<std::string>
316DylibResolverImpl::tryWithExtensions(StringRef LibStem) const {
317 LLVM_DEBUG(dbgs() << "tryWithExtensions: baseName = " << LibStem << "\n";);
318 SmallVector<SmallString<256>, 8> Candidates;
319
320 // Add extensions by platform
321#if defined(__APPLE__)
322 Candidates.emplace_back(LibStem);
323 Candidates.back() += ".dylib";
324#elif defined(_WIN32)
325 Candidates.emplace_back(LibStem);
326 Candidates.back() += ".dll";
327#else
328 Candidates.emplace_back(LibStem);
329 Candidates.back() += ".so";
330#endif
331
332 // Optionally try "lib" prefix if not already there
333 StringRef FileName = sys::path::filename(LibStem);
335 if (!FileName.starts_with("lib")) {
336 SmallString<256> WithPrefix(Base);
337 if (!WithPrefix.empty())
338 sys::path::append(WithPrefix, ""); // ensure separator if needed
339 WithPrefix += "lib";
340 WithPrefix += FileName;
341
342#if defined(__APPLE__)
343 WithPrefix += ".dylib";
344#elif defined(_WIN32)
345 WithPrefix += ".dll";
346#else
347 WithPrefix += ".so";
348#endif
349
350 Candidates.push_back(std::move(WithPrefix));
351 }
352
353 LLVM_DEBUG({
354 dbgs() << " Candidates to try:\n";
355 for (const auto &C : Candidates)
356 dbgs() << " " << C << "\n";
357 });
358
359 // Try all variants using tryAllPaths
360 for (const auto &Name : Candidates) {
361
362 LLVM_DEBUG(dbgs() << " Trying candidate: " << Name << "\n";);
363
364 for (const auto &R : Resolvers) {
365 if (auto Res = R.resolve(Name, Substitutor, Validator))
366 return Res;
367 }
368 }
369
370 LLVM_DEBUG(dbgs() << " -> No candidate Resolved.\n";);
371
372 return std::nullopt;
373}
374
375std::optional<std::string>
376DylibResolverImpl::resolve(StringRef LibStem, bool VariateLibStem) const {
377 LLVM_DEBUG(dbgs() << "Resolving library stem: " << LibStem << "\n";);
378
379 // If it is an absolute path, don't try iterate over the paths.
380 if (sys::path::is_absolute(LibStem)) {
381 LLVM_DEBUG(dbgs() << " -> Absolute path detected.\n";);
382 return Validator.validate(LibStem);
383 }
384
385 if (!LibStem.starts_with_insensitive("@rpath")) {
386 if (auto norm = Validator.validate(Substitutor.substitute(LibStem))) {
387 LLVM_DEBUG(dbgs() << " -> Resolved after substitution: " << *norm
388 << "\n";);
389
390 return norm;
391 }
392 }
393
394 for (const auto &R : Resolvers) {
395 LLVM_DEBUG(dbgs() << " -> Resolving via search path ... \n";);
396 if (auto Result = R.resolve(LibStem, Substitutor, Validator)) {
397 LLVM_DEBUG(dbgs() << " -> Resolved via search path: " << *Result
398 << "\n";);
399
400 return Result;
401 }
402 }
403
404 // Expand libStem with paths, extensions, etc.
405 // std::string foundName;
406 if (VariateLibStem) {
407 LLVM_DEBUG(dbgs() << " -> Trying with extensions...\n";);
408
409 if (auto Norm = tryWithExtensions(LibStem)) {
410 LLVM_DEBUG(dbgs() << " -> Resolved via tryWithExtensions: " << *Norm
411 << "\n";);
412 return Norm;
413 }
414 }
415
416 LLVM_DEBUG(dbgs() << " -> Could not resolve: " << LibStem << "\n";);
417
418 return std::nullopt;
419}
420
421#ifndef _WIN32
423 // If already cached - retun cached result
424 if (auto Cache = LibPathCache->read_lstat(Path))
425 return *Cache;
426
427 // Not cached: perform lstat and store
428 struct stat buf{};
429 mode_t st_mode = (lstat(Path.str().c_str(), &buf) == -1) ? 0 : buf.st_mode;
430
431 LibPathCache->insert_lstat(Path, st_mode);
432
433 return st_mode;
434}
435
436std::optional<std::string> PathResolver::readlinkCached(StringRef Path) {
437 // If already cached - retun cached result
438 if (auto Cache = LibPathCache->read_link(Path))
439 return Cache;
440
441 // If result not in cache - call system function and cache result
443 if (!sys::fs::readlink(Path, Buf)) {
444 std::string s(Buf.str());
445 LibPathCache->insert_link(Path, s);
446 return s;
447 }
448 return std::nullopt;
449}
450
451void createComponent(StringRef Path, StringRef BasePath, bool BaseIsResolved,
452 SmallVector<StringRef, 16> &Component) {
454 if (!BaseIsResolved) {
455 if (Path[0] == '~' &&
456 (Path.size() == 1 || sys::path::is_separator(Path[1]))) {
457 static SmallString<128> HomeP;
458 if (HomeP.str().empty())
460 StringRef(HomeP).split(Component, Separator, /*MaxSplit*/ -1,
461 /*KeepEmpty*/ false);
462 } else if (BasePath.empty()) {
463 static SmallString<256> CurrentPath;
464 if (CurrentPath.str().empty())
465 sys::fs::current_path(CurrentPath);
466 StringRef(CurrentPath)
467 .split(Component, Separator, /*MaxSplit*/ -1, /*KeepEmpty*/ false);
468 } else {
469 BasePath.split(Component, Separator, /*MaxSplit*/ -1,
470 /*KeepEmpty*/ false);
471 }
472 }
473
474 Path.split(Component, Separator, /*MaxSplit*/ -1, /*KeepEmpty*/ false);
475}
476
478 SmallVector<StringRef, 16> NormalizedPath;
479 for (auto &Part : PathParts) {
480 if (Part == ".") {
481 continue;
482 } else if (Part == "..") {
483 if (!NormalizedPath.empty() && NormalizedPath.back() != "..") {
484 NormalizedPath.pop_back();
485 } else {
486 NormalizedPath.push_back("..");
487 }
488 } else {
489 NormalizedPath.push_back(Part);
490 }
491 }
492 PathParts.swap(NormalizedPath);
493}
494#endif
495
496std::optional<std::string> PathResolver::realpathCached(StringRef Path,
497 std::error_code &EC,
499 bool BaseIsResolved,
500 long SymLoopLevel) {
501 EC.clear();
502
503 if (Path.empty()) {
504 EC = std::make_error_code(std::errc::no_such_file_or_directory);
505 LLVM_DEBUG(dbgs() << "PathResolver::realpathCached: Empty path\n";);
506
507 return std::nullopt;
508 }
509
510 if (SymLoopLevel <= 0) {
511 EC = std::make_error_code(std::errc::too_many_symbolic_link_levels);
513 dbgs() << "PathResolver::realpathCached: Too many Symlink levels: "
514 << Path << "\n";);
515
516 return std::nullopt;
517 }
518
519 // If already cached - retun cached result
520 bool isRelative = sys::path::is_relative(Path);
521 if (!isRelative) {
522 if (auto Cached = LibPathCache->read_realpath(Path)) {
523 EC = Cached->ErrnoCode;
524 if (EC) {
525 LLVM_DEBUG(dbgs() << "PathResolver::realpathCached: Cached (error) for "
526 << Path << "\n";);
527 } else {
529 dbgs() << "PathResolver::realpathCached: Cached (success) for "
530 << Path << " => " << Cached->canonicalPath << "\n";);
531 }
532 return Cached->canonicalPath.empty()
533 ? std::nullopt
534 : std::make_optional(Cached->canonicalPath);
535 }
536 }
537
538 LLVM_DEBUG(dbgs() << "PathResolver::realpathCached: Resolving path: " << Path
539 << "\n";);
540
541 // If result not in cache - call system function and cache result
542
544 SmallString<256> Resolved(Separator);
545#ifndef _WIN32
547
548 if (isRelative) {
549 if (BaseIsResolved) {
550 Resolved.assign(Base);
551 LLVM_DEBUG(dbgs() << " Using Resolved base: " << Base << "\n";);
552 }
553 createComponent(Path, Base, BaseIsResolved, Components);
554 } else {
555 Path.split(Components, Separator, /*MaxSplit*/ -1, /*KeepEmpty*/ false);
556 }
557
558 normalizePathSegments(Components);
559 LLVM_DEBUG({
560 for (auto &C : Components)
561 dbgs() << " " << C << " ";
562
563 dbgs() << "\n";
564 });
565
566 // Handle path list items
567 for (const auto &Component : Components) {
568 if (Component == ".")
569 continue;
570 if (Component == "..") {
571 // collapse "a/b/../c" to "a/c"
572 size_t S = Resolved.rfind(Separator);
573 if (S != llvm::StringRef::npos)
574 Resolved.resize(S);
575 if (Resolved.empty())
576 Resolved = Separator;
577 continue;
578 }
579
580 size_t oldSize = Resolved.size();
581 sys::path::append(Resolved, Component);
582 const char *ResolvedPath = Resolved.c_str();
583 LLVM_DEBUG(dbgs() << " Processing Component: " << Component << " => "
584 << ResolvedPath << "\n";);
585 mode_t st_mode = lstatCached(ResolvedPath);
586
587 if (S_ISLNK(st_mode)) {
588 LLVM_DEBUG(dbgs() << " Found symlink: " << ResolvedPath << "\n";);
589
590 auto SymlinkOpt = readlinkCached(ResolvedPath);
591 if (!SymlinkOpt) {
592 EC = std::make_error_code(std::errc::no_such_file_or_directory);
593 LibPathCache->insert_realpath(Path, LibraryPathCache::PathInfo{"", EC});
594 LLVM_DEBUG(dbgs() << " Failed to read symlink: " << ResolvedPath
595 << "\n";);
596
597 return std::nullopt;
598 }
599
600 StringRef Symlink = *SymlinkOpt;
601 LLVM_DEBUG(dbgs() << " Symlink points to: " << Symlink << "\n";);
602
603 std::string resolvedBase = "";
604 if (sys::path::is_relative(Symlink)) {
605 Resolved.resize(oldSize);
606 resolvedBase = Resolved.str().str();
607 }
608
609 auto RealSymlink =
610 realpathCached(Symlink, EC, resolvedBase,
611 /*BaseIsResolved=*/true, SymLoopLevel - 1);
612 if (!RealSymlink) {
613 LibPathCache->insert_realpath(Path, LibraryPathCache::PathInfo{"", EC});
614 LLVM_DEBUG(dbgs() << " Failed to resolve symlink target: " << Symlink
615 << "\n";);
616
617 return std::nullopt;
618 }
619
620 Resolved.assign(*RealSymlink);
621 LLVM_DEBUG(dbgs() << " Symlink Resolved to: " << Resolved << "\n";);
622
623 } else if (st_mode == 0) {
624 EC = std::make_error_code(std::errc::no_such_file_or_directory);
625 LibPathCache->insert_realpath(Path, LibraryPathCache::PathInfo{"", EC});
626 LLVM_DEBUG(dbgs() << " Component does not exist: " << ResolvedPath
627 << "\n";);
628
629 return std::nullopt;
630 }
631 }
632#else
633 EC = sys::fs::real_path(Path, Resolved); // Windows fallback
634#endif
635
636 std::string Canonical = Resolved.str().str();
637 {
638 LibPathCache->insert_realpath(Path, LibraryPathCache::PathInfo{
639 Canonical,
640 std::error_code() // success
641 });
642 }
643 LLVM_DEBUG(dbgs() << "PathResolver::realpathCached: Final Resolved: " << Path
644 << " => " << Canonical << "\n";);
645 return Canonical;
646}
647
648void LibraryScanHelper::addBasePath(const std::string &Path, PathType K) {
649 std::error_code EC;
650 std::string Canon = resolveCanonical(Path, EC);
651 if (EC) {
653 dbgs()
654 << "LibraryScanHelper::addBasePath: Failed to canonicalize path: "
655 << Path << "\n";);
656 return;
657 }
658 std::unique_lock<std::shared_mutex> Lock(Mtx);
659 if (LibSearchPaths.count(Canon)) {
660 LLVM_DEBUG(dbgs() << "LibraryScanHelper::addBasePath: Already added: "
661 << Canon << "\n";);
662 return;
663 }
664 K = K == PathType::Unknown ? classifyKind(Canon) : K;
665 LibSearchPaths[Canon] = std::make_unique<LibrarySearchPath>(Canon, K);
666 auto &SP = LibSearchPaths[Canon];
667
668 if (K == PathType::User) {
669 LLVM_DEBUG(dbgs() << "LibraryScanHelper::addBasePath: Added User path: "
670 << Canon << "\n";);
671 UnscannedUsr.push_back(StringRef(SP->BasePath));
672 } else {
673 LLVM_DEBUG(dbgs() << "LibraryScanHelper::addBasePath: Added System path: "
674 << Canon << "\n";);
675 UnscannedSys.push_back(StringRef(SP->BasePath));
676 }
677}
678
680 PathType K, size_t BatchSize,
682 auto &Queue = (K == PathType::User) ? UnscannedUsr : UnscannedSys;
683
684 std::unique_lock<std::shared_mutex> Lock(Mtx);
685
686 while (!Queue.empty() && (BatchSize == 0 || Result.size() < BatchSize)) {
687 StringRef Base = Queue.front();
688 auto It = LibSearchPaths.find(Base);
689 if (It != LibSearchPaths.end()) {
690 auto &SP = It->second;
692 if (SP->State.compare_exchange_strong(Expected, ScanState::Scanning)) {
693 Result.push_back(SP.get());
694 }
695 }
696 Queue.pop_front();
697 }
698}
699
701 std::error_code EC;
702 std::string Canon = resolveCanonical(Path, EC);
703 if (EC)
704 return false;
705
706 std::shared_lock<std::shared_mutex> Lock(Mtx);
707 return LibSearchPaths.count(Canon) > 0;
708}
709
711 std::shared_lock<std::shared_mutex> Lock(Mtx);
712 for (const auto &KV : LibSearchPaths) {
713 const auto &SP = KV.second;
714 if (SP->Kind == K && SP->State == ScanState::NotScanned)
715 return true;
716 }
717 return false;
718}
719
721 std::shared_lock<std::shared_mutex> Lock(Mtx);
722
723 for (auto &[_, SP] : LibSearchPaths) {
725
726 if (!SP->State.compare_exchange_strong(Expected, ScanState::NotScanned))
727 continue;
728
729 auto &TargetList =
730 (SP->Kind == PathType::User) ? UnscannedUsr : UnscannedSys;
731 TargetList.emplace_back(SP->BasePath);
732 }
733}
734
735std::string LibraryScanHelper::resolveCanonical(StringRef Path,
736 std::error_code &EC) const {
737 auto Canon = LibPathResolver->resolve(Path, EC);
738 return EC ? Path.str() : *Canon;
739}
740
741PathType LibraryScanHelper::classifyKind(StringRef Path) const {
742 // Detect home directory
743 const char *Home = getenv("HOME");
744 if (Home && Path.starts_with(Home))
745 return PathType::User;
746
747 static const std::array<std::string, 5> UserPrefixes = {
748 "/usr/local", // often used by users for manual installs
749 "/opt/homebrew", // common on macOS
750 "/opt/local", // MacPorts
751 "/home", // Linux home dirs
752 "/Users", // macOS user dirs
753 };
754
755 for (const auto &Prefix : UserPrefixes) {
756 if (Path.starts_with(Prefix))
757 return PathType::User;
758 }
759
760 return PathType::System;
761}
762
764 LibraryDepsInfo Libdeps;
765 LLVM_DEBUG(dbgs() << "Parsing Mach-O dependencies...\n";);
766 for (const auto &Command : Obj.load_commands()) {
767 switch (Command.C.cmd) {
768 case MachO::LC_LOAD_DYLIB: {
769 MachO::dylib_command dylibCmd = Obj.getDylibIDLoadCommand(Command);
770 const char *name = Command.Ptr + dylibCmd.dylib.name;
771 Libdeps.addDep(name);
772 LLVM_DEBUG(dbgs() << " Found LC_LOAD_DYLIB: " << name << "\n";);
773 } break;
774 case MachO::LC_LOAD_WEAK_DYLIB:
775 case MachO::LC_REEXPORT_DYLIB:
776 case MachO::LC_LOAD_UPWARD_DYLIB:
777 case MachO::LC_LAZY_LOAD_DYLIB:
778 break;
779 case MachO::LC_RPATH: {
780 // Extract RPATH
781 MachO::rpath_command rpathCmd = Obj.getRpathCommand(Command);
782 const char *rpath = Command.Ptr + rpathCmd.path;
783 LLVM_DEBUG(dbgs() << " Found LC_RPATH: " << rpath << "\n";);
784
786 SplitString(StringRef(rpath), RawPaths,
787 sys::EnvPathSeparator == ':' ? ":" : ";");
788
789 for (const auto &raw : RawPaths) {
790 Libdeps.addRPath(raw.str()); // Convert to std::string
791 LLVM_DEBUG(dbgs() << " Parsed RPATH entry: " << raw << "\n";);
792 }
793 break;
794 }
795 }
796 }
797
798 return Expected<LibraryDepsInfo>(std::move(Libdeps));
799}
800
801template <class ELFT>
803 auto DynamicEntriesOrError = Elf.dynamicEntries();
804 if (!DynamicEntriesOrError)
805 return DynamicEntriesOrError.takeError();
806
807 for (const typename ELFT::Dyn &Dyn : *DynamicEntriesOrError) {
808 if (Dyn.d_tag == ELF::DT_STRTAB) {
809 auto MappedAddrOrError = Elf.toMappedAddr(Dyn.getPtr());
810 if (!MappedAddrOrError)
811 return MappedAddrOrError.takeError();
812 return StringRef(reinterpret_cast<const char *>(*MappedAddrOrError));
813 }
814 }
815
816 // If the dynamic segment is not present, we fall back on the sections.
817 auto SectionsOrError = Elf.sections();
818 if (!SectionsOrError)
819 return SectionsOrError.takeError();
820
821 for (const typename ELFT::Shdr &Sec : *SectionsOrError) {
822 if (Sec.sh_type == ELF::SHT_DYNSYM)
823 return Elf.getStringTableForSymtab(Sec);
824 }
825
826 return make_error<StringError>("dynamic string table not found",
828}
829
830template <typename ELFT>
832 LibraryDepsInfo Deps;
833 Expected<StringRef> StrTabOrErr = getDynamicStrTab(Elf);
834 if (!StrTabOrErr)
835 return StrTabOrErr.takeError();
836
837 const char *Data = StrTabOrErr->data();
838
839 auto DynamicEntriesOrError = Elf.dynamicEntries();
840 if (!DynamicEntriesOrError) {
841 return DynamicEntriesOrError.takeError();
842 }
843
844 for (const typename ELFT::Dyn &Dyn : *DynamicEntriesOrError) {
845 switch (Dyn.d_tag) {
846 case ELF::DT_NEEDED:
847 Deps.addDep(Data + Dyn.d_un.d_val);
848 break;
849 case ELF::DT_RPATH: {
851 SplitString(Data + Dyn.d_un.d_val, RawPaths,
852 sys::EnvPathSeparator == ':' ? ":" : ";");
853 for (const auto &raw : RawPaths)
854 Deps.addRPath(raw.str());
855 break;
856 }
857 case ELF::DT_RUNPATH: {
859 SplitString(Data + Dyn.d_un.d_val, RawPaths,
860 sys::EnvPathSeparator == ':' ? ":" : ";");
861 for (const auto &raw : RawPaths)
862 Deps.addRunPath(raw.str());
863 break;
864 }
865 case ELF::DT_FLAGS_1:
866 // Check if this is not a pie executable.
867 if (Dyn.d_un.d_val & ELF::DF_1_PIE)
868 Deps.isPIE = true;
869 break;
870 // (Dyn.d_tag == ELF::DT_NULL) continue;
871 // (Dyn.d_tag == ELF::DT_AUXILIARY || Dyn.d_tag == ELF::DT_FILTER)
872 default:
873 break;
874 }
875 }
876
877 return Expected<LibraryDepsInfo>(std::move(Deps));
878}
879
881 using namespace object;
882 LLVM_DEBUG(dbgs() << "parseELFDeps: Detected ELF object\n";);
883 if (const auto *ELF = dyn_cast<ELF32LEObjectFile>(&Obj))
884 return parseELF(ELF->getELFFile());
885 else if (const auto *ELF = dyn_cast<ELF32BEObjectFile>(&Obj))
886 return parseELF(ELF->getELFFile());
887 else if (const auto *ELF = dyn_cast<ELF64LEObjectFile>(&Obj))
888 return parseELF(ELF->getELFFile());
889 else if (const auto *ELF = dyn_cast<ELF64BEObjectFile>(&Obj))
890 return parseELF(ELF->getELFFile());
891
892 LLVM_DEBUG(dbgs() << "parseELFDeps: Unknown ELF format\n";);
893 return createStringError(std::errc::not_supported, "Unknown ELF format");
894}
895
897 object::ObjectFile *Obj) {
898
899 if (auto *elfObj = dyn_cast<object::ELFObjectFileBase>(Obj)) {
900 LLVM_DEBUG(dbgs() << "extractDeps: File " << FilePath
901 << " is an ELF object\n";);
902
903 return parseELFDeps(*elfObj);
904 }
905
906 if (auto *macho = dyn_cast<object::MachOObjectFile>(Obj)) {
907 LLVM_DEBUG(dbgs() << "extractDeps: File " << FilePath
908 << " is a Mach-O object\n";);
909 return parseMachODeps(*macho);
910 }
911
912 if (Obj->isCOFF()) {
913 // TODO: COFF support
914 return LibraryDepsInfo();
915 }
916
917 LLVM_DEBUG(dbgs() << "extractDeps: Unsupported binary format for file "
918 << FilePath << "\n";);
920 "Unsupported binary format: %s",
921 FilePath.str().c_str());
922}
923
924Expected<LibraryDepsInfo> LibraryScanner::extractDeps(StringRef FilePath) {
925 LLVM_DEBUG(dbgs() << "extractDeps: Attempting to open file " << FilePath
926 << "\n";);
927 // check cache first
928 if (auto Cached = ObjCache.take(FilePath)) {
929 auto ObjOrErr = Cached->getObjectFile();
930 if (!ObjOrErr)
931 return ObjOrErr.takeError();
932 return parseDependencies(FilePath, &*ObjOrErr);
933 }
934
935 // fall back to normal loading
936 ObjectFileLoader ObjLoader(FilePath);
937 auto ObjOrErr = ObjLoader.getObjectFile();
938 if (!ObjOrErr) {
939 LLVM_DEBUG(dbgs() << "extractDeps: Failed to open " << FilePath << "\n";);
940 return ObjOrErr.takeError();
941 }
942
943 return parseDependencies(FilePath, &*ObjOrErr);
944}
945
946bool LibraryScanner::shouldScan(StringRef FilePath, bool IsResolvingDep) {
947 LLVM_DEBUG(dbgs() << "[shouldScan] Checking: " << FilePath << "\n";);
948
949 LibraryPathCache &Cache = ScanHelper.getCache();
950 // [1] Skip if we've already seen this path (via cache)
951 if (Cache.hasSeen(FilePath)) {
952 LLVM_DEBUG(dbgs() << " -> Skipped: already seen.\n";);
953 return false;
954 }
955
956 // [2] Already tracked in LibraryManager?
957 /*if (LibMgr.hasLibrary(FilePath)) {
958 LLVM_DEBUG(dbgs() << " -> Skipped: already tracked by LibraryManager.\n";);
959 return false;
960 }*/
961
962 // [3] Skip if it's not a shared library.
963 if (!IsResolvingDep && !Validator.isSharedLibrary(FilePath)) {
964 LLVM_DEBUG(dbgs() << " -> Skipped: not a shared library.\n";);
965 return false;
966 }
967
968 // Mark seen this path
969 Cache.markSeen(FilePath.str());
970
971 // [4] Run user-defined hook (default: always true)
972 if (!ShouldScanCall(FilePath)) {
973 LLVM_DEBUG(dbgs() << " -> Skipped: user-defined hook rejected.\n";);
974 return false;
975 }
976
977 LLVM_DEBUG(dbgs() << " -> Accepted: ready to scan " << FilePath << "\n";);
978 return true;
979}
980
981void LibraryScanner::handleLibrary(StringRef FilePath, PathType K, int level) {
982 LLVM_DEBUG(dbgs() << "LibraryScanner::handleLibrary: Scanning: " << FilePath
983 << ", level=" << level << "\n";);
984 if (!shouldScan(FilePath, level > 0)) {
985 LLVM_DEBUG(dbgs() << " Skipped (shouldScan returned false): " << FilePath
986 << "\n";);
987 return;
988 }
989
990 auto DepsOrErr = extractDeps(FilePath);
991 if (!DepsOrErr) {
992 LLVM_DEBUG(dbgs() << " Failed to extract deps for: " << FilePath << "\n";);
993 handleError(DepsOrErr.takeError());
994 return;
995 }
996
997 LibraryDepsInfo &Deps = *DepsOrErr;
998
999 LLVM_DEBUG({
1000 dbgs() << " Found deps : \n";
1001 for (const auto &dep : Deps.deps)
1002 dbgs() << " : " << dep << "\n";
1003 dbgs() << " Found @rpath : " << Deps.rpath.size() << "\n";
1004 for (const auto &r : Deps.rpath)
1005 dbgs() << " : " << r << "\n";
1006 dbgs() << " Found @runpath : \n";
1007 for (const auto &r : Deps.runPath)
1008 dbgs() << " : " << r << "\n";
1009 });
1010
1011 if (Deps.isPIE && level == 0) {
1012 LLVM_DEBUG(dbgs() << " Skipped PIE executable at top level: " << FilePath
1013 << "\n";);
1014
1015 return;
1016 }
1017
1018 bool Added = LibMgr.addLibrary(FilePath.str(), K);
1019 if (!Added) {
1020 LLVM_DEBUG(dbgs() << " Already added: " << FilePath << "\n";);
1021 return;
1022 }
1023
1024 // Heuristic 1: No RPATH/RUNPATH, skip deps
1025 if (Deps.rpath.empty() && Deps.runPath.empty()) {
1026 LLVM_DEBUG(
1027 dbgs() << "LibraryScanner::handleLibrary: Skipping deps (Heuristic1): "
1028 << FilePath << "\n";);
1029 return;
1030 }
1031
1032 // Heuristic 2: All RPATH and RUNPATH already tracked
1033 auto allTracked = [&](const auto &Paths) {
1034 LLVM_DEBUG(dbgs() << " Checking : " << Paths.size() << "\n";);
1035 return std::all_of(Paths.begin(), Paths.end(), [&](StringRef P) {
1036 LLVM_DEBUG(dbgs() << " Checking isTrackedBasePath : " << P << "\n";);
1037 return ScanHelper.isTrackedBasePath(
1038 DylibResolver::resolvelinkerFlag(P, FilePath));
1039 });
1040 };
1041
1042 if (allTracked(Deps.rpath) && allTracked(Deps.runPath)) {
1043 LLVM_DEBUG(
1044 dbgs() << "LibraryScanner::handleLibrary: Skipping deps (Heuristic2): "
1045 << FilePath << "\n";);
1046 return;
1047 }
1048
1049 DylibResolver Resolver(Validator);
1050 Resolver.configure(FilePath,
1051 {{Deps.rpath, SearchPathType::RPath},
1052 {ScanHelper.getSearchPaths(), SearchPathType::UsrOrSys},
1053 {Deps.runPath, SearchPathType::RunPath}});
1054 for (StringRef Dep : Deps.deps) {
1055 LLVM_DEBUG(dbgs() << " Resolving dep: " << Dep << "\n";);
1056 auto DepFullOpt = Resolver.resolve(Dep);
1057 if (!DepFullOpt) {
1058 LLVM_DEBUG(dbgs() << " Failed to resolve dep: " << Dep << "\n";);
1059 continue;
1060 }
1061 LLVM_DEBUG(dbgs() << " Resolved dep to: " << *DepFullOpt << "\n";);
1062
1063 handleLibrary(*DepFullOpt, K, level + 1);
1064 }
1065}
1066
1067void LibraryScanner::scanBaseDir(LibrarySearchPath *SP) {
1068 if (!sys::fs::is_directory(SP->BasePath) || SP->BasePath.empty()) {
1069 LLVM_DEBUG(
1070 dbgs() << "LibraryScanner::scanBaseDir: Invalid or empty basePath: "
1071 << SP->BasePath << "\n";);
1072 return;
1073 }
1074
1075 LLVM_DEBUG(dbgs() << "LibraryScanner::scanBaseDir: Scanning directory: "
1076 << SP->BasePath << "\n";);
1077 std::error_code EC;
1078
1079 SP->State.store(ScanState::Scanning);
1080
1081 for (sys::fs::directory_iterator It(SP->BasePath, EC), end; It != end && !EC;
1082 It.increment(EC)) {
1083 auto Entry = *It;
1084 if (!Entry.status())
1085 continue;
1086
1087 auto Status = *Entry.status();
1088 if (sys::fs::is_regular_file(Status) || sys::fs::is_symlink_file(Status)) {
1089 LLVM_DEBUG(dbgs() << " Found file: " << Entry.path() << "\n";);
1090
1091 std::string FinalPath;
1092 bool IsSymlink = sys::fs::is_symlink_file(Status);
1093
1094 // Resolve symlink
1095 if (IsSymlink) {
1096 LLVM_DEBUG(dbgs() << " Symlink → resolving...\n");
1097
1098 auto CanonicalOpt = ScanHelper.resolve(Entry.path(), EC);
1099 if (EC || !CanonicalOpt) {
1100 LLVM_DEBUG(dbgs() << " -> Skipped: resolve failed (EC="
1101 << EC.message() << ")\n");
1102 continue;
1103 }
1104
1105 FinalPath = std::move(*CanonicalOpt);
1106
1107 LLVM_DEBUG(dbgs() << " Canonical: " << FinalPath << "\n");
1108
1109 } else {
1110 // make absolute
1111 SmallString<256> Abs(Entry.path());
1113 FinalPath = Abs.str().str();
1114
1115 LLVM_DEBUG(dbgs() << " Regular: absolute = " << FinalPath << "\n");
1116 }
1117
1118 // Check if it's a directory — skip directories
1119 if (sys::fs::is_directory(Status)) {
1120 LLVM_DEBUG(dbgs() << " -> Skipped: path is a directory.\n";);
1121 continue;
1122 }
1123
1124 // async support ?
1125 handleLibrary(FinalPath, SP->Kind);
1126 }
1127 }
1128
1129 SP->State.store(ScanState::Scanned);
1130}
1131
1132void LibraryScanner::scanNext(PathType K, size_t BatchSize) {
1133 LLVM_DEBUG(dbgs() << "LibraryScanner::scanNext: Scanning next batch of size "
1134 << BatchSize << " for kind "
1135 << (K == PathType::User ? "User" : "System") << "\n";);
1136
1138 ScanHelper.getNextBatch(K, BatchSize, SearchPaths);
1139 for (const auto *SP : SearchPaths) {
1140 LLVM_DEBUG(dbgs() << " Scanning unit with basePath: " << SP->BasePath
1141 << "\n";);
1142 scanBaseDir(const_cast<LibrarySearchPath *>(SP));
1143 }
1144}
1145} // end namespace llvm::orc
std::deque< BasicBlock * > PathType
#define _
#define P(N)
static const char * name
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:114
Base class for error info classes.
Definition Error.h:44
virtual std::string message() const
Return the error message as a string.
Definition Error.h:52
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void append(StringRef RHS)
Append from a StringRef.
Definition SmallString.h:68
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void swap(SmallVectorImpl &RHS)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:730
static constexpr size_t npos
Definition StringRef.h:57
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:222
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:140
LLVM_ABI bool starts_with_insensitive(StringRef Prefix) const
Check if this string starts with the given Prefix, ignoring case.
Definition StringRef.cpp:41
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:629
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
Definition Triple.h:453
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition Triple.h:427
uint16_t getCharacteristics() const
Definition COFF.h:974
const Elf_Ehdr & getHeader() const
Definition ELF.h:347
Expected< Elf_Phdr_Range > program_headers() const
Iterate over program header table.
Definition ELF.h:444
Expected< StringRef > getStringTableForSymtab(const Elf_Shdr &Section) const
Definition ELF.h:1397
Expected< Elf_Dyn_Range > dynamicEntries() const
Definition ELF.cpp:625
Expected< Elf_Shdr_Range > sections() const
Definition ELF.h:1038
Expected< const uint8_t * > toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler=&defaultWarningHandler) const
Definition ELF.cpp:677
This class is the base class for all object file types.
Definition ObjectFile.h:231
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Validates and normalizes dynamic library paths.
bool isSharedLibrary(StringRef Path) const
std::optional< std::string > validate(StringRef Path) const
Validate the given path as a shared library.
std::optional< std::string > resolve(StringRef Stem, bool VariateLibStem=false) const
Performs placeholder substitution in dynamic library paths.
std::string substitute(StringRef input) const
void configure(StringRef loaderPath)
bool isTrackedBasePath(StringRef P) const
void getNextBatch(PathType Kind, size_t batchSize, SmallVectorImpl< const LibrarySearchPath * > &Out)
bool leftToScan(PathType K) const
void addBasePath(const std::string &P, PathType Kind=PathType::Unknown)
void scanNext(PathType Kind, size_t batchSize=1)
std::optional< ObjectFileLoader > take(StringRef Path)
Loads an object file and provides access to it.
static bool isArchitectureCompatible(const object::ObjectFile &Obj)
Expected< object::ObjectFile & > getObjectFile()
Get the loaded object file, or return an error if loading failed.
std::optional< std::string > readlinkCached(StringRef Path)
mode_t lstatCached(StringRef Path)
std::optional< std::string > realpathCached(StringRef Path, std::error_code &ec, StringRef base="", bool baseIsResolved=false, long symloopLevel=40)
std::optional< std::string > resolve(StringRef libStem, const DylibSubstitutor &Subst, DylibPathValidator &Validator) const
@ Entry
Definition COFF.h:862
@ IMAGE_FILE_DLL
The image file is a DLL.
Definition COFF.h:170
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ DF_1_PIE
Definition ELF.h:1678
@ SHT_DYNSYM
Definition ELF.h:1158
@ PT_INTERP
Definition ELF.h:1561
@ ET_DYN
Definition ELF.h:121
@ MH_DYLIB
Definition MachO.h:48
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.
Definition Binary.cpp:45
Expected< LibraryDepsInfo > parseELF(const object::ELFFile< ELFT > &Elf)
LibraryScanner::LibraryDepsInfo LibraryDepsInfo
Expected< LibraryDepsInfo > parseMachODeps(const object::MachOObjectFile &Obj)
void createComponent(StringRef Path, StringRef BasePath, bool BaseIsResolved, SmallVector< StringRef, 16 > &Component)
void handleError(Error Err, StringRef context="")
void normalizePathSegments(SmallVector< StringRef, 16 > &PathParts)
bool isELFSharedLibrary(const object::ELFFile< ELFT > &ELFObj)
@ Resolved
Queried, materialization begun.
Definition Core.h:793
Expected< LibraryDepsInfo > parseDependencies(StringRef FilePath, object::ObjectFile *Obj)
bool isSharedLibraryObject(object::ObjectFile &Obj)
Expected< LibraryDepsInfo > parseELFDeps(const object::ELFObjectFileBase &Obj)
static Expected< StringRef > getDynamicStrTab(const object::ELFFile< ELFT > &Elf)
LLVM_ABI std::error_code readlink(const Twine &path, SmallVectorImpl< char > &output)
Read the target of a symbolic link.
LLVM_ABI bool is_regular_file(const basic_file_status &status)
Does status represent a regular file?
Definition Path.cpp:1120
LLVM_ABI bool is_symlink_file(const basic_file_status &status)
Does status represent a symlink file?
Definition Path.cpp:1134
LLVM_ABI std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
LLVM_ABI std::string getMainExecutable(const char *argv0, void *MainExecAddr)
Return the path to the main executable, given the value of argv[0] from program startup and the addre...
LLVM_ABI file_type get_file_type(const Twine &Path, bool Follow=true)
Does status represent a directory?
Definition Path.cpp:1099
LLVM_ABI std::error_code make_absolute(SmallVectorImpl< char > &path)
Make path an absolute path.
Definition Path.cpp:963
LLVM_ABI std::error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
LLVM_ABI bool is_directory(const basic_file_status &status)
Does status represent a directory?
Definition Path.cpp:1106
LLVM_ABI StringRef get_separator(Style style=Style::native)
Return the preferred separator for this platform.
Definition Path.cpp:610
LLVM_ABI void remove_filename(SmallVectorImpl< char > &path, Style style=Style::native)
Remove the last component from path unless it is the root dir.
Definition Path.cpp:475
LLVM_ABI StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
Definition Path.cpp:468
LLVM_ABI bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
Definition Path.cpp:700
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition Path.cpp:578
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition Path.cpp:672
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition Path.cpp:457
LLVM_ABI bool home_directory(SmallVectorImpl< char > &result)
Get the user's home directory.
LLVM_ABI bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
Definition Path.cpp:602
const char EnvPathSeparator
This is the OS-specific separator for PATH like environment variables:
Definition Program.h:33
LLVM_ABI std::string getProcessTriple()
getProcessTriple() - Return an appropriate target triple for generating code to be loaded into the cu...
Definition Host.cpp:2576
LLVM_ABI file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition Magic.cpp:33
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:94
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition Error.h:967
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
LLVM_ABI void SplitString(StringRef Source, SmallVectorImpl< StringRef > &OutFragments, StringRef Delimiters=" \t\n\v\f\r")
SplitString - Split up the specified string according to the specified delimiters,...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1083
uint32_t name
Definition MachO.h:671
file_magic - An "enum class" enumeration of file types based on magic (the first N bytes of the file)...
Definition Magic.h:21
@ archive
ar style archive file
Definition Magic.h:26
@ elf_shared_object
ELF dynamically linked shared lib.
Definition Magic.h:30
@ macho_dynamically_linked_shared_lib
Mach-O dynlinked shared lib.
Definition Magic.h:38
@ macho_dynamically_linked_shared_lib_stub
Mach-O Shared lib stub.
Definition Magic.h:41
@ pecoff_executable
PECOFF executable file.
Definition Magic.h:50
@ macho_universal_binary
Mach-O universal binary.
Definition Magic.h:44
@ macho_fixed_virtual_memory_shared_lib
Mach-O Shared Lib, FVM.
Definition Magic.h:35