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