Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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
 
26
namespace llvm {
27
namespace orc {
28
 
29
/// Mediates between MachO initialization and ExecutionSession state.
30
class MachOPlatform : public Platform {
31
public:
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
         std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
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
 
109
private:
110
  // Data needed for bootstrap only.
111
  struct BootstrapInfo {
112
    std::mutex Mutex;
113
    std::condition_variable CV;
114
    size_t ActiveGraphs = 0;
115
    shared::AllocActions DeferredAAs;
116
    ExecutorAddr MachOHeaderAddr;
117
  };
118
 
119
  // The MachOPlatformPlugin scans/modifies LinkGraphs to support MachO
120
  // platform features including initializers, exceptions, TLV, and language
121
  // runtime registration.
122
  class MachOPlatformPlugin : public ObjectLinkingLayer::Plugin {
123
  public:
124
    MachOPlatformPlugin(MachOPlatform &MP) : MP(MP) {}
125
 
126
    void modifyPassConfig(MaterializationResponsibility &MR,
127
                          jitlink::LinkGraph &G,
128
                          jitlink::PassConfiguration &Config) override;
129
 
130
    SyntheticSymbolDependenciesMap
131
    getSyntheticSymbolDependencies(MaterializationResponsibility &MR) override;
132
 
133
    // FIXME: We should be tentatively tracking scraped sections and discarding
134
    // if the MR fails.
135
    Error notifyFailed(MaterializationResponsibility &MR) override {
136
      return Error::success();
137
    }
138
 
139
    Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
140
      return Error::success();
141
    }
142
 
143
    void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
144
                                     ResourceKey SrcKey) override {}
145
 
146
  private:
147
    using InitSymbolDepMap =
148
        DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>;
149
 
150
    struct UnwindSections {
151
      SmallVector<ExecutorAddrRange> CodeRanges;
152
      ExecutorAddrRange DwarfSection;
153
      ExecutorAddrRange CompactUnwindSection;
154
    };
155
 
156
    Error bootstrapPipelineStart(jitlink::LinkGraph &G);
157
    Error bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G);
158
    Error bootstrapPipelineEnd(jitlink::LinkGraph &G);
159
 
160
    Error recordRuntimeRegistrationFunctions(jitlink::LinkGraph &G);
161
 
162
    Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G,
163
                                        MaterializationResponsibility &MR);
164
 
165
    Error preserveInitSections(jitlink::LinkGraph &G,
166
                               MaterializationResponsibility &MR);
167
 
168
    Error processObjCImageInfo(jitlink::LinkGraph &G,
169
                               MaterializationResponsibility &MR);
170
 
171
    Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
172
 
173
    std::optional<UnwindSections> findUnwindSectionInfo(jitlink::LinkGraph &G);
174
 
175
    Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD,
176
                                         bool InBootstrapPhase);
177
 
178
    std::mutex PluginMutex;
179
    MachOPlatform &MP;
180
 
181
    // FIXME: ObjCImageInfos and HeaderAddrs need to be cleared when
182
    // JITDylibs are removed.
183
    DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
184
    DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
185
    InitSymbolDepMap InitSymbolDeps;
186
  };
187
 
188
  using GetJITDylibHeaderSendResultFn =
189
      unique_function<void(Expected<ExecutorAddr>)>;
190
  using GetJITDylibNameSendResultFn =
191
      unique_function<void(Expected<StringRef>)>;
192
  using PushInitializersSendResultFn =
193
      unique_function<void(Expected<MachOJITDylibDepInfoMap>)>;
194
  using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>;
195
 
196
  static bool supportedTarget(const Triple &TT);
197
 
198
  MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
199
                JITDylib &PlatformJD,
200
                std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
201
                Error &Err);
202
 
203
  // Associate MachOPlatform JIT-side runtime support functions with handlers.
204
  Error associateRuntimeSupportFunctions();
205
 
206
  // Implements rt_pushInitializers by making repeat async lookups for
207
  // initializer symbols (each lookup may spawn more initializer symbols if
208
  // it pulls in new materializers, e.g. from objects in a static library).
209
  void pushInitializersLoop(PushInitializersSendResultFn SendResult,
210
                            JITDylibSP JD);
211
 
212
  // Handle requests from the ORC runtime to push MachO initializer info.
213
  void rt_pushInitializers(PushInitializersSendResultFn SendResult,
214
                           ExecutorAddr JDHeaderAddr);
215
 
216
  // Handle requests for symbol addresses from the ORC runtime.
217
  void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddr Handle,
218
                       StringRef SymbolName);
219
 
220
  // Call the ORC runtime to create a pthread key.
221
  Expected<uint64_t> createPThreadKey();
222
 
223
  ExecutionSession &ES;
224
  JITDylib &PlatformJD;
225
  ObjectLinkingLayer &ObjLinkingLayer;
226
 
227
  SymbolStringPtr MachOHeaderStartSymbol = ES.intern("___dso_handle");
228
 
229
  struct RuntimeFunction {
230
    RuntimeFunction(SymbolStringPtr Name) : Name(std::move(Name)) {}
231
    SymbolStringPtr Name;
232
    ExecutorAddr Addr;
233
  };
234
 
235
  RuntimeFunction PlatformBootstrap{
236
      ES.intern("___orc_rt_macho_platform_bootstrap")};
237
  RuntimeFunction PlatformShutdown{
238
      ES.intern("___orc_rt_macho_platform_shutdown")};
239
  RuntimeFunction RegisterEHFrameSection{
240
      ES.intern("___orc_rt_macho_register_ehframe_section")};
241
  RuntimeFunction DeregisterEHFrameSection{
242
      ES.intern("___orc_rt_macho_deregister_ehframe_section")};
243
  RuntimeFunction RegisterJITDylib{
244
      ES.intern("___orc_rt_macho_register_jitdylib")};
245
  RuntimeFunction DeregisterJITDylib{
246
      ES.intern("___orc_rt_macho_deregister_jitdylib")};
247
  RuntimeFunction RegisterObjectPlatformSections{
248
      ES.intern("___orc_rt_macho_register_object_platform_sections")};
249
  RuntimeFunction DeregisterObjectPlatformSections{
250
      ES.intern("___orc_rt_macho_deregister_object_platform_sections")};
251
  RuntimeFunction CreatePThreadKey{
252
      ES.intern("___orc_rt_macho_create_pthread_key")};
253
 
254
  DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
255
 
256
  std::mutex PlatformMutex;
257
  DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr;
258
  DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
259
  DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
260
 
261
  std::atomic<BootstrapInfo *> Bootstrap;
262
};
263
 
264
namespace shared {
265
 
266
using SPSNamedExecutorAddrRangeSequence =
267
    SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
268
 
269
} // end namespace shared
270
} // end namespace orc
271
} // end namespace llvm
272
 
273
#endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H