//===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld backed ORC ObjectLayer -===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" namespace { using namespace llvm; using namespace llvm::orc; class JITDylibSearchOrderResolver : public JITSymbolResolver { public: JITDylibSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {} Expected lookup(const LookupSet &Symbols) { auto &ES = MR.getTargetJITDylib().getExecutionSession(); SymbolNameSet InternedSymbols; for (auto &S : Symbols) InternedSymbols.insert(ES.getSymbolStringPool().intern(S)); auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) { MR.addDependenciesForAll(Deps); }; auto InternedResult = MR.getTargetJITDylib().withSearchOrderDo([&](const JITDylibList &JDs) { return ES.lookup(JDs, InternedSymbols, RegisterDependencies, false); }); if (!InternedResult) return InternedResult.takeError(); LookupResult Result; for (auto &KV : *InternedResult) Result[*KV.first] = std::move(KV.second); return Result; } Expected getResponsibilitySet(const LookupSet &Symbols) { LookupSet Result; for (auto &KV : MR.getSymbols()) { if (Symbols.count(*KV.first)) Result.insert(*KV.first); } return Result; } private: MaterializationResponsibility &MR; }; } // end anonymous namespace namespace llvm { namespace orc { RTDyldObjectLinkingLayer2::RTDyldObjectLinkingLayer2( ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager, NotifyLoadedFunction NotifyLoaded, NotifyEmittedFunction NotifyEmitted) : ObjectLayer(ES), GetMemoryManager(GetMemoryManager), NotifyLoaded(std::move(NotifyLoaded)), NotifyEmitted(std::move(NotifyEmitted)) {} void RTDyldObjectLinkingLayer2::emit(MaterializationResponsibility R, VModuleKey K, std::unique_ptr O) { assert(O && "Object must not be null"); auto &ES = getExecutionSession(); auto ObjFile = object::ObjectFile::createObjectFile(*O); if (!ObjFile) { getExecutionSession().reportError(ObjFile.takeError()); R.failMaterialization(); } auto MemoryManager = GetMemoryManager(K); JITDylibSearchOrderResolver Resolver(R); auto RTDyld = llvm::make_unique(*MemoryManager, Resolver); RTDyld->setProcessAllSections(ProcessAllSections); { std::lock_guard Lock(RTDyldLayerMutex); assert(!MemMgrs.count(K) && "A memory manager already exists for this key?"); MemMgrs[K] = std::move(MemoryManager); } auto Info = RTDyld->loadObject(**ObjFile); { std::set InternalSymbols; for (auto &Sym : (*ObjFile)->symbols()) { if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) { if (auto SymName = Sym.getName()) InternalSymbols.insert(*SymName); else { ES.reportError(SymName.takeError()); R.failMaterialization(); return; } } } SymbolFlagsMap ExtraSymbolsToClaim; SymbolMap Symbols; for (auto &KV : RTDyld->getSymbolTable()) { // Scan the symbols and add them to the Symbols map for resolution. // We never claim internal symbols. if (InternalSymbols.count(KV.first)) continue; auto InternedName = ES.getSymbolStringPool().intern(KV.first); auto Flags = KV.second.getFlags(); // Override object flags and claim responsibility for symbols if // requested. if (OverrideObjectFlags || AutoClaimObjectSymbols) { auto I = R.getSymbols().find(InternedName); if (OverrideObjectFlags && I != R.getSymbols().end()) Flags = JITSymbolFlags::stripTransientFlags(I->second); else if (AutoClaimObjectSymbols && I == R.getSymbols().end()) ExtraSymbolsToClaim[InternedName] = Flags; } Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags); } if (!ExtraSymbolsToClaim.empty()) if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim)) { ES.reportError(std::move(Err)); R.failMaterialization(); return; } R.resolve(Symbols); } if (NotifyLoaded) NotifyLoaded(K, **ObjFile, *Info); RTDyld->finalizeWithMemoryManagerLocking(); if (RTDyld->hasError()) { ES.reportError(make_error(RTDyld->getErrorString(), inconvertibleErrorCode())); R.failMaterialization(); return; } R.emit(); if (NotifyEmitted) NotifyEmitted(K); } } // End namespace orc. } // End namespace llvm.