xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp (revision 4eaff6c58ae2f130ac8d63cf2c87bbb483114876)
19189a266SSunho Kim //===------- COFFPlatform.cpp - Utilities for executing COFF in Orc -------===//
29189a266SSunho Kim //
39189a266SSunho Kim // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49189a266SSunho Kim // See https://llvm.org/LICENSE.txt for license information.
59189a266SSunho Kim // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69189a266SSunho Kim //
79189a266SSunho Kim //===----------------------------------------------------------------------===//
89189a266SSunho Kim 
99189a266SSunho Kim #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
10dc11c060SLang Hames #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
119189a266SSunho Kim #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
129189a266SSunho Kim #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
1373c40339Ssunho #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
143d4e9d5eSLang Hames #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
159189a266SSunho Kim 
169189a266SSunho Kim #include "llvm/Object/COFF.h"
179189a266SSunho Kim 
189189a266SSunho Kim #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
199189a266SSunho Kim 
209189a266SSunho Kim #include "llvm/ExecutionEngine/JITLink/x86_64.h"
219189a266SSunho Kim 
229189a266SSunho Kim #define DEBUG_TYPE "orc"
239189a266SSunho Kim 
249189a266SSunho Kim using namespace llvm;
259189a266SSunho Kim using namespace llvm::orc;
269189a266SSunho Kim using namespace llvm::orc::shared;
279189a266SSunho Kim 
289189a266SSunho Kim namespace llvm {
299189a266SSunho Kim namespace orc {
309189a266SSunho Kim namespace shared {
319189a266SSunho Kim 
329189a266SSunho Kim using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>;
339189a266SSunho Kim using SPSCOFFJITDylibDepInfoMap =
349189a266SSunho Kim     SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>;
359189a266SSunho Kim using SPSCOFFObjectSectionsMap =
369189a266SSunho Kim     SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
379189a266SSunho Kim using SPSCOFFRegisterObjectSectionsArgs =
389189a266SSunho Kim     SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap, bool>;
399189a266SSunho Kim using SPSCOFFDeregisterObjectSectionsArgs =
409189a266SSunho Kim     SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap>;
419189a266SSunho Kim 
429189a266SSunho Kim } // namespace shared
439189a266SSunho Kim } // namespace orc
449189a266SSunho Kim } // namespace llvm
459189a266SSunho Kim namespace {
469189a266SSunho Kim 
479189a266SSunho Kim class COFFHeaderMaterializationUnit : public MaterializationUnit {
489189a266SSunho Kim public:
499189a266SSunho Kim   COFFHeaderMaterializationUnit(COFFPlatform &CP,
509189a266SSunho Kim                                 const SymbolStringPtr &HeaderStartSymbol)
519189a266SSunho Kim       : MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)),
529189a266SSunho Kim         CP(CP) {}
539189a266SSunho Kim 
549189a266SSunho Kim   StringRef getName() const override { return "COFFHeaderMU"; }
559189a266SSunho Kim 
569189a266SSunho Kim   void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
579189a266SSunho Kim     auto G = std::make_unique<jitlink::LinkGraph>(
58*4eaff6c5SLang Hames         "<COFFHeaderMU>", CP.getExecutionSession().getSymbolStringPool(),
59*4eaff6c5SLang Hames         CP.getExecutionSession().getTargetTriple(), SubtargetFeatures(),
60*4eaff6c5SLang Hames         jitlink::getGenericEdgeKindName);
61d3d9f7caSLang Hames     auto &HeaderSection = G->createSection("__header", MemProt::Read);
629189a266SSunho Kim     auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
639189a266SSunho Kim 
649189a266SSunho Kim     // Init symbol is __ImageBase symbol.
659189a266SSunho Kim     auto &ImageBaseSymbol = G->addDefinedSymbol(
669189a266SSunho Kim         HeaderBlock, 0, *R->getInitializerSymbol(), HeaderBlock.getSize(),
6728e2a891SLang Hames         jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
689189a266SSunho Kim 
699189a266SSunho Kim     addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol);
709189a266SSunho Kim 
719189a266SSunho Kim     CP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
729189a266SSunho Kim   }
739189a266SSunho Kim 
749189a266SSunho Kim   void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
759189a266SSunho Kim 
769189a266SSunho Kim private:
779189a266SSunho Kim   struct HeaderSymbol {
789189a266SSunho Kim     const char *Name;
799189a266SSunho Kim     uint64_t Offset;
809189a266SSunho Kim   };
819189a266SSunho Kim 
829189a266SSunho Kim   struct NTHeader {
839189a266SSunho Kim     support::ulittle32_t PEMagic;
849189a266SSunho Kim     object::coff_file_header FileHeader;
859189a266SSunho Kim     struct PEHeader {
869189a266SSunho Kim       object::pe32plus_header Header;
879189a266SSunho Kim       object::data_directory DataDirectory[COFF::NUM_DATA_DIRECTORIES + 1];
889189a266SSunho Kim     } OptionalHeader;
899189a266SSunho Kim   };
909189a266SSunho Kim 
919189a266SSunho Kim   struct HeaderBlockContent {
929189a266SSunho Kim     object::dos_header DOSHeader;
937332b18fSSunho Kim     COFFHeaderMaterializationUnit::NTHeader NTHeader;
949189a266SSunho Kim   };
959189a266SSunho Kim 
969189a266SSunho Kim   static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
979189a266SSunho Kim                                            jitlink::Section &HeaderSection) {
989189a266SSunho Kim     HeaderBlockContent Hdr = {};
999189a266SSunho Kim 
1009189a266SSunho Kim     // Set up magic
1019189a266SSunho Kim     Hdr.DOSHeader.Magic[0] = 'M';
1029189a266SSunho Kim     Hdr.DOSHeader.Magic[1] = 'Z';
1039189a266SSunho Kim     Hdr.DOSHeader.AddressOfNewExeHeader =
1049189a266SSunho Kim         offsetof(HeaderBlockContent, NTHeader);
1059189a266SSunho Kim     uint32_t PEMagic = *reinterpret_cast<const uint32_t *>(COFF::PEMagic);
1069189a266SSunho Kim     Hdr.NTHeader.PEMagic = PEMagic;
1079189a266SSunho Kim     Hdr.NTHeader.OptionalHeader.Header.Magic = COFF::PE32Header::PE32_PLUS;
1089189a266SSunho Kim 
1099189a266SSunho Kim     switch (G.getTargetTriple().getArch()) {
1109189a266SSunho Kim     case Triple::x86_64:
1119189a266SSunho Kim       Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
1129189a266SSunho Kim       break;
1139189a266SSunho Kim     default:
1149189a266SSunho Kim       llvm_unreachable("Unrecognized architecture");
1159189a266SSunho Kim     }
1169189a266SSunho Kim 
11710b5fec2SLang Hames     auto HeaderContent = G.allocateContent(
11810b5fec2SLang Hames         ArrayRef<char>(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
1199189a266SSunho Kim 
1209189a266SSunho Kim     return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
1219189a266SSunho Kim                                 0);
1229189a266SSunho Kim   }
1239189a266SSunho Kim 
1249189a266SSunho Kim   static void addImageBaseRelocationEdge(jitlink::Block &B,
1259189a266SSunho Kim                                          jitlink::Symbol &ImageBase) {
1269189a266SSunho Kim     auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader) +
1279189a266SSunho Kim                            offsetof(NTHeader, OptionalHeader) +
1289189a266SSunho Kim                            offsetof(object::pe32plus_header, ImageBase);
1299189a266SSunho Kim     B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0);
1309189a266SSunho Kim   }
1319189a266SSunho Kim 
1329189a266SSunho Kim   static MaterializationUnit::Interface
1339189a266SSunho Kim   createHeaderInterface(COFFPlatform &MOP,
1349189a266SSunho Kim                         const SymbolStringPtr &HeaderStartSymbol) {
1359189a266SSunho Kim     SymbolFlagsMap HeaderSymbolFlags;
1369189a266SSunho Kim 
1379189a266SSunho Kim     HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
1389189a266SSunho Kim 
1399189a266SSunho Kim     return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
1409189a266SSunho Kim                                           HeaderStartSymbol);
1419189a266SSunho Kim   }
1429189a266SSunho Kim 
1439189a266SSunho Kim   COFFPlatform &CP;
1449189a266SSunho Kim };
1459189a266SSunho Kim 
1469189a266SSunho Kim } // end anonymous namespace
1479189a266SSunho Kim 
1489189a266SSunho Kim namespace llvm {
1499189a266SSunho Kim namespace orc {
1509189a266SSunho Kim 
1511b6a46abSTyler Kenney Expected<std::unique_ptr<COFFPlatform>>
1521b6a46abSTyler Kenney COFFPlatform::Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
1531b6a46abSTyler Kenney                      std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,
15473c40339Ssunho                      LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
1551b6a46abSTyler Kenney                      const char *VCRuntimePath,
1561b6a46abSTyler Kenney                      std::optional<SymbolAliasMap> RuntimeAliases) {
1571b6a46abSTyler Kenney 
1581b6a46abSTyler Kenney   auto &ES = ObjLinkingLayer.getExecutionSession();
1599189a266SSunho Kim 
1609189a266SSunho Kim   // If the target is not supported then bail out immediately.
1610df66569SLang Hames   if (!supportedTarget(ES.getTargetTriple()))
1629189a266SSunho Kim     return make_error<StringError>("Unsupported COFFPlatform triple: " +
1630df66569SLang Hames                                        ES.getTargetTriple().str(),
1649189a266SSunho Kim                                    inconvertibleErrorCode());
1659189a266SSunho Kim 
1660df66569SLang Hames   auto &EPC = ES.getExecutorProcessControl();
1670df66569SLang Hames 
168231107a8SLang Hames   auto GeneratorArchive =
169231107a8SLang Hames       object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef());
170231107a8SLang Hames   if (!GeneratorArchive)
171231107a8SLang Hames     return GeneratorArchive.takeError();
172231107a8SLang Hames 
173231107a8SLang Hames   auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Create(
174231107a8SLang Hames       ObjLinkingLayer, nullptr, std::move(*GeneratorArchive));
175231107a8SLang Hames   if (!OrcRuntimeArchiveGenerator)
176231107a8SLang Hames     return OrcRuntimeArchiveGenerator.takeError();
177231107a8SLang Hames 
178231107a8SLang Hames   // We need a second instance of the archive (for now) for the Platform. We
179231107a8SLang Hames   // can `cantFail` this call, since if it were going to fail it would have
180231107a8SLang Hames   // failed above.
181231107a8SLang Hames   auto RuntimeArchive = cantFail(
182231107a8SLang Hames       object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef()));
183231107a8SLang Hames 
1849189a266SSunho Kim   // Create default aliases if the caller didn't supply any.
1859189a266SSunho Kim   if (!RuntimeAliases)
1869189a266SSunho Kim     RuntimeAliases = standardPlatformAliases(ES);
1879189a266SSunho Kim 
1889189a266SSunho Kim   // Define the aliases.
1899189a266SSunho Kim   if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
1909189a266SSunho Kim     return std::move(Err);
1919189a266SSunho Kim 
192bc24e6abSsunho   auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");
193bc24e6abSsunho 
1949189a266SSunho Kim   // Add JIT-dispatch function support symbols.
1958b1771bdSLang Hames   if (auto Err = HostFuncJD.define(
1968b1771bdSLang Hames           absoluteSymbols({{ES.intern("__orc_rt_jit_dispatch"),
1978b1771bdSLang Hames                             {EPC.getJITDispatchInfo().JITDispatchFunction,
1989189a266SSunho Kim                              JITSymbolFlags::Exported}},
1999189a266SSunho Kim                            {ES.intern("__orc_rt_jit_dispatch_ctx"),
2008b1771bdSLang Hames                             {EPC.getJITDispatchInfo().JITDispatchContext,
2019189a266SSunho Kim                              JITSymbolFlags::Exported}}})))
2029189a266SSunho Kim     return std::move(Err);
2039189a266SSunho Kim 
204bc24e6abSsunho   PlatformJD.addToLinkOrder(HostFuncJD);
2059189a266SSunho Kim 
2069189a266SSunho Kim   // Create the instance.
2079189a266SSunho Kim   Error Err = Error::success();
2089189a266SSunho Kim   auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(
2091b6a46abSTyler Kenney       ObjLinkingLayer, PlatformJD, std::move(*OrcRuntimeArchiveGenerator),
210231107a8SLang Hames       std::move(OrcRuntimeArchiveBuffer), std::move(RuntimeArchive),
21173c40339Ssunho       std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));
2129189a266SSunho Kim   if (Err)
2139189a266SSunho Kim     return std::move(Err);
2149189a266SSunho Kim   return std::move(P);
2159189a266SSunho Kim }
2169189a266SSunho Kim 
217231107a8SLang Hames Expected<std::unique_ptr<COFFPlatform>>
2181b6a46abSTyler Kenney COFFPlatform::Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
2191b6a46abSTyler Kenney                      const char *OrcRuntimePath,
220231107a8SLang Hames                      LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
221231107a8SLang Hames                      const char *VCRuntimePath,
222231107a8SLang Hames                      std::optional<SymbolAliasMap> RuntimeAliases) {
223231107a8SLang Hames 
224231107a8SLang Hames   auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
225231107a8SLang Hames   if (!ArchiveBuffer)
226231107a8SLang Hames     return createFileError(OrcRuntimePath, ArchiveBuffer.getError());
227231107a8SLang Hames 
2281b6a46abSTyler Kenney   return Create(ObjLinkingLayer, PlatformJD, std::move(*ArchiveBuffer),
229231107a8SLang Hames                 std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath,
230231107a8SLang Hames                 std::move(RuntimeAliases));
231231107a8SLang Hames }
232231107a8SLang Hames 
23373c40339Ssunho Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
23473c40339Ssunho   auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
23573c40339Ssunho   if (!PerJDObj)
23673c40339Ssunho     return PerJDObj.takeError();
23773c40339Ssunho 
23873c40339Ssunho   if (!*PerJDObj)
23973c40339Ssunho     return make_error<StringError>("Could not find per jd object file",
24073c40339Ssunho                                    inconvertibleErrorCode());
24173c40339Ssunho 
24273c40339Ssunho   auto Buffer = (*PerJDObj)->getAsBinary();
24373c40339Ssunho   if (!Buffer)
24473c40339Ssunho     return Buffer.takeError();
24573c40339Ssunho 
24673c40339Ssunho   return (*Buffer)->getMemoryBufferRef();
24773c40339Ssunho }
24873c40339Ssunho 
24973c40339Ssunho static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
25073c40339Ssunho                        ArrayRef<std::pair<const char *, const char *>> AL) {
25173c40339Ssunho   for (auto &KV : AL) {
25273c40339Ssunho     auto AliasName = ES.intern(KV.first);
25373c40339Ssunho     assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
25473c40339Ssunho     Aliases[std::move(AliasName)] = {ES.intern(KV.second),
25573c40339Ssunho                                      JITSymbolFlags::Exported};
25673c40339Ssunho   }
25773c40339Ssunho }
25873c40339Ssunho 
2599189a266SSunho Kim Error COFFPlatform::setupJITDylib(JITDylib &JD) {
2609189a266SSunho Kim   if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>(
2619189a266SSunho Kim           *this, COFFHeaderStartSymbol)))
2629189a266SSunho Kim     return Err;
2639189a266SSunho Kim 
2649189a266SSunho Kim   if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError())
2659189a266SSunho Kim     return Err;
2669189a266SSunho Kim 
26773c40339Ssunho   // Define the CXX aliases.
26873c40339Ssunho   SymbolAliasMap CXXAliases;
26973c40339Ssunho   addAliases(ES, CXXAliases, requiredCXXAliases());
27073c40339Ssunho   if (auto Err = JD.define(symbolAliases(std::move(CXXAliases))))
271e57ded44Ssunho     return Err;
27273c40339Ssunho 
27373c40339Ssunho   auto PerJDObj = getPerJDObjectFile();
27473c40339Ssunho   if (!PerJDObj)
27573c40339Ssunho     return PerJDObj.takeError();
27673c40339Ssunho 
27773c40339Ssunho   auto I = getObjectFileInterface(ES, *PerJDObj);
27873c40339Ssunho   if (!I)
27973c40339Ssunho     return I.takeError();
28073c40339Ssunho 
28173c40339Ssunho   if (auto Err = ObjLinkingLayer.add(
28273c40339Ssunho           JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I)))
28373c40339Ssunho     return Err;
28473c40339Ssunho 
2859189a266SSunho Kim   if (!Bootstrapping) {
28673c40339Ssunho     auto ImportedLibs = StaticVCRuntime
28773c40339Ssunho                             ? VCRuntimeBootstrap->loadStaticVCRuntime(JD)
28873c40339Ssunho                             : VCRuntimeBootstrap->loadDynamicVCRuntime(JD);
2899189a266SSunho Kim     if (!ImportedLibs)
2909189a266SSunho Kim       return ImportedLibs.takeError();
2919189a266SSunho Kim     for (auto &Lib : *ImportedLibs)
2929189a266SSunho Kim       if (auto Err = LoadDynLibrary(JD, Lib))
2939189a266SSunho Kim         return Err;
29473c40339Ssunho     if (StaticVCRuntime)
2959189a266SSunho Kim       if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD))
2969189a266SSunho Kim         return Err;
2979189a266SSunho Kim   }
2989189a266SSunho Kim 
299bc24e6abSsunho   JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer));
3009189a266SSunho Kim   return Error::success();
3019189a266SSunho Kim }
3029189a266SSunho Kim 
3039189a266SSunho Kim Error COFFPlatform::teardownJITDylib(JITDylib &JD) {
3049189a266SSunho Kim   std::lock_guard<std::mutex> Lock(PlatformMutex);
3059189a266SSunho Kim   auto I = JITDylibToHeaderAddr.find(&JD);
3069189a266SSunho Kim   if (I != JITDylibToHeaderAddr.end()) {
3079189a266SSunho Kim     assert(HeaderAddrToJITDylib.count(I->second) &&
3089189a266SSunho Kim            "HeaderAddrToJITDylib missing entry");
3099189a266SSunho Kim     HeaderAddrToJITDylib.erase(I->second);
3109189a266SSunho Kim     JITDylibToHeaderAddr.erase(I);
3119189a266SSunho Kim   }
3129189a266SSunho Kim   return Error::success();
3139189a266SSunho Kim }
3149189a266SSunho Kim 
3159189a266SSunho Kim Error COFFPlatform::notifyAdding(ResourceTracker &RT,
3169189a266SSunho Kim                                  const MaterializationUnit &MU) {
3179189a266SSunho Kim   auto &JD = RT.getJITDylib();
3189189a266SSunho Kim   const auto &InitSym = MU.getInitializerSymbol();
3199189a266SSunho Kim   if (!InitSym)
3209189a266SSunho Kim     return Error::success();
3219189a266SSunho Kim 
3229189a266SSunho Kim   RegisteredInitSymbols[&JD].add(InitSym,
3239189a266SSunho Kim                                  SymbolLookupFlags::WeaklyReferencedSymbol);
3249189a266SSunho Kim 
3259189a266SSunho Kim   LLVM_DEBUG({
3269189a266SSunho Kim     dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU "
3279189a266SSunho Kim            << MU.getName() << "\n";
3289189a266SSunho Kim   });
3299189a266SSunho Kim   return Error::success();
3309189a266SSunho Kim }
3319189a266SSunho Kim 
3329189a266SSunho Kim Error COFFPlatform::notifyRemoving(ResourceTracker &RT) {
3339189a266SSunho Kim   llvm_unreachable("Not supported yet");
3349189a266SSunho Kim }
3359189a266SSunho Kim 
3369189a266SSunho Kim SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) {
3379189a266SSunho Kim   SymbolAliasMap Aliases;
3389189a266SSunho Kim   addAliases(ES, Aliases, standardRuntimeUtilityAliases());
3399189a266SSunho Kim   return Aliases;
3409189a266SSunho Kim }
3419189a266SSunho Kim 
3429189a266SSunho Kim ArrayRef<std::pair<const char *, const char *>>
3439189a266SSunho Kim COFFPlatform::requiredCXXAliases() {
3449189a266SSunho Kim   static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
3459189a266SSunho Kim       {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},
34673c40339Ssunho       {"_onexit", "__orc_rt_coff_onexit_per_jd"},
34773c40339Ssunho       {"atexit", "__orc_rt_coff_atexit_per_jd"}};
3489189a266SSunho Kim 
3499189a266SSunho Kim   return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
3509189a266SSunho Kim }
3519189a266SSunho Kim 
3529189a266SSunho Kim ArrayRef<std::pair<const char *, const char *>>
3539189a266SSunho Kim COFFPlatform::standardRuntimeUtilityAliases() {
3549189a266SSunho Kim   static const std::pair<const char *, const char *>
3559189a266SSunho Kim       StandardRuntimeUtilityAliases[] = {
3569189a266SSunho Kim           {"__orc_rt_run_program", "__orc_rt_coff_run_program"},
3579189a266SSunho Kim           {"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"},
3589189a266SSunho Kim           {"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"},
3599189a266SSunho Kim           {"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"},
3609189a266SSunho Kim           {"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"},
3619189a266SSunho Kim           {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
3629189a266SSunho Kim 
3639189a266SSunho Kim   return ArrayRef<std::pair<const char *, const char *>>(
3649189a266SSunho Kim       StandardRuntimeUtilityAliases);
3659189a266SSunho Kim }
3669189a266SSunho Kim 
3679189a266SSunho Kim bool COFFPlatform::supportedTarget(const Triple &TT) {
3689189a266SSunho Kim   switch (TT.getArch()) {
3699189a266SSunho Kim   case Triple::x86_64:
3709189a266SSunho Kim     return true;
3719189a266SSunho Kim   default:
3729189a266SSunho Kim     return false;
3739189a266SSunho Kim   }
3749189a266SSunho Kim }
3759189a266SSunho Kim 
376231107a8SLang Hames COFFPlatform::COFFPlatform(
3771b6a46abSTyler Kenney     ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
378231107a8SLang Hames     std::unique_ptr<StaticLibraryDefinitionGenerator> OrcRuntimeGenerator,
379231107a8SLang Hames     std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,
380231107a8SLang Hames     std::unique_ptr<object::Archive> OrcRuntimeArchive,
381231107a8SLang Hames     LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
382231107a8SLang Hames     const char *VCRuntimePath, Error &Err)
3831b6a46abSTyler Kenney     : ES(ObjLinkingLayer.getExecutionSession()),
3841b6a46abSTyler Kenney       ObjLinkingLayer(ObjLinkingLayer),
385231107a8SLang Hames       LoadDynLibrary(std::move(LoadDynLibrary)),
386231107a8SLang Hames       OrcRuntimeArchiveBuffer(std::move(OrcRuntimeArchiveBuffer)),
387231107a8SLang Hames       OrcRuntimeArchive(std::move(OrcRuntimeArchive)),
38873c40339Ssunho       StaticVCRuntime(StaticVCRuntime),
3899189a266SSunho Kim       COFFHeaderStartSymbol(ES.intern("__ImageBase")) {
390d02c1676SLang Hames   ErrorAsOutParameter _(Err);
3919189a266SSunho Kim 
3929189a266SSunho Kim   Bootstrapping.store(true);
3939189a266SSunho Kim   ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));
3949189a266SSunho Kim 
3959189a266SSunho Kim   // Load vc runtime
3969189a266SSunho Kim   auto VCRT =
3979189a266SSunho Kim       COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath);
3989189a266SSunho Kim   if (!VCRT) {
39950f30501SSunho Kim     Err = VCRT.takeError();
4009189a266SSunho Kim     return;
4019189a266SSunho Kim   }
4029189a266SSunho Kim   VCRuntimeBootstrap = std::move(*VCRT);
4039189a266SSunho Kim 
404231107a8SLang Hames   for (auto &Lib : OrcRuntimeGenerator->getImportedDynamicLibraries())
4059189a266SSunho Kim     DylibsToPreload.insert(Lib);
4069189a266SSunho Kim 
40773c40339Ssunho   auto ImportedLibs =
40873c40339Ssunho       StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD)
40973c40339Ssunho                       : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD);
4109189a266SSunho Kim   if (!ImportedLibs) {
4119189a266SSunho Kim     Err = ImportedLibs.takeError();
4129189a266SSunho Kim     return;
4139189a266SSunho Kim   }
4149189a266SSunho Kim 
4159189a266SSunho Kim   for (auto &Lib : *ImportedLibs)
4169189a266SSunho Kim     DylibsToPreload.insert(Lib);
4179189a266SSunho Kim 
418231107a8SLang Hames   PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
41973c40339Ssunho 
4209189a266SSunho Kim   // PlatformJD hasn't been set up by the platform yet (since we're creating
4219189a266SSunho Kim   // the platform now), so set it up.
4229189a266SSunho Kim   if (auto E2 = setupJITDylib(PlatformJD)) {
4239189a266SSunho Kim     Err = std::move(E2);
4249189a266SSunho Kim     return;
4259189a266SSunho Kim   }
426d1c4d961Ssunho 
427d1c4d961Ssunho   for (auto& Lib : DylibsToPreload)
428231107a8SLang Hames     if (auto E2 = this->LoadDynLibrary(PlatformJD, Lib)) {
429d1c4d961Ssunho       Err = std::move(E2);
430d1c4d961Ssunho       return;
4319189a266SSunho Kim     }
4329189a266SSunho Kim 
43373c40339Ssunho   if (StaticVCRuntime)
434d1c4d961Ssunho       if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {
435d1c4d961Ssunho           Err = std::move(E2);
436d1c4d961Ssunho           return;
437d1c4d961Ssunho       }
4389189a266SSunho Kim 
4399189a266SSunho Kim   // Associate wrapper function tags with JIT-side function implementations.
440d1c4d961Ssunho   if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
441d1c4d961Ssunho       Err = std::move(E2);
442d1c4d961Ssunho       return;
4439189a266SSunho Kim   }
4449189a266SSunho Kim 
4459189a266SSunho Kim   // Lookup addresses of runtime functions callable by the platform,
4469189a266SSunho Kim   // call the platform bootstrap function to initialize the platform-state
4479189a266SSunho Kim   // object in the executor.
448d1c4d961Ssunho   if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) {
449d1c4d961Ssunho       Err = std::move(E2);
450d1c4d961Ssunho       return;
4519189a266SSunho Kim   }
4529189a266SSunho Kim 
4539189a266SSunho Kim   Bootstrapping.store(false);
4549189a266SSunho Kim   JDBootstrapStates.clear();
4559189a266SSunho Kim }
4569189a266SSunho Kim 
4579189a266SSunho Kim Expected<COFFPlatform::JITDylibDepMap>
4589189a266SSunho Kim COFFPlatform::buildJDDepMap(JITDylib &JD) {
4599189a266SSunho Kim   return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> {
4609189a266SSunho Kim     JITDylibDepMap JDDepMap;
4619189a266SSunho Kim 
4629189a266SSunho Kim     SmallVector<JITDylib *, 16> Worklist({&JD});
4639189a266SSunho Kim     while (!Worklist.empty()) {
4649189a266SSunho Kim       auto CurJD = Worklist.back();
4659189a266SSunho Kim       Worklist.pop_back();
4669189a266SSunho Kim 
4679189a266SSunho Kim       auto &DM = JDDepMap[CurJD];
4689189a266SSunho Kim       CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
4699189a266SSunho Kim         DM.reserve(O.size());
4709189a266SSunho Kim         for (auto &KV : O) {
4719189a266SSunho Kim           if (KV.first == CurJD)
4729189a266SSunho Kim             continue;
4739189a266SSunho Kim           {
4749189a266SSunho Kim             // Bare jitdylibs not known to the platform
4759189a266SSunho Kim             std::lock_guard<std::mutex> Lock(PlatformMutex);
4769189a266SSunho Kim             if (!JITDylibToHeaderAddr.count(KV.first)) {
4779189a266SSunho Kim               LLVM_DEBUG({
4789189a266SSunho Kim                 dbgs() << "JITDylib unregistered to COFFPlatform detected in "
4799189a266SSunho Kim                           "LinkOrder: "
4809189a266SSunho Kim                        << CurJD->getName() << "\n";
4819189a266SSunho Kim               });
4829189a266SSunho Kim               continue;
4839189a266SSunho Kim             }
4849189a266SSunho Kim           }
4859189a266SSunho Kim           DM.push_back(KV.first);
4869189a266SSunho Kim           // Push unvisited entry.
4879189a266SSunho Kim           if (!JDDepMap.count(KV.first)) {
4889189a266SSunho Kim             Worklist.push_back(KV.first);
4899189a266SSunho Kim             JDDepMap[KV.first] = {};
4909189a266SSunho Kim           }
4919189a266SSunho Kim         }
4929189a266SSunho Kim       });
4939189a266SSunho Kim     }
4949189a266SSunho Kim     return std::move(JDDepMap);
4959189a266SSunho Kim   });
4969189a266SSunho Kim }
4979189a266SSunho Kim 
4989189a266SSunho Kim void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult,
4999189a266SSunho Kim                                         JITDylibSP JD,
5009189a266SSunho Kim                                         JITDylibDepMap &JDDepMap) {
5019189a266SSunho Kim   SmallVector<JITDylib *, 16> Worklist({JD.get()});
5029189a266SSunho Kim   DenseSet<JITDylib *> Visited({JD.get()});
5039189a266SSunho Kim   DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
5049189a266SSunho Kim   ES.runSessionLocked([&]() {
5059189a266SSunho Kim     while (!Worklist.empty()) {
5069189a266SSunho Kim       auto CurJD = Worklist.back();
5079189a266SSunho Kim       Worklist.pop_back();
5089189a266SSunho Kim 
5099189a266SSunho Kim       auto RISItr = RegisteredInitSymbols.find(CurJD);
5109189a266SSunho Kim       if (RISItr != RegisteredInitSymbols.end()) {
5119189a266SSunho Kim         NewInitSymbols[CurJD] = std::move(RISItr->second);
5129189a266SSunho Kim         RegisteredInitSymbols.erase(RISItr);
5139189a266SSunho Kim       }
5149189a266SSunho Kim 
5150e9d37ffSKazu Hirata       for (auto *DepJD : JDDepMap[CurJD])
51647b22301SKazu Hirata         if (Visited.insert(DepJD).second)
5179189a266SSunho Kim           Worklist.push_back(DepJD);
5189189a266SSunho Kim     }
5199189a266SSunho Kim   });
5209189a266SSunho Kim 
5219189a266SSunho Kim   // If there are no further init symbols to look up then send the link order
5229189a266SSunho Kim   // (as a list of header addresses) to the caller.
5239189a266SSunho Kim   if (NewInitSymbols.empty()) {
5249189a266SSunho Kim     // Build the dep info map to return.
5259189a266SSunho Kim     COFFJITDylibDepInfoMap DIM;
5269189a266SSunho Kim     DIM.reserve(JDDepMap.size());
5279189a266SSunho Kim     for (auto &KV : JDDepMap) {
5289189a266SSunho Kim       std::lock_guard<std::mutex> Lock(PlatformMutex);
5299189a266SSunho Kim       COFFJITDylibDepInfo DepInfo;
5309189a266SSunho Kim       DepInfo.reserve(KV.second.size());
5319189a266SSunho Kim       for (auto &Dep : KV.second) {
5329189a266SSunho Kim         DepInfo.push_back(JITDylibToHeaderAddr[Dep]);
5339189a266SSunho Kim       }
5349189a266SSunho Kim       auto H = JITDylibToHeaderAddr[KV.first];
5359189a266SSunho Kim       DIM.push_back(std::make_pair(H, std::move(DepInfo)));
5369189a266SSunho Kim     }
5379189a266SSunho Kim     SendResult(DIM);
5389189a266SSunho Kim     return;
5399189a266SSunho Kim   }
5409189a266SSunho Kim 
5419189a266SSunho Kim   // Otherwise issue a lookup and re-run this phase when it completes.
5429189a266SSunho Kim   lookupInitSymbolsAsync(
5439189a266SSunho Kim       [this, SendResult = std::move(SendResult), &JD,
5449189a266SSunho Kim        JDDepMap = std::move(JDDepMap)](Error Err) mutable {
5459189a266SSunho Kim         if (Err)
5469189a266SSunho Kim           SendResult(std::move(Err));
5479189a266SSunho Kim         else
5489189a266SSunho Kim           pushInitializersLoop(std::move(SendResult), JD, JDDepMap);
5499189a266SSunho Kim       },
5509189a266SSunho Kim       ES, std::move(NewInitSymbols));
5519189a266SSunho Kim }
5529189a266SSunho Kim 
5539189a266SSunho Kim void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
5549189a266SSunho Kim                                        ExecutorAddr JDHeaderAddr) {
5559189a266SSunho Kim   JITDylibSP JD;
5569189a266SSunho Kim   {
5579189a266SSunho Kim     std::lock_guard<std::mutex> Lock(PlatformMutex);
5589189a266SSunho Kim     auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
5599189a266SSunho Kim     if (I != HeaderAddrToJITDylib.end())
5609189a266SSunho Kim       JD = I->second;
5619189a266SSunho Kim   }
5629189a266SSunho Kim 
5639189a266SSunho Kim   LLVM_DEBUG({
5649189a266SSunho Kim     dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
5659189a266SSunho Kim     if (JD)
5669189a266SSunho Kim       dbgs() << "pushing initializers for " << JD->getName() << "\n";
5679189a266SSunho Kim     else
5689189a266SSunho Kim       dbgs() << "No JITDylib for header address.\n";
5699189a266SSunho Kim   });
5709189a266SSunho Kim 
5719189a266SSunho Kim   if (!JD) {
572fdd9df19SLang Hames     SendResult(make_error<StringError>("No JITDylib with header addr " +
573fdd9df19SLang Hames                                            formatv("{0:x}", JDHeaderAddr),
5749189a266SSunho Kim                                        inconvertibleErrorCode()));
5759189a266SSunho Kim     return;
5769189a266SSunho Kim   }
5779189a266SSunho Kim 
5789189a266SSunho Kim   auto JDDepMap = buildJDDepMap(*JD);
5799189a266SSunho Kim   if (!JDDepMap) {
5809189a266SSunho Kim     SendResult(JDDepMap.takeError());
5819189a266SSunho Kim     return;
5829189a266SSunho Kim   }
5839189a266SSunho Kim 
5849189a266SSunho Kim   pushInitializersLoop(std::move(SendResult), JD, *JDDepMap);
5859189a266SSunho Kim }
5869189a266SSunho Kim 
5879189a266SSunho Kim void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
5889189a266SSunho Kim                                    ExecutorAddr Handle, StringRef SymbolName) {
589fdd9df19SLang Hames   LLVM_DEBUG(dbgs() << "COFFPlatform::rt_lookupSymbol(\"" << Handle << "\")\n");
5909189a266SSunho Kim 
5919189a266SSunho Kim   JITDylib *JD = nullptr;
5929189a266SSunho Kim 
5939189a266SSunho Kim   {
5949189a266SSunho Kim     std::lock_guard<std::mutex> Lock(PlatformMutex);
5959189a266SSunho Kim     auto I = HeaderAddrToJITDylib.find(Handle);
5969189a266SSunho Kim     if (I != HeaderAddrToJITDylib.end())
5979189a266SSunho Kim       JD = I->second;
5989189a266SSunho Kim   }
5999189a266SSunho Kim 
6009189a266SSunho Kim   if (!JD) {
601fdd9df19SLang Hames     LLVM_DEBUG(dbgs() << "  No JITDylib for handle " << Handle << "\n");
6029189a266SSunho Kim     SendResult(make_error<StringError>("No JITDylib associated with handle " +
603fdd9df19SLang Hames                                            formatv("{0:x}", Handle),
6049189a266SSunho Kim                                        inconvertibleErrorCode()));
6059189a266SSunho Kim     return;
6069189a266SSunho Kim   }
6079189a266SSunho Kim 
6089189a266SSunho Kim   // Use functor class to work around XL build compiler issue on AIX.
6099189a266SSunho Kim   class RtLookupNotifyComplete {
6109189a266SSunho Kim   public:
6119189a266SSunho Kim     RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
6129189a266SSunho Kim         : SendResult(std::move(SendResult)) {}
6139189a266SSunho Kim     void operator()(Expected<SymbolMap> Result) {
6149189a266SSunho Kim       if (Result) {
6159189a266SSunho Kim         assert(Result->size() == 1 && "Unexpected result map count");
6165baaf0c2SLang Hames         SendResult(Result->begin()->second.getAddress());
6179189a266SSunho Kim       } else {
6189189a266SSunho Kim         SendResult(Result.takeError());
6199189a266SSunho Kim       }
6209189a266SSunho Kim     }
6219189a266SSunho Kim 
6229189a266SSunho Kim   private:
6239189a266SSunho Kim     SendSymbolAddressFn SendResult;
6249189a266SSunho Kim   };
6259189a266SSunho Kim 
6269189a266SSunho Kim   ES.lookup(
6279189a266SSunho Kim       LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
6289189a266SSunho Kim       SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
6299189a266SSunho Kim       RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
6309189a266SSunho Kim }
6319189a266SSunho Kim 
6329189a266SSunho Kim Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
6339189a266SSunho Kim   ExecutionSession::JITDispatchHandlerAssociationMap WFs;
6349189a266SSunho Kim 
6359189a266SSunho Kim   using LookupSymbolSPSSig =
6369189a266SSunho Kim       SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
6379189a266SSunho Kim   WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] =
6389189a266SSunho Kim       ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
6399189a266SSunho Kim                                               &COFFPlatform::rt_lookupSymbol);
6409189a266SSunho Kim   using PushInitializersSPSSig =
6419189a266SSunho Kim       SPSExpected<SPSCOFFJITDylibDepInfoMap>(SPSExecutorAddr);
6429189a266SSunho Kim   WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] =
6439189a266SSunho Kim       ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
6449189a266SSunho Kim           this, &COFFPlatform::rt_pushInitializers);
6459189a266SSunho Kim 
6469189a266SSunho Kim   return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
6479189a266SSunho Kim }
6489189a266SSunho Kim 
6499189a266SSunho Kim Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {
6509189a266SSunho Kim   llvm::sort(BState.Initializers);
6519189a266SSunho Kim   if (auto Err =
6529189a266SSunho Kim           runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ"))
6539189a266SSunho Kim     return Err;
6549189a266SSunho Kim 
6559189a266SSunho Kim   if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init"))
6569189a266SSunho Kim     return Err;
6579189a266SSunho Kim 
6589189a266SSunho Kim   if (auto Err =
6599189a266SSunho Kim           runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ"))
6609189a266SSunho Kim     return Err;
6619189a266SSunho Kim   return Error::success();
6629189a266SSunho Kim }
6639189a266SSunho Kim 
6649189a266SSunho Kim Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
6659189a266SSunho Kim                                                        StringRef Start,
6669189a266SSunho Kim                                                        StringRef End) {
6679189a266SSunho Kim   for (auto &Initializer : BState.Initializers)
6689189a266SSunho Kim     if (Initializer.first >= Start && Initializer.first <= End &&
6699189a266SSunho Kim         Initializer.second) {
6709189a266SSunho Kim       auto Res =
6719189a266SSunho Kim           ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second);
6729189a266SSunho Kim       if (!Res)
6739189a266SSunho Kim         return Res.takeError();
6749189a266SSunho Kim     }
6759189a266SSunho Kim   return Error::success();
6769189a266SSunho Kim }
6779189a266SSunho Kim 
6789189a266SSunho Kim Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
6799189a266SSunho Kim   // Lookup of runtime symbols causes the collection of initializers if
6809189a266SSunho Kim   // it's static linking setting.
6819189a266SSunho Kim   if (auto Err = lookupAndRecordAddrs(
6829189a266SSunho Kim           ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
6839189a266SSunho Kim           {
6849189a266SSunho Kim               {ES.intern("__orc_rt_coff_platform_bootstrap"),
6859189a266SSunho Kim                &orc_rt_coff_platform_bootstrap},
6869189a266SSunho Kim               {ES.intern("__orc_rt_coff_platform_shutdown"),
6879189a266SSunho Kim                &orc_rt_coff_platform_shutdown},
6889189a266SSunho Kim               {ES.intern("__orc_rt_coff_register_jitdylib"),
6899189a266SSunho Kim                &orc_rt_coff_register_jitdylib},
6909189a266SSunho Kim               {ES.intern("__orc_rt_coff_deregister_jitdylib"),
6919189a266SSunho Kim                &orc_rt_coff_deregister_jitdylib},
6929189a266SSunho Kim               {ES.intern("__orc_rt_coff_register_object_sections"),
6939189a266SSunho Kim                &orc_rt_coff_register_object_sections},
6949189a266SSunho Kim               {ES.intern("__orc_rt_coff_deregister_object_sections"),
6959189a266SSunho Kim                &orc_rt_coff_deregister_object_sections},
6969189a266SSunho Kim           }))
6979189a266SSunho Kim     return Err;
6989189a266SSunho Kim 
6999189a266SSunho Kim   // Call bootstrap functions
7009189a266SSunho Kim   if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap))
7019189a266SSunho Kim     return Err;
7029189a266SSunho Kim 
7039189a266SSunho Kim   // Do the pending jitdylib registration actions that we couldn't do
7049189a266SSunho Kim   // because orc runtime was not linked fully.
7059189a266SSunho Kim   for (auto KV : JDBootstrapStates) {
7069189a266SSunho Kim     auto &JDBState = KV.second;
7079189a266SSunho Kim     if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>(
7089189a266SSunho Kim             orc_rt_coff_register_jitdylib, JDBState.JDName,
7099189a266SSunho Kim             JDBState.HeaderAddr))
7109189a266SSunho Kim       return Err;
7119189a266SSunho Kim 
7129189a266SSunho Kim     for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps)
7139189a266SSunho Kim       if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr,
7149189a266SSunho Kim                                             SPSCOFFObjectSectionsMap, bool)>(
7159189a266SSunho Kim               orc_rt_coff_register_object_sections, JDBState.HeaderAddr,
7169189a266SSunho Kim               ObjSectionMap, false))
7179189a266SSunho Kim         return Err;
7189189a266SSunho Kim   }
7199189a266SSunho Kim 
72073c40339Ssunho   // Run static initializers collected in bootstrap stage.
72173c40339Ssunho   for (auto KV : JDBootstrapStates) {
72273c40339Ssunho     auto &JDBState = KV.second;
72373c40339Ssunho     if (auto Err = runBootstrapInitializers(JDBState))
72473c40339Ssunho       return Err;
72573c40339Ssunho   }
72673c40339Ssunho 
7279189a266SSunho Kim   return Error::success();
7289189a266SSunho Kim }
7299189a266SSunho Kim 
7309189a266SSunho Kim Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
7319189a266SSunho Kim                                       StringRef SymbolName) {
7329189a266SSunho Kim   ExecutorAddr jit_function;
7339189a266SSunho Kim   auto AfterCLookupErr = lookupAndRecordAddrs(
7349189a266SSunho Kim       ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
7359189a266SSunho Kim       {{ES.intern(SymbolName), &jit_function}});
7369189a266SSunho Kim   if (!AfterCLookupErr) {
7379189a266SSunho Kim     auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function);
7389189a266SSunho Kim     if (!Res)
7399189a266SSunho Kim       return Res.takeError();
7409189a266SSunho Kim     return Error::success();
7419189a266SSunho Kim   }
7429189a266SSunho Kim   if (!AfterCLookupErr.isA<SymbolsNotFound>())
7439189a266SSunho Kim     return AfterCLookupErr;
7449189a266SSunho Kim   consumeError(std::move(AfterCLookupErr));
7459189a266SSunho Kim   return Error::success();
7469189a266SSunho Kim }
7479189a266SSunho Kim 
7489189a266SSunho Kim void COFFPlatform::COFFPlatformPlugin::modifyPassConfig(
7499189a266SSunho Kim     MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
7509189a266SSunho Kim     jitlink::PassConfiguration &Config) {
7519189a266SSunho Kim 
7529189a266SSunho Kim   bool IsBootstrapping = CP.Bootstrapping.load();
7539189a266SSunho Kim 
7549189a266SSunho Kim   if (auto InitSymbol = MR.getInitializerSymbol()) {
7559189a266SSunho Kim     if (InitSymbol == CP.COFFHeaderStartSymbol) {
7569189a266SSunho Kim       Config.PostAllocationPasses.push_back(
7579189a266SSunho Kim           [this, &MR, IsBootstrapping](jitlink::LinkGraph &G) {
7589189a266SSunho Kim             return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping);
7599189a266SSunho Kim           });
7609189a266SSunho Kim       return;
7619189a266SSunho Kim     }
7629189a266SSunho Kim     Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
7639189a266SSunho Kim       return preserveInitializerSections(G, MR);
7649189a266SSunho Kim     });
7659189a266SSunho Kim   }
7669189a266SSunho Kim 
7679189a266SSunho Kim   if (!IsBootstrapping)
7689189a266SSunho Kim     Config.PostFixupPasses.push_back(
7699189a266SSunho Kim         [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
7709189a266SSunho Kim           return registerObjectPlatformSections(G, JD);
7719189a266SSunho Kim         });
7729189a266SSunho Kim   else
7739189a266SSunho Kim     Config.PostFixupPasses.push_back(
7749189a266SSunho Kim         [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
7759189a266SSunho Kim           return registerObjectPlatformSectionsInBootstrap(G, JD);
7769189a266SSunho Kim         });
7779189a266SSunho Kim }
7789189a266SSunho Kim 
7799189a266SSunho Kim Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol(
7809189a266SSunho Kim     jitlink::LinkGraph &G, MaterializationResponsibility &MR,
7819189a266SSunho Kim     bool IsBootstraping) {
7829189a266SSunho Kim   auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
7832ccf7ed2SJared Wyles     return *Sym->getName() == *CP.COFFHeaderStartSymbol;
7849189a266SSunho Kim   });
7859189a266SSunho Kim   assert(I != G.defined_symbols().end() && "Missing COFF header start symbol");
7869189a266SSunho Kim 
7879189a266SSunho Kim   auto &JD = MR.getTargetJITDylib();
7889189a266SSunho Kim   std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
7899189a266SSunho Kim   auto HeaderAddr = (*I)->getAddress();
7909189a266SSunho Kim   CP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
7919189a266SSunho Kim   CP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
7929189a266SSunho Kim   if (!IsBootstraping) {
7939189a266SSunho Kim     G.allocActions().push_back(
7949189a266SSunho Kim         {cantFail(WrapperFunctionCall::Create<
7959189a266SSunho Kim                   SPSArgList<SPSString, SPSExecutorAddr>>(
7969189a266SSunho Kim              CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)),
7979189a266SSunho Kim          cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
7989189a266SSunho Kim              CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
7999189a266SSunho Kim   } else {
8009189a266SSunho Kim     G.allocActions().push_back(
8019189a266SSunho Kim         {{},
8029189a266SSunho Kim          cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
8039189a266SSunho Kim              CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
8049189a266SSunho Kim     JDBootstrapState BState;
8059189a266SSunho Kim     BState.JD = &JD;
8069189a266SSunho Kim     BState.JDName = JD.getName();
8079189a266SSunho Kim     BState.HeaderAddr = HeaderAddr;
8089189a266SSunho Kim     CP.JDBootstrapStates.emplace(&JD, BState);
8099189a266SSunho Kim   }
8109189a266SSunho Kim 
8119189a266SSunho Kim   return Error::success();
8129189a266SSunho Kim }
8139189a266SSunho Kim 
8149189a266SSunho Kim Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections(
8159189a266SSunho Kim     jitlink::LinkGraph &G, JITDylib &JD) {
8169189a266SSunho Kim   COFFObjectSectionsMap ObjSecs;
8179189a266SSunho Kim   auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
8189189a266SSunho Kim   assert(HeaderAddr && "Must be registered jitdylib");
8199189a266SSunho Kim   for (auto &S : G.sections()) {
8209189a266SSunho Kim     jitlink::SectionRange Range(S);
8219189a266SSunho Kim     if (Range.getSize())
8229189a266SSunho Kim       ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
8239189a266SSunho Kim   }
8249189a266SSunho Kim 
8259189a266SSunho Kim   G.allocActions().push_back(
8269189a266SSunho Kim       {cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>(
8279189a266SSunho Kim            CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)),
8289189a266SSunho Kim        cantFail(
8299189a266SSunho Kim            WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
8309189a266SSunho Kim                CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
8319189a266SSunho Kim                ObjSecs))});
8329189a266SSunho Kim 
8339189a266SSunho Kim   return Error::success();
8349189a266SSunho Kim }
8359189a266SSunho Kim 
8369189a266SSunho Kim Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(
8379189a266SSunho Kim     jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
8389189a266SSunho Kim 
8390074cea4SLang Hames   if (const auto &InitSymName = MR.getInitializerSymbol()) {
8400074cea4SLang Hames 
8410074cea4SLang Hames     jitlink::Symbol *InitSym = nullptr;
8420074cea4SLang Hames 
8430074cea4SLang Hames     for (auto &InitSection : G.sections()) {
8440074cea4SLang Hames       // Skip non-init sections.
8450074cea4SLang Hames       if (!isCOFFInitializerSection(InitSection.getName()) ||
8460074cea4SLang Hames           InitSection.empty())
8470074cea4SLang Hames         continue;
8480074cea4SLang Hames 
8490074cea4SLang Hames       // Create the init symbol if it has not been created already and attach it
8500074cea4SLang Hames       // to the first block.
8510074cea4SLang Hames       if (!InitSym) {
8520074cea4SLang Hames         auto &B = **InitSection.blocks().begin();
853d0970707SLang Hames         InitSym = &G.addDefinedSymbol(
854d0970707SLang Hames             B, 0, *InitSymName, B.getSize(), jitlink::Linkage::Strong,
855d0970707SLang Hames             jitlink::Scope::SideEffectsOnly, false, true);
8560074cea4SLang Hames       }
8570074cea4SLang Hames 
8580074cea4SLang Hames       // Add keep-alive edges to anonymous symbols in all other init blocks.
8590074cea4SLang Hames       for (auto *B : InitSection.blocks()) {
8600074cea4SLang Hames         if (B == &InitSym->getBlock())
8610074cea4SLang Hames           continue;
8620074cea4SLang Hames 
8630074cea4SLang Hames         auto &S = G.addAnonymousSymbol(*B, 0, B->getSize(), false, true);
8640074cea4SLang Hames         InitSym->getBlock().addEdge(jitlink::Edge::KeepAlive, 0, S, 0);
8650074cea4SLang Hames       }
8660074cea4SLang Hames     }
8670074cea4SLang Hames   }
8680074cea4SLang Hames 
8699189a266SSunho Kim   return Error::success();
8709189a266SSunho Kim }
8719189a266SSunho Kim 
8729189a266SSunho Kim Error COFFPlatform::COFFPlatformPlugin::
8739189a266SSunho Kim     registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,
8749189a266SSunho Kim                                               JITDylib &JD) {
8759189a266SSunho Kim   std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
8769189a266SSunho Kim   auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
8779189a266SSunho Kim   COFFObjectSectionsMap ObjSecs;
8789189a266SSunho Kim   for (auto &S : G.sections()) {
8799189a266SSunho Kim     jitlink::SectionRange Range(S);
8809189a266SSunho Kim     if (Range.getSize())
8819189a266SSunho Kim       ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
8829189a266SSunho Kim   }
8839189a266SSunho Kim 
8849189a266SSunho Kim   G.allocActions().push_back(
8859189a266SSunho Kim       {{},
8869189a266SSunho Kim        cantFail(
8879189a266SSunho Kim            WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
8889189a266SSunho Kim                CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
8899189a266SSunho Kim                ObjSecs))});
8909189a266SSunho Kim 
8919189a266SSunho Kim   auto &BState = CP.JDBootstrapStates[&JD];
8929189a266SSunho Kim   BState.ObjectSectionsMaps.push_back(std::move(ObjSecs));
8939189a266SSunho Kim 
8949189a266SSunho Kim   // Collect static initializers
8959189a266SSunho Kim   for (auto &S : G.sections())
8963d4e9d5eSLang Hames     if (isCOFFInitializerSection(S.getName()))
8979189a266SSunho Kim       for (auto *B : S.blocks()) {
8989189a266SSunho Kim         if (B->edges_empty())
8999189a266SSunho Kim           continue;
9009189a266SSunho Kim         for (auto &E : B->edges())
9019189a266SSunho Kim           BState.Initializers.push_back(std::make_pair(
9025baaf0c2SLang Hames               S.getName().str(), E.getTarget().getAddress() + E.getAddend()));
9039189a266SSunho Kim       }
9049189a266SSunho Kim 
9059189a266SSunho Kim   return Error::success();
9069189a266SSunho Kim }
9079189a266SSunho Kim 
9089189a266SSunho Kim } // End namespace orc.
9099189a266SSunho Kim } // End namespace llvm.
910