xref: /openbsd-src/gnu/llvm/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
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