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