LLVM 24.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 /// Optional LC_TARGET_TRIPLE.
93 std::optional<std::string> TargetTriple;
94
95 /// Optional UUID. If set, this will be used to add an LC_UUID command.
96 std::optional<std::array<uint8_t, 16>> UUID;
97
98 HeaderOptions() = default;
100 };
101
102 /// Callback for generating HeaderOptions structs for new JITDylibs.
104
105 /// Used by setupJITDylib to create MachO header MaterializationUnits for
106 /// JITDylibs.
109 HeaderOptions Opts)>;
110
111 /// Simple MachO header graph builder.
112 static inline std::unique_ptr<MaterializationUnit>
113 buildSimpleMachOHeaderMU(MachOPlatform &MOP, HeaderOptions Opts);
114
115 /// Try to create a MachOPlatform instance, adding the ORC runtime to the
116 /// given JITDylib.
117 ///
118 /// The ORC runtime requires access to a number of symbols in libc++, and
119 /// requires access to symbols in libobjc, and libswiftCore to support
120 /// Objective-C and Swift code. It is up to the caller to ensure that the
121 /// required symbols can be referenced by code added to PlatformJD. The
122 /// standard way to achieve this is to first attach dynamic library search
123 /// generators for either the given process, or for the specific required
124 /// libraries, to PlatformJD, then to create the platform instance:
125 ///
126 /// \code{.cpp}
127 /// auto &PlatformJD = ES.createBareJITDylib("stdlib");
128 /// PlatformJD.addGenerator(
129 /// ExitOnErr(EPCDynamicLibrarySearchGenerator
130 /// ::GetForTargetProcess(EPC)));
131 /// ES.setPlatform(
132 /// ExitOnErr(MachOPlatform::Create(ES, ObjLayer, EPC, PlatformJD,
133 /// "/path/to/orc/runtime")));
134 /// \endcode
135 ///
136 /// Alternatively, these symbols could be added to another JITDylib that
137 /// PlatformJD links against.
138 ///
139 /// Clients are also responsible for ensuring that any JIT'd code that
140 /// depends on runtime functions (including any code using TLV or static
141 /// destructors) can reference the runtime symbols. This is usually achieved
142 /// by linking any JITDylibs containing regular code against
143 /// PlatformJD.
144 ///
145 /// By default, MachOPlatform will add the set of aliases returned by the
146 /// standardPlatformAliases function. This includes both required aliases
147 /// (e.g. __cxa_atexit -> __orc_rt_macho_cxa_atexit for static destructor
148 /// support), and optional aliases that provide JIT versions of common
149 /// functions (e.g. dlopen -> __orc_rt_macho_jit_dlopen). Clients can
150 /// override these defaults by passing a non-None value for the
151 /// RuntimeAliases function, in which case the client is responsible for
152 /// setting up all aliases (including the required ones).
154 Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
155 std::unique_ptr<DefinitionGenerator> OrcRuntime,
156 HeaderOptionsBuilder BuildHeaderOpts = defaultHeaderOpts,
157 HeaderOptions PlatformJDOpts = {},
158 MachOHeaderMUBuilder BuildMachOHeaderMU = buildSimpleMachOHeaderMU,
159 std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
160
161 /// Construct using a path to the ORC runtime.
163 Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
164 const char *OrcRuntimePath,
165 HeaderOptionsBuilder BuildHeaderOpts = defaultHeaderOpts,
166 HeaderOptions PlatformJDOpts = {},
167 MachOHeaderMUBuilder BuildMachOHeaderMU = buildSimpleMachOHeaderMU,
168 std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
169
170 ExecutionSession &getExecutionSession() const { return ES; }
171 ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
172
174 return NonOwningSymbolStringPtr(MachOHeaderStartSymbol);
175 }
176
177 Error setupJITDylib(JITDylib &JD) override;
178
179 /// Install any platform-specific symbols (e.g. `__dso_handle`) and create a
180 /// mach-o header based on the given options.
181 Error setupJITDylib(JITDylib &JD, HeaderOptions Opts);
182
183 Error teardownJITDylib(JITDylib &JD) override;
184 Error notifyAdding(ResourceTracker &RT,
185 const MaterializationUnit &MU) override;
186 Error notifyRemoving(ResourceTracker &RT) override;
187
188 /// Returns an AliasMap containing the default aliases for the MachOPlatform.
189 /// This can be modified by clients when constructing the platform to add
190 /// or remove aliases.
191 static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES);
192
193 /// Returns the array of required CXX aliases.
194 static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases();
195
196 /// Returns the array of standard runtime utility aliases for MachO.
198 standardRuntimeUtilityAliases();
199
200 /// Returns a list of aliases required to enable lazy compilation via the
201 /// ORC runtime.
203 standardLazyCompilationAliases();
204
205 static HeaderOptions defaultHeaderOpts(JITDylib &JD);
206
207private:
208 using SymbolTableVector = SmallVector<
209 std::tuple<ExecutorAddr, ExecutorAddr, MachOExecutorSymbolFlags>>;
210
211 // Data needed for bootstrap only.
212 struct BootstrapInfo {
213 std::condition_variable CV;
214 size_t ActiveGraphs = 0;
215 shared::AllocActions DeferredAAs;
216 ExecutorAddr MachOHeaderAddr;
217 SymbolTableVector SymTab;
218 };
219
220 // The MachOPlatformPlugin scans/modifies LinkGraphs to support MachO
221 // platform features including initializers, exceptions, TLV, and language
222 // runtime registration.
223 class LLVM_ABI MachOPlatformPlugin : public ObjectLinkingLayer::Plugin {
224 public:
225 MachOPlatformPlugin(MachOPlatform &MP) : MP(MP) {}
226
227 void modifyPassConfig(MaterializationResponsibility &MR,
228 jitlink::LinkGraph &G,
229 jitlink::PassConfiguration &Config) override;
230
231 // FIXME: We should be tentatively tracking scraped sections and discarding
232 // if the MR fails.
233 Error notifyFailed(MaterializationResponsibility &MR) override {
234 return Error::success();
235 }
236
237 Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
238 return Error::success();
239 }
240
241 void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
242 ResourceKey SrcKey) override {}
243
244 private:
245 struct UnwindSections {
246 SmallVector<ExecutorAddrRange> CodeRanges;
247 ExecutorAddrRange DwarfSection;
248 ExecutorAddrRange CompactUnwindSection;
249 };
250
251 struct ObjCImageInfo {
252 uint32_t Version = 0;
253 uint32_t Flags = 0;
254 /// Whether this image info can no longer be mutated, as it may have been
255 /// registered with the objc runtime.
256 bool Finalized = false;
257 };
258
259 struct SymbolTablePair {
260 jitlink::Symbol *OriginalSym = nullptr;
261 jitlink::Symbol *NameSym = nullptr;
262 };
263 using JITSymTabVector = SmallVector<SymbolTablePair>;
264
265 Error bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G);
266 Error bootstrapPipelineEnd(jitlink::LinkGraph &G);
267
268 Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G,
269 MaterializationResponsibility &MR);
270
271 Error preserveImportantSections(jitlink::LinkGraph &G,
272 MaterializationResponsibility &MR);
273
274 Error processObjCImageInfo(jitlink::LinkGraph &G,
275 MaterializationResponsibility &MR);
276 Error mergeImageInfoFlags(jitlink::LinkGraph &G,
277 MaterializationResponsibility &MR,
278 ObjCImageInfo &Info, uint32_t NewFlags);
279
280 Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
281
282 std::optional<UnwindSections> findUnwindSectionInfo(jitlink::LinkGraph &G);
283 Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD,
284 ExecutorAddr HeaderAddr,
285 bool InBootstrapPhase);
286
287 Error createObjCRuntimeObject(jitlink::LinkGraph &G);
288 Error populateObjCRuntimeObject(jitlink::LinkGraph &G,
289 MaterializationResponsibility &MR);
290
291 Error prepareSymbolTableRegistration(jitlink::LinkGraph &G,
292 JITSymTabVector &JITSymTabInfo);
293 Error addSymbolTableRegistration(jitlink::LinkGraph &G,
294 MaterializationResponsibility &MR,
295 JITSymTabVector &JITSymTabInfo,
296 bool InBootstrapPhase);
297
298 std::mutex PluginMutex;
299 MachOPlatform &MP;
300
301 // FIXME: ObjCImageInfos and HeaderAddrs need to be cleared when
302 // JITDylibs are removed.
303 DenseMap<JITDylib *, ObjCImageInfo> ObjCImageInfos;
304 };
305
306 using GetJITDylibHeaderSendResultFn =
307 unique_function<void(Expected<ExecutorAddr>)>;
308 using GetJITDylibNameSendResultFn =
309 unique_function<void(Expected<StringRef>)>;
310 using PushInitializersSendResultFn =
311 unique_function<void(Expected<MachOJITDylibDepInfoMap>)>;
312 using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>;
313 using PushSymbolsInSendResultFn = unique_function<void(Error)>;
314
315 static bool supportedTarget(const Triple &TT);
316
317 static jitlink::Edge::Kind getPointerEdgeKind(jitlink::LinkGraph &G);
318
319 static MachOExecutorSymbolFlags flagsForSymbol(jitlink::Symbol &Sym);
320
321 MachOPlatform(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
322 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
323 HeaderOptionsBuilder BuildHeaderOpts,
324 HeaderOptions PlatformJDOpts,
325 MachOHeaderMUBuilder BuildMachOHeaderMU, Error &Err);
326
327 // Associate MachOPlatform JIT-side runtime support functions with handlers.
328 Error associateRuntimeSupportFunctions();
329
330 // Implements rt_pushInitializers by making repeat async lookups for
331 // initializer symbols (each lookup may spawn more initializer symbols if
332 // it pulls in new materializers, e.g. from objects in a static library).
333 void pushInitializersLoop(PushInitializersSendResultFn SendResult,
334 JITDylibSP JD);
335
336 // Handle requests from the ORC runtime to push MachO initializer info.
337 void rt_pushInitializers(PushInitializersSendResultFn SendResult,
338 ExecutorAddr JDHeaderAddr);
339
340 // Request that that the given symbols be materialized. The bool element of
341 // each pair indicates whether the symbol must be initialized, or whether it
342 // is optional. If any required symbol is not found then the pushSymbols
343 // function will return an error.
344 void rt_pushSymbols(PushSymbolsInSendResultFn SendResult, ExecutorAddr Handle,
345 const std::vector<std::pair<StringRef, bool>> &Symbols);
346
347 // Call the ORC runtime to create a pthread key.
348 Expected<uint64_t> createPThreadKey();
349
350 ExecutionSession &ES;
351 JITDylib &PlatformJD;
352 ObjectLinkingLayer &ObjLinkingLayer;
353 HeaderOptionsBuilder BuildHeaderOpts;
354 MachOHeaderMUBuilder BuildMachOHeaderMU;
355
356 SymbolStringPtr MachOHeaderStartSymbol = ES.intern("___dso_handle");
357
358 struct RuntimeFunction {
359 RuntimeFunction(SymbolStringPtr Name) : Name(std::move(Name)) {}
360 SymbolStringPtr Name;
361 ExecutorAddr Addr;
362 };
363
364 RuntimeFunction PlatformBootstrap{
365 ES.intern("___orc_rt_macho_platform_bootstrap")};
366 RuntimeFunction PlatformShutdown{
367 ES.intern("___orc_rt_macho_platform_shutdown")};
368 RuntimeFunction RegisterEHFrameSection{
369 ES.intern("___orc_rt_macho_register_ehframe_section")};
370 RuntimeFunction DeregisterEHFrameSection{
371 ES.intern("___orc_rt_macho_deregister_ehframe_section")};
372 RuntimeFunction RegisterJITDylib{
373 ES.intern("___orc_rt_macho_register_jitdylib")};
374 RuntimeFunction DeregisterJITDylib{
375 ES.intern("___orc_rt_macho_deregister_jitdylib")};
376 RuntimeFunction RegisterObjectSymbolTable{
377 ES.intern("___orc_rt_macho_register_object_symbol_table")};
378 RuntimeFunction DeregisterObjectSymbolTable{
379 ES.intern("___orc_rt_macho_deregister_object_symbol_table")};
380 RuntimeFunction RegisterObjectPlatformSections{
381 ES.intern("___orc_rt_macho_register_object_platform_sections")};
382 RuntimeFunction DeregisterObjectPlatformSections{
383 ES.intern("___orc_rt_macho_deregister_object_platform_sections")};
384 RuntimeFunction CreatePThreadKey{
385 ES.intern("___orc_rt_macho_create_pthread_key")};
386 RuntimeFunction RegisterObjCRuntimeObject{
387 ES.intern("___orc_rt_macho_register_objc_runtime_object")};
388 RuntimeFunction DeregisterObjCRuntimeObject{
389 ES.intern("___orc_rt_macho_deregister_objc_runtime_object")};
390
391 DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
392
393 std::mutex PlatformMutex;
394 bool ForceEHFrames = false;
395 BootstrapInfo *Bootstrap = nullptr;
396 DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr;
397 DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
398 DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
399};
400
401// Generates a MachO header.
403public:
406 StringRef getName() const override { return "MachOHeaderMU"; }
407 void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
408 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override;
409
410protected:
412 jitlink::Section &HeaderSection);
413
416
417private:
418 struct HeaderSymbol {
419 const char *Name;
421 };
422
423 static constexpr HeaderSymbol AdditionalHeaderSymbols[] = {
424 {"___mh_executable_header", 0}};
425
426 void addMachOHeader(JITDylib &JD, jitlink::LinkGraph &G,
427 const SymbolStringPtr &InitializerSymbol);
428 static MaterializationUnit::Interface
429 createHeaderInterface(MachOPlatform &MOP,
430 const SymbolStringPtr &HeaderStartSymbol);
431};
432
433/// Simple MachO header graph builder.
434inline std::unique_ptr<MaterializationUnit>
436 HeaderOptions Opts) {
437 return std::make_unique<SimpleMachOHeaderMU>(MOP, MOP.MachOHeaderStartSymbol,
438 std::move(Opts));
439}
440
447
448} // end namespace orc
449} // end namespace llvm
450
451#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:215
#define G(x, y, z)
Definition MD5.cpp:55
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.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
An ExecutionSession represents a running JIT program.
Definition Core.h:1111
Represents an address in the executor process.
Represents a JIT'd dynamic library.
Definition Core.h:675
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:1038
API to remove / transfer ownership of JIT resources.
Definition Core.h:63
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:173
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
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:878
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< std::string > TargetTriple
Optional LC_TARGET_TRIPLE.
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.