1bdd1243dSDimitry Andric //===--- COFFPlatform.h -- Utilities for executing COFF in Orc --*- C++ -*-===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric // 9bdd1243dSDimitry Andric // Utilities for executing JIT'd COFF in Orc. 10bdd1243dSDimitry Andric // 11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 12bdd1243dSDimitry Andric 13bdd1243dSDimitry Andric #ifndef LLVM_EXECUTIONENGINE_ORC_COFFPLATFORM_H 14bdd1243dSDimitry Andric #define LLVM_EXECUTIONENGINE_ORC_COFFPLATFORM_H 15bdd1243dSDimitry Andric 16bdd1243dSDimitry Andric #include "llvm/ADT/StringRef.h" 17bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h" 18bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h" 19bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 20bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" 21bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 22bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" 23bdd1243dSDimitry Andric 24bdd1243dSDimitry Andric #include <future> 25bdd1243dSDimitry Andric #include <memory> 26bdd1243dSDimitry Andric #include <thread> 27bdd1243dSDimitry Andric #include <vector> 28bdd1243dSDimitry Andric 29bdd1243dSDimitry Andric namespace llvm { 30bdd1243dSDimitry Andric namespace orc { 31bdd1243dSDimitry Andric 32bdd1243dSDimitry Andric /// Mediates between COFF initialization and ExecutionSession state. 33bdd1243dSDimitry Andric class COFFPlatform : public Platform { 34bdd1243dSDimitry Andric public: 35bdd1243dSDimitry Andric /// A function that will be called with the name of dll file that must be 36bdd1243dSDimitry Andric /// loaded. 37bdd1243dSDimitry Andric using LoadDynamicLibrary = 38bdd1243dSDimitry Andric unique_function<Error(JITDylib &JD, StringRef DLLFileName)>; 39bdd1243dSDimitry Andric 40bdd1243dSDimitry Andric /// Try to create a COFFPlatform instance, adding the ORC runtime to the 41bdd1243dSDimitry Andric /// given JITDylib. 42bdd1243dSDimitry Andric static Expected<std::unique_ptr<COFFPlatform>> 43bdd1243dSDimitry Andric Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 44*06c3fb27SDimitry Andric JITDylib &PlatformJD, 45*06c3fb27SDimitry Andric std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer, 46*06c3fb27SDimitry Andric LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime = false, 47*06c3fb27SDimitry Andric const char *VCRuntimePath = nullptr, 48*06c3fb27SDimitry Andric std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt); 49*06c3fb27SDimitry Andric 50*06c3fb27SDimitry Andric static Expected<std::unique_ptr<COFFPlatform>> 51*06c3fb27SDimitry Andric Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 52bdd1243dSDimitry Andric JITDylib &PlatformJD, const char *OrcRuntimePath, 53bdd1243dSDimitry Andric LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime = false, 54bdd1243dSDimitry Andric const char *VCRuntimePath = nullptr, 55bdd1243dSDimitry Andric std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt); 56bdd1243dSDimitry Andric getExecutionSession()57bdd1243dSDimitry Andric ExecutionSession &getExecutionSession() const { return ES; } getObjectLinkingLayer()58bdd1243dSDimitry Andric ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; } 59bdd1243dSDimitry Andric 60bdd1243dSDimitry Andric Error setupJITDylib(JITDylib &JD) override; 61bdd1243dSDimitry Andric Error teardownJITDylib(JITDylib &JD) override; 62bdd1243dSDimitry Andric Error notifyAdding(ResourceTracker &RT, 63bdd1243dSDimitry Andric const MaterializationUnit &MU) override; 64bdd1243dSDimitry Andric Error notifyRemoving(ResourceTracker &RT) override; 65bdd1243dSDimitry Andric 66bdd1243dSDimitry Andric /// Returns an AliasMap containing the default aliases for the COFFPlatform. 67bdd1243dSDimitry Andric /// This can be modified by clients when constructing the platform to add 68bdd1243dSDimitry Andric /// or remove aliases. 69bdd1243dSDimitry Andric static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES); 70bdd1243dSDimitry Andric 71bdd1243dSDimitry Andric /// Returns the array of required CXX aliases. 72bdd1243dSDimitry Andric static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases(); 73bdd1243dSDimitry Andric 74bdd1243dSDimitry Andric /// Returns the array of standard runtime utility aliases for COFF. 75bdd1243dSDimitry Andric static ArrayRef<std::pair<const char *, const char *>> 76bdd1243dSDimitry Andric standardRuntimeUtilityAliases(); 77bdd1243dSDimitry Andric getSEHFrameSectionName()78bdd1243dSDimitry Andric static StringRef getSEHFrameSectionName() { return ".pdata"; } 79bdd1243dSDimitry Andric 80bdd1243dSDimitry Andric private: 81bdd1243dSDimitry Andric using COFFJITDylibDepInfo = std::vector<ExecutorAddr>; 82bdd1243dSDimitry Andric using COFFJITDylibDepInfoMap = 83bdd1243dSDimitry Andric std::vector<std::pair<ExecutorAddr, COFFJITDylibDepInfo>>; 84bdd1243dSDimitry Andric using COFFObjectSectionsMap = 85bdd1243dSDimitry Andric SmallVector<std::pair<std::string, ExecutorAddrRange>>; 86bdd1243dSDimitry Andric using PushInitializersSendResultFn = 87bdd1243dSDimitry Andric unique_function<void(Expected<COFFJITDylibDepInfoMap>)>; 88bdd1243dSDimitry Andric using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>; 89bdd1243dSDimitry Andric using JITDylibDepMap = DenseMap<JITDylib *, SmallVector<JITDylib *>>; 90bdd1243dSDimitry Andric 91bdd1243dSDimitry Andric // The COFFPlatformPlugin scans/modifies LinkGraphs to support COFF 92bdd1243dSDimitry Andric // platform features including initializers, exceptions, and language 93bdd1243dSDimitry Andric // runtime registration. 94bdd1243dSDimitry Andric class COFFPlatformPlugin : public ObjectLinkingLayer::Plugin { 95bdd1243dSDimitry Andric public: COFFPlatformPlugin(COFFPlatform & CP)96bdd1243dSDimitry Andric COFFPlatformPlugin(COFFPlatform &CP) : CP(CP) {} 97bdd1243dSDimitry Andric 98bdd1243dSDimitry Andric void modifyPassConfig(MaterializationResponsibility &MR, 99bdd1243dSDimitry Andric jitlink::LinkGraph &G, 100bdd1243dSDimitry Andric jitlink::PassConfiguration &Config) override; 101bdd1243dSDimitry Andric 102bdd1243dSDimitry Andric SyntheticSymbolDependenciesMap 103bdd1243dSDimitry Andric getSyntheticSymbolDependencies(MaterializationResponsibility &MR) override; 104bdd1243dSDimitry Andric 105bdd1243dSDimitry Andric // FIXME: We should be tentatively tracking scraped sections and discarding 106bdd1243dSDimitry Andric // if the MR fails. notifyFailed(MaterializationResponsibility & MR)107bdd1243dSDimitry Andric Error notifyFailed(MaterializationResponsibility &MR) override { 108bdd1243dSDimitry Andric return Error::success(); 109bdd1243dSDimitry Andric } 110bdd1243dSDimitry Andric notifyRemovingResources(JITDylib & JD,ResourceKey K)111bdd1243dSDimitry Andric Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override { 112bdd1243dSDimitry Andric return Error::success(); 113bdd1243dSDimitry Andric } 114bdd1243dSDimitry Andric notifyTransferringResources(JITDylib & JD,ResourceKey DstKey,ResourceKey SrcKey)115bdd1243dSDimitry Andric void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, 116bdd1243dSDimitry Andric ResourceKey SrcKey) override {} 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric private: 119bdd1243dSDimitry Andric using InitSymbolDepMap = 120bdd1243dSDimitry Andric DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>; 121bdd1243dSDimitry Andric 122bdd1243dSDimitry Andric Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G, 123bdd1243dSDimitry Andric MaterializationResponsibility &MR, 124bdd1243dSDimitry Andric bool Bootstrap); 125bdd1243dSDimitry Andric 126bdd1243dSDimitry Andric Error preserveInitializerSections(jitlink::LinkGraph &G, 127bdd1243dSDimitry Andric MaterializationResponsibility &MR); 128bdd1243dSDimitry Andric Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD); 129bdd1243dSDimitry Andric Error registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G, 130bdd1243dSDimitry Andric JITDylib &JD); 131bdd1243dSDimitry Andric 132bdd1243dSDimitry Andric std::mutex PluginMutex; 133bdd1243dSDimitry Andric COFFPlatform &CP; 134bdd1243dSDimitry Andric InitSymbolDepMap InitSymbolDeps; 135bdd1243dSDimitry Andric }; 136bdd1243dSDimitry Andric 137bdd1243dSDimitry Andric struct JDBootstrapState { 138bdd1243dSDimitry Andric JITDylib *JD = nullptr; 139bdd1243dSDimitry Andric std::string JDName; 140bdd1243dSDimitry Andric ExecutorAddr HeaderAddr; 141bdd1243dSDimitry Andric std::list<COFFObjectSectionsMap> ObjectSectionsMaps; 142bdd1243dSDimitry Andric SmallVector<std::pair<std::string, ExecutorAddr>> Initializers; 143bdd1243dSDimitry Andric }; 144bdd1243dSDimitry Andric 145bdd1243dSDimitry Andric static bool supportedTarget(const Triple &TT); 146bdd1243dSDimitry Andric 147*06c3fb27SDimitry Andric COFFPlatform( 148*06c3fb27SDimitry Andric ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 149*06c3fb27SDimitry Andric JITDylib &PlatformJD, 150*06c3fb27SDimitry Andric std::unique_ptr<StaticLibraryDefinitionGenerator> OrcRuntimeGenerator, 151*06c3fb27SDimitry Andric std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer, 152*06c3fb27SDimitry Andric std::unique_ptr<object::Archive> OrcRuntimeArchive, 153bdd1243dSDimitry Andric LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, 154bdd1243dSDimitry Andric const char *VCRuntimePath, Error &Err); 155bdd1243dSDimitry Andric 156bdd1243dSDimitry Andric // Associate COFFPlatform JIT-side runtime support functions with handlers. 157bdd1243dSDimitry Andric Error associateRuntimeSupportFunctions(JITDylib &PlatformJD); 158bdd1243dSDimitry Andric 159bdd1243dSDimitry Andric // Records the addresses of runtime symbols used by the platform. 160bdd1243dSDimitry Andric Error bootstrapCOFFRuntime(JITDylib &PlatformJD); 161bdd1243dSDimitry Andric 162bdd1243dSDimitry Andric // Run a specific void function if it exists. 163bdd1243dSDimitry Andric Error runSymbolIfExists(JITDylib &PlatformJD, StringRef SymbolName); 164bdd1243dSDimitry Andric 165bdd1243dSDimitry Andric // Run collected initializers in boostrap stage. 166bdd1243dSDimitry Andric Error runBootstrapInitializers(JDBootstrapState &BState); 167bdd1243dSDimitry Andric Error runBootstrapSubsectionInitializers(JDBootstrapState &BState, 168bdd1243dSDimitry Andric StringRef Start, StringRef End); 169bdd1243dSDimitry Andric 170bdd1243dSDimitry Andric // Build dependency graph of a JITDylib 171bdd1243dSDimitry Andric Expected<JITDylibDepMap> buildJDDepMap(JITDylib &JD); 172bdd1243dSDimitry Andric 173bdd1243dSDimitry Andric Expected<MemoryBufferRef> getPerJDObjectFile(); 174bdd1243dSDimitry Andric 175bdd1243dSDimitry Andric // Implements rt_pushInitializers by making repeat async lookups for 176bdd1243dSDimitry Andric // initializer symbols (each lookup may spawn more initializer symbols if 177bdd1243dSDimitry Andric // it pulls in new materializers, e.g. from objects in a static library). 178bdd1243dSDimitry Andric void pushInitializersLoop(PushInitializersSendResultFn SendResult, 179bdd1243dSDimitry Andric JITDylibSP JD, JITDylibDepMap &JDDepMap); 180bdd1243dSDimitry Andric 181bdd1243dSDimitry Andric void rt_pushInitializers(PushInitializersSendResultFn SendResult, 182bdd1243dSDimitry Andric ExecutorAddr JDHeaderAddr); 183bdd1243dSDimitry Andric 184bdd1243dSDimitry Andric void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddr Handle, 185bdd1243dSDimitry Andric StringRef SymbolName); 186bdd1243dSDimitry Andric 187bdd1243dSDimitry Andric ExecutionSession &ES; 188bdd1243dSDimitry Andric ObjectLinkingLayer &ObjLinkingLayer; 189bdd1243dSDimitry Andric 190bdd1243dSDimitry Andric LoadDynamicLibrary LoadDynLibrary; 191bdd1243dSDimitry Andric std::unique_ptr<COFFVCRuntimeBootstrapper> VCRuntimeBootstrap; 192bdd1243dSDimitry Andric std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer; 193bdd1243dSDimitry Andric std::unique_ptr<object::Archive> OrcRuntimeArchive; 194bdd1243dSDimitry Andric bool StaticVCRuntime; 195bdd1243dSDimitry Andric 196bdd1243dSDimitry Andric SymbolStringPtr COFFHeaderStartSymbol; 197bdd1243dSDimitry Andric 198bdd1243dSDimitry Andric // State of bootstrap in progress 199bdd1243dSDimitry Andric std::map<JITDylib *, JDBootstrapState> JDBootstrapStates; 200bdd1243dSDimitry Andric std::atomic<bool> Bootstrapping; 201bdd1243dSDimitry Andric 202bdd1243dSDimitry Andric ExecutorAddr orc_rt_coff_platform_bootstrap; 203bdd1243dSDimitry Andric ExecutorAddr orc_rt_coff_platform_shutdown; 204bdd1243dSDimitry Andric ExecutorAddr orc_rt_coff_register_object_sections; 205bdd1243dSDimitry Andric ExecutorAddr orc_rt_coff_deregister_object_sections; 206bdd1243dSDimitry Andric ExecutorAddr orc_rt_coff_register_jitdylib; 207bdd1243dSDimitry Andric ExecutorAddr orc_rt_coff_deregister_jitdylib; 208bdd1243dSDimitry Andric 209bdd1243dSDimitry Andric DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr; 210bdd1243dSDimitry Andric DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib; 211bdd1243dSDimitry Andric 212bdd1243dSDimitry Andric DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols; 213bdd1243dSDimitry Andric 214bdd1243dSDimitry Andric std::set<std::string> DylibsToPreload; 215bdd1243dSDimitry Andric 216bdd1243dSDimitry Andric std::mutex PlatformMutex; 217bdd1243dSDimitry Andric }; 218bdd1243dSDimitry Andric 219bdd1243dSDimitry Andric } // end namespace orc 220bdd1243dSDimitry Andric } // end namespace llvm 221bdd1243dSDimitry Andric 222bdd1243dSDimitry Andric #endif // LLVM_EXECUTIONENGINE_ORC_COFFPLATFORM_H 223