1 //===-- JITLinkRedirectableSymbolManager.cpp - JITLink redirection in Orc -===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h" 10 #include "llvm/ExecutionEngine/Orc/Core.h" 11 12 #define DEBUG_TYPE "orc" 13 14 using namespace llvm; 15 using namespace llvm::orc; 16 17 namespace { 18 constexpr StringRef JumpStubSectionName = "__orc_stubs"; 19 constexpr StringRef StubPtrSectionName = "__orc_stub_ptrs"; 20 constexpr StringRef StubSuffix = "$__stub_ptr"; 21 } // namespace 22 23 void JITLinkRedirectableSymbolManager::emitRedirectableSymbols( 24 std::unique_ptr<MaterializationResponsibility> R, SymbolMap InitialDests) { 25 26 auto &ES = ObjLinkingLayer.getExecutionSession(); 27 auto G = std::make_unique<jitlink::LinkGraph>( 28 ("<indirect stubs graph #" + Twine(++StubGraphIdx) + ">").str(), 29 ES.getSymbolStringPool(), ES.getTargetTriple(), SubtargetFeatures(), 30 jitlink::getGenericEdgeKindName); 31 auto &PointerSection = 32 G->createSection(StubPtrSectionName, MemProt::Write | MemProt::Read); 33 auto &StubsSection = 34 G->createSection(JumpStubSectionName, MemProt::Exec | MemProt::Read); 35 36 SymbolFlagsMap NewSymbols; 37 for (auto &[Name, Def] : InitialDests) { 38 jitlink::Symbol *TargetSym = nullptr; 39 if (Def.getAddress()) 40 TargetSym = &G->addAbsoluteSymbol( 41 G->allocateName(*Name + "$__init_tgt"), Def.getAddress(), 0, 42 jitlink::Linkage::Strong, jitlink::Scope::Local, false); 43 44 auto PtrName = ES.intern((*Name + StubSuffix).str()); 45 auto &Ptr = AnonymousPtrCreator(*G, PointerSection, TargetSym, 0); 46 Ptr.setName(PtrName); 47 Ptr.setScope(jitlink::Scope::Hidden); 48 auto &Stub = PtrJumpStubCreator(*G, StubsSection, Ptr); 49 Stub.setName(Name); 50 Stub.setScope(jitlink::Scope::Default); 51 NewSymbols[std::move(PtrName)] = JITSymbolFlags(); 52 } 53 54 // Try to claim responsibility for the new stub symbols. 55 if (auto Err = R->defineMaterializing(std::move(NewSymbols))) { 56 ES.reportError(std::move(Err)); 57 return R->failMaterialization(); 58 } 59 60 ObjLinkingLayer.emit(std::move(R), std::move(G)); 61 } 62 63 Error JITLinkRedirectableSymbolManager::redirect(JITDylib &JD, 64 const SymbolMap &NewDests) { 65 auto &ES = ObjLinkingLayer.getExecutionSession(); 66 SymbolLookupSet LS; 67 DenseMap<NonOwningSymbolStringPtr, SymbolStringPtr> PtrToStub; 68 for (auto &[StubName, Sym] : NewDests) { 69 auto PtrName = ES.intern((*StubName + StubSuffix).str()); 70 PtrToStub[NonOwningSymbolStringPtr(PtrName)] = StubName; 71 LS.add(std::move(PtrName)); 72 } 73 auto PtrSyms = 74 ES.lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}}, std::move(LS)); 75 if (!PtrSyms) 76 return PtrSyms.takeError(); 77 78 std::vector<tpctypes::PointerWrite> PtrWrites; 79 for (auto &[PtrName, PtrSym] : *PtrSyms) { 80 auto DestSymI = NewDests.find(PtrToStub[NonOwningSymbolStringPtr(PtrName)]); 81 assert(DestSymI != NewDests.end() && "Bad ptr -> stub mapping"); 82 auto &DestSym = DestSymI->second; 83 PtrWrites.push_back({PtrSym.getAddress(), DestSym.getAddress()}); 84 } 85 86 return ObjLinkingLayer.getExecutionSession() 87 .getExecutorProcessControl() 88 .getMemoryAccess() 89 .writePointers(PtrWrites); 90 } 91