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