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"
17#include "llvm/ExecutionEngine/Orc/Core.h"
18#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
19#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
20#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.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.
33 struct MachOJITDylibDepInfo {
34 bool Sealed = false;
35 std::vector<ExecutorAddr> DepHeaders;
36 };
37
38 // Used internally by MachOPlatform, but made public to enable serialization.
39 using MachOJITDylibDepInfoMap =
40 std::vector<std::pair<ExecutorAddr, MachOJITDylibDepInfo>>;
41
42 /// Try to create a MachOPlatform instance, adding the ORC runtime to the
43 /// given JITDylib.
44 ///
45 /// The ORC runtime requires access to a number of symbols in libc++, and
46 /// requires access to symbols in libobjc, and libswiftCore to support
47 /// Objective-C and Swift code. It is up to the caller to ensure that the
48 /// requried symbols can be referenced by code added to PlatformJD. The
49 /// standard way to achieve this is to first attach dynamic library search
50 /// generators for either the given process, or for the specific required
51 /// libraries, to PlatformJD, then to create the platform instance:
52 ///
53 /// \code{.cpp}
54 /// auto &PlatformJD = ES.createBareJITDylib("stdlib");
55 /// PlatformJD.addGenerator(
56 /// ExitOnErr(EPCDynamicLibrarySearchGenerator
57 /// ::GetForTargetProcess(EPC)));
58 /// ES.setPlatform(
59 /// ExitOnErr(MachOPlatform::Create(ES, ObjLayer, EPC, PlatformJD,
60 /// "/path/to/orc/runtime")));
61 /// \endcode
62 ///
63 /// Alternatively, these symbols could be added to another JITDylib that
64 /// PlatformJD links against.
65 ///
66 /// Clients are also responsible for ensuring that any JIT'd code that
67 /// depends on runtime functions (including any code using TLV or static
68 /// destructors) can reference the runtime symbols. This is usually achieved
69 /// by linking any JITDylibs containing regular code against
70 /// PlatformJD.
71 ///
72 /// By default, MachOPlatform will add the set of aliases returned by the
73 /// standardPlatformAliases function. This includes both required aliases
74 /// (e.g. __cxa_atexit -> __orc_rt_macho_cxa_atexit for static destructor
75 /// support), and optional aliases that provide JIT versions of common
76 /// functions (e.g. dlopen -> __orc_rt_macho_jit_dlopen). Clients can
77 /// override these defaults by passing a non-None value for the
78 /// RuntimeAliases function, in which case the client is responsible for
79 /// setting up all aliases (including the required ones).
80 static Expected<std::unique_ptr<MachOPlatform>>
81 Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
82 JITDylib &PlatformJD, const char *OrcRuntimePath,
83 Optional<SymbolAliasMap> RuntimeAliases = None);
84
85 ExecutionSession &getExecutionSession() const { return ES; }
86 ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
87
88 Error setupJITDylib(JITDylib &JD) override;
89 Error teardownJITDylib(JITDylib &JD) override;
90 Error notifyAdding(ResourceTracker &RT,
91 const MaterializationUnit &MU) override;
92 Error notifyRemoving(ResourceTracker &RT) override;
93
94 /// Returns an AliasMap containing the default aliases for the MachOPlatform.
95 /// This can be modified by clients when constructing the platform to add
96 /// or remove aliases.
97 static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES);
98
99 /// Returns the array of required CXX aliases.
100 static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases();
101
102 /// Returns the array of standard runtime utility aliases for MachO.
103 static ArrayRef<std::pair<const char *, const char *>>
104 standardRuntimeUtilityAliases();
105
106 /// Returns true if the given section name is an initializer section.
107 static bool isInitializerSection(StringRef SegName, StringRef SectName);
108
109private:
110 // The MachOPlatformPlugin scans/modifies LinkGraphs to support MachO
111 // platform features including initializers, exceptions, TLV, and language
112 // runtime registration.
113 class MachOPlatformPlugin : public ObjectLinkingLayer::Plugin {
114 public:
115 MachOPlatformPlugin(MachOPlatform &MP) : MP(MP) {}
116
117 void modifyPassConfig(MaterializationResponsibility &MR,
118 jitlink::LinkGraph &G,
119 jitlink::PassConfiguration &Config) override;
120
121 SyntheticSymbolDependenciesMap
122 getSyntheticSymbolDependencies(MaterializationResponsibility &MR) override;
123
124 // FIXME: We should be tentatively tracking scraped sections and discarding
125 // if the MR fails.
126 Error notifyFailed(MaterializationResponsibility &MR) override {
127 return Error::success();
128 }
129
130 Error notifyRemovingResources(ResourceKey K) override {
131 return Error::success();
132 }
133
134 void notifyTransferringResources(ResourceKey DstKey,
135 ResourceKey SrcKey) override {}
136
137 private:
138 using InitSymbolDepMap =
139 DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>;
140
141 Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G,
142 MaterializationResponsibility &MR);
143
144 Error preserveInitSections(jitlink::LinkGraph &G,
145 MaterializationResponsibility &MR);
146
147 Error processObjCImageInfo(jitlink::LinkGraph &G,
148 MaterializationResponsibility &MR);
149
150 Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
151
152 Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD);
153
154 Error registerEHSectionsPhase1(jitlink::LinkGraph &G);
155
156 std::mutex PluginMutex;
157 MachOPlatform &MP;
158
159 // FIXME: ObjCImageInfos and HeaderAddrs need to be cleared when
160 // JITDylibs are removed.
161 DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
162 DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
163 InitSymbolDepMap InitSymbolDeps;
164 };
165
166 using GetJITDylibHeaderSendResultFn =
167 unique_function<void(Expected<ExecutorAddr>)>;
168 using GetJITDylibNameSendResultFn =
169 unique_function<void(Expected<StringRef>)>;
170 using PushInitializersSendResultFn =
171 unique_function<void(Expected<MachOJITDylibDepInfoMap>)>;
172 using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>;
173
174 static bool supportedTarget(const Triple &TT);
175
176 MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
177 JITDylib &PlatformJD,
178 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
179 Error &Err);
180
181 // Associate MachOPlatform JIT-side runtime support functions with handlers.
182 Error associateRuntimeSupportFunctions(JITDylib &PlatformJD);
183
184 // Implements rt_pushInitializers by making repeat async lookups for
185 // initializer symbols (each lookup may spawn more initializer symbols if
186 // it pulls in new materializers, e.g. from objects in a static library).
187 void pushInitializersLoop(PushInitializersSendResultFn SendResult,
188 JITDylibSP JD);
189
190 // Handle requests from the ORC runtime to push MachO initializer info.
191 void rt_pushInitializers(PushInitializersSendResultFn SendResult,
192 ExecutorAddr JDHeaderAddr);
193
194 // Handle requests for symbol addresses from the ORC runtime.
195 void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddr Handle,
196 StringRef SymbolName);
197
198 // Records the addresses of runtime symbols used by the platform.
199 Error bootstrapMachORuntime(JITDylib &PlatformJD);
200
201 // Call the ORC runtime to create a pthread key.
202 Expected<uint64_t> createPThreadKey();
203
204 enum PlatformState { BootstrapPhase1, BootstrapPhase2, Initialized };
205
206 ExecutionSession &ES;
207 ObjectLinkingLayer &ObjLinkingLayer;
208
209 SymbolStringPtr MachOHeaderStartSymbol;
210 std::atomic<PlatformState> State{BootstrapPhase1};
211
212 ExecutorAddr orc_rt_macho_platform_bootstrap;
213 ExecutorAddr orc_rt_macho_platform_shutdown;
214 ExecutorAddr orc_rt_macho_register_ehframe_section;
215 ExecutorAddr orc_rt_macho_deregister_ehframe_section;
216 ExecutorAddr orc_rt_macho_register_jitdylib;
217 ExecutorAddr orc_rt_macho_deregister_jitdylib;
218 ExecutorAddr orc_rt_macho_register_object_platform_sections;
219 ExecutorAddr orc_rt_macho_deregister_object_platform_sections;
220 ExecutorAddr orc_rt_macho_create_pthread_key;
221
222 DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
223
224 std::mutex PlatformMutex;
225 DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr;
226 DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
227 DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
228};
229
230namespace shared {
231
232using SPSNamedExecutorAddrRangeSequence =
233 SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
234
235} // end namespace shared
236} // end namespace orc
237} // end namespace llvm
238
239#endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
240

source code of llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h