1*d415bd75Srobert //===------- COFFPlatform.cpp - Utilities for executing COFF in Orc -------===//
2*d415bd75Srobert //
3*d415bd75Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*d415bd75Srobert // See https://llvm.org/LICENSE.txt for license information.
5*d415bd75Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*d415bd75Srobert //
7*d415bd75Srobert //===----------------------------------------------------------------------===//
8*d415bd75Srobert
9*d415bd75Srobert #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
10*d415bd75Srobert #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
11*d415bd75Srobert #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
12*d415bd75Srobert #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
13*d415bd75Srobert
14*d415bd75Srobert #include "llvm/Object/COFF.h"
15*d415bd75Srobert
16*d415bd75Srobert #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
17*d415bd75Srobert
18*d415bd75Srobert #include "llvm/ExecutionEngine/JITLink/x86_64.h"
19*d415bd75Srobert
20*d415bd75Srobert #define DEBUG_TYPE "orc"
21*d415bd75Srobert
22*d415bd75Srobert using namespace llvm;
23*d415bd75Srobert using namespace llvm::orc;
24*d415bd75Srobert using namespace llvm::orc::shared;
25*d415bd75Srobert
26*d415bd75Srobert namespace llvm {
27*d415bd75Srobert namespace orc {
28*d415bd75Srobert namespace shared {
29*d415bd75Srobert
30*d415bd75Srobert using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>;
31*d415bd75Srobert using SPSCOFFJITDylibDepInfoMap =
32*d415bd75Srobert SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>;
33*d415bd75Srobert using SPSCOFFObjectSectionsMap =
34*d415bd75Srobert SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
35*d415bd75Srobert using SPSCOFFRegisterObjectSectionsArgs =
36*d415bd75Srobert SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap, bool>;
37*d415bd75Srobert using SPSCOFFDeregisterObjectSectionsArgs =
38*d415bd75Srobert SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap>;
39*d415bd75Srobert
40*d415bd75Srobert } // namespace shared
41*d415bd75Srobert } // namespace orc
42*d415bd75Srobert } // namespace llvm
43*d415bd75Srobert namespace {
44*d415bd75Srobert
45*d415bd75Srobert class COFFHeaderMaterializationUnit : public MaterializationUnit {
46*d415bd75Srobert public:
COFFHeaderMaterializationUnit(COFFPlatform & CP,const SymbolStringPtr & HeaderStartSymbol)47*d415bd75Srobert COFFHeaderMaterializationUnit(COFFPlatform &CP,
48*d415bd75Srobert const SymbolStringPtr &HeaderStartSymbol)
49*d415bd75Srobert : MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)),
50*d415bd75Srobert CP(CP) {}
51*d415bd75Srobert
getName() const52*d415bd75Srobert StringRef getName() const override { return "COFFHeaderMU"; }
53*d415bd75Srobert
materialize(std::unique_ptr<MaterializationResponsibility> R)54*d415bd75Srobert void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
55*d415bd75Srobert unsigned PointerSize;
56*d415bd75Srobert support::endianness Endianness;
57*d415bd75Srobert const auto &TT =
58*d415bd75Srobert CP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
59*d415bd75Srobert
60*d415bd75Srobert switch (TT.getArch()) {
61*d415bd75Srobert case Triple::x86_64:
62*d415bd75Srobert PointerSize = 8;
63*d415bd75Srobert Endianness = support::endianness::little;
64*d415bd75Srobert break;
65*d415bd75Srobert default:
66*d415bd75Srobert llvm_unreachable("Unrecognized architecture");
67*d415bd75Srobert }
68*d415bd75Srobert
69*d415bd75Srobert auto G = std::make_unique<jitlink::LinkGraph>(
70*d415bd75Srobert "<COFFHeaderMU>", TT, PointerSize, Endianness,
71*d415bd75Srobert jitlink::getGenericEdgeKindName);
72*d415bd75Srobert auto &HeaderSection = G->createSection("__header", MemProt::Read);
73*d415bd75Srobert auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
74*d415bd75Srobert
75*d415bd75Srobert // Init symbol is __ImageBase symbol.
76*d415bd75Srobert auto &ImageBaseSymbol = G->addDefinedSymbol(
77*d415bd75Srobert HeaderBlock, 0, *R->getInitializerSymbol(), HeaderBlock.getSize(),
78*d415bd75Srobert jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
79*d415bd75Srobert
80*d415bd75Srobert addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol);
81*d415bd75Srobert
82*d415bd75Srobert CP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
83*d415bd75Srobert }
84*d415bd75Srobert
discard(const JITDylib & JD,const SymbolStringPtr & Sym)85*d415bd75Srobert void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
86*d415bd75Srobert
87*d415bd75Srobert private:
88*d415bd75Srobert struct HeaderSymbol {
89*d415bd75Srobert const char *Name;
90*d415bd75Srobert uint64_t Offset;
91*d415bd75Srobert };
92*d415bd75Srobert
93*d415bd75Srobert struct NTHeader {
94*d415bd75Srobert support::ulittle32_t PEMagic;
95*d415bd75Srobert object::coff_file_header FileHeader;
96*d415bd75Srobert struct PEHeader {
97*d415bd75Srobert object::pe32plus_header Header;
98*d415bd75Srobert object::data_directory DataDirectory[COFF::NUM_DATA_DIRECTORIES + 1];
99*d415bd75Srobert } OptionalHeader;
100*d415bd75Srobert };
101*d415bd75Srobert
102*d415bd75Srobert struct HeaderBlockContent {
103*d415bd75Srobert object::dos_header DOSHeader;
104*d415bd75Srobert COFFHeaderMaterializationUnit::NTHeader NTHeader;
105*d415bd75Srobert };
106*d415bd75Srobert
createHeaderBlock(jitlink::LinkGraph & G,jitlink::Section & HeaderSection)107*d415bd75Srobert static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
108*d415bd75Srobert jitlink::Section &HeaderSection) {
109*d415bd75Srobert HeaderBlockContent Hdr = {};
110*d415bd75Srobert
111*d415bd75Srobert // Set up magic
112*d415bd75Srobert Hdr.DOSHeader.Magic[0] = 'M';
113*d415bd75Srobert Hdr.DOSHeader.Magic[1] = 'Z';
114*d415bd75Srobert Hdr.DOSHeader.AddressOfNewExeHeader =
115*d415bd75Srobert offsetof(HeaderBlockContent, NTHeader);
116*d415bd75Srobert uint32_t PEMagic = *reinterpret_cast<const uint32_t *>(COFF::PEMagic);
117*d415bd75Srobert Hdr.NTHeader.PEMagic = PEMagic;
118*d415bd75Srobert Hdr.NTHeader.OptionalHeader.Header.Magic = COFF::PE32Header::PE32_PLUS;
119*d415bd75Srobert
120*d415bd75Srobert switch (G.getTargetTriple().getArch()) {
121*d415bd75Srobert case Triple::x86_64:
122*d415bd75Srobert Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
123*d415bd75Srobert break;
124*d415bd75Srobert default:
125*d415bd75Srobert llvm_unreachable("Unrecognized architecture");
126*d415bd75Srobert }
127*d415bd75Srobert
128*d415bd75Srobert auto HeaderContent = G.allocateString(
129*d415bd75Srobert StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
130*d415bd75Srobert
131*d415bd75Srobert return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
132*d415bd75Srobert 0);
133*d415bd75Srobert }
134*d415bd75Srobert
addImageBaseRelocationEdge(jitlink::Block & B,jitlink::Symbol & ImageBase)135*d415bd75Srobert static void addImageBaseRelocationEdge(jitlink::Block &B,
136*d415bd75Srobert jitlink::Symbol &ImageBase) {
137*d415bd75Srobert auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader) +
138*d415bd75Srobert offsetof(NTHeader, OptionalHeader) +
139*d415bd75Srobert offsetof(object::pe32plus_header, ImageBase);
140*d415bd75Srobert B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0);
141*d415bd75Srobert }
142*d415bd75Srobert
143*d415bd75Srobert static MaterializationUnit::Interface
createHeaderInterface(COFFPlatform & MOP,const SymbolStringPtr & HeaderStartSymbol)144*d415bd75Srobert createHeaderInterface(COFFPlatform &MOP,
145*d415bd75Srobert const SymbolStringPtr &HeaderStartSymbol) {
146*d415bd75Srobert SymbolFlagsMap HeaderSymbolFlags;
147*d415bd75Srobert
148*d415bd75Srobert HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
149*d415bd75Srobert
150*d415bd75Srobert return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
151*d415bd75Srobert HeaderStartSymbol);
152*d415bd75Srobert }
153*d415bd75Srobert
154*d415bd75Srobert COFFPlatform &CP;
155*d415bd75Srobert };
156*d415bd75Srobert
157*d415bd75Srobert } // end anonymous namespace
158*d415bd75Srobert
159*d415bd75Srobert namespace llvm {
160*d415bd75Srobert namespace orc {
161*d415bd75Srobert
162*d415bd75Srobert Expected<std::unique_ptr<COFFPlatform>>
Create(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,const char * OrcRuntimePath,LoadDynamicLibrary LoadDynLibrary,bool StaticVCRuntime,const char * VCRuntimePath,std::optional<SymbolAliasMap> RuntimeAliases)163*d415bd75Srobert COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
164*d415bd75Srobert JITDylib &PlatformJD, const char *OrcRuntimePath,
165*d415bd75Srobert LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
166*d415bd75Srobert const char *VCRuntimePath,
167*d415bd75Srobert std::optional<SymbolAliasMap> RuntimeAliases) {
168*d415bd75Srobert auto &EPC = ES.getExecutorProcessControl();
169*d415bd75Srobert
170*d415bd75Srobert // If the target is not supported then bail out immediately.
171*d415bd75Srobert if (!supportedTarget(EPC.getTargetTriple()))
172*d415bd75Srobert return make_error<StringError>("Unsupported COFFPlatform triple: " +
173*d415bd75Srobert EPC.getTargetTriple().str(),
174*d415bd75Srobert inconvertibleErrorCode());
175*d415bd75Srobert
176*d415bd75Srobert // Create default aliases if the caller didn't supply any.
177*d415bd75Srobert if (!RuntimeAliases)
178*d415bd75Srobert RuntimeAliases = standardPlatformAliases(ES);
179*d415bd75Srobert
180*d415bd75Srobert // Define the aliases.
181*d415bd75Srobert if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
182*d415bd75Srobert return std::move(Err);
183*d415bd75Srobert
184*d415bd75Srobert auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");
185*d415bd75Srobert
186*d415bd75Srobert // Add JIT-dispatch function support symbols.
187*d415bd75Srobert if (auto Err = HostFuncJD.define(absoluteSymbols(
188*d415bd75Srobert {{ES.intern("__orc_rt_jit_dispatch"),
189*d415bd75Srobert {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
190*d415bd75Srobert JITSymbolFlags::Exported}},
191*d415bd75Srobert {ES.intern("__orc_rt_jit_dispatch_ctx"),
192*d415bd75Srobert {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
193*d415bd75Srobert JITSymbolFlags::Exported}}})))
194*d415bd75Srobert return std::move(Err);
195*d415bd75Srobert
196*d415bd75Srobert PlatformJD.addToLinkOrder(HostFuncJD);
197*d415bd75Srobert
198*d415bd75Srobert // Create the instance.
199*d415bd75Srobert Error Err = Error::success();
200*d415bd75Srobert auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(
201*d415bd75Srobert ES, ObjLinkingLayer, PlatformJD, OrcRuntimePath,
202*d415bd75Srobert std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));
203*d415bd75Srobert if (Err)
204*d415bd75Srobert return std::move(Err);
205*d415bd75Srobert return std::move(P);
206*d415bd75Srobert }
207*d415bd75Srobert
getPerJDObjectFile()208*d415bd75Srobert Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
209*d415bd75Srobert auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
210*d415bd75Srobert if (!PerJDObj)
211*d415bd75Srobert return PerJDObj.takeError();
212*d415bd75Srobert
213*d415bd75Srobert if (!*PerJDObj)
214*d415bd75Srobert return make_error<StringError>("Could not find per jd object file",
215*d415bd75Srobert inconvertibleErrorCode());
216*d415bd75Srobert
217*d415bd75Srobert auto Buffer = (*PerJDObj)->getAsBinary();
218*d415bd75Srobert if (!Buffer)
219*d415bd75Srobert return Buffer.takeError();
220*d415bd75Srobert
221*d415bd75Srobert return (*Buffer)->getMemoryBufferRef();
222*d415bd75Srobert }
223*d415bd75Srobert
addAliases(ExecutionSession & ES,SymbolAliasMap & Aliases,ArrayRef<std::pair<const char *,const char * >> AL)224*d415bd75Srobert static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
225*d415bd75Srobert ArrayRef<std::pair<const char *, const char *>> AL) {
226*d415bd75Srobert for (auto &KV : AL) {
227*d415bd75Srobert auto AliasName = ES.intern(KV.first);
228*d415bd75Srobert assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
229*d415bd75Srobert Aliases[std::move(AliasName)] = {ES.intern(KV.second),
230*d415bd75Srobert JITSymbolFlags::Exported};
231*d415bd75Srobert }
232*d415bd75Srobert }
233*d415bd75Srobert
setupJITDylib(JITDylib & JD)234*d415bd75Srobert Error COFFPlatform::setupJITDylib(JITDylib &JD) {
235*d415bd75Srobert if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>(
236*d415bd75Srobert *this, COFFHeaderStartSymbol)))
237*d415bd75Srobert return Err;
238*d415bd75Srobert
239*d415bd75Srobert if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError())
240*d415bd75Srobert return Err;
241*d415bd75Srobert
242*d415bd75Srobert // Define the CXX aliases.
243*d415bd75Srobert SymbolAliasMap CXXAliases;
244*d415bd75Srobert addAliases(ES, CXXAliases, requiredCXXAliases());
245*d415bd75Srobert if (auto Err = JD.define(symbolAliases(std::move(CXXAliases))))
246*d415bd75Srobert return Err;
247*d415bd75Srobert
248*d415bd75Srobert auto PerJDObj = getPerJDObjectFile();
249*d415bd75Srobert if (!PerJDObj)
250*d415bd75Srobert return PerJDObj.takeError();
251*d415bd75Srobert
252*d415bd75Srobert auto I = getObjectFileInterface(ES, *PerJDObj);
253*d415bd75Srobert if (!I)
254*d415bd75Srobert return I.takeError();
255*d415bd75Srobert
256*d415bd75Srobert if (auto Err = ObjLinkingLayer.add(
257*d415bd75Srobert JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I)))
258*d415bd75Srobert return Err;
259*d415bd75Srobert
260*d415bd75Srobert if (!Bootstrapping) {
261*d415bd75Srobert auto ImportedLibs = StaticVCRuntime
262*d415bd75Srobert ? VCRuntimeBootstrap->loadStaticVCRuntime(JD)
263*d415bd75Srobert : VCRuntimeBootstrap->loadDynamicVCRuntime(JD);
264*d415bd75Srobert if (!ImportedLibs)
265*d415bd75Srobert return ImportedLibs.takeError();
266*d415bd75Srobert for (auto &Lib : *ImportedLibs)
267*d415bd75Srobert if (auto Err = LoadDynLibrary(JD, Lib))
268*d415bd75Srobert return Err;
269*d415bd75Srobert if (StaticVCRuntime)
270*d415bd75Srobert if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD))
271*d415bd75Srobert return Err;
272*d415bd75Srobert }
273*d415bd75Srobert
274*d415bd75Srobert JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer));
275*d415bd75Srobert return Error::success();
276*d415bd75Srobert }
277*d415bd75Srobert
teardownJITDylib(JITDylib & JD)278*d415bd75Srobert Error COFFPlatform::teardownJITDylib(JITDylib &JD) {
279*d415bd75Srobert std::lock_guard<std::mutex> Lock(PlatformMutex);
280*d415bd75Srobert auto I = JITDylibToHeaderAddr.find(&JD);
281*d415bd75Srobert if (I != JITDylibToHeaderAddr.end()) {
282*d415bd75Srobert assert(HeaderAddrToJITDylib.count(I->second) &&
283*d415bd75Srobert "HeaderAddrToJITDylib missing entry");
284*d415bd75Srobert HeaderAddrToJITDylib.erase(I->second);
285*d415bd75Srobert JITDylibToHeaderAddr.erase(I);
286*d415bd75Srobert }
287*d415bd75Srobert return Error::success();
288*d415bd75Srobert }
289*d415bd75Srobert
notifyAdding(ResourceTracker & RT,const MaterializationUnit & MU)290*d415bd75Srobert Error COFFPlatform::notifyAdding(ResourceTracker &RT,
291*d415bd75Srobert const MaterializationUnit &MU) {
292*d415bd75Srobert auto &JD = RT.getJITDylib();
293*d415bd75Srobert const auto &InitSym = MU.getInitializerSymbol();
294*d415bd75Srobert if (!InitSym)
295*d415bd75Srobert return Error::success();
296*d415bd75Srobert
297*d415bd75Srobert RegisteredInitSymbols[&JD].add(InitSym,
298*d415bd75Srobert SymbolLookupFlags::WeaklyReferencedSymbol);
299*d415bd75Srobert
300*d415bd75Srobert LLVM_DEBUG({
301*d415bd75Srobert dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU "
302*d415bd75Srobert << MU.getName() << "\n";
303*d415bd75Srobert });
304*d415bd75Srobert return Error::success();
305*d415bd75Srobert }
306*d415bd75Srobert
notifyRemoving(ResourceTracker & RT)307*d415bd75Srobert Error COFFPlatform::notifyRemoving(ResourceTracker &RT) {
308*d415bd75Srobert llvm_unreachable("Not supported yet");
309*d415bd75Srobert }
310*d415bd75Srobert
standardPlatformAliases(ExecutionSession & ES)311*d415bd75Srobert SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) {
312*d415bd75Srobert SymbolAliasMap Aliases;
313*d415bd75Srobert addAliases(ES, Aliases, standardRuntimeUtilityAliases());
314*d415bd75Srobert return Aliases;
315*d415bd75Srobert }
316*d415bd75Srobert
317*d415bd75Srobert ArrayRef<std::pair<const char *, const char *>>
requiredCXXAliases()318*d415bd75Srobert COFFPlatform::requiredCXXAliases() {
319*d415bd75Srobert static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
320*d415bd75Srobert {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},
321*d415bd75Srobert {"_onexit", "__orc_rt_coff_onexit_per_jd"},
322*d415bd75Srobert {"atexit", "__orc_rt_coff_atexit_per_jd"}};
323*d415bd75Srobert
324*d415bd75Srobert return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
325*d415bd75Srobert }
326*d415bd75Srobert
327*d415bd75Srobert ArrayRef<std::pair<const char *, const char *>>
standardRuntimeUtilityAliases()328*d415bd75Srobert COFFPlatform::standardRuntimeUtilityAliases() {
329*d415bd75Srobert static const std::pair<const char *, const char *>
330*d415bd75Srobert StandardRuntimeUtilityAliases[] = {
331*d415bd75Srobert {"__orc_rt_run_program", "__orc_rt_coff_run_program"},
332*d415bd75Srobert {"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"},
333*d415bd75Srobert {"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"},
334*d415bd75Srobert {"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"},
335*d415bd75Srobert {"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"},
336*d415bd75Srobert {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
337*d415bd75Srobert
338*d415bd75Srobert return ArrayRef<std::pair<const char *, const char *>>(
339*d415bd75Srobert StandardRuntimeUtilityAliases);
340*d415bd75Srobert }
341*d415bd75Srobert
supportedTarget(const Triple & TT)342*d415bd75Srobert bool COFFPlatform::supportedTarget(const Triple &TT) {
343*d415bd75Srobert switch (TT.getArch()) {
344*d415bd75Srobert case Triple::x86_64:
345*d415bd75Srobert return true;
346*d415bd75Srobert default:
347*d415bd75Srobert return false;
348*d415bd75Srobert }
349*d415bd75Srobert }
350*d415bd75Srobert
COFFPlatform(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,const char * OrcRuntimePath,LoadDynamicLibrary LoadDynLibrary,bool StaticVCRuntime,const char * VCRuntimePath,Error & Err)351*d415bd75Srobert COFFPlatform::COFFPlatform(ExecutionSession &ES,
352*d415bd75Srobert ObjectLinkingLayer &ObjLinkingLayer,
353*d415bd75Srobert JITDylib &PlatformJD, const char *OrcRuntimePath,
354*d415bd75Srobert LoadDynamicLibrary LoadDynLibrary,
355*d415bd75Srobert bool StaticVCRuntime, const char *VCRuntimePath,
356*d415bd75Srobert Error &Err)
357*d415bd75Srobert : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
358*d415bd75Srobert LoadDynLibrary(std::move(LoadDynLibrary)),
359*d415bd75Srobert StaticVCRuntime(StaticVCRuntime),
360*d415bd75Srobert COFFHeaderStartSymbol(ES.intern("__ImageBase")) {
361*d415bd75Srobert ErrorAsOutParameter _(&Err);
362*d415bd75Srobert
363*d415bd75Srobert // Create a generator for the ORC runtime archive.
364*d415bd75Srobert auto OrcRuntimeArchiveGenerator =
365*d415bd75Srobert StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
366*d415bd75Srobert if (!OrcRuntimeArchiveGenerator) {
367*d415bd75Srobert Err = OrcRuntimeArchiveGenerator.takeError();
368*d415bd75Srobert return;
369*d415bd75Srobert }
370*d415bd75Srobert
371*d415bd75Srobert auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
372*d415bd75Srobert if (!ArchiveBuffer) {
373*d415bd75Srobert Err = createFileError(OrcRuntimePath, ArchiveBuffer.getError());
374*d415bd75Srobert return;
375*d415bd75Srobert }
376*d415bd75Srobert OrcRuntimeArchiveBuffer = std::move(*ArchiveBuffer);
377*d415bd75Srobert OrcRuntimeArchive =
378*d415bd75Srobert std::make_unique<object::Archive>(*OrcRuntimeArchiveBuffer, Err);
379*d415bd75Srobert if (Err)
380*d415bd75Srobert return;
381*d415bd75Srobert
382*d415bd75Srobert Bootstrapping.store(true);
383*d415bd75Srobert ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));
384*d415bd75Srobert
385*d415bd75Srobert // Load vc runtime
386*d415bd75Srobert auto VCRT =
387*d415bd75Srobert COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath);
388*d415bd75Srobert if (!VCRT) {
389*d415bd75Srobert Err = VCRT.takeError();
390*d415bd75Srobert return;
391*d415bd75Srobert }
392*d415bd75Srobert VCRuntimeBootstrap = std::move(*VCRT);
393*d415bd75Srobert
394*d415bd75Srobert for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries())
395*d415bd75Srobert DylibsToPreload.insert(Lib);
396*d415bd75Srobert
397*d415bd75Srobert auto ImportedLibs =
398*d415bd75Srobert StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD)
399*d415bd75Srobert : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD);
400*d415bd75Srobert if (!ImportedLibs) {
401*d415bd75Srobert Err = ImportedLibs.takeError();
402*d415bd75Srobert return;
403*d415bd75Srobert }
404*d415bd75Srobert
405*d415bd75Srobert for (auto &Lib : *ImportedLibs)
406*d415bd75Srobert DylibsToPreload.insert(Lib);
407*d415bd75Srobert
408*d415bd75Srobert PlatformJD.addGenerator(std::move(*OrcRuntimeArchiveGenerator));
409*d415bd75Srobert
410*d415bd75Srobert // PlatformJD hasn't been set up by the platform yet (since we're creating
411*d415bd75Srobert // the platform now), so set it up.
412*d415bd75Srobert if (auto E2 = setupJITDylib(PlatformJD)) {
413*d415bd75Srobert Err = std::move(E2);
414*d415bd75Srobert return;
415*d415bd75Srobert }
416*d415bd75Srobert
417*d415bd75Srobert for (auto& Lib : DylibsToPreload)
418*d415bd75Srobert if (auto E2 = LoadDynLibrary(PlatformJD, Lib)) {
419*d415bd75Srobert Err = std::move(E2);
420*d415bd75Srobert return;
421*d415bd75Srobert }
422*d415bd75Srobert
423*d415bd75Srobert if (StaticVCRuntime)
424*d415bd75Srobert if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {
425*d415bd75Srobert Err = std::move(E2);
426*d415bd75Srobert return;
427*d415bd75Srobert }
428*d415bd75Srobert
429*d415bd75Srobert // Associate wrapper function tags with JIT-side function implementations.
430*d415bd75Srobert if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
431*d415bd75Srobert Err = std::move(E2);
432*d415bd75Srobert return;
433*d415bd75Srobert }
434*d415bd75Srobert
435*d415bd75Srobert // Lookup addresses of runtime functions callable by the platform,
436*d415bd75Srobert // call the platform bootstrap function to initialize the platform-state
437*d415bd75Srobert // object in the executor.
438*d415bd75Srobert if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) {
439*d415bd75Srobert Err = std::move(E2);
440*d415bd75Srobert return;
441*d415bd75Srobert }
442*d415bd75Srobert
443*d415bd75Srobert Bootstrapping.store(false);
444*d415bd75Srobert JDBootstrapStates.clear();
445*d415bd75Srobert }
446*d415bd75Srobert
447*d415bd75Srobert Expected<COFFPlatform::JITDylibDepMap>
buildJDDepMap(JITDylib & JD)448*d415bd75Srobert COFFPlatform::buildJDDepMap(JITDylib &JD) {
449*d415bd75Srobert return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> {
450*d415bd75Srobert JITDylibDepMap JDDepMap;
451*d415bd75Srobert
452*d415bd75Srobert SmallVector<JITDylib *, 16> Worklist({&JD});
453*d415bd75Srobert while (!Worklist.empty()) {
454*d415bd75Srobert auto CurJD = Worklist.back();
455*d415bd75Srobert Worklist.pop_back();
456*d415bd75Srobert
457*d415bd75Srobert auto &DM = JDDepMap[CurJD];
458*d415bd75Srobert CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
459*d415bd75Srobert DM.reserve(O.size());
460*d415bd75Srobert for (auto &KV : O) {
461*d415bd75Srobert if (KV.first == CurJD)
462*d415bd75Srobert continue;
463*d415bd75Srobert {
464*d415bd75Srobert // Bare jitdylibs not known to the platform
465*d415bd75Srobert std::lock_guard<std::mutex> Lock(PlatformMutex);
466*d415bd75Srobert if (!JITDylibToHeaderAddr.count(KV.first)) {
467*d415bd75Srobert LLVM_DEBUG({
468*d415bd75Srobert dbgs() << "JITDylib unregistered to COFFPlatform detected in "
469*d415bd75Srobert "LinkOrder: "
470*d415bd75Srobert << CurJD->getName() << "\n";
471*d415bd75Srobert });
472*d415bd75Srobert continue;
473*d415bd75Srobert }
474*d415bd75Srobert }
475*d415bd75Srobert DM.push_back(KV.first);
476*d415bd75Srobert // Push unvisited entry.
477*d415bd75Srobert if (!JDDepMap.count(KV.first)) {
478*d415bd75Srobert Worklist.push_back(KV.first);
479*d415bd75Srobert JDDepMap[KV.first] = {};
480*d415bd75Srobert }
481*d415bd75Srobert }
482*d415bd75Srobert });
483*d415bd75Srobert }
484*d415bd75Srobert return std::move(JDDepMap);
485*d415bd75Srobert });
486*d415bd75Srobert }
487*d415bd75Srobert
pushInitializersLoop(PushInitializersSendResultFn SendResult,JITDylibSP JD,JITDylibDepMap & JDDepMap)488*d415bd75Srobert void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult,
489*d415bd75Srobert JITDylibSP JD,
490*d415bd75Srobert JITDylibDepMap &JDDepMap) {
491*d415bd75Srobert SmallVector<JITDylib *, 16> Worklist({JD.get()});
492*d415bd75Srobert DenseSet<JITDylib *> Visited({JD.get()});
493*d415bd75Srobert DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
494*d415bd75Srobert ES.runSessionLocked([&]() {
495*d415bd75Srobert while (!Worklist.empty()) {
496*d415bd75Srobert auto CurJD = Worklist.back();
497*d415bd75Srobert Worklist.pop_back();
498*d415bd75Srobert
499*d415bd75Srobert auto RISItr = RegisteredInitSymbols.find(CurJD);
500*d415bd75Srobert if (RISItr != RegisteredInitSymbols.end()) {
501*d415bd75Srobert NewInitSymbols[CurJD] = std::move(RISItr->second);
502*d415bd75Srobert RegisteredInitSymbols.erase(RISItr);
503*d415bd75Srobert }
504*d415bd75Srobert
505*d415bd75Srobert for (auto *DepJD : JDDepMap[CurJD])
506*d415bd75Srobert if (!Visited.count(DepJD)) {
507*d415bd75Srobert Worklist.push_back(DepJD);
508*d415bd75Srobert Visited.insert(DepJD);
509*d415bd75Srobert }
510*d415bd75Srobert }
511*d415bd75Srobert });
512*d415bd75Srobert
513*d415bd75Srobert // If there are no further init symbols to look up then send the link order
514*d415bd75Srobert // (as a list of header addresses) to the caller.
515*d415bd75Srobert if (NewInitSymbols.empty()) {
516*d415bd75Srobert // Build the dep info map to return.
517*d415bd75Srobert COFFJITDylibDepInfoMap DIM;
518*d415bd75Srobert DIM.reserve(JDDepMap.size());
519*d415bd75Srobert for (auto &KV : JDDepMap) {
520*d415bd75Srobert std::lock_guard<std::mutex> Lock(PlatformMutex);
521*d415bd75Srobert COFFJITDylibDepInfo DepInfo;
522*d415bd75Srobert DepInfo.reserve(KV.second.size());
523*d415bd75Srobert for (auto &Dep : KV.second) {
524*d415bd75Srobert DepInfo.push_back(JITDylibToHeaderAddr[Dep]);
525*d415bd75Srobert }
526*d415bd75Srobert auto H = JITDylibToHeaderAddr[KV.first];
527*d415bd75Srobert DIM.push_back(std::make_pair(H, std::move(DepInfo)));
528*d415bd75Srobert }
529*d415bd75Srobert SendResult(DIM);
530*d415bd75Srobert return;
531*d415bd75Srobert }
532*d415bd75Srobert
533*d415bd75Srobert // Otherwise issue a lookup and re-run this phase when it completes.
534*d415bd75Srobert lookupInitSymbolsAsync(
535*d415bd75Srobert [this, SendResult = std::move(SendResult), &JD,
536*d415bd75Srobert JDDepMap = std::move(JDDepMap)](Error Err) mutable {
537*d415bd75Srobert if (Err)
538*d415bd75Srobert SendResult(std::move(Err));
539*d415bd75Srobert else
540*d415bd75Srobert pushInitializersLoop(std::move(SendResult), JD, JDDepMap);
541*d415bd75Srobert },
542*d415bd75Srobert ES, std::move(NewInitSymbols));
543*d415bd75Srobert }
544*d415bd75Srobert
rt_pushInitializers(PushInitializersSendResultFn SendResult,ExecutorAddr JDHeaderAddr)545*d415bd75Srobert void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
546*d415bd75Srobert ExecutorAddr JDHeaderAddr) {
547*d415bd75Srobert JITDylibSP JD;
548*d415bd75Srobert {
549*d415bd75Srobert std::lock_guard<std::mutex> Lock(PlatformMutex);
550*d415bd75Srobert auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
551*d415bd75Srobert if (I != HeaderAddrToJITDylib.end())
552*d415bd75Srobert JD = I->second;
553*d415bd75Srobert }
554*d415bd75Srobert
555*d415bd75Srobert LLVM_DEBUG({
556*d415bd75Srobert dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
557*d415bd75Srobert if (JD)
558*d415bd75Srobert dbgs() << "pushing initializers for " << JD->getName() << "\n";
559*d415bd75Srobert else
560*d415bd75Srobert dbgs() << "No JITDylib for header address.\n";
561*d415bd75Srobert });
562*d415bd75Srobert
563*d415bd75Srobert if (!JD) {
564*d415bd75Srobert SendResult(
565*d415bd75Srobert make_error<StringError>("No JITDylib with header addr " +
566*d415bd75Srobert formatv("{0:x}", JDHeaderAddr.getValue()),
567*d415bd75Srobert inconvertibleErrorCode()));
568*d415bd75Srobert return;
569*d415bd75Srobert }
570*d415bd75Srobert
571*d415bd75Srobert auto JDDepMap = buildJDDepMap(*JD);
572*d415bd75Srobert if (!JDDepMap) {
573*d415bd75Srobert SendResult(JDDepMap.takeError());
574*d415bd75Srobert return;
575*d415bd75Srobert }
576*d415bd75Srobert
577*d415bd75Srobert pushInitializersLoop(std::move(SendResult), JD, *JDDepMap);
578*d415bd75Srobert }
579*d415bd75Srobert
rt_lookupSymbol(SendSymbolAddressFn SendResult,ExecutorAddr Handle,StringRef SymbolName)580*d415bd75Srobert void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
581*d415bd75Srobert ExecutorAddr Handle, StringRef SymbolName) {
582*d415bd75Srobert LLVM_DEBUG({
583*d415bd75Srobert dbgs() << "COFFPlatform::rt_lookupSymbol(\""
584*d415bd75Srobert << formatv("{0:x}", Handle.getValue()) << "\")\n";
585*d415bd75Srobert });
586*d415bd75Srobert
587*d415bd75Srobert JITDylib *JD = nullptr;
588*d415bd75Srobert
589*d415bd75Srobert {
590*d415bd75Srobert std::lock_guard<std::mutex> Lock(PlatformMutex);
591*d415bd75Srobert auto I = HeaderAddrToJITDylib.find(Handle);
592*d415bd75Srobert if (I != HeaderAddrToJITDylib.end())
593*d415bd75Srobert JD = I->second;
594*d415bd75Srobert }
595*d415bd75Srobert
596*d415bd75Srobert if (!JD) {
597*d415bd75Srobert LLVM_DEBUG({
598*d415bd75Srobert dbgs() << " No JITDylib for handle "
599*d415bd75Srobert << formatv("{0:x}", Handle.getValue()) << "\n";
600*d415bd75Srobert });
601*d415bd75Srobert SendResult(make_error<StringError>("No JITDylib associated with handle " +
602*d415bd75Srobert formatv("{0:x}", Handle.getValue()),
603*d415bd75Srobert inconvertibleErrorCode()));
604*d415bd75Srobert return;
605*d415bd75Srobert }
606*d415bd75Srobert
607*d415bd75Srobert // Use functor class to work around XL build compiler issue on AIX.
608*d415bd75Srobert class RtLookupNotifyComplete {
609*d415bd75Srobert public:
610*d415bd75Srobert RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
611*d415bd75Srobert : SendResult(std::move(SendResult)) {}
612*d415bd75Srobert void operator()(Expected<SymbolMap> Result) {
613*d415bd75Srobert if (Result) {
614*d415bd75Srobert assert(Result->size() == 1 && "Unexpected result map count");
615*d415bd75Srobert SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
616*d415bd75Srobert } else {
617*d415bd75Srobert SendResult(Result.takeError());
618*d415bd75Srobert }
619*d415bd75Srobert }
620*d415bd75Srobert
621*d415bd75Srobert private:
622*d415bd75Srobert SendSymbolAddressFn SendResult;
623*d415bd75Srobert };
624*d415bd75Srobert
625*d415bd75Srobert ES.lookup(
626*d415bd75Srobert LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
627*d415bd75Srobert SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
628*d415bd75Srobert RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
629*d415bd75Srobert }
630*d415bd75Srobert
associateRuntimeSupportFunctions(JITDylib & PlatformJD)631*d415bd75Srobert Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
632*d415bd75Srobert ExecutionSession::JITDispatchHandlerAssociationMap WFs;
633*d415bd75Srobert
634*d415bd75Srobert using LookupSymbolSPSSig =
635*d415bd75Srobert SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
636*d415bd75Srobert WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] =
637*d415bd75Srobert ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
638*d415bd75Srobert &COFFPlatform::rt_lookupSymbol);
639*d415bd75Srobert using PushInitializersSPSSig =
640*d415bd75Srobert SPSExpected<SPSCOFFJITDylibDepInfoMap>(SPSExecutorAddr);
641*d415bd75Srobert WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] =
642*d415bd75Srobert ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
643*d415bd75Srobert this, &COFFPlatform::rt_pushInitializers);
644*d415bd75Srobert
645*d415bd75Srobert return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
646*d415bd75Srobert }
647*d415bd75Srobert
runBootstrapInitializers(JDBootstrapState & BState)648*d415bd75Srobert Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {
649*d415bd75Srobert llvm::sort(BState.Initializers);
650*d415bd75Srobert if (auto Err =
651*d415bd75Srobert runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ"))
652*d415bd75Srobert return Err;
653*d415bd75Srobert
654*d415bd75Srobert if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init"))
655*d415bd75Srobert return Err;
656*d415bd75Srobert
657*d415bd75Srobert if (auto Err =
658*d415bd75Srobert runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ"))
659*d415bd75Srobert return Err;
660*d415bd75Srobert return Error::success();
661*d415bd75Srobert }
662*d415bd75Srobert
runBootstrapSubsectionInitializers(JDBootstrapState & BState,StringRef Start,StringRef End)663*d415bd75Srobert Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
664*d415bd75Srobert StringRef Start,
665*d415bd75Srobert StringRef End) {
666*d415bd75Srobert for (auto &Initializer : BState.Initializers)
667*d415bd75Srobert if (Initializer.first >= Start && Initializer.first <= End &&
668*d415bd75Srobert Initializer.second) {
669*d415bd75Srobert auto Res =
670*d415bd75Srobert ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second);
671*d415bd75Srobert if (!Res)
672*d415bd75Srobert return Res.takeError();
673*d415bd75Srobert }
674*d415bd75Srobert return Error::success();
675*d415bd75Srobert }
676*d415bd75Srobert
bootstrapCOFFRuntime(JITDylib & PlatformJD)677*d415bd75Srobert Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
678*d415bd75Srobert // Lookup of runtime symbols causes the collection of initializers if
679*d415bd75Srobert // it's static linking setting.
680*d415bd75Srobert if (auto Err = lookupAndRecordAddrs(
681*d415bd75Srobert ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
682*d415bd75Srobert {
683*d415bd75Srobert {ES.intern("__orc_rt_coff_platform_bootstrap"),
684*d415bd75Srobert &orc_rt_coff_platform_bootstrap},
685*d415bd75Srobert {ES.intern("__orc_rt_coff_platform_shutdown"),
686*d415bd75Srobert &orc_rt_coff_platform_shutdown},
687*d415bd75Srobert {ES.intern("__orc_rt_coff_register_jitdylib"),
688*d415bd75Srobert &orc_rt_coff_register_jitdylib},
689*d415bd75Srobert {ES.intern("__orc_rt_coff_deregister_jitdylib"),
690*d415bd75Srobert &orc_rt_coff_deregister_jitdylib},
691*d415bd75Srobert {ES.intern("__orc_rt_coff_register_object_sections"),
692*d415bd75Srobert &orc_rt_coff_register_object_sections},
693*d415bd75Srobert {ES.intern("__orc_rt_coff_deregister_object_sections"),
694*d415bd75Srobert &orc_rt_coff_deregister_object_sections},
695*d415bd75Srobert }))
696*d415bd75Srobert return Err;
697*d415bd75Srobert
698*d415bd75Srobert // Call bootstrap functions
699*d415bd75Srobert if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap))
700*d415bd75Srobert return Err;
701*d415bd75Srobert
702*d415bd75Srobert // Do the pending jitdylib registration actions that we couldn't do
703*d415bd75Srobert // because orc runtime was not linked fully.
704*d415bd75Srobert for (auto KV : JDBootstrapStates) {
705*d415bd75Srobert auto &JDBState = KV.second;
706*d415bd75Srobert if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>(
707*d415bd75Srobert orc_rt_coff_register_jitdylib, JDBState.JDName,
708*d415bd75Srobert JDBState.HeaderAddr))
709*d415bd75Srobert return Err;
710*d415bd75Srobert
711*d415bd75Srobert for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps)
712*d415bd75Srobert if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr,
713*d415bd75Srobert SPSCOFFObjectSectionsMap, bool)>(
714*d415bd75Srobert orc_rt_coff_register_object_sections, JDBState.HeaderAddr,
715*d415bd75Srobert ObjSectionMap, false))
716*d415bd75Srobert return Err;
717*d415bd75Srobert }
718*d415bd75Srobert
719*d415bd75Srobert // Run static initializers collected in bootstrap stage.
720*d415bd75Srobert for (auto KV : JDBootstrapStates) {
721*d415bd75Srobert auto &JDBState = KV.second;
722*d415bd75Srobert if (auto Err = runBootstrapInitializers(JDBState))
723*d415bd75Srobert return Err;
724*d415bd75Srobert }
725*d415bd75Srobert
726*d415bd75Srobert return Error::success();
727*d415bd75Srobert }
728*d415bd75Srobert
runSymbolIfExists(JITDylib & PlatformJD,StringRef SymbolName)729*d415bd75Srobert Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
730*d415bd75Srobert StringRef SymbolName) {
731*d415bd75Srobert ExecutorAddr jit_function;
732*d415bd75Srobert auto AfterCLookupErr = lookupAndRecordAddrs(
733*d415bd75Srobert ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
734*d415bd75Srobert {{ES.intern(SymbolName), &jit_function}});
735*d415bd75Srobert if (!AfterCLookupErr) {
736*d415bd75Srobert auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function);
737*d415bd75Srobert if (!Res)
738*d415bd75Srobert return Res.takeError();
739*d415bd75Srobert return Error::success();
740*d415bd75Srobert }
741*d415bd75Srobert if (!AfterCLookupErr.isA<SymbolsNotFound>())
742*d415bd75Srobert return AfterCLookupErr;
743*d415bd75Srobert consumeError(std::move(AfterCLookupErr));
744*d415bd75Srobert return Error::success();
745*d415bd75Srobert }
746*d415bd75Srobert
modifyPassConfig(MaterializationResponsibility & MR,jitlink::LinkGraph & LG,jitlink::PassConfiguration & Config)747*d415bd75Srobert void COFFPlatform::COFFPlatformPlugin::modifyPassConfig(
748*d415bd75Srobert MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
749*d415bd75Srobert jitlink::PassConfiguration &Config) {
750*d415bd75Srobert
751*d415bd75Srobert bool IsBootstrapping = CP.Bootstrapping.load();
752*d415bd75Srobert
753*d415bd75Srobert if (auto InitSymbol = MR.getInitializerSymbol()) {
754*d415bd75Srobert if (InitSymbol == CP.COFFHeaderStartSymbol) {
755*d415bd75Srobert Config.PostAllocationPasses.push_back(
756*d415bd75Srobert [this, &MR, IsBootstrapping](jitlink::LinkGraph &G) {
757*d415bd75Srobert return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping);
758*d415bd75Srobert });
759*d415bd75Srobert return;
760*d415bd75Srobert }
761*d415bd75Srobert Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
762*d415bd75Srobert return preserveInitializerSections(G, MR);
763*d415bd75Srobert });
764*d415bd75Srobert }
765*d415bd75Srobert
766*d415bd75Srobert if (!IsBootstrapping)
767*d415bd75Srobert Config.PostFixupPasses.push_back(
768*d415bd75Srobert [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
769*d415bd75Srobert return registerObjectPlatformSections(G, JD);
770*d415bd75Srobert });
771*d415bd75Srobert else
772*d415bd75Srobert Config.PostFixupPasses.push_back(
773*d415bd75Srobert [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
774*d415bd75Srobert return registerObjectPlatformSectionsInBootstrap(G, JD);
775*d415bd75Srobert });
776*d415bd75Srobert }
777*d415bd75Srobert
778*d415bd75Srobert ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
getSyntheticSymbolDependencies(MaterializationResponsibility & MR)779*d415bd75Srobert COFFPlatform::COFFPlatformPlugin::getSyntheticSymbolDependencies(
780*d415bd75Srobert MaterializationResponsibility &MR) {
781*d415bd75Srobert std::lock_guard<std::mutex> Lock(PluginMutex);
782*d415bd75Srobert auto I = InitSymbolDeps.find(&MR);
783*d415bd75Srobert if (I != InitSymbolDeps.end()) {
784*d415bd75Srobert SyntheticSymbolDependenciesMap Result;
785*d415bd75Srobert Result[MR.getInitializerSymbol()] = std::move(I->second);
786*d415bd75Srobert InitSymbolDeps.erase(&MR);
787*d415bd75Srobert return Result;
788*d415bd75Srobert }
789*d415bd75Srobert return SyntheticSymbolDependenciesMap();
790*d415bd75Srobert }
791*d415bd75Srobert
associateJITDylibHeaderSymbol(jitlink::LinkGraph & G,MaterializationResponsibility & MR,bool IsBootstraping)792*d415bd75Srobert Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol(
793*d415bd75Srobert jitlink::LinkGraph &G, MaterializationResponsibility &MR,
794*d415bd75Srobert bool IsBootstraping) {
795*d415bd75Srobert auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
796*d415bd75Srobert return Sym->getName() == *CP.COFFHeaderStartSymbol;
797*d415bd75Srobert });
798*d415bd75Srobert assert(I != G.defined_symbols().end() && "Missing COFF header start symbol");
799*d415bd75Srobert
800*d415bd75Srobert auto &JD = MR.getTargetJITDylib();
801*d415bd75Srobert std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
802*d415bd75Srobert auto HeaderAddr = (*I)->getAddress();
803*d415bd75Srobert CP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
804*d415bd75Srobert CP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
805*d415bd75Srobert if (!IsBootstraping) {
806*d415bd75Srobert G.allocActions().push_back(
807*d415bd75Srobert {cantFail(WrapperFunctionCall::Create<
808*d415bd75Srobert SPSArgList<SPSString, SPSExecutorAddr>>(
809*d415bd75Srobert CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)),
810*d415bd75Srobert cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
811*d415bd75Srobert CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
812*d415bd75Srobert } else {
813*d415bd75Srobert G.allocActions().push_back(
814*d415bd75Srobert {{},
815*d415bd75Srobert cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
816*d415bd75Srobert CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
817*d415bd75Srobert JDBootstrapState BState;
818*d415bd75Srobert BState.JD = &JD;
819*d415bd75Srobert BState.JDName = JD.getName();
820*d415bd75Srobert BState.HeaderAddr = HeaderAddr;
821*d415bd75Srobert CP.JDBootstrapStates.emplace(&JD, BState);
822*d415bd75Srobert }
823*d415bd75Srobert
824*d415bd75Srobert return Error::success();
825*d415bd75Srobert }
826*d415bd75Srobert
registerObjectPlatformSections(jitlink::LinkGraph & G,JITDylib & JD)827*d415bd75Srobert Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections(
828*d415bd75Srobert jitlink::LinkGraph &G, JITDylib &JD) {
829*d415bd75Srobert COFFObjectSectionsMap ObjSecs;
830*d415bd75Srobert auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
831*d415bd75Srobert assert(HeaderAddr && "Must be registered jitdylib");
832*d415bd75Srobert for (auto &S : G.sections()) {
833*d415bd75Srobert jitlink::SectionRange Range(S);
834*d415bd75Srobert if (Range.getSize())
835*d415bd75Srobert ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
836*d415bd75Srobert }
837*d415bd75Srobert
838*d415bd75Srobert G.allocActions().push_back(
839*d415bd75Srobert {cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>(
840*d415bd75Srobert CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)),
841*d415bd75Srobert cantFail(
842*d415bd75Srobert WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
843*d415bd75Srobert CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
844*d415bd75Srobert ObjSecs))});
845*d415bd75Srobert
846*d415bd75Srobert return Error::success();
847*d415bd75Srobert }
848*d415bd75Srobert
preserveInitializerSections(jitlink::LinkGraph & G,MaterializationResponsibility & MR)849*d415bd75Srobert Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(
850*d415bd75Srobert jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
851*d415bd75Srobert JITLinkSymbolSet InitSectionSymbols;
852*d415bd75Srobert for (auto &Sec : G.sections())
853*d415bd75Srobert if (COFFPlatform::isInitializerSection(Sec.getName()))
854*d415bd75Srobert for (auto *B : Sec.blocks())
855*d415bd75Srobert if (!B->edges_empty())
856*d415bd75Srobert InitSectionSymbols.insert(
857*d415bd75Srobert &G.addAnonymousSymbol(*B, 0, 0, false, true));
858*d415bd75Srobert
859*d415bd75Srobert std::lock_guard<std::mutex> Lock(PluginMutex);
860*d415bd75Srobert InitSymbolDeps[&MR] = InitSectionSymbols;
861*d415bd75Srobert return Error::success();
862*d415bd75Srobert }
863*d415bd75Srobert
864*d415bd75Srobert Error COFFPlatform::COFFPlatformPlugin::
registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph & G,JITDylib & JD)865*d415bd75Srobert registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,
866*d415bd75Srobert JITDylib &JD) {
867*d415bd75Srobert std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
868*d415bd75Srobert auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
869*d415bd75Srobert COFFObjectSectionsMap ObjSecs;
870*d415bd75Srobert for (auto &S : G.sections()) {
871*d415bd75Srobert jitlink::SectionRange Range(S);
872*d415bd75Srobert if (Range.getSize())
873*d415bd75Srobert ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
874*d415bd75Srobert }
875*d415bd75Srobert
876*d415bd75Srobert G.allocActions().push_back(
877*d415bd75Srobert {{},
878*d415bd75Srobert cantFail(
879*d415bd75Srobert WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
880*d415bd75Srobert CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
881*d415bd75Srobert ObjSecs))});
882*d415bd75Srobert
883*d415bd75Srobert auto &BState = CP.JDBootstrapStates[&JD];
884*d415bd75Srobert BState.ObjectSectionsMaps.push_back(std::move(ObjSecs));
885*d415bd75Srobert
886*d415bd75Srobert // Collect static initializers
887*d415bd75Srobert for (auto &S : G.sections())
888*d415bd75Srobert if (COFFPlatform::isInitializerSection(S.getName()))
889*d415bd75Srobert for (auto *B : S.blocks()) {
890*d415bd75Srobert if (B->edges_empty())
891*d415bd75Srobert continue;
892*d415bd75Srobert for (auto &E : B->edges())
893*d415bd75Srobert BState.Initializers.push_back(std::make_pair(
894*d415bd75Srobert S.getName().str(),
895*d415bd75Srobert ExecutorAddr(E.getTarget().getAddress() + E.getAddend())));
896*d415bd75Srobert }
897*d415bd75Srobert
898*d415bd75Srobert return Error::success();
899*d415bd75Srobert }
900*d415bd75Srobert
901*d415bd75Srobert } // End namespace orc.
902*d415bd75Srobert } // End namespace llvm.
903