29#define DEBUG_TYPE "orc-resolver"
37 ScanHelper(S.BasePaths, LibPathCache, LibPathResolver),
39 ShouldScanCall(S.ShouldScanCall ? S.ShouldScanCall
41 scanBatchSize(S.ScanBatchSize) {
43 if (!ScanHelper.hasSearchPath()) {
44 LLVM_DEBUG(
dbgs() <<
"Warning: No base paths provided for scanning.\n");
48std::unique_ptr<LibraryResolutionDriver>
50 auto LR = std::make_unique<LibraryResolver>(S);
51 return std::unique_ptr<LibraryResolutionDriver>(
52 new LibraryResolutionDriver(std::move(LR)));
56 LR->ScanHelper.addBasePath(Path, K);
60 LR->LibMgr.markLoaded(Path);
64 LR->LibMgr.markUnloaded(Path);
70 LR->searchSymbolsInLibraries(Symbols, std::move(OnCompletion), Config);
84 if ((IgnoreFlags & Filter::IgnoreUndefined) &&
87 if ((IgnoreFlags & Filter::IgnoreNonExported) &&
90 if ((IgnoreFlags & Filter::IgnoreNonGlobal) &&
93 if ((IgnoreFlags & Filter::IgnoreHidden) &&
96 if ((IgnoreFlags & Filter::IgnoreIndirect) &&
99 if ((IgnoreFlags & Filter::IgnoreWeak) &&
112 auto processSymbolRange =
114 for (
const auto &Sym :
Range) {
118 auto NameOrErr = Sym.getName();
129 if (Res != EnumerateResult::Continue)
132 return EnumerateResult::Continue;
136 if (Res != EnumerateResult::Continue)
137 return Res == EnumerateResult::Stop;
141 Res = processSymbolRange(ElfObj->getDynamicSymbolIterators());
142 if (Res != EnumerateResult::Continue)
143 return Res == EnumerateResult::Stop;
144 }
else if (Obj->isCOFF()) {
146 for (
auto I = CoffObj->export_directory_begin(),
147 E = CoffObj->export_directory_end();
150 if (
I->getSymbolName(Name))
156 if (Res != EnumerateResult::Continue)
157 return Res == EnumerateResult::Stop;
159 }
else if (Obj->isMachO()) {
175 <<
"\nError: " << ErrMsg <<
"\n");
183 for (
auto S :
file->sections()) {
185 if (
name ==
".gnu.hash") {
210 if (contents.
size() < 16)
213 const char *hashContent = contents.
data();
220 uint32_t n = (hash / bits) % maskWords;
222 const char *bloomfilter = hashContent + 16;
223 const char *hash_pos = bloomfilter + n * (bits / 8);
225 uint64_t bitmask = ((1ULL << (hash % bits)) | (1ULL << (hash2 % bits)));
226 return (bitmask & word) == bitmask;
229void LibraryResolver::resolveSymbolsInLibrary(
230 LibraryInfo *
Lib, SymbolQuery &Query,
const SymbolEnumeratorOptions &Opts) {
232 <<
" in library : " <<
Lib->getFileName() <<
"\n";);
234 if (!Query.hasUnresolved()) {
236 <<
" — unresolved symbols exist.\n";);
240 bool HadAnySym =
false;
243 SmallVector<StringRef, 24> CandidateVec;
245 Query.getUnresolvedSymbols(CandidateVec, [&](StringRef S) {
246 return !Lib->hasFilter() || Lib->mayContain(S);
249 LLVM_DEBUG(
dbgs() <<
"Total candidate symbols : " << CandidateVec.size()
251 if (CandidateVec.empty()) {
254 <<
Lib->getFullPath() <<
"\n";);
258 bool BuildingFilter = !
Lib->hasFilter();
260 ObjectFileLoader ObjLoader(
Lib->getFullPath());
261 auto ObjOrErr = ObjLoader.getObjectFile();
265 [&](
const ErrorInfoBase &EIB) { ErrMsg = EIB.message(); });
267 <<
"\nError: " << ErrMsg <<
"\n");
271 object::ObjectFile *
Obj = &ObjOrErr.get();
272 if (BuildingFilter &&
Obj->isELF()) {
276 if (CandidateVec.empty())
280 SmallVector<StringRef, 256> SymbolVec;
285 SymbolEnumerator::enumerateSymbols(
290 SymbolVec.push_back(S);
294 auto It = std::find(CandidateVec.begin(), CandidateVec.end(), S);
295 if (It != CandidateVec.end() && *It == S) {
298 <<
Lib->getFullPath() <<
"\n";);
299 Query.resolve(S,
Lib->getFullPath());
301 *It = CandidateVec.back();
302 CandidateVec.pop_back();
305 if (!BuildingFilter && CandidateVec.empty()) {
306 return EnumerateResult::Stop;
309 if (!BuildingFilter && !Query.hasUnresolved())
310 return EnumerateResult::Stop;
313 return EnumerateResult::Continue;
317 if (BuildingFilter) {
320 if (SymbolVec.empty()) {
322 <<
Lib->getFullPath() <<
"\n";);
326 Lib->ensureFilterBuilt(FB, SymbolVec);
328 dbgs() <<
"DiscoveredSymbols : " << SymbolVec.size() <<
"\n";
329 for (
const auto &S : SymbolVec)
330 dbgs() <<
"DiscoveredSymbols : " << S <<
"\n";
334 if (HadAnySym &&
Lib->getState() != LibState::Loaded)
335 Lib->setState(LibState::Queried);
344 auto tryResolveFrom = [&](
LibState S, LibraryType K) {
345 LLVM_DEBUG(
dbgs() <<
"Trying resolve from state=" <<
static_cast<int>(S)
346 <<
" type=" <<
static_cast<int>(K) <<
"\n";);
353 if (!scanForNewLibraries(K, Cur))
366 for (
const auto &[St, Ty] : Config.
Policy.
Plan) {
367 tryResolveFrom(St, Ty);
374 dbgs() <<
"Search complete.\n";
376 dbgs() <<
"Resolved Symbol:" << r->Name <<
" -> " << r->ResolvedLibPath
384 while (ScanHelper.leftToScan(K)) {
385 scanLibrariesIfNeeded(K, scanBatchSize);
396bool LibraryResolver::scanLibrariesIfNeeded(
PathType PK,
size_t BatchSize) {
397 LLVM_DEBUG(dbgs() <<
"LibraryResolver::scanLibrariesIfNeeded: Scanning for "
398 << (PK == PathType::User ?
"User" :
"System")
400 if (!ScanHelper.leftToScan(PK))
403 LibraryScanner Scanner(ScanHelper, LibMgr, ShouldScanCall);
404 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)"
StringSet - A set-like wrapper for the StringMap.
ArrayRef - 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.
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - 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.
void resolveSymbols(ArrayRef< StringRef > Symbols, LibraryResolver::OnSearchComplete OnCompletion, const SearchConfig &Config=SearchConfig())
void addScanPath(const std::string &Path, PathType Kind)
void markLibraryUnLoaded(StringRef Path)
void markLibraryLoaded(StringRef Path)
static std::unique_ptr< LibraryResolutionDriver > create(const LibraryResolver::Setup &S)
std::function< EnumerateResult(StringRef Sym)> OnEachSymbolFn
static 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
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