Skip to content
53 changes: 30 additions & 23 deletions core/metacling/src/TClingCallbacks.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -104,38 +104,45 @@ class AutoloadLibraryGenerator : public llvm::orc::DefinitionGenerator {
// so no need to check that again. Instead search for the library that
// provides the symbol and create one MaterializationUnit per library to
// actually load it if needed.
std::unordered_map<std::string, llvm::orc::SymbolNameVector> found;
llvm::StringMap<llvm::orc::SymbolNameVector> found;

// TODO: Do we need to take gInterpreterMutex?
// R__LOCKGUARD(gInterpreterMutex);

for (auto &&KV : Symbols) {
llvm::orc::SymbolStringPtr name = KV.first;

const cling::DynamicLibraryManager &DLM = *fInterpreter->getDynamicLibraryManager();

std::string libName = DLM.searchLibrariesForSymbol((*name).str(),
/*searchSystem=*/true);

// libNew overrides memory management functions; must never autoload that.
assert(libName.find("/libNew.") == std::string::npos && "We must not autoload libNew!");

// libCling symbols are intentionally hidden from the process, and libCling must not be
// dlopened. Instead, symbols must be resolved by specifically querying the dynlib handle of
// libCling, which by definition is loaded - else we could not call this code. The handle
// is made available as argument to `CreateInterpreter`.
assert(libName.find("/libCling.") == std::string::npos && "Must not autoload libCling!");

if (!libName.empty())
found[libName].push_back(name);
}
SmallVector<StringRef> Syms;
for (auto &KV : Symbols)
Syms.push_back(*KV.first);

const cling::DynamicLibraryManager &DLM = *fInterpreter->getDynamicLibraryManager();
DLM.searchLibrariesForSymbol(
Syms,
[&](llvm::orc::SymbolQuery &Q) {
for (auto &&KV : Symbols) {
auto ResolvedLibOrOpt = Q.getResolvedLib(*KV.first);
if (!ResolvedLibOrOpt || ResolvedLibOrOpt->empty())
continue;
auto ResolvedLib = *ResolvedLibOrOpt;
// libNew overrides memory management functions; must never autoload that.
assert(ResolvedLib.find("/libNew.") == std::string::npos && "We must not autoload libNew!");

// libCling symbols are intentionally hidden from the process, and libCling must not be
// dlopened. Instead, symbols must be resolved by specifically querying the dynlib handle of
// libCling, which by definition is loaded - else we could not call this code. The handle
// is made available as argument to `CreateInterpreter`.
assert(ResolvedLib.find("/libCling.") == std::string::npos && "Must not autoload libCling!");

if (!ResolvedLib.empty())
found[ResolvedLib].push_back(KV.first);
}
},
/*searchSystem=*/true);

llvm::orc::SymbolMap loadedSymbols;
for (const auto &KV : found) {
// Try to load the library which should provide the symbol definition.
// TODO: Should this interface with the DynamicLibraryManager directly?
if (TCling__LoadLibrary(KV.first.c_str()) < 0) {
ROOT::TMetaUtils::Error("AutoloadLibraryMU", "Failed to load library %s", KV.first.c_str());
if (TCling__LoadLibrary(KV.first().data()) < 0) {
ROOT::TMetaUtils::Error("AutoloadLibraryMU", "Failed to load library %s", KV.first().data());
}

for (const auto &symbol : KV.second) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#ifndef CLING_DYNAMIC_LIBRARY_MANAGER_H
#define CLING_DYNAMIC_LIBRARY_MANAGER_H

#include "llvm/ExecutionEngine/Orc/TargetProcess/LibraryResolver.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
Expand Down Expand Up @@ -66,6 +67,8 @@ namespace cling {

Dyld* m_Dyld = nullptr;

std::unique_ptr<llvm::orc::LibraryResolutionDriver> m_DyldController;

///\brief Concatenates current include paths and the system include paths
/// and performs a lookup for the filename.
/// See more information for RPATH and RUNPATH: https://en.wikipedia.org/wiki/Rpath
Expand Down Expand Up @@ -128,6 +131,10 @@ namespace cling {
return;
auto pos = prepend ? m_SearchPaths.begin() : m_SearchPaths.end();
m_SearchPaths.insert(pos, SearchPathInfo{dir.str(), isUser});
if (m_DyldController)
m_DyldController->addScanPath(dir.str(),
isUser ? llvm::orc::PathType::User
: llvm::orc::PathType::System);
}
}

Expand Down Expand Up @@ -189,6 +196,11 @@ namespace cling {
std::string searchLibrariesForSymbol(llvm::StringRef mangledName,
bool searchSystem = true) const;

void
searchLibrariesForSymbol(llvm::ArrayRef<llvm::StringRef> Symbols,
llvm::orc::LibraryResolver::OnSearchComplete OnCompletion,
bool searchSystem = true) const;

void dump(llvm::raw_ostream* S = nullptr) const;

/// On a success returns to full path to a shared object that holds the
Expand Down
7 changes: 7 additions & 0 deletions interpreter/cling/lib/Interpreter/DynamicLibraryManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ namespace cling {
#endif
};

// m_DyldController = llvm::orc::LibraryResolutionDriver::create(
// llvm::orc::LibraryResolver::Setup::create({}));

// Behaviour is to not add paths that don't exist...In an interpreted env
// does this make sense? Path could pop into existance at any time.
for (const char* Var : kSysLibraryEnv) {
Expand Down Expand Up @@ -393,6 +396,8 @@ namespace cling {
if (!insRes.second)
return kLoadLibAlreadyLoaded;
m_LoadedLibraries.insert(canonicalLoadedLib);
if (m_DyldController)
m_DyldController->markLibraryLoaded(canonicalLoadedLib);
return kLoadLibSuccess;
}

Expand Down Expand Up @@ -424,6 +429,8 @@ namespace cling {

m_DyLibs.erase(dyLibHandle);
m_LoadedLibraries.erase(canonicalLoadedLib);
if (m_DyldController)
m_DyldController->markLibraryUnLoaded(canonicalLoadedLib);
}

bool DynamicLibraryManager::isLibraryLoaded(llvm::StringRef fullPath) const {
Expand Down
Loading
Loading