diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 77c23b46d32..7932688290e 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -137,17 +137,15 @@ protected: virtual char *getMemoryForGV(const GlobalVariable *GV); static ExecutionEngine *(*MCJITCtor)( - std::unique_ptr M, - std::string *ErrorStr, - std::shared_ptr MM, - std::shared_ptr SR, - std::unique_ptr TM); + std::unique_ptr M, std::string *ErrorStr, + std::shared_ptr MM, + std::shared_ptr SR, + std::unique_ptr TM); static ExecutionEngine *(*OrcMCJITReplacementCtor)( - std::string *ErrorStr, - std::shared_ptr MM, - std::shared_ptr SR, - std::unique_ptr TM); + std::string *ErrorStr, std::shared_ptr MM, + std::shared_ptr SR, + std::unique_ptr TM); static ExecutionEngine *(*InterpCtor)(std::unique_ptr M, std::string *ErrorStr); @@ -532,7 +530,7 @@ private: std::string *ErrorStr; CodeGenOpt::Level OptLevel; std::shared_ptr MemMgr; - std::shared_ptr Resolver; + std::shared_ptr Resolver; TargetOptions Options; Optional RelocModel; Optional CMModel; @@ -571,8 +569,7 @@ public: EngineBuilder& setMemoryManager(std::unique_ptr MM); - EngineBuilder& - setSymbolResolver(std::unique_ptr SR); + EngineBuilder &setSymbolResolver(std::unique_ptr SR); /// setErrorStr - Set the error string to write to on error. This option /// defaults to NULL. diff --git a/include/llvm/ExecutionEngine/JITSymbol.h b/include/llvm/ExecutionEngine/JITSymbol.h index d171f998e6f..6aba236b619 100644 --- a/include/llvm/ExecutionEngine/JITSymbol.h +++ b/include/llvm/ExecutionEngine/JITSymbol.h @@ -19,8 +19,11 @@ #include #include #include +#include +#include #include +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" namespace llvm { @@ -269,11 +272,50 @@ private: JITSymbolFlags Flags; }; -/// \brief Symbol resolution. +/// @brief Symbol resolution interface. +/// +/// Allows symbol flags and addresses to be looked up by name. +/// Symbol queries are done in bulk (i.e. you request resolution of a set of +/// symbols, rather than a single one) to reduce IPC overhead in the case of +/// remote JITing, and expose opportunities for parallel compilation. class JITSymbolResolver { public: + using SymbolNameSet = std::set; + using LookupResult = std::map; + using LookupFlagsResult = std::map; + virtual ~JITSymbolResolver() = default; + /// @brief Returns the fully resolved address and flags for each of the given + /// symbols. + /// + /// This method will return an error if any of the given symbols can not be + /// resolved, or if the resolution process itself triggers an error. + virtual Expected lookup(const SymbolNameSet &Symbols) = 0; + + /// @brief Returns the symbol flags for each of the given symbols. + /// + /// This method does NOT return an error if any of the given symbols is + /// missing. Instead, that symbol will be left out of the result map. + virtual Expected + lookupFlags(const SymbolNameSet &Symbols) = 0; + +private: + virtual void anchor(); +}; + +/// \brief Legacy symbol resolution interface. +class LegacyJITSymbolResolver : public JITSymbolResolver { +public: + /// @brief Performs lookup by, for each symbol, first calling + /// findSymbolInLogicalDylib and if that fails calling + /// findSymbol. + Expected lookup(const SymbolNameSet &Symbols) final; + + /// @brief Performs flags lookup by calling findSymbolInLogicalDylib and + /// returning the flags value for that symbol. + Expected lookupFlags(const SymbolNameSet &Symbols) final; + /// This method returns the address of the specified symbol if it exists /// within the logical dynamic library represented by this JITSymbolResolver. /// Unlike findSymbol, queries through this interface should return addresses diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index a961992c214..3281c354676 100644 --- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -183,7 +183,7 @@ private: return Error::success(); } - std::shared_ptr ExternalSymbolResolver; + std::shared_ptr ExternalSymbolResolver; std::unique_ptr StubsMgr; StaticGlobalRenamer StaticRenamer; SourceModulesList SourceModules; @@ -223,7 +223,7 @@ public: /// @brief Add a module to the compile-on-demand layer. Expected addModule(std::shared_ptr M, - std::shared_ptr Resolver) { + std::shared_ptr Resolver) { LogicalDylibs.push_back(LogicalDylib()); auto &LD = LogicalDylibs.back(); diff --git a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h index 228392ae0d4..7b6f3d2f92a 100644 --- a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h +++ b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h @@ -23,7 +23,7 @@ namespace llvm { namespace orc { template -class LambdaResolver : public JITSymbolResolver { +class LambdaResolver : public LegacyJITSymbolResolver { public: LambdaResolver(DylibLookupFtorT DylibLookupFtor, ExternalLookupFtorT ExternalLookupFtor) diff --git a/include/llvm/ExecutionEngine/Orc/NullResolver.h b/include/llvm/ExecutionEngine/Orc/NullResolver.h index 957b94912b3..fc5cb3e7c71 100644 --- a/include/llvm/ExecutionEngine/Orc/NullResolver.h +++ b/include/llvm/ExecutionEngine/Orc/NullResolver.h @@ -22,7 +22,7 @@ namespace orc { /// SymbolResolver impliementation that rejects all resolution requests. /// Useful for clients that have no cross-object fixups. -class NullResolver : public JITSymbolResolver { +class NullResolver : public LegacyJITSymbolResolver { public: JITSymbol findSymbol(const std::string &Name) final; diff --git a/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h b/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h index 17255954a99..21d0b68a771 100644 --- a/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h +++ b/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h @@ -328,7 +328,8 @@ public: /// @return A handle that can be used to refer to the loaded object (for /// symbol searching, finalization, freeing memory, etc.). Expected - addObject(ObjectPtr Object, std::shared_ptr Resolver) { + addObject(ObjectPtr Object, + std::shared_ptr Resolver) { StringRef ObjBuffer = Object->getBinary()->getData(); if (auto HandleOrErr = this->Remote.template callB(ObjBuffer)) { @@ -386,7 +387,8 @@ private: } std::map> Resolvers; + std::shared_ptr> + Resolvers; }; /// RemoteObjectServerLayer acts as a server and handling RPC calls for the diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index 0c1862c5c3e..ee75202d2b6 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -56,7 +56,7 @@ public: // FIXME: As the RuntimeDyld fills out, additional routines will be needed // for the varying types of objects to be allocated. class RTDyldMemoryManager : public MCJITMemoryManager, - public JITSymbolResolver { + public LegacyJITSymbolResolver { public: RTDyldMemoryManager() = default; RTDyldMemoryManager(const RTDyldMemoryManager&) = delete; diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 233ece29422..e4efc15f2ae 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -49,14 +49,13 @@ STATISTIC(NumGlobals , "Number of global vars initialized"); ExecutionEngine *(*ExecutionEngine::MCJITCtor)( std::unique_ptr M, std::string *ErrorStr, std::shared_ptr MemMgr, - - std::shared_ptr Resolver, + std::shared_ptr Resolver, std::unique_ptr TM) = nullptr; ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)( - std::string *ErrorStr, std::shared_ptr MemMgr, - std::shared_ptr Resolver, - std::unique_ptr TM) = nullptr; + std::string *ErrorStr, std::shared_ptr MemMgr, + std::shared_ptr Resolver, + std::unique_ptr TM) = nullptr; ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr M, std::string *ErrorStr) =nullptr; @@ -502,9 +501,9 @@ EngineBuilder::setMemoryManager(std::unique_ptr MM) { return *this; } -EngineBuilder& -EngineBuilder::setSymbolResolver(std::unique_ptr SR) { - Resolver = std::shared_ptr(std::move(SR)); +EngineBuilder & +EngineBuilder::setSymbolResolver(std::unique_ptr SR) { + Resolver = std::shared_ptr(std::move(SR)); return *this; } diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index f7b8a3b657e..438e656b60f 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -39,11 +39,10 @@ static struct RegisterJIT { extern "C" void LLVMLinkInMCJIT() { } -ExecutionEngine* -MCJIT::createJIT(std::unique_ptr M, - std::string *ErrorStr, +ExecutionEngine * +MCJIT::createJIT(std::unique_ptr M, std::string *ErrorStr, std::shared_ptr MemMgr, - std::shared_ptr Resolver, + std::shared_ptr Resolver, std::unique_ptr TM) { // Try to register the program as a source of symbols to resolve against. // @@ -64,7 +63,7 @@ MCJIT::createJIT(std::unique_ptr M, MCJIT::MCJIT(std::unique_ptr M, std::unique_ptr TM, std::shared_ptr MemMgr, - std::shared_ptr Resolver) + std::shared_ptr Resolver) : ExecutionEngine(TM->createDataLayout(), std::move(M)), TM(std::move(TM)), Ctx(nullptr), MemMgr(std::move(MemMgr)), Resolver(*this, std::move(Resolver)), Dyld(*this->MemMgr, this->Resolver), diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index daf578f5daa..110cfa675cf 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -26,11 +26,11 @@ class MCJIT; // functions across modules that it owns. It aggregates the memory manager // that is passed in to the MCJIT constructor and defers most functionality // to that object. -class LinkingSymbolResolver : public JITSymbolResolver { +class LinkingSymbolResolver : public LegacyJITSymbolResolver { public: LinkingSymbolResolver(MCJIT &Parent, - std::shared_ptr Resolver) - : ParentEngine(Parent), ClientResolver(std::move(Resolver)) {} + std::shared_ptr Resolver) + : ParentEngine(Parent), ClientResolver(std::move(Resolver)) {} JITSymbol findSymbol(const std::string &Name) override; @@ -41,7 +41,7 @@ public: private: MCJIT &ParentEngine; - std::shared_ptr ClientResolver; + std::shared_ptr ClientResolver; }; // About Module states: added->loaded->finalized. @@ -67,7 +67,7 @@ private: class MCJIT : public ExecutionEngine { MCJIT(std::unique_ptr M, std::unique_ptr tm, std::shared_ptr MemMgr, - std::shared_ptr Resolver); + std::shared_ptr Resolver); typedef llvm::SmallPtrSet ModulePtrSet; @@ -300,11 +300,10 @@ public: MCJITCtor = createJIT; } - static ExecutionEngine* - createJIT(std::unique_ptr M, - std::string *ErrorStr, + static ExecutionEngine * + createJIT(std::unique_ptr M, std::string *ErrorStr, std::shared_ptr MemMgr, - std::shared_ptr Resolver, + std::shared_ptr Resolver, std::unique_ptr TM); // @} diff --git a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index 405970e063d..05b1f47eb5b 100644 --- a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -196,7 +196,7 @@ public: return mapError(IndirectStubsMgr->updatePointer(Name, Addr)); } - std::shared_ptr + std::shared_ptr createResolver(LLVMOrcSymbolResolverFn ExternalResolver, void *ExternalResolverCtx) { return orc::createLambdaResolver( diff --git a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 1dc8d4ac7bc..166d1369c72 100644 --- a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -138,7 +138,7 @@ class OrcMCJITReplacement : public ExecutionEngine { std::shared_ptr ClientMM; }; - class LinkingResolver : public JITSymbolResolver { + class LinkingResolver : public LegacyJITSymbolResolver { public: LinkingResolver(OrcMCJITReplacement &M) : M(M) {} @@ -160,20 +160,19 @@ private: static ExecutionEngine * createOrcMCJITReplacement(std::string *ErrorMsg, std::shared_ptr MemMgr, - std::shared_ptr Resolver, + std::shared_ptr Resolver, std::unique_ptr TM) { return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver), std::move(TM)); } public: - OrcMCJITReplacement( - std::shared_ptr MemMgr, - std::shared_ptr ClientResolver, - std::unique_ptr TM) + OrcMCJITReplacement(std::shared_ptr MemMgr, + std::shared_ptr ClientResolver, + std::unique_ptr TM) : ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)), - MemMgr(std::make_shared(*this, - std::move(MemMgr))), + MemMgr( + std::make_shared(*this, std::move(MemMgr))), Resolver(std::make_shared(*this)), ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this), NotifyFinalized(*this), @@ -378,7 +377,7 @@ private: std::unique_ptr TM; std::shared_ptr MemMgr; std::shared_ptr Resolver; - std::shared_ptr ClientResolver; + std::shared_ptr ClientResolver; Mangler Mang; // IMPORTANT: ShouldDelete *must* come before LocalModules: The shared_ptr diff --git a/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp b/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp index 87059ef2b88..670c6d2fa3f 100644 --- a/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp @@ -47,3 +47,53 @@ ARMJITSymbolFlags llvm::ARMJITSymbolFlags::fromObjectSymbol( Flags |= ARMJITSymbolFlags::Thumb; return Flags; } + +/// @brief Performs lookup by, for each symbol, first calling +/// findSymbolInLogicalDylib and if that fails calling +/// findSymbol. +Expected +LegacyJITSymbolResolver::lookup(const SymbolNameSet &Symbols) { + JITSymbolResolver::LookupResult Result; + for (auto &Symbol : Symbols) { + std::string SymName = Symbol.str(); + if (auto Sym = findSymbolInLogicalDylib(SymName)) { + if (auto AddrOrErr = Sym.getAddress()) + Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags()); + else + return AddrOrErr.takeError(); + } else if (auto Err = Sym.takeError()) + return std::move(Err); + else { + // findSymbolInLogicalDylib failed. Lets try findSymbol. + if (auto Sym = findSymbol(SymName)) { + if (auto AddrOrErr = Sym.getAddress()) + Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags()); + else + return AddrOrErr.takeError(); + } else if (auto Err = Sym.takeError()) + return std::move(Err); + else + return make_error("Symbol not found: " + Symbol, + inconvertibleErrorCode()); + } + } + + return std::move(Result); +} + +/// @brief Performs flags lookup by calling findSymbolInLogicalDylib and +/// returning the flags value for that symbol. +Expected +LegacyJITSymbolResolver::lookupFlags(const SymbolNameSet &Symbols) { + JITSymbolResolver::LookupFlagsResult Result; + + for (auto &Symbol : Symbols) { + std::string SymName = Symbol.str(); + if (auto Sym = findSymbolInLogicalDylib(SymName)) + Result[Symbol] = Sym.getFlags(); + else if (auto Err = Sym.takeError()) + return std::move(Err); + } + + return std::move(Result); +} diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 3a025f4c026..ce8d480a408 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -202,7 +202,33 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { ObjSectionToIDMap LocalSections; // Common symbols requiring allocation, with their sizes and alignments - CommonSymbolList CommonSymbols; + CommonSymbolList CommonSymbolsToAllocate; + + uint64_t CommonSize = 0; + uint32_t CommonAlign = 0; + + // First, collect all weak and common symbols. We need to know if stronger + // definitions occur elsewhere. + JITSymbolResolver::LookupFlagsResult SymbolFlags; + { + JITSymbolResolver::SymbolNameSet Symbols; + for (auto &Sym : Obj.symbols()) { + uint32_t Flags = Sym.getFlags(); + if ((Flags & SymbolRef::SF_Common) || (Flags & SymbolRef::SF_Weak)) { + // Get symbol name. + StringRef Name; + if (auto NameOrErr = Sym.getName()) + Symbols.insert(*NameOrErr); + else + return NameOrErr.takeError(); + } + } + + if (auto FlagsResultOrErr = Resolver.lookupFlags(Symbols)) + SymbolFlags = std::move(*FlagsResultOrErr); + else + return FlagsResultOrErr.takeError(); + } // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); @@ -214,102 +240,108 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { if (Flags & SymbolRef::SF_Undefined) continue; - if (Flags & SymbolRef::SF_Common) - CommonSymbols.push_back(*I); - else { + // Get the symbol type. + object::SymbolRef::Type SymType; + if (auto SymTypeOrErr = I->getType()) + SymType = *SymTypeOrErr; + else + return SymTypeOrErr.takeError(); - // Get the symbol type. - object::SymbolRef::Type SymType; - if (auto SymTypeOrErr = I->getType()) - SymType = *SymTypeOrErr; + // Get symbol name. + StringRef Name; + if (auto NameOrErr = I->getName()) + Name = *NameOrErr; + else + return NameOrErr.takeError(); + + // Compute JIT symbol flags. + JITSymbolFlags JITSymFlags = getJITSymbolFlags(*I); + + // If this is a weak definition, check to see if there's a strong one. + // If there is, skip this symbol (we won't be providing it: the strong + // definition will). If there's no strong definition, make this definition + // strong. + if (JITSymFlags.isWeak() || JITSymFlags.isCommon()) { + // First check whether there's already a definition in this instance. + // FIXME: Override existing weak definitions with strong ones. + if (GlobalSymbolTable.count(Name)) + continue; + + // Then check whether we found flags for an existing symbol during the + // flags lookup earlier. + auto FlagsI = SymbolFlags.find(Name); + if (FlagsI == SymbolFlags.end() || + (JITSymFlags.isWeak() && !FlagsI->second.isStrong()) || + (JITSymFlags.isCommon() && FlagsI->second.isCommon())) { + if (JITSymFlags.isWeak()) + JITSymFlags &= ~JITSymbolFlags::Weak; + if (JITSymFlags.isCommon()) { + JITSymFlags &= ~JITSymbolFlags::Common; + uint32_t Align = I->getAlignment(); + uint64_t Size = I->getCommonSize(); + if (!CommonAlign) + CommonAlign = Align; + CommonSize += alignTo(CommonSize, Align) + Size; + CommonSymbolsToAllocate.push_back(*I); + } + } else + continue; + } + + if (Flags & SymbolRef::SF_Absolute && + SymType != object::SymbolRef::ST_File) { + uint64_t Addr = 0; + if (auto AddrOrErr = I->getAddress()) + Addr = *AddrOrErr; else - return SymTypeOrErr.takeError(); + return AddrOrErr.takeError(); - // Get symbol name. - StringRef Name; - if (auto NameOrErr = I->getName()) - Name = *NameOrErr; + unsigned SectionID = AbsoluteSymbolSection; + + DEBUG(dbgs() << "\tType: " << SymType << " (absolute) Name: " << Name + << " SID: " << SectionID + << " Offset: " << format("%p", (uintptr_t)Addr) + << " flags: " << Flags << "\n"); + GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, Addr, JITSymFlags); + } else if (SymType == object::SymbolRef::ST_Function || + SymType == object::SymbolRef::ST_Data || + SymType == object::SymbolRef::ST_Unknown || + SymType == object::SymbolRef::ST_Other) { + + section_iterator SI = Obj.section_end(); + if (auto SIOrErr = I->getSection()) + SI = *SIOrErr; else - return NameOrErr.takeError(); + return SIOrErr.takeError(); - // Compute JIT symbol flags. - JITSymbolFlags JITSymFlags = getJITSymbolFlags(*I); + if (SI == Obj.section_end()) + continue; - // If this is a weak definition, check to see if there's a strong one. - // If there is, skip this symbol (we won't be providing it: the strong - // definition will). If there's no strong definition, make this definition - // strong. - if (JITSymFlags.isWeak()) { - // First check whether there's already a definition in this instance. - // FIXME: Override existing weak definitions with strong ones. - if (GlobalSymbolTable.count(Name)) - continue; - // Then check the symbol resolver to see if there's a definition - // elsewhere in this logical dylib. - if (auto Sym = Resolver.findSymbolInLogicalDylib(Name)) { - if (Sym.getFlags().isStrong()) - continue; - } else if (auto Err = Sym.takeError()) - return std::move(Err); - // else - JITSymFlags &= ~JITSymbolFlags::Weak; - } + // Get symbol offset. + uint64_t SectOffset; + if (auto Err = getOffset(*I, *SI, SectOffset)) + return std::move(Err); - if (Flags & SymbolRef::SF_Absolute && - SymType != object::SymbolRef::ST_File) { - uint64_t Addr = 0; - if (auto AddrOrErr = I->getAddress()) - Addr = *AddrOrErr; - else - return AddrOrErr.takeError(); + bool IsCode = SI->isText(); + unsigned SectionID; + if (auto SectionIDOrErr = + findOrEmitSection(Obj, *SI, IsCode, LocalSections)) + SectionID = *SectionIDOrErr; + else + return SectionIDOrErr.takeError(); - unsigned SectionID = AbsoluteSymbolSection; - - DEBUG(dbgs() << "\tType: " << SymType << " (absolute) Name: " << Name - << " SID: " << SectionID << " Offset: " - << format("%p", (uintptr_t)Addr) - << " flags: " << Flags << "\n"); - GlobalSymbolTable[Name] = - SymbolTableEntry(SectionID, Addr, JITSymFlags); - } else if (SymType == object::SymbolRef::ST_Function || - SymType == object::SymbolRef::ST_Data || - SymType == object::SymbolRef::ST_Unknown || - SymType == object::SymbolRef::ST_Other) { - - section_iterator SI = Obj.section_end(); - if (auto SIOrErr = I->getSection()) - SI = *SIOrErr; - else - return SIOrErr.takeError(); - - if (SI == Obj.section_end()) - continue; - - // Get symbol offset. - uint64_t SectOffset; - if (auto Err = getOffset(*I, *SI, SectOffset)) - return std::move(Err); - - bool IsCode = SI->isText(); - unsigned SectionID; - if (auto SectionIDOrErr = findOrEmitSection(Obj, *SI, IsCode, - LocalSections)) - SectionID = *SectionIDOrErr; - else - return SectionIDOrErr.takeError(); - - DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name - << " SID: " << SectionID << " Offset: " - << format("%p", (uintptr_t)SectOffset) - << " flags: " << Flags << "\n"); - GlobalSymbolTable[Name] = + DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name + << " SID: " << SectionID + << " Offset: " << format("%p", (uintptr_t)SectOffset) + << " flags: " << Flags << "\n"); + GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, SectOffset, JITSymFlags); - } } } // Allocate common symbols - if (auto Err = emitCommonSymbols(Obj, CommonSymbols)) + if (auto Err = emitCommonSymbols(Obj, CommonSymbolsToAllocate, CommonSize, + CommonAlign)) return std::move(Err); // Parse and process relocations @@ -621,45 +653,12 @@ JITSymbolFlags RuntimeDyldImpl::getJITSymbolFlags(const BasicSymbolRef &SR) { } Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, - CommonSymbolList &CommonSymbols) { - if (CommonSymbols.empty()) + CommonSymbolList &SymbolsToAllocate, + uint64_t CommonSize, + uint32_t CommonAlign) { + if (SymbolsToAllocate.empty()) return Error::success(); - uint64_t CommonSize = 0; - uint32_t CommonAlign = CommonSymbols.begin()->getAlignment(); - CommonSymbolList SymbolsToAllocate; - - DEBUG(dbgs() << "Processing common symbols...\n"); - - for (const auto &Sym : CommonSymbols) { - StringRef Name; - if (auto NameOrErr = Sym.getName()) - Name = *NameOrErr; - else - return NameOrErr.takeError(); - - // Skip common symbols already elsewhere. - if (GlobalSymbolTable.count(Name)) { - DEBUG(dbgs() << "\tSkipping already emitted common symbol '" << Name - << "'\n"); - continue; - } - - if (auto Sym = Resolver.findSymbolInLogicalDylib(Name)) { - if (!Sym.getFlags().isCommon()) { - DEBUG(dbgs() << "\tSkipping common symbol '" << Name - << "' in favor of stronger definition.\n"); - continue; - } - } - uint32_t Align = Sym.getAlignment(); - uint64_t Size = Sym.getCommonSize(); - - CommonSize = alignTo(CommonSize, Align) + Size; - - SymbolsToAllocate.push_back(Sym); - } - // Allocate memory for the section unsigned SectionID = Sections.size(); uint8_t *Addr = MemMgr.allocateDataSection(CommonSize, CommonAlign, SectionID, @@ -997,7 +996,40 @@ void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs, } Error RuntimeDyldImpl::resolveExternalSymbols() { + JITSymbolResolver::LookupResult ExternalSymbolMap; + + // Resolution can trigger emission of more symbols, so iterate until + // we've resolved *everything*. + { + JITSymbolResolver::SymbolNameSet ResolvedSymbols; + + while (true) { + JITSymbolResolver::SymbolNameSet NewSymbols; + + for (auto &RelocKV : ExternalSymbolRelocations) { + StringRef Name = RelocKV.first(); + if (!Name.empty() && !GlobalSymbolTable.count(Name) && + !ResolvedSymbols.count(Name)) + NewSymbols.insert(Name); + } + + if (NewSymbols.empty()) + break; + + auto NewResolverResults = Resolver.lookup(NewSymbols); + if (!NewResolverResults) + return NewResolverResults.takeError(); + + for (auto &RRKV : *NewResolverResults) { + assert(!ResolvedSymbols.count(RRKV.first) && "Redundant resolution?"); + ExternalSymbolMap.insert(RRKV); + ResolvedSymbols.insert(RRKV.first); + } + } + } + while (!ExternalSymbolRelocations.empty()) { + StringMap::iterator i = ExternalSymbolRelocations.begin(); StringRef Name = i->first(); @@ -1012,29 +1044,10 @@ Error RuntimeDyldImpl::resolveExternalSymbols() { JITSymbolFlags Flags; RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(Name); if (Loc == GlobalSymbolTable.end()) { - // This is an external symbol, try to get its address from the symbol - // resolver. - // First search for the symbol in this logical dylib. - if (auto Sym = Resolver.findSymbolInLogicalDylib(Name.data())) { - if (auto AddrOrErr = Sym.getAddress()) { - Addr = *AddrOrErr; - Flags = Sym.getFlags(); - } else - return AddrOrErr.takeError(); - } else if (auto Err = Sym.takeError()) - return Err; - - // If that fails, try searching for an external symbol. - if (!Addr) { - if (auto Sym = Resolver.findSymbol(Name.data())) { - if (auto AddrOrErr = Sym.getAddress()) { - Addr = *AddrOrErr; - Flags = Sym.getFlags(); - } else - return AddrOrErr.takeError(); - } else if (auto Err = Sym.takeError()) - return Err; - } + auto RRI = ExternalSymbolMap.find(Name); + assert(RRI != ExternalSymbolMap.end() && "No result for symbol"); + Addr = RRI->second.getAddress(); + Flags = RRI->second.getFlags(); // The call to getSymbolAddress may have caused additional modules to // be loaded, which may have added new entries to the // ExternalSymbolRelocations map. Consquently, we need to update our @@ -1095,6 +1108,7 @@ uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress( void RuntimeDyld::MemoryManager::anchor() {} void JITSymbolResolver::anchor() {} +void LegacyJITSymbolResolver::anchor() {} RuntimeDyld::RuntimeDyld(RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver) diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp index 5bc7434e703..0f4534f2c9f 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp @@ -731,7 +731,14 @@ bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix, bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const { if (getRTDyld().getSymbol(Symbol)) return true; - return !!getRTDyld().Resolver.findSymbol(Symbol); + JITSymbolResolver::SymbolNameSet Symbols({Symbol}); + auto Result = getRTDyld().Resolver.lookup(Symbols); + if (!Result) { + logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: "); + return false; + } + assert(Result->count(Symbol) && "Missing symbol result"); + return true; } uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const { @@ -742,7 +749,16 @@ uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const { uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const { if (auto InternalSymbol = getRTDyld().getSymbol(Symbol)) return InternalSymbol.getAddress(); - return cantFail(getRTDyld().Resolver.findSymbol(Symbol).getAddress()); + + JITSymbolResolver::SymbolNameSet Symbols({Symbol}); + auto Result = getRTDyld().Resolver.lookup(Symbols); + if (!Result) { + logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: "); + return 0; + } + auto I = Result->find(Symbol); + assert(I != Result->end() && "Missing symbol result"); + return I->second.getAddress(); } uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr, diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index e046a8504e9..e940004bb2e 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -385,7 +385,8 @@ protected: /// new section for them and update the symbol mappings in the object and /// symbol table. Error emitCommonSymbols(const ObjectFile &Obj, - CommonSymbolList &CommonSymbols); + CommonSymbolList &CommonSymbols, uint64_t CommonSize, + uint32_t CommonAlign); /// \brief Emits section data from the object file to the MemoryManager. /// \param IsCode if it's true then allocateCodeSection() will be diff --git a/tools/lli/RemoteJITUtils.h b/tools/lli/RemoteJITUtils.h index 4e948413865..944881070c7 100644 --- a/tools/lli/RemoteJITUtils.h +++ b/tools/lli/RemoteJITUtils.h @@ -84,7 +84,7 @@ public: this->MemMgr = std::move(MemMgr); } - void setResolver(std::shared_ptr Resolver) { + void setResolver(std::shared_ptr Resolver) { this->Resolver = std::move(Resolver); } @@ -145,7 +145,7 @@ public: private: std::unique_ptr MemMgr; - std::shared_ptr Resolver; + std::shared_ptr Resolver; }; }