| //===-- JITLinkRedirectableSymbolManager.cpp - JITLink redirection in Orc -===// | |
| // | |
| // 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h" | |
| #include "llvm/ExecutionEngine/Orc/Core.h" | |
| #define DEBUG_TYPE "orc" | |
| using namespace llvm; | |
| using namespace llvm::orc; | |
| namespace { | |
| constexpr StringRef JumpStubSectionName = "__orc_stubs"; | |
| constexpr StringRef StubPtrSectionName = "__orc_stub_ptrs"; | |
| constexpr StringRef StubSuffix = "$__stub_ptr"; | |
| } // namespace | |
| void JITLinkRedirectableSymbolManager::emitRedirectableSymbols( | |
| std::unique_ptr<MaterializationResponsibility> R, SymbolMap InitialDests) { | |
| auto &ES = ObjLinkingLayer.getExecutionSession(); | |
| auto G = std::make_unique<jitlink::LinkGraph>( | |
| ("<indirect stubs graph #" + Twine(++StubGraphIdx) + ">").str(), | |
| ES.getSymbolStringPool(), ES.getTargetTriple(), | |
| ES.getTargetTriple().getArchPointerBitWidth() / 8, SubtargetFeatures(), | |
| jitlink::getGenericEdgeKindName); | |
| auto &PointerSection = | |
| G->createSection(StubPtrSectionName, MemProt::Write | MemProt::Read); | |
| auto &StubsSection = | |
| G->createSection(JumpStubSectionName, MemProt::Exec | MemProt::Read); | |
| SymbolFlagsMap NewSymbols; | |
| for (auto &[Name, Def] : InitialDests) { | |
| jitlink::Symbol *TargetSym = nullptr; | |
| if (Def.getAddress()) | |
| TargetSym = &G->addAbsoluteSymbol( | |
| G->allocateName(*Name + "$__init_tgt"), Def.getAddress(), 0, | |
| jitlink::Linkage::Strong, jitlink::Scope::Local, false); | |
| auto PtrName = ES.intern((*Name + StubSuffix).str()); | |
| auto &Ptr = AnonymousPtrCreator(*G, PointerSection, TargetSym, 0); | |
| Ptr.setName(PtrName); | |
| Ptr.setScope(jitlink::Scope::Hidden); | |
| auto &Stub = PtrJumpStubCreator(*G, StubsSection, Ptr); | |
| Stub.setName(Name); | |
| Stub.setScope(Def.getFlags().isExported() ? jitlink::Scope::Default | |
| : jitlink::Scope::Hidden); | |
| Stub.setLinkage(!Def.getFlags().isWeak() ? jitlink::Linkage::Strong | |
| : jitlink::Linkage::Weak); | |
| NewSymbols[std::move(PtrName)] = JITSymbolFlags(); | |
| } | |
| // Try to claim responsibility for the new stub symbols. | |
| if (auto Err = R->defineMaterializing(std::move(NewSymbols))) { | |
| ES.reportError(std::move(Err)); | |
| return R->failMaterialization(); | |
| } | |
| ObjLinkingLayer.emit(std::move(R), std::move(G)); | |
| } | |
| Error JITLinkRedirectableSymbolManager::redirect(JITDylib &JD, | |
| const SymbolMap &NewDests) { | |
| auto &ES = ObjLinkingLayer.getExecutionSession(); | |
| SymbolLookupSet LS; | |
| DenseMap<NonOwningSymbolStringPtr, SymbolStringPtr> PtrToStub; | |
| for (auto &[StubName, Sym] : NewDests) { | |
| auto PtrName = ES.intern((*StubName + StubSuffix).str()); | |
| PtrToStub[NonOwningSymbolStringPtr(PtrName)] = StubName; | |
| LS.add(std::move(PtrName)); | |
| } | |
| auto PtrSyms = | |
| ES.lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}}, std::move(LS)); | |
| if (!PtrSyms) | |
| return PtrSyms.takeError(); | |
| std::vector<tpctypes::PointerWrite> PtrWrites; | |
| for (auto &[PtrName, PtrSym] : *PtrSyms) { | |
| auto DestSymI = NewDests.find(PtrToStub[NonOwningSymbolStringPtr(PtrName)]); | |
| assert(DestSymI != NewDests.end() && "Bad ptr -> stub mapping"); | |
| auto &DestSym = DestSymI->second; | |
| PtrWrites.push_back({PtrSym.getAddress(), DestSym.getAddress()}); | |
| } | |
| return MemAccess.writePointers(PtrWrites); | |
| } |