LLVM 18.0.0git
MachOPlatform.h
Go to the documentation of this file.
1//===-- MachOPlatform.h - Utilities for executing MachO 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 MachO in Orc.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
14#define LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
15
16#include "llvm/ADT/StringRef.h"
21
22#include <future>
23#include <thread>
24#include <vector>
25
26namespace llvm {
27namespace orc {
28
29/// Mediates between MachO initialization and ExecutionSession state.
30class MachOPlatform : public Platform {
31public:
32 // Used internally by MachOPlatform, but made public to enable serialization.
34 bool Sealed = false;
35 std::vector<ExecutorAddr> DepHeaders;
36 };
37
38 // Used internally by MachOPlatform, but made public to enable serialization.
40 std::vector<std::pair<ExecutorAddr, MachOJITDylibDepInfo>>;
41
42 // Used internally by MachOPlatform, but made public to enable serialization.
43 enum class MachOExecutorSymbolFlags : uint8_t {
44 None = 0,
45 Weak = 1U << 0,
46 Callable = 1U << 1,
47 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Callable)
48 };
49
50 /// Try to create a MachOPlatform instance, adding the ORC runtime to the
51 /// given JITDylib.
52 ///
53 /// The ORC runtime requires access to a number of symbols in libc++, and
54 /// requires access to symbols in libobjc, and libswiftCore to support
55 /// Objective-C and Swift code. It is up to the caller to ensure that the
56 /// required symbols can be referenced by code added to PlatformJD. The
57 /// standard way to achieve this is to first attach dynamic library search
58 /// generators for either the given process, or for the specific required
59 /// libraries, to PlatformJD, then to create the platform instance:
60 ///
61 /// \code{.cpp}
62 /// auto &PlatformJD = ES.createBareJITDylib("stdlib");
63 /// PlatformJD.addGenerator(
64 /// ExitOnErr(EPCDynamicLibrarySearchGenerator
65 /// ::GetForTargetProcess(EPC)));
66 /// ES.setPlatform(
67 /// ExitOnErr(MachOPlatform::Create(ES, ObjLayer, EPC, PlatformJD,
68 /// "/path/to/orc/runtime")));
69 /// \endcode
70 ///
71 /// Alternatively, these symbols could be added to another JITDylib that
72 /// PlatformJD links against.
73 ///
74 /// Clients are also responsible for ensuring that any JIT'd code that
75 /// depends on runtime functions (including any code using TLV or static
76 /// destructors) can reference the runtime symbols. This is usually achieved
77 /// by linking any JITDylibs containing regular code against
78 /// PlatformJD.
79 ///
80 /// By default, MachOPlatform will add the set of aliases returned by the
81 /// standardPlatformAliases function. This includes both required aliases
82 /// (e.g. __cxa_atexit -> __orc_rt_macho_cxa_atexit for static destructor
83 /// support), and optional aliases that provide JIT versions of common
84 /// functions (e.g. dlopen -> __orc_rt_macho_jit_dlopen). Clients can
85 /// override these defaults by passing a non-None value for the
86 /// RuntimeAliases function, in which case the client is responsible for
87 /// setting up all aliases (including the required ones).
89 Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
90 JITDylib &PlatformJD, std::unique_ptr<DefinitionGenerator> OrcRuntime,
91 std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
92
93 /// Construct using a path to the ORC runtime.
95 Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
96 JITDylib &PlatformJD, const char *OrcRuntimePath,
97 std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
98
99 ExecutionSession &getExecutionSession() const { return ES; }
100 ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
101
102 Error setupJITDylib(JITDylib &JD) override;
103 Error teardownJITDylib(JITDylib &JD) override;
105 const MaterializationUnit &MU) override;
107
108 /// Returns an AliasMap containing the default aliases for the MachOPlatform.
109 /// This can be modified by clients when constructing the platform to add
110 /// or remove aliases.
112
113 /// Returns the array of required CXX aliases.
115
116 /// Returns the array of standard runtime utility aliases for MachO.
119
120private:
121 using SymbolTableVector = SmallVector<
122 std::tuple<ExecutorAddr, ExecutorAddr, MachOExecutorSymbolFlags>>;
123
124 // Data needed for bootstrap only.
125 struct BootstrapInfo {
126 std::mutex Mutex;
127 std::condition_variable CV;
128 size_t ActiveGraphs = 0;
129 shared::AllocActions DeferredAAs;
130 ExecutorAddr MachOHeaderAddr;
131 SymbolTableVector SymTab;
132 };
133
134 // The MachOPlatformPlugin scans/modifies LinkGraphs to support MachO
135 // platform features including initializers, exceptions, TLV, and language
136 // runtime registration.
137 class MachOPlatformPlugin : public ObjectLinkingLayer::Plugin {
138 public:
139 MachOPlatformPlugin(MachOPlatform &MP) : MP(MP) {}
140
141 void modifyPassConfig(MaterializationResponsibility &MR,
142 jitlink::LinkGraph &G,
143 jitlink::PassConfiguration &Config) override;
144
146 getSyntheticSymbolDependencies(MaterializationResponsibility &MR) override;
147
148 // FIXME: We should be tentatively tracking scraped sections and discarding
149 // if the MR fails.
150 Error notifyFailed(MaterializationResponsibility &MR) override {
151 return Error::success();
152 }
153
154 Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
155 return Error::success();
156 }
157
158 void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
159 ResourceKey SrcKey) override {}
160
161 private:
162 using InitSymbolDepMap =
163 DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>;
164
165 struct UnwindSections {
166 SmallVector<ExecutorAddrRange> CodeRanges;
167 ExecutorAddrRange DwarfSection;
168 ExecutorAddrRange CompactUnwindSection;
169 };
170
171 struct ObjCImageInfo {
172 uint32_t Version = 0;
173 uint32_t Flags = 0;
174 /// Whether this image info can no longer be mutated, as it may have been
175 /// registered with the objc runtime.
176 bool Finalized = false;
177 };
178
179 struct SymbolTablePair {
180 jitlink::Symbol *OriginalSym = nullptr;
181 jitlink::Symbol *NameSym = nullptr;
182 };
183 using JITSymTabVector = SmallVector<SymbolTablePair>;
184
185 Error bootstrapPipelineStart(jitlink::LinkGraph &G);
186 Error bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G);
187 Error bootstrapPipelineEnd(jitlink::LinkGraph &G);
188
189 Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G,
190 MaterializationResponsibility &MR);
191
192 Error preserveImportantSections(jitlink::LinkGraph &G,
193 MaterializationResponsibility &MR);
194
195 Error processObjCImageInfo(jitlink::LinkGraph &G,
196 MaterializationResponsibility &MR);
197 Error mergeImageInfoFlags(jitlink::LinkGraph &G,
198 MaterializationResponsibility &MR,
199 ObjCImageInfo &Info, uint32_t NewFlags);
200
201 Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
202
203 std::optional<UnwindSections> findUnwindSectionInfo(jitlink::LinkGraph &G);
204 Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD,
205 bool InBootstrapPhase);
206
207 Error createObjCRuntimeObject(jitlink::LinkGraph &G);
208 Error populateObjCRuntimeObject(jitlink::LinkGraph &G,
209 MaterializationResponsibility &MR);
210
211 Error prepareSymbolTableRegistration(jitlink::LinkGraph &G,
212 JITSymTabVector &JITSymTabInfo);
213 Error addSymbolTableRegistration(jitlink::LinkGraph &G,
214 MaterializationResponsibility &MR,
215 JITSymTabVector &JITSymTabInfo,
216 bool InBootstrapPhase);
217
218 std::mutex PluginMutex;
219 MachOPlatform &MP;
220
221 // FIXME: ObjCImageInfos and HeaderAddrs need to be cleared when
222 // JITDylibs are removed.
223 DenseMap<JITDylib *, ObjCImageInfo> ObjCImageInfos;
224 DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
225 InitSymbolDepMap InitSymbolDeps;
226 };
227
228 using GetJITDylibHeaderSendResultFn =
229 unique_function<void(Expected<ExecutorAddr>)>;
230 using GetJITDylibNameSendResultFn =
231 unique_function<void(Expected<StringRef>)>;
232 using PushInitializersSendResultFn =
233 unique_function<void(Expected<MachOJITDylibDepInfoMap>)>;
234 using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>;
235 using PushSymbolsInSendResultFn = unique_function<void(Error)>;
236
237 static bool supportedTarget(const Triple &TT);
238
239 static jitlink::Edge::Kind getPointerEdgeKind(jitlink::LinkGraph &G);
240
241 static MachOExecutorSymbolFlags flagsForSymbol(jitlink::Symbol &Sym);
242
243 MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
244 JITDylib &PlatformJD,
245 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
246 Error &Err);
247
248 // Associate MachOPlatform JIT-side runtime support functions with handlers.
249 Error associateRuntimeSupportFunctions();
250
251 // Implements rt_pushInitializers by making repeat async lookups for
252 // initializer symbols (each lookup may spawn more initializer symbols if
253 // it pulls in new materializers, e.g. from objects in a static library).
254 void pushInitializersLoop(PushInitializersSendResultFn SendResult,
255 JITDylibSP JD);
256
257 // Handle requests from the ORC runtime to push MachO initializer info.
258 void rt_pushInitializers(PushInitializersSendResultFn SendResult,
259 ExecutorAddr JDHeaderAddr);
260
261 // Request that that the given symbols be materialized. The bool element of
262 // each pair indicates whether the symbol must be initialized, or whether it
263 // is optional. If any required symbol is not found then the pushSymbols
264 // function will return an error.
265 void rt_pushSymbols(PushSymbolsInSendResultFn SendResult, ExecutorAddr Handle,
266 const std::vector<std::pair<StringRef, bool>> &Symbols);
267
268 // Call the ORC runtime to create a pthread key.
269 Expected<uint64_t> createPThreadKey();
270
271 ExecutionSession &ES;
272 JITDylib &PlatformJD;
273 ObjectLinkingLayer &ObjLinkingLayer;
274
275 SymbolStringPtr MachOHeaderStartSymbol = ES.intern("___dso_handle");
276
277 struct RuntimeFunction {
278 RuntimeFunction(SymbolStringPtr Name) : Name(std::move(Name)) {}
279 SymbolStringPtr Name;
280 ExecutorAddr Addr;
281 };
282
283 RuntimeFunction PlatformBootstrap{
284 ES.intern("___orc_rt_macho_platform_bootstrap")};
285 RuntimeFunction PlatformShutdown{
286 ES.intern("___orc_rt_macho_platform_shutdown")};
287 RuntimeFunction RegisterEHFrameSection{
288 ES.intern("___orc_rt_macho_register_ehframe_section")};
289 RuntimeFunction DeregisterEHFrameSection{
290 ES.intern("___orc_rt_macho_deregister_ehframe_section")};
291 RuntimeFunction RegisterJITDylib{
292 ES.intern("___orc_rt_macho_register_jitdylib")};
293 RuntimeFunction DeregisterJITDylib{
294 ES.intern("___orc_rt_macho_deregister_jitdylib")};
295 RuntimeFunction RegisterObjectSymbolTable{
296 ES.intern("___orc_rt_macho_register_object_symbol_table")};
297 RuntimeFunction DeregisterObjectSymbolTable{
298 ES.intern("___orc_rt_macho_deregister_object_symbol_table")};
299 RuntimeFunction RegisterObjectPlatformSections{
300 ES.intern("___orc_rt_macho_register_object_platform_sections")};
301 RuntimeFunction DeregisterObjectPlatformSections{
302 ES.intern("___orc_rt_macho_deregister_object_platform_sections")};
303 RuntimeFunction CreatePThreadKey{
304 ES.intern("___orc_rt_macho_create_pthread_key")};
305 RuntimeFunction RegisterObjCRuntimeObject{
306 ES.intern("___orc_rt_macho_register_objc_runtime_object")};
307 RuntimeFunction DeregisterObjCRuntimeObject{
308 ES.intern("___orc_rt_macho_deregister_objc_runtime_object")};
309
310 DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
311
312 std::mutex PlatformMutex;
313 DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr;
314 DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
315 DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
316
317 std::atomic<BootstrapInfo *> Bootstrap;
318};
319
320} // end namespace orc
321} // end namespace llvm
322
323#endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
uint64_t Addr
RelaxConfig Config
Definition: ELF_riscv.cpp:504
Symbol * Sym
Definition: ELF_riscv.cpp:477
#define G(x, y, z)
Definition: MD5.cpp:56
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:334
Tagged union holding either a T or a Error.
Definition: Error.h:474
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
An ExecutionSession represents a running JIT program.
Definition: Core.h:1389
Represents an address in the executor process.
Represents a JIT'd dynamic library.
Definition: Core.h:958
Mediates between MachO initialization and ExecutionSession state.
Definition: MachOPlatform.h:30
ObjectLinkingLayer & getObjectLinkingLayer() const
Error teardownJITDylib(JITDylib &JD) override
This method will be called outside the session lock each time a JITDylib is removed to allow the Plat...
Error setupJITDylib(JITDylib &JD) override
This method will be called outside the session lock each time a JITDylib is created (unless it is cre...
static ArrayRef< std::pair< const char *, const char * > > standardRuntimeUtilityAliases()
Returns the array of standard runtime utility aliases for MachO.
std::vector< std::pair< ExecutorAddr, MachOJITDylibDepInfo > > MachOJITDylibDepInfoMap
Definition: MachOPlatform.h:40
Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) override
This method will be called under the ExecutionSession lock each time a MaterializationUnit is added t...
static Expected< std::unique_ptr< MachOPlatform > > Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, std::unique_ptr< DefinitionGenerator > OrcRuntime, std::optional< SymbolAliasMap > RuntimeAliases=std::nullopt)
Try to create a MachOPlatform instance, adding the ORC runtime to the given JITDylib.
static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES)
Returns an AliasMap containing the default aliases for the MachOPlatform.
ExecutionSession & getExecutionSession() const
Definition: MachOPlatform.h:99
Error notifyRemoving(ResourceTracker &RT) override
This method will be called under the ExecutionSession lock when a ResourceTracker is removed.
static ArrayRef< std::pair< const char *, const char * > > requiredCXXAliases()
Returns the array of required CXX aliases.
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Definition: Core.h:662
DenseMap< SymbolStringPtr, JITLinkSymbolSet > SyntheticSymbolDependenciesMap
An ObjectLayer implementation built on JITLink.
Platforms set up standard symbols and mediate interactions between dynamic initializers (e....
Definition: Core.h:1318
API to remove / transfer ownership of JIT resources.
Definition: Core.h:56
const uint64_t Version
Definition: InstrProf.h:1027
RuntimeFunction
IDs for all omp runtime library (RTL) functions.
Definition: OMPConstants.h:46
std::vector< AllocActionCallPair > AllocActions
A vector of allocation actions to be run for this allocation.
IntrusiveRefCntPtr< JITDylib > JITDylibSP
Definition: Core.h:51
uintptr_t ResourceKey
Definition: Core.h:53
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1853
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858