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