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