LLVM 23.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"
22
23#include <array>
24#include <future>
25#include <optional>
26#include <thread>
27#include <vector>
28
29namespace llvm {
30namespace orc {
31
32/// Mediates between MachO initialization and ExecutionSession state.
33class LLVM_ABI MachOPlatform : public Platform {
34public:
35 // Used internally by MachOPlatform, but made public to enable serialization.
37 bool Sealed = false;
38 std::vector<ExecutorAddr> DepHeaders;
39 };
40
41 // Used internally by MachOPlatform, but made public to enable serialization.
43 std::vector<std::pair<ExecutorAddr, MachOJITDylibDepInfo>>;
44
45 // Used internally by MachOPlatform, but made public to enable serialization.
47 None = 0,
48 Weak = 1U << 0,
49 Callable = 1U << 1,
50 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Callable)
51 };
52
53 /// Configuration for the mach-o header of a JITDylib. Specify common load
54 /// commands that should be added to the header.
56 /// A dylib for use with a dylib command (e.g. LC_ID_DYLIB, LC_LOAD_DYLIB).
63
64 struct LoadDylibCmd {
65 enum class LoadKind { Default, Weak };
66
69 };
70
72
73 // Derive platform from triple if possible.
74 LLVM_ABI static std::optional<BuildVersionOpts>
76
77 uint32_t Platform; // Platform.
78 uint32_t MinOS; // X.Y.Z is encoded in nibbles xxxx.yy.zz
79 uint32_t SDK; // X.Y.Z is encoded in nibbles xxxx.yy.zz
80 };
81
82 /// Override for LC_IC_DYLIB. If this is nullopt, {JD.getName(), 0, 0, 0}
83 /// will be used.
84 std::optional<Dylib> IDDylib;
85
86 /// List of LC_LOAD_DYLIBs.
87 std::vector<LoadDylibCmd> LoadDylibs;
88 /// List of LC_RPATHs.
89 std::vector<std::string> RPaths;
90 /// List of LC_BUILD_VERSIONs.
91 std::vector<BuildVersionOpts> BuildVersions;
92
93 /// Optional UUID. If set, this will be used to add an LC_UUID command.
94 std::optional<std::array<uint8_t, 16>> UUID;
95
96 HeaderOptions() = default;
98 };
99
100 /// Callback for generating HeaderOptions structs for new JITDylibs.
102
103 /// Used by setupJITDylib to create MachO header MaterializationUnits for
104 /// JITDylibs.
107 HeaderOptions Opts)>;
108
109 /// Simple MachO header graph builder.
110 static inline std::unique_ptr<MaterializationUnit>
111 buildSimpleMachOHeaderMU(MachOPlatform &MOP, HeaderOptions Opts);
112
113 /// Try to create a MachOPlatform instance, adding the ORC runtime to the
114 /// given JITDylib.
115 ///
116 /// The ORC runtime requires access to a number of symbols in libc++, and
117 /// requires access to symbols in libobjc, and libswiftCore to support
118 /// Objective-C and Swift code. It is up to the caller to ensure that the
119 /// required symbols can be referenced by code added to PlatformJD. The
120 /// standard way to achieve this is to first attach dynamic library search
121 /// generators for either the given process, or for the specific required
122 /// libraries, to PlatformJD, then to create the platform instance:
123 ///
124 /// \code{.cpp}
125 /// auto &PlatformJD = ES.createBareJITDylib("stdlib");
126 /// PlatformJD.addGenerator(
127 /// ExitOnErr(EPCDynamicLibrarySearchGenerator
128 /// ::GetForTargetProcess(EPC)));
129 /// ES.setPlatform(
130 /// ExitOnErr(MachOPlatform::Create(ES, ObjLayer, EPC, PlatformJD,
131 /// "/path/to/orc/runtime")));
132 /// \endcode
133 ///
134 /// Alternatively, these symbols could be added to another JITDylib that
135 /// PlatformJD links against.
136 ///
137 /// Clients are also responsible for ensuring that any JIT'd code that
138 /// depends on runtime functions (including any code using TLV or static
139 /// destructors) can reference the runtime symbols. This is usually achieved
140 /// by linking any JITDylibs containing regular code against
141 /// PlatformJD.
142 ///
143 /// By default, MachOPlatform will add the set of aliases returned by the
144 /// standardPlatformAliases function. This includes both required aliases
145 /// (e.g. __cxa_atexit -> __orc_rt_macho_cxa_atexit for static destructor
146 /// support), and optional aliases that provide JIT versions of common
147 /// functions (e.g. dlopen -> __orc_rt_macho_jit_dlopen). Clients can
148 /// override these defaults by passing a non-None value for the
149 /// RuntimeAliases function, in which case the client is responsible for
150 /// setting up all aliases (including the required ones).
152 Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
153 std::unique_ptr<DefinitionGenerator> OrcRuntime,
154 HeaderOptionsBuilder BuildHeaderOpts = defaultHeaderOpts,
155 HeaderOptions PlatformJDOpts = {},
156 MachOHeaderMUBuilder BuildMachOHeaderMU = buildSimpleMachOHeaderMU,
157 std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
158
159 /// Construct using a path to the ORC runtime.
161 Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
162 const char *OrcRuntimePath,
163 HeaderOptionsBuilder BuildHeaderOpts = defaultHeaderOpts,
164 HeaderOptions PlatformJDOpts = {},
165 MachOHeaderMUBuilder BuildMachOHeaderMU = buildSimpleMachOHeaderMU,
166 std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
167
168 ExecutionSession &getExecutionSession() const { return ES; }
169 ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
170
172 return NonOwningSymbolStringPtr(MachOHeaderStartSymbol);
173 }
174
175 Error setupJITDylib(JITDylib &JD) override;
176
177 /// Install any platform-specific symbols (e.g. `__dso_handle`) and create a
178 /// mach-o header based on the given options.
179 Error setupJITDylib(JITDylib &JD, HeaderOptions Opts);
180
181 Error teardownJITDylib(JITDylib &JD) override;
182 Error notifyAdding(ResourceTracker &RT,
183 const MaterializationUnit &MU) override;
184 Error notifyRemoving(ResourceTracker &RT) override;
185
186 /// Returns an AliasMap containing the default aliases for the MachOPlatform.
187 /// This can be modified by clients when constructing the platform to add
188 /// or remove aliases.
189 static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES);
190
191 /// Returns the array of required CXX aliases.
192 static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases();
193
194 /// Returns the array of standard runtime utility aliases for MachO.
196 standardRuntimeUtilityAliases();
197
198 /// Returns a list of aliases required to enable lazy compilation via the
199 /// ORC runtime.
201 standardLazyCompilationAliases();
202
203 static HeaderOptions defaultHeaderOpts(JITDylib &JD);
204
205private:
206 using SymbolTableVector = SmallVector<
207 std::tuple<ExecutorAddr, ExecutorAddr, MachOExecutorSymbolFlags>>;
208
209 // Data needed for bootstrap only.
210 struct BootstrapInfo {
211 std::condition_variable CV;
212 size_t ActiveGraphs = 0;
213 shared::AllocActions DeferredAAs;
214 ExecutorAddr MachOHeaderAddr;
215 SymbolTableVector SymTab;
216 };
217
218 // The MachOPlatformPlugin scans/modifies LinkGraphs to support MachO
219 // platform features including initializers, exceptions, TLV, and language
220 // runtime registration.
221 class LLVM_ABI MachOPlatformPlugin : public ObjectLinkingLayer::Plugin {
222 public:
223 MachOPlatformPlugin(MachOPlatform &MP) : MP(MP) {}
224
225 void modifyPassConfig(MaterializationResponsibility &MR,
226 jitlink::LinkGraph &G,
227 jitlink::PassConfiguration &Config) override;
228
229 // FIXME: We should be tentatively tracking scraped sections and discarding
230 // if the MR fails.
231 Error notifyFailed(MaterializationResponsibility &MR) override {
232 return Error::success();
233 }
234
235 Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
236 return Error::success();
237 }
238
239 void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
240 ResourceKey SrcKey) override {}
241
242 private:
243 struct UnwindSections {
244 SmallVector<ExecutorAddrRange> CodeRanges;
245 ExecutorAddrRange DwarfSection;
246 ExecutorAddrRange CompactUnwindSection;
247 };
248
249 struct ObjCImageInfo {
250 uint32_t Version = 0;
251 uint32_t Flags = 0;
252 /// Whether this image info can no longer be mutated, as it may have been
253 /// registered with the objc runtime.
254 bool Finalized = false;
255 };
256
257 struct SymbolTablePair {
258 jitlink::Symbol *OriginalSym = nullptr;
259 jitlink::Symbol *NameSym = nullptr;
260 };
261 using JITSymTabVector = SmallVector<SymbolTablePair>;
262
263 Error bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G);
264 Error bootstrapPipelineEnd(jitlink::LinkGraph &G);
265
266 Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G,
267 MaterializationResponsibility &MR);
268
269 Error preserveImportantSections(jitlink::LinkGraph &G,
270 MaterializationResponsibility &MR);
271
272 Error processObjCImageInfo(jitlink::LinkGraph &G,
273 MaterializationResponsibility &MR);
274 Error mergeImageInfoFlags(jitlink::LinkGraph &G,
275 MaterializationResponsibility &MR,
276 ObjCImageInfo &Info, uint32_t NewFlags);
277
278 Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
279
280 std::optional<UnwindSections> findUnwindSectionInfo(jitlink::LinkGraph &G);
281 Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD,
282 ExecutorAddr HeaderAddr,
283 bool InBootstrapPhase);
284
285 Error createObjCRuntimeObject(jitlink::LinkGraph &G);
286 Error populateObjCRuntimeObject(jitlink::LinkGraph &G,
287 MaterializationResponsibility &MR);
288
289 Error prepareSymbolTableRegistration(jitlink::LinkGraph &G,
290 JITSymTabVector &JITSymTabInfo);
291 Error addSymbolTableRegistration(jitlink::LinkGraph &G,
292 MaterializationResponsibility &MR,
293 JITSymTabVector &JITSymTabInfo,
294 bool InBootstrapPhase);
295
296 std::mutex PluginMutex;
297 MachOPlatform &MP;
298
299 // FIXME: ObjCImageInfos and HeaderAddrs need to be cleared when
300 // JITDylibs are removed.
301 DenseMap<JITDylib *, ObjCImageInfo> ObjCImageInfos;
302 };
303
304 using GetJITDylibHeaderSendResultFn =
305 unique_function<void(Expected<ExecutorAddr>)>;
306 using GetJITDylibNameSendResultFn =
307 unique_function<void(Expected<StringRef>)>;
308 using PushInitializersSendResultFn =
309 unique_function<void(Expected<MachOJITDylibDepInfoMap>)>;
310 using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>;
311 using PushSymbolsInSendResultFn = unique_function<void(Error)>;
312
313 static bool supportedTarget(const Triple &TT);
314
315 static jitlink::Edge::Kind getPointerEdgeKind(jitlink::LinkGraph &G);
316
317 static MachOExecutorSymbolFlags flagsForSymbol(jitlink::Symbol &Sym);
318
319 MachOPlatform(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
320 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
321 HeaderOptionsBuilder BuildHeaderOpts,
322 HeaderOptions PlatformJDOpts,
323 MachOHeaderMUBuilder BuildMachOHeaderMU, Error &Err);
324
325 // Associate MachOPlatform JIT-side runtime support functions with handlers.
326 Error associateRuntimeSupportFunctions();
327
328 // Implements rt_pushInitializers by making repeat async lookups for
329 // initializer symbols (each lookup may spawn more initializer symbols if
330 // it pulls in new materializers, e.g. from objects in a static library).
331 void pushInitializersLoop(PushInitializersSendResultFn SendResult,
332 JITDylibSP JD);
333
334 // Handle requests from the ORC runtime to push MachO initializer info.
335 void rt_pushInitializers(PushInitializersSendResultFn SendResult,
336 ExecutorAddr JDHeaderAddr);
337
338 // Request that that the given symbols be materialized. The bool element of
339 // each pair indicates whether the symbol must be initialized, or whether it
340 // is optional. If any required symbol is not found then the pushSymbols
341 // function will return an error.
342 void rt_pushSymbols(PushSymbolsInSendResultFn SendResult, ExecutorAddr Handle,
343 const std::vector<std::pair<StringRef, bool>> &Symbols);
344
345 // Call the ORC runtime to create a pthread key.
346 Expected<uint64_t> createPThreadKey();
347
348 ExecutionSession &ES;
349 JITDylib &PlatformJD;
350 ObjectLinkingLayer &ObjLinkingLayer;
351 HeaderOptionsBuilder BuildHeaderOpts;
352 MachOHeaderMUBuilder BuildMachOHeaderMU;
353
354 SymbolStringPtr MachOHeaderStartSymbol = ES.intern("___dso_handle");
355
356 struct RuntimeFunction {
357 RuntimeFunction(SymbolStringPtr Name) : Name(std::move(Name)) {}
358 SymbolStringPtr Name;
359 ExecutorAddr Addr;
360 };
361
362 RuntimeFunction PlatformBootstrap{
363 ES.intern("___orc_rt_macho_platform_bootstrap")};
364 RuntimeFunction PlatformShutdown{
365 ES.intern("___orc_rt_macho_platform_shutdown")};
366 RuntimeFunction RegisterEHFrameSection{
367 ES.intern("___orc_rt_macho_register_ehframe_section")};
368 RuntimeFunction DeregisterEHFrameSection{
369 ES.intern("___orc_rt_macho_deregister_ehframe_section")};
370 RuntimeFunction RegisterJITDylib{
371 ES.intern("___orc_rt_macho_register_jitdylib")};
372 RuntimeFunction DeregisterJITDylib{
373 ES.intern("___orc_rt_macho_deregister_jitdylib")};
374 RuntimeFunction RegisterObjectSymbolTable{
375 ES.intern("___orc_rt_macho_register_object_symbol_table")};
376 RuntimeFunction DeregisterObjectSymbolTable{
377 ES.intern("___orc_rt_macho_deregister_object_symbol_table")};
378 RuntimeFunction RegisterObjectPlatformSections{
379 ES.intern("___orc_rt_macho_register_object_platform_sections")};
380 RuntimeFunction DeregisterObjectPlatformSections{
381 ES.intern("___orc_rt_macho_deregister_object_platform_sections")};
382 RuntimeFunction CreatePThreadKey{
383 ES.intern("___orc_rt_macho_create_pthread_key")};
384 RuntimeFunction RegisterObjCRuntimeObject{
385 ES.intern("___orc_rt_macho_register_objc_runtime_object")};
386 RuntimeFunction DeregisterObjCRuntimeObject{
387 ES.intern("___orc_rt_macho_deregister_objc_runtime_object")};
388
389 DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
390
391 std::mutex PlatformMutex;
392 bool ForceEHFrames = false;
393 BootstrapInfo *Bootstrap = nullptr;
394 DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr;
395 DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
396 DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
397};
398
399// Generates a MachO header.
401public:
404 StringRef getName() const override { return "MachOHeaderMU"; }
405 void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
406 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override;
407
408protected:
410 jitlink::Section &HeaderSection);
411
414
415private:
416 struct HeaderSymbol {
417 const char *Name;
419 };
420
421 static constexpr HeaderSymbol AdditionalHeaderSymbols[] = {
422 {"___mh_executable_header", 0}};
423
424 void addMachOHeader(JITDylib &JD, jitlink::LinkGraph &G,
425 const SymbolStringPtr &InitializerSymbol);
426 static MaterializationUnit::Interface
427 createHeaderInterface(MachOPlatform &MOP,
428 const SymbolStringPtr &HeaderStartSymbol);
429};
430
431/// Simple MachO header graph builder.
432inline std::unique_ptr<MaterializationUnit>
434 HeaderOptions Opts) {
435 return std::make_unique<SimpleMachOHeaderMU>(MOP, MOP.MachOHeaderStartSymbol,
436 std::move(Opts));
437}
438
445
446} // end namespace orc
447} // end namespace llvm
448
449#endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
#define LLVM_MARK_AS_BITMASK_ENUM(LargestValue)
LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can perform bitwise operatio...
Definition BitmaskEnum.h:42
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_ABI
Definition Compiler.h:213
#define G(x, y, z)
Definition MD5.cpp:55
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
An ExecutionSession represents a running JIT program.
Definition Core.h:1355
Represents an address in the executor process.
Represents a JIT'd dynamic library.
Definition Core.h:919
Mediates between MachO initialization and ExecutionSession state.
ObjectLinkingLayer & getObjectLinkingLayer() const
NonOwningSymbolStringPtr getMachOHeaderStartSymbol() const
static std::unique_ptr< MaterializationUnit > buildSimpleMachOHeaderMU(MachOPlatform &MOP, HeaderOptions Opts)
Simple MachO header graph builder.
static Expected< std::unique_ptr< MachOPlatform > > Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, std::unique_ptr< DefinitionGenerator > OrcRuntime, HeaderOptionsBuilder BuildHeaderOpts=defaultHeaderOpts, HeaderOptions PlatformJDOpts={}, MachOHeaderMUBuilder BuildMachOHeaderMU=buildSimpleMachOHeaderMU, std::optional< SymbolAliasMap > RuntimeAliases=std::nullopt)
Try to create a MachOPlatform instance, adding the ORC runtime to the given JITDylib.
static HeaderOptions defaultHeaderOpts(JITDylib &JD)
std::vector< std::pair< ExecutorAddr, MachOJITDylibDepInfo > > MachOJITDylibDepInfoMap
unique_function< std::unique_ptr< MaterializationUnit >(MachOPlatform &MOP, HeaderOptions Opts)> MachOHeaderMUBuilder
Used by setupJITDylib to create MachO header MaterializationUnits for JITDylibs.
ExecutionSession & getExecutionSession() const
unique_function< HeaderOptions(JITDylib &JD)> HeaderOptionsBuilder
Callback for generating HeaderOptions structs for new JITDylibs.
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Non-owning SymbolStringPool entry pointer.
An ObjectLayer implementation built on JITLink.
Platforms set up standard symbols and mediate interactions between dynamic initializers (e....
Definition Core.h:1282
API to remove / transfer ownership of JIT resources.
Definition Core.h:82
StringRef getName() const override
Return the name of this materialization unit.
MachOPlatform::HeaderOptions Opts
SimpleMachOHeaderMU(MachOPlatform &MOP, SymbolStringPtr HeaderStartSymbol, MachOPlatform::HeaderOptions Opts)
Pointer to a pooled string representing a symbol name.
unique_function is a type-erasing functor similar to std::function.
RuntimeFunction
IDs for all omp runtime library (RTL) functions.
std::vector< AllocActionCallPair > AllocActions
A vector of allocation actions to be run for this allocation.
jitlink::Block & createHeaderBlock(MachOPlatform &MOP, const MachOPlatform::HeaderOptions &Opts, JITDylib &JD, jitlink::LinkGraph &G, jitlink::Section &HeaderSection)
LLVM_ABI MachOHeaderInfo getMachOHeaderInfoFromTriple(const Triple &TT)
DenseMap< SymbolStringPtr, SymbolAliasMapEntry > SymbolAliasMap
A map of Symbols to (Symbol, Flags) pairs.
Definition Core.h:417
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
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:1917
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
static LLVM_ABI std::optional< BuildVersionOpts > fromTriple(const Triple &TT, uint32_t MinOS, uint32_t SDK)
A dylib for use with a dylib command (e.g. LC_ID_DYLIB, LC_LOAD_DYLIB).
Configuration for the mach-o header of a JITDylib.
std::optional< Dylib > IDDylib
Override for LC_IC_DYLIB.
std::optional< std::array< uint8_t, 16 > > UUID
Optional UUID. If set, this will be used to add an LC_UUID command.
std::vector< std::string > RPaths
List of LC_RPATHs.
std::vector< BuildVersionOpts > BuildVersions
List of LC_BUILD_VERSIONs.
std::vector< LoadDylibCmd > LoadDylibs
List of LC_LOAD_DYLIBs.