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