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, |
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(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, |
52 | JITDylib &PlatformJD, const char *OrcRuntimePath, |
53 | LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime = false, |
54 | const char *VCRuntimePath = nullptr, |
55 | std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt); |
56 | |
57 | ExecutionSession &getExecutionSession() const { return ES; } |
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 | |
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 = |
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 COFFPlatformPlugin : public ObjectLinkingLayer::Plugin { |
95 | public: |
96 | COFFPlatformPlugin(COFFPlatform &CP) : CP(CP) {} |
97 | |
98 | void modifyPassConfig(MaterializationResponsibility &MR, |
99 | jitlink::LinkGraph &G, |
100 | jitlink::PassConfiguration &Config) override; |
101 | |
102 | SyntheticSymbolDependenciesMap |
103 | getSyntheticSymbolDependencies(MaterializationResponsibility &MR) override; |
104 | |
105 | // FIXME: We should be tentatively tracking scraped sections and discarding |
106 | // if the MR fails. |
107 | Error notifyFailed(MaterializationResponsibility &MR) override { |
108 | return Error::success(); |
109 | } |
110 | |
111 | Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override { |
112 | return Error::success(); |
113 | } |
114 | |
115 | void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, |
116 | ResourceKey SrcKey) override {} |
117 | |
118 | private: |
119 | using InitSymbolDepMap = |
120 | DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>; |
121 | |
122 | Error (jitlink::LinkGraph &G, |
123 | MaterializationResponsibility &MR, |
124 | bool Bootstrap); |
125 | |
126 | Error preserveInitializerSections(jitlink::LinkGraph &G, |
127 | MaterializationResponsibility &MR); |
128 | Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD); |
129 | Error registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G, |
130 | JITDylib &JD); |
131 | |
132 | std::mutex PluginMutex; |
133 | COFFPlatform &CP; |
134 | InitSymbolDepMap InitSymbolDeps; |
135 | }; |
136 | |
137 | struct JDBootstrapState { |
138 | JITDylib *JD = nullptr; |
139 | std::string JDName; |
140 | ExecutorAddr ; |
141 | std::list<COFFObjectSectionsMap> ObjectSectionsMaps; |
142 | SmallVector<std::pair<std::string, ExecutorAddr>> Initializers; |
143 | }; |
144 | |
145 | static bool supportedTarget(const Triple &TT); |
146 | |
147 | COFFPlatform( |
148 | ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, |
149 | JITDylib &PlatformJD, |
150 | std::unique_ptr<StaticLibraryDefinitionGenerator> OrcRuntimeGenerator, |
151 | std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer, |
152 | std::unique_ptr<object::Archive> OrcRuntimeArchive, |
153 | LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, |
154 | const char *VCRuntimePath, Error &Err); |
155 | |
156 | // Associate COFFPlatform JIT-side runtime support functions with handlers. |
157 | Error associateRuntimeSupportFunctions(JITDylib &PlatformJD); |
158 | |
159 | // Records the addresses of runtime symbols used by the platform. |
160 | Error bootstrapCOFFRuntime(JITDylib &PlatformJD); |
161 | |
162 | // Run a specific void function if it exists. |
163 | Error runSymbolIfExists(JITDylib &PlatformJD, StringRef SymbolName); |
164 | |
165 | // Run collected initializers in boostrap stage. |
166 | Error runBootstrapInitializers(JDBootstrapState &BState); |
167 | Error runBootstrapSubsectionInitializers(JDBootstrapState &BState, |
168 | StringRef Start, StringRef End); |
169 | |
170 | // Build dependency graph of a JITDylib |
171 | Expected<JITDylibDepMap> buildJDDepMap(JITDylib &JD); |
172 | |
173 | Expected<MemoryBufferRef> getPerJDObjectFile(); |
174 | |
175 | // Implements rt_pushInitializers by making repeat async lookups for |
176 | // initializer symbols (each lookup may spawn more initializer symbols if |
177 | // it pulls in new materializers, e.g. from objects in a static library). |
178 | void pushInitializersLoop(PushInitializersSendResultFn SendResult, |
179 | JITDylibSP JD, JITDylibDepMap &JDDepMap); |
180 | |
181 | void rt_pushInitializers(PushInitializersSendResultFn SendResult, |
182 | ExecutorAddr ); |
183 | |
184 | void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddr Handle, |
185 | StringRef SymbolName); |
186 | |
187 | ExecutionSession &ES; |
188 | ObjectLinkingLayer &ObjLinkingLayer; |
189 | |
190 | LoadDynamicLibrary LoadDynLibrary; |
191 | std::unique_ptr<COFFVCRuntimeBootstrapper> VCRuntimeBootstrap; |
192 | std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer; |
193 | std::unique_ptr<object::Archive> OrcRuntimeArchive; |
194 | bool StaticVCRuntime; |
195 | |
196 | SymbolStringPtr ; |
197 | |
198 | // State of bootstrap in progress |
199 | std::map<JITDylib *, JDBootstrapState> JDBootstrapStates; |
200 | std::atomic<bool> Bootstrapping; |
201 | |
202 | ExecutorAddr orc_rt_coff_platform_bootstrap; |
203 | ExecutorAddr orc_rt_coff_platform_shutdown; |
204 | ExecutorAddr orc_rt_coff_register_object_sections; |
205 | ExecutorAddr orc_rt_coff_deregister_object_sections; |
206 | ExecutorAddr orc_rt_coff_register_jitdylib; |
207 | ExecutorAddr orc_rt_coff_deregister_jitdylib; |
208 | |
209 | DenseMap<JITDylib *, ExecutorAddr> ; |
210 | DenseMap<ExecutorAddr, JITDylib *> ; |
211 | |
212 | DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols; |
213 | |
214 | std::set<std::string> DylibsToPreload; |
215 | |
216 | std::mutex PlatformMutex; |
217 | }; |
218 | |
219 | } // end namespace orc |
220 | } // end namespace llvm |
221 | |
222 | #endif // LLVM_EXECUTIONENGINE_ORC_COFFPLATFORM_H |
223 | |