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