| //===- NativeDylibManager.cpp ---------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // NativeDylibManager and related APIs. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "orc-rt/bedrock/NativeDylibManager.h" | |
| #include "orc-rt-internal/bedrock/sys/DynamicLibrary.h" | |
| #include "orc-rt/bedrock/Session.h" | |
| namespace orc_rt { | |
| Expected<std::unique_ptr<NativeDylibManager>> | |
| NativeDylibManager::Create(Session &S, SimpleSymbolTable &ST, | |
| const char *InstanceName, | |
| SimpleSymbolTable::MutatorFn AddInterface) { | |
| std::unique_ptr<NativeDylibManager> Instance(new NativeDylibManager(S)); | |
| SimpleSymbolTable NDMST; | |
| if (auto Err = AddInterface(NDMST)) | |
| return Err; | |
| std::pair<SymbolNameSpec, const void *> InstanceSym[] = { | |
| {SymbolNameSpec::c(InstanceName), | |
| static_cast<const void *>(Instance.get())}}; | |
| if (auto Err = NDMST.addUnique(InstanceSym)) | |
| return std::move(Err); | |
| if (auto Err = ST.addUnique(std::move(NDMST))) | |
| return std::move(Err); | |
| return std::move(Instance); | |
| } | |
| void NativeDylibManager::load(OnLoadCompleteFn &&OnComplete, std::string Path) { | |
| // Empty path -> global handle; no shutdown callback (RTLD_DEFAULT | |
| // mustn't be dlclose'd). | |
| if (Path.empty()) | |
| return OnComplete(sys::globalLookupHandle()); | |
| auto H = sys::loadLibrary(Path); | |
| if (!H) | |
| return OnComplete(H.takeError()); | |
| // Capture S by reference, rather than this, so that the callback remains | |
| // valid even if the NativeDylibManager is destroyed prior to shutdown. | |
| S.addOnShutdown([&S = this->S, Handle = *H]() { | |
| if (auto Err = sys::unloadLibrary(Handle)) | |
| S.reportError(std::move(Err)); | |
| }); | |
| OnComplete(std::move(H)); | |
| } | |
| void NativeDylibManager::lookup(OnLookupCompleteFn &&OnLookupComplete, | |
| void *Handle, SymbolLookupSet Symbols) { | |
| std::vector<std::string> Names; | |
| Names.reserve(Symbols.size()); | |
| for (auto &S : Symbols) | |
| Names.push_back(std::move(S.first)); | |
| auto Addrs = sys::lookupLibrarySymbols(Handle, Names); | |
| // Convert weak-missing entries (empty optional from lookupLibrarySymbols) | |
| // to a present zero address. This matches the resolve semantics of | |
| // llvm::orc::rt_bootstrap::SimpleExecutorDylibManager: an empty optional | |
| // in the result signals a missing required symbol, while a missing | |
| // weakly-referenced symbol is reported as a zero address. | |
| for (size_t I = 0, E = Symbols.size(); I != E; ++I) | |
| if (!Addrs[I] && Symbols[I].second == WeaklyReferencedSymbol) | |
| Addrs[I] = nullptr; | |
| OnLookupComplete(std::move(Addrs)); | |
| } | |
| void NativeDylibManager::onDetach(Service::OnCompleteFn OnComplete, | |
| bool ShutdownRequested) { | |
| // Detach is a noop for now. If/when we add bloom-filter support this will be | |
| // a good time to update filters. | |
| OnComplete(); | |
| } | |
| void NativeDylibManager::onShutdown(Service::OnCompleteFn OnComplete) { | |
| // Unloads happen via Session shutdown callbacks registered in load(). | |
| OnComplete(); | |
| } | |
| } // namespace orc_rt |