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