//===-- 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 R, SymbolMap InitialDests) { auto &ES = ObjLinkingLayer.getExecutionSession(); auto G = std::make_unique( ("").str(), ES.getSymbolStringPool(), ES.getTargetTriple(), 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 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 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 ObjLinkingLayer.getExecutionSession() .getExecutorProcessControl() .getMemoryAccess() .writePointers(PtrWrites); }