1 //===-- JITLinkRedirectableSymbolManager.cpp - JITLink redirection in Orc -===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h"
10 #include "llvm/ExecutionEngine/Orc/Core.h"
12 #define DEBUG_TYPE "orc"
15 using namespace llvm::orc
;
18 constexpr StringRef JumpStubSectionName
= "__orc_stubs";
19 constexpr StringRef StubPtrSectionName
= "__orc_stub_ptrs";
20 constexpr StringRef StubSuffix
= "$__stub_ptr";
23 void JITLinkRedirectableSymbolManager::emitRedirectableSymbols(
24 std::unique_ptr
<MaterializationResponsibility
> R
, SymbolMap InitialDests
) {
26 auto &ES
= ObjLinkingLayer
.getExecutionSession();
27 Triple TT
= ES
.getTargetTriple();
29 auto G
= std::make_unique
<jitlink::LinkGraph
>(
30 ("<indirect stubs graph #" + Twine(++StubGraphIdx
) + ">").str(),
31 ES
.getSymbolStringPool(), TT
, TT
.isArch64Bit() ? 8 : 4,
32 TT
.isLittleEndian() ? endianness::little
: endianness::big
,
33 jitlink::getGenericEdgeKindName
);
34 auto &PointerSection
=
35 G
->createSection(StubPtrSectionName
, MemProt::Write
| MemProt::Read
);
37 G
->createSection(JumpStubSectionName
, MemProt::Exec
| MemProt::Read
);
39 SymbolFlagsMap NewSymbols
;
40 for (auto &[Name
, Def
] : InitialDests
) {
41 jitlink::Symbol
*TargetSym
= nullptr;
43 TargetSym
= &G
->addAbsoluteSymbol(
44 G
->allocateName(*Name
+ "$__init_tgt"), Def
.getAddress(), 0,
45 jitlink::Linkage::Strong
, jitlink::Scope::Local
, false);
47 auto PtrName
= ES
.intern((*Name
+ StubSuffix
).str());
48 auto &Ptr
= AnonymousPtrCreator(*G
, PointerSection
, TargetSym
, 0);
50 Ptr
.setScope(jitlink::Scope::Hidden
);
51 auto &Stub
= PtrJumpStubCreator(*G
, StubsSection
, Ptr
);
53 Stub
.setScope(jitlink::Scope::Default
);
54 NewSymbols
[std::move(PtrName
)] = JITSymbolFlags();
57 // Try to claim responsibility for the new stub symbols.
58 if (auto Err
= R
->defineMaterializing(std::move(NewSymbols
))) {
59 ES
.reportError(std::move(Err
));
60 return R
->failMaterialization();
63 ObjLinkingLayer
.emit(std::move(R
), std::move(G
));
66 Error
JITLinkRedirectableSymbolManager::redirect(JITDylib
&JD
,
67 const SymbolMap
&NewDests
) {
68 auto &ES
= ObjLinkingLayer
.getExecutionSession();
70 DenseMap
<NonOwningSymbolStringPtr
, SymbolStringPtr
> PtrToStub
;
71 for (auto &[StubName
, Sym
] : NewDests
) {
72 auto PtrName
= ES
.intern((*StubName
+ StubSuffix
).str());
73 PtrToStub
[NonOwningSymbolStringPtr(PtrName
)] = StubName
;
74 LS
.add(std::move(PtrName
));
77 ES
.lookup({{&JD
, JITDylibLookupFlags::MatchAllSymbols
}}, std::move(LS
));
79 return PtrSyms
.takeError();
81 std::vector
<tpctypes::PointerWrite
> PtrWrites
;
82 for (auto &[PtrName
, PtrSym
] : *PtrSyms
) {
83 auto DestSymI
= NewDests
.find(PtrToStub
[NonOwningSymbolStringPtr(PtrName
)]);
84 assert(DestSymI
!= NewDests
.end() && "Bad ptr -> stub mapping");
85 auto &DestSym
= DestSymI
->second
;
86 PtrWrites
.push_back({PtrSym
.getAddress(), DestSym
.getAddress()});
89 return ObjLinkingLayer
.getExecutionSession()
90 .getExecutorProcessControl()
92 .writePointers(PtrWrites
);