22#define DEBUG_TYPE "orc-resolver"
30 ScanHelper(S.BasePaths, LibPathCache, LibPathResolver),
32 ShouldScanCall(S.ShouldScanCall ? S.ShouldScanCall
34 scanBatchSize(S.ScanBatchSize) {
36 if (!ScanHelper.hasSearchPath()) {
37 LLVM_DEBUG(
dbgs() <<
"Warning: No base paths provided for scanning.\n");
41std::unique_ptr<LibraryResolutionDriver>
43 auto LR = std::make_unique<LibraryResolver>(S);
44 return std::unique_ptr<LibraryResolutionDriver>(
45 new LibraryResolutionDriver(std::move(LR)));
49 LR->ScanHelper.addBasePath(Path, K);
53 LR->LibMgr.markLoaded(Path);
57 LR->LibMgr.markUnloaded(Path);
63 LR->searchSymbolsInLibraries(Symbols, std::move(OnCompletion), Config);
77 if ((IgnoreFlags & Filter::IgnoreUndefined) &&
80 if ((IgnoreFlags & Filter::IgnoreNonExported) &&
83 if ((IgnoreFlags & Filter::IgnoreNonGlobal) &&
86 if ((IgnoreFlags & Filter::IgnoreHidden) &&
89 if ((IgnoreFlags & Filter::IgnoreIndirect) &&
92 if ((IgnoreFlags & Filter::IgnoreWeak) &&
105 auto processSymbolRange =
107 for (
const auto &Sym :
Range) {
111 auto NameOrErr = Sym.getName();
122 if (Res != EnumerateResult::Continue)
125 return EnumerateResult::Continue;
129 if (Res != EnumerateResult::Continue)
130 return Res == EnumerateResult::Stop;
134 Res = processSymbolRange(ElfObj->getDynamicSymbolIterators());
135 if (Res != EnumerateResult::Continue)
136 return Res == EnumerateResult::Stop;
137 }
else if (Obj->isCOFF()) {
139 for (
auto I = CoffObj->export_directory_begin(),
140 E = CoffObj->export_directory_end();
143 if (
I->getSymbolName(Name))
149 if (Res != EnumerateResult::Continue)
150 return Res == EnumerateResult::Stop;
152 }
else if (Obj->isMachO()) {
168 <<
"\nError: " << ErrMsg <<
"\n");
176 for (
auto S :
file->sections()) {
178 if (
name ==
".gnu.hash") {
203 if (contents.
size() < 16)
206 const char *hashContent = contents.
data();
213 uint32_t n = (hash / bits) % maskWords;
215 const char *bloomfilter = hashContent + 16;
216 const char *hash_pos = bloomfilter + n * (bits / 8);
218 uint64_t bitmask = ((1ULL << (hash % bits)) | (1ULL << (hash2 % bits)));
219 return (bitmask & word) == bitmask;
222void LibraryResolver::resolveSymbolsInLibrary(
223 LibraryInfo *
Lib, SymbolQuery &Query,
const SymbolEnumeratorOptions &Opts) {
225 <<
" in library : " <<
Lib->getFileName() <<
"\n";);
227 if (!Query.hasUnresolved()) {
229 <<
" — unresolved symbols exist.\n";);
233 bool HadAnySym =
false;
236 SmallVector<StringRef, 24> CandidateVec;
238 Query.getUnresolvedSymbols(CandidateVec, [&](StringRef S) {
239 return !Lib->hasFilter() || Lib->mayContain(S);
242 LLVM_DEBUG(
dbgs() <<
"Total candidate symbols : " << CandidateVec.size()
244 if (CandidateVec.empty()) {
247 <<
Lib->getFullPath() <<
"\n";);
251 bool BuildingFilter = !
Lib->hasFilter();
253 ObjectFileLoader ObjLoader(
Lib->getFullPath());
254 auto ObjOrErr = ObjLoader.getObjectFile();
258 [&](
const ErrorInfoBase &EIB) { ErrMsg = EIB.message(); });
260 <<
"\nError: " << ErrMsg <<
"\n");
264 object::ObjectFile *
Obj = &ObjOrErr.get();
265 if (BuildingFilter &&
Obj->isELF()) {
269 if (CandidateVec.empty())
273 SmallVector<StringRef, 256> SymbolVec;
278 SymbolEnumerator::enumerateSymbols(
283 SymbolVec.push_back(S);
287 auto It = std::find(CandidateVec.begin(), CandidateVec.end(), S);
288 if (It != CandidateVec.end() && *It == S) {
291 <<
Lib->getFullPath() <<
"\n";);
292 Query.resolve(S,
Lib->getFullPath());
294 *It = CandidateVec.back();
295 CandidateVec.pop_back();
298 if (!BuildingFilter && CandidateVec.empty()) {
299 return EnumerateResult::Stop;
302 if (!BuildingFilter && !Query.hasUnresolved())
303 return EnumerateResult::Stop;
306 return EnumerateResult::Continue;
310 if (BuildingFilter) {
313 if (SymbolVec.empty()) {
315 <<
Lib->getFullPath() <<
"\n";);
319 Lib->ensureFilterBuilt(FB, SymbolVec);
321 dbgs() <<
"DiscoveredSymbols : " << SymbolVec.size() <<
"\n";
322 for (
const auto &S : SymbolVec)
323 dbgs() <<
"DiscoveredSymbols : " << S <<
"\n";
327 if (HadAnySym &&
Lib->getState() != LibState::Loaded)
328 Lib->setState(LibState::Queried);
337 auto tryResolveFrom = [&](
LibState S, LibraryType K) {
338 LLVM_DEBUG(
dbgs() <<
"Trying resolve from state=" <<
static_cast<int>(S)
339 <<
" type=" <<
static_cast<int>(K) <<
"\n";);
346 if (!scanForNewLibraries(K, Cur))
359 for (
const auto &[St, Ty] : Config.
Policy.
Plan) {
360 tryResolveFrom(St, Ty);
367 dbgs() <<
"Search complete.\n";
369 dbgs() <<
"Resolved Symbol:" << r->Name <<
" -> " << r->ResolvedLibPath
377 while (ScanHelper.leftToScan(K)) {
378 scanLibrariesIfNeeded(K, scanBatchSize);
389bool LibraryResolver::scanLibrariesIfNeeded(
PathType PK,
size_t BatchSize) {
390 LLVM_DEBUG(dbgs() <<
"LibraryResolver::scanLibrariesIfNeeded: Scanning for "
391 << (PK == PathType::User ?
"User" :
"System")
393 if (!ScanHelper.leftToScan(PK))
396 LibraryScanner Scanner(ScanHelper, LibMgr, ShouldScanCall);
397 Scanner.scanNext(PK, BatchSize);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
std::deque< BasicBlock * > PathType
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
dot regions Print regions of function to dot file(with no function bodies)"
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Base class for error info classes.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
Represent a constant reference to a string, i.e.
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Expected< uint32_t > getFlags() const
Get symbol flags (bitwise OR of SymbolRef::Flags)
This class is the base class for all object file types.
virtual uint8_t getBytesInAddress() const =0
The number of bytes used to represent an address in this object file format.
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.
bool hasMoreValidLib() const
Manages library metadata and state for symbol resolution.
LLVM_ABI void resolveSymbols(ArrayRef< StringRef > Symbols, LibraryResolver::OnSearchComplete OnCompletion, const SearchConfig &Config=SearchConfig())
LLVM_ABI void addScanPath(const std::string &Path, PathType Kind)
LLVM_ABI void markLibraryUnLoaded(StringRef Path)
LLVM_ABI void markLibraryLoaded(StringRef Path)
static LLVM_ABI std::unique_ptr< LibraryResolutionDriver > create(const LibraryResolver::Setup &S)
std::function< EnumerateResult(StringRef Sym)> OnEachSymbolFn
static LLVM_ABI bool enumerateSymbols(object::ObjectFile *Obj, OnEachSymbolFn OnEach, const SymbolEnumeratorOptions &Opts)
Tracks a set of symbols and the libraries where they are resolved.
std::vector< const Entry * > getAllResults() const
unique_function< void(SymbolQuery &)> OnSearchComplete
LLVM_ABI void searchSymbolsInLibraries(ArrayRef< StringRef > SymList, OnSearchComplete OnComplete, const SearchConfig &Config=SearchConfig())
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.
static bool shouldIgnoreSymbol(const object::SymbolRef &Sym, uint32_t IgnoreFlags)
static StringRef GetGnuHashSection(llvm::object::ObjectFile *file)
static bool MayExistInElfObjectFile(llvm::object::ObjectFile *soFile, StringRef Sym)
Bloom filter is a stochastic data structure which can tell us if a symbol name does not exist in a li...
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.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
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