LLVM: lib/ExecutionEngine/Orc/TargetProcess/LibraryResolver.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
15
17
25
26#include
27#include
28
29#define DEBUG_TYPE "orc-resolver"
30
32
35 LibPathResolver(S.PResolver
36 ? S.PResolver
38 ScanHelper(S.BasePaths, LibPathCache, LibPathResolver),
39 FB(S.FilterBuilder), LibMgr(),
40 ShouldScanCall(S.ShouldScanCall ? S.ShouldScanCall
42 scanBatchSize(S.ScanBatchSize) {
43
44 if (ScanHelper.getAllUnits().empty()) {
45 LLVM_DEBUG(dbgs() << "Warning: No base paths provided for scanning.\n");
46 }
47}
48
49std::unique_ptr
51 auto LR = std::make_unique(S);
52 return std::unique_ptr(
53 new LibraryResolutionDriver(std::move(LR)));
54}
55
57 LR->ScanHelper.addBasePath(Path, K);
58}
59
61 auto Lib = LR->LibMgr.getLibrary(Path);
63 return false;
64
66
67 return true;
68}
69
71 auto Lib = LR->LibMgr.getLibrary(Path);
73 return false;
74
76
77 return true;
78}
79
81 std::vectorstd::string Syms,
84 LR->searchSymbolsInLibraries(Syms, std::move(OnCompletion), Config);
85}
86
90 if (!FlagsOrErr) {
92 return true;
93 }
94
96
98 if ((IgnoreFlags & Filter::IgnoreUndefined) &&
100 return true;
101 if ((IgnoreFlags & Filter::IgnoreIndirect) &&
103 return true;
104 if ((IgnoreFlags & Filter::IgnoreWeak) &&
106 return true;
107
108 return false;
109}
110
113 if (Path.empty())
114 return false;
115
117
119 if (!ObjOrErr) {
120 std::string ErrMsg;
122 [&](const ErrorInfoBase &EIB) { ErrMsg = EIB.message(); });
123 LLVM_DEBUG(dbgs() << "Failed loading object file: " << Path
124 << "\nError: " << ErrMsg << "\n");
125 return false;
126 }
127
129
130 auto processSymbolRange =
132 for (const auto &Sym : Range) {
134 continue;
135
136 auto NameOrErr = Sym.getName();
137 if (!NameOrErr) {
139 continue;
140 }
141
143 if (Name.empty())
144 continue;
145
147 if (Res != EnumerateResult::Continue)
148 return Res;
149 }
150 return EnumerateResult::Continue;
151 };
152
153 EnumerateResult Res = processSymbolRange(Obj->symbols());
154 if (Res != EnumerateResult::Continue)
155 return Res == EnumerateResult::Stop;
156
157 if (Obj->isELF()) {
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))
169 continue;
170 if (Name.empty())
171 continue;
172
174 if (Res != EnumerateResult::Continue)
175 return Res == EnumerateResult::Stop;
176 }
177 } else if (Obj->isMachO()) {
178 }
179
180 return true;
181}
182
184public:
186
188
190
191 inline bool allResolved() const { return Q.allResolved(); }
192
194
195private:
198};
199
200void LibraryResolver::resolveSymbolsInLibrary(
201 LibraryInfo &Lib, SymbolQuery &UnresolvedSymbols,
202 const SymbolEnumeratorOptions &Opts) {
204 << " in library : " << Lib.getFileName() << "\n";);
206
207 if (!UnresolvedSymbols.hasUnresolved()) {
209 << " — unresolved symbols exist.\n";);
210 return;
211 }
212
213 bool HasEnumerated = false;
214 auto enumerateSymbolsIfNeeded = [&]() {
215 if (HasEnumerated)
216 return;
217
218 HasEnumerated = true;
219
220 LLVM_DEBUG(dbgs() << "Enumerating symbols in library: " << Lib.getFullPath()
221 << "\n";);
222 SymbolEnumerator::enumerateSymbols(
223 Lib.getFullPath(),
224 [&](StringRef sym) {
225 DiscoveredSymbols.insert(sym);
226 return EnumerateResult::Continue;
227 },
228 Opts);
229 };
230
231 if (.hasFilter()) {
232 LLVM_DEBUG(dbgs() << "Building filter for library: " << Lib.getFullPath()
233 << "\n";);
234 enumerateSymbolsIfNeeded();
235 if (DiscoveredSymbols.empty()) {
236 LLVM_DEBUG(dbgs() << " No symbols and remove library : "
237 << Lib.getFullPath() << "\n";);
238 LibMgr.removeLibrary(Lib.getFullPath());
239 return;
240 }
241 SmallVector SymbolVec;
242 SymbolVec.reserve(DiscoveredSymbols.size());
243 for (const auto &KV : DiscoveredSymbols)
244 SymbolVec.push_back(KV.first());
245
246 Lib.ensureFilterBuilt(FB, SymbolVec);
248 dbgs() << "DiscoveredSymbols : " << DiscoveredSymbols.size() << "\n";
249 for (const auto &KV : DiscoveredSymbols)
250 dbgs() << "DiscoveredSymbols : " << KV.first() << "\n";
251 });
252 }
253
254 const auto &Unresolved = UnresolvedSymbols.getUnresolvedSymbols();
255 bool HadAnySym = false;
256 LLVM_DEBUG(dbgs() << "Total unresolved symbols : " << Unresolved.size()
257 << "\n";);
258 for (const auto &Sym : Unresolved) {
259 if (Lib.mayContain(Sym)) {
261 << "' in library: " << Lib.getFullPath() << "\n";);
262 enumerateSymbolsIfNeeded();
263 if (DiscoveredSymbols.count(Sym) > 0) {
265 << " in library: " << Lib.getFullPath() << "\n";);
266 UnresolvedSymbols.resolve(Sym, Lib.getFullPath());
267 HadAnySym = true;
268 }
269 }
270 }
271
272 using LibraryState = LibraryManager::LibState;
273 if (HadAnySym && Lib.getState() != LibraryState::Loaded)
274 Lib.setState(LibraryState::Queried);
275}
276
278 std::vectorstd::string &SymbolList, OnSearchComplete OnComplete,
281
283 using LibraryType = PathType;
284 auto tryResolveFrom = [&](LibraryState S, LibraryType K) {
285 LLVM_DEBUG(dbgs() << "Trying resolve from state=" << static_cast<int>(S)
286 << " type=" << static_cast<int>(K) << "\n";);
287
289 while (!Ctx.allResolved()) {
290 std::vector<std::shared_ptr> Libs;
291 LibMgr.getLibraries(S, K, Libs, [&](const LibraryInfo &Lib) {
292 return !Ctx.hasSearched(&Lib);
293 });
294
295 if (Libs.empty() && !scanLibrariesIfNeeded(K, scanBatchSize))
296 break;
297
298 for (auto &Lib : Libs) {
299
300 resolveSymbolsInLibrary(*Lib, Ctx.query(), Config.Options);
301 Ctx.markSearched(Lib.get());
302
303 if (Ctx.allResolved())
304 return;
305 }
306 }
307 };
308
309 for (const auto &[St, Ty] : Config.Policy.Plan) {
310 tryResolveFrom(St, Ty);
312 break;
313 }
314
315
317 dbgs() << "Search complete.\n";
319 dbgs() << "Resolved Symbol:" << r->Name << " -> " << r->ResolvedLibPath
320 << "\n";
321 });
322
323 OnComplete(Q);
324}
325
326bool LibraryResolver::scanLibrariesIfNeeded(PathType PK, size_t BatchSize) {
327 LLVM_DEBUG(dbgs() << "LibraryResolver::scanLibrariesIfNeeded: Scanning for "
328 << (PK == PathType::User ? "User" : "System")
329 << " libraries\n";);
330 if (!ScanHelper.leftToScan(PK))
331 return false;
332
333 LibraryScanner Scanner(ScanHelper, LibMgr, ShouldScanCall);
334 Scanner.scanNext(PK, BatchSize);
335 return true;
336}
337
338bool LibraryResolver::symbolExistsInLibrary(const LibraryInfo &Lib,
340 std::vectorstd::string *AllSyms) {
341 SymbolEnumeratorOptions Opts;
342 return symbolExistsInLibrary(Lib, SymName, AllSyms, Opts);
343}
344
345bool LibraryResolver::symbolExistsInLibrary(
346 const LibraryInfo &Lib, StringRef SymName,
347 std::vectorstd::string *AllSyms, const SymbolEnumeratorOptions &Opts) {
348 bool Found = false;
349
350 SymbolEnumerator::enumerateSymbols(
351 Lib.getFullPath(),
352 [&](StringRef Sym) {
353 if (AllSyms)
354 AllSyms->emplace_back(Sym.str());
355
356 if (Sym == SymName) {
357 Found = true;
358 }
359
360 return EnumerateResult::Continue;
361 },
362 Opts);
363
364 return Found;
365}
366
367}
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.
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())
Definition LibraryResolver.cpp:80
void addScanPath(const std::string &Path, PathType Kind)
Definition LibraryResolver.cpp:56
bool markLibraryLoaded(StringRef Path)
Definition LibraryResolver.cpp:60
static std::unique_ptr< LibraryResolutionDriver > create(const LibraryResolver::Setup &S)
Definition LibraryResolver.cpp:50
bool markLibraryUnLoaded(StringRef Path)
Definition LibraryResolver.cpp:70
std::function< EnumerateResult(StringRef Sym)> OnEachSymbolFn
static bool enumerateSymbols(StringRef Path, OnEachSymbolFn OnEach, const SymbolEnumeratorOptions &Opts)
Definition LibraryResolver.cpp:111
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())
Definition LibraryResolver.cpp:277
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.
Definition LibraryResolver.cpp:183
bool hasSearched(const LibraryInfo *Lib) const
Definition LibraryResolver.cpp:187
void markSearched(const LibraryInfo *Lib)
Definition LibraryResolver.cpp:189
SymbolQuery & query()
Definition LibraryResolver.cpp:193
bool allResolved() const
Definition LibraryResolver.cpp:191
SymbolSearchContext(SymbolQuery &Q)
Definition LibraryResolver.cpp:185
LibraryManager::LibraryInfo LibraryInfo
static bool shouldIgnoreSymbol(const object::SymbolRef &Sym, uint32_t IgnoreFlags)
Definition LibraryResolver.cpp:87
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 - 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