29#define DEBUG_TYPE "orc-resolver"
35 LibPathResolver(S.PResolver
38 ScanHelper(S.BasePaths, LibPathCache, LibPathResolver),
39 FB(S.FilterBuilder), LibMgr(),
40 ShouldScanCall(S.ShouldScanCall ? S.ShouldScanCall
42 scanBatchSize(S.ScanBatchSize) {
44 if (ScanHelper.getAllUnits().empty()) {
45 LLVM_DEBUG(
dbgs() <<
"Warning: No base paths provided for scanning.\n");
49std::unique_ptr<LibraryResolutionDriver>
51 auto LR = std::make_unique<LibraryResolver>(S);
52 return std::unique_ptr<LibraryResolutionDriver>(
53 new LibraryResolutionDriver(std::move(LR)));
57 LR->ScanHelper.addBasePath(Path, K);
61 auto Lib = LR->LibMgr.getLibrary(Path);
71 auto Lib = LR->LibMgr.getLibrary(Path);
81 std::vector<std::string> Syms,
84 LR->searchSymbolsInLibraries(Syms, std::move(OnCompletion), Config);
98 if ((IgnoreFlags & Filter::IgnoreUndefined) &&
101 if ((IgnoreFlags & Filter::IgnoreIndirect) &&
104 if ((IgnoreFlags & Filter::IgnoreWeak) &&
124 <<
"\nError: " << ErrMsg <<
"\n");
130 auto processSymbolRange =
132 for (
const auto &Sym :
Range) {
136 auto NameOrErr = Sym.getName();
147 if (Res != EnumerateResult::Continue)
150 return EnumerateResult::Continue;
154 if (Res != EnumerateResult::Continue)
155 return Res == EnumerateResult::Stop;
159 Res = processSymbolRange(ElfObj->getDynamicSymbolIterators());
160 if (Res != EnumerateResult::Continue)
161 return Res == EnumerateResult::Stop;
162 }
else if (Obj->
isCOFF()) {
164 for (
auto I = CoffObj->export_directory_begin(),
165 E = CoffObj->export_directory_end();
168 if (
I->getSymbolName(Name))
174 if (Res != EnumerateResult::Continue)
175 return Res == EnumerateResult::Stop;
200void LibraryResolver::resolveSymbolsInLibrary(
201 LibraryInfo &
Lib, SymbolQuery &UnresolvedSymbols,
202 const SymbolEnumeratorOptions &Opts) {
204 <<
" in library : " <<
Lib.getFileName() <<
"\n";);
207 if (!UnresolvedSymbols.hasUnresolved()) {
209 <<
" — unresolved symbols exist.\n";);
213 bool HasEnumerated =
false;
214 auto enumerateSymbolsIfNeeded = [&]() {
218 HasEnumerated =
true;
220 LLVM_DEBUG(dbgs() <<
"Enumerating symbols in library: " << Lib.getFullPath()
222 SymbolEnumerator::enumerateSymbols(
225 DiscoveredSymbols.insert(sym);
226 return EnumerateResult::Continue;
230 if (DiscoveredSymbols.
empty()) {
231 LLVM_DEBUG(dbgs() <<
" No symbols and remove library : "
232 << Lib.getFullPath() <<
"\n";);
233 LibMgr.removeLibrary(Lib.getFullPath());
238 if (!
Lib.hasFilter()) {
241 enumerateSymbolsIfNeeded();
242 SmallVector<StringRef> SymbolVec;
243 SymbolVec.reserve(DiscoveredSymbols.
size());
244 for (
const auto &KV : DiscoveredSymbols)
245 SymbolVec.push_back(KV.first());
247 Lib.ensureFilterBuilt(FB, SymbolVec);
249 dbgs() <<
"DiscoveredSymbols : " << DiscoveredSymbols.size() <<
"\n";
250 for (
const auto &KV : DiscoveredSymbols)
251 dbgs() <<
"DiscoveredSymbols : " << KV.first() <<
"\n";
255 const auto &Unresolved = UnresolvedSymbols.getUnresolvedSymbols();
256 bool HadAnySym =
false;
257 LLVM_DEBUG(
dbgs() <<
"Total unresolved symbols : " << Unresolved.size()
259 for (
const auto &Sym : Unresolved) {
260 if (
Lib.mayContain(Sym)) {
262 <<
"' in library: " <<
Lib.getFullPath() <<
"\n";);
263 enumerateSymbolsIfNeeded();
264 if (DiscoveredSymbols.count(Sym) > 0) {
266 <<
" in library: " <<
Lib.getFullPath() <<
"\n";);
267 UnresolvedSymbols.resolve(Sym,
Lib.getFullPath());
273 using LibraryState = LibraryManager::LibState;
274 if (HadAnySym &&
Lib.getState() != LibraryState::Loaded)
275 Lib.setState(LibraryState::Queried);
285 auto tryResolveFrom = [&](LibraryState S, LibraryType K) {
286 LLVM_DEBUG(
dbgs() <<
"Trying resolve from state=" <<
static_cast<int>(S)
287 <<
" type=" <<
static_cast<int>(K) <<
"\n";);
290 while (!Ctx.allResolved()) {
292 for (
auto &
Lib : LibMgr.getView(S, K)) {
293 if (Ctx.hasSearched(
Lib.get()))
297 resolveSymbolsInLibrary(*
Lib, Ctx.query(), Config.
Options);
298 Ctx.markSearched(
Lib.get());
300 if (Ctx.allResolved())
304 if (Ctx.allResolved())
307 if (!scanLibrariesIfNeeded(K, scanBatchSize))
312 for (
const auto &[St, Ty] : Config.
Policy.
Plan) {
313 tryResolveFrom(St, Ty);
320 dbgs() <<
"Search complete.\n";
322 dbgs() <<
"Resolved Symbol:" << r->Name <<
" -> " << r->ResolvedLibPath
329bool LibraryResolver::scanLibrariesIfNeeded(
PathType PK,
size_t BatchSize) {
330 LLVM_DEBUG(
dbgs() <<
"LibraryResolver::scanLibrariesIfNeeded: Scanning for "
331 << (PK == PathType::User ?
"User" :
"System")
333 if (!ScanHelper.leftToScan(PK))
337 Scanner.scanNext(PK, BatchSize);
341bool LibraryResolver::symbolExistsInLibrary(
const LibraryInfo &
Lib,
343 std::vector<std::string> *AllSyms) {
344 SymbolEnumeratorOptions Opts;
345 return symbolExistsInLibrary(
Lib, SymName, AllSyms, Opts);
348bool LibraryResolver::symbolExistsInLibrary(
349 const LibraryInfo &Lib, StringRef SymName,
350 std::vector<std::string> *AllSyms,
const SymbolEnumeratorOptions &Opts) {
353 SymbolEnumerator::enumerateSymbols(
357 AllSyms->emplace_back(Sym.str());
359 if (Sym == SymName) {
363 return EnumerateResult::Continue;
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
StringSet - A set-like wrapper for the StringMap.
Implements a dense probed hash-table based set.
Base class for error info classes.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
StringRef - Represent a constant reference to a string, i.e.
StringSet - A wrapper for StringMap that provides set-like functionality.
Expected< uint32_t > getFlags() const
Get symbol flags (bitwise OR of SymbolRef::Flags)
This class is the base class for all object file types.
symbol_iterator_range symbols() const
iterator_range< symbol_iterator > symbol_iterator_range
This is a value type class that represents a single symbol in the list of symbols in the object file.
void resolveSymbols(std::vector< std::string > Symbols, LibraryResolver::OnSearchComplete OnCompletion, const SearchConfig &Config=SearchConfig())
void addScanPath(const std::string &Path, PathType Kind)
bool markLibraryLoaded(StringRef Path)
static std::unique_ptr< LibraryResolutionDriver > create(const LibraryResolver::Setup &S)
bool markLibraryUnLoaded(StringRef Path)
std::function< EnumerateResult(StringRef Sym)> OnEachSymbolFn
static bool enumerateSymbols(StringRef Path, OnEachSymbolFn OnEach, const SymbolEnumeratorOptions &Opts)
Tracks a set of symbols and the libraries where they are resolved.
std::vector< const Result * > getAllResults() const
unique_function< void(SymbolQuery &)> OnSearchComplete
void searchSymbolsInLibraries(std::vector< std::string > &SymList, OnSearchComplete OnComplete, const SearchConfig &Config=SearchConfig())
Scans libraries, resolves dependencies, and registers them.
Loads an object file and provides access to it.
Expected< object::ObjectFile & > getObjectFile()
Get the loaded object file, or return an error if loading failed.
Resolves file system paths with optional caching of results.
bool hasSearched(LibraryInfo *Lib) const
void markSearched(LibraryInfo *Lib)
SymbolSearchContext(SymbolQuery &Q)
LibraryManager::LibraryInfo LibraryInfo
static bool shouldIgnoreSymbol(const object::SymbolRef &Sym, uint32_t IgnoreFlags)
LibraryResolver::SymbolQuery SymbolQuery
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void consumeError(Error Err)
Consume a Error without doing anything.
Implement std::hash so that hash_code can be used in STL containers.
SymbolEnumeratorOptions Options
std::vector< SearchPlanEntry > Plan