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
//===-- ELFNixPlatform.h -- Utilities for executing ELF 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
// Linux/BSD support for executing JIT'd ELF in Orc.
10
//
11
//===----------------------------------------------------------------------===//
12
 
13
#ifndef LLVM_EXECUTIONENGINE_ORC_ELFNIXPLATFORM_H
14
#define LLVM_EXECUTIONENGINE_ORC_ELFNIXPLATFORM_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
struct ELFPerObjectSectionsToRegister {
30
  ExecutorAddrRange EHFrameSection;
31
  ExecutorAddrRange ThreadDataSection;
32
};
33
 
34
struct ELFNixJITDylibInitializers {
35
  using SectionList = std::vector<ExecutorAddrRange>;
36
 
37
  ELFNixJITDylibInitializers(std::string Name, ExecutorAddr DSOHandleAddress)
38
      : Name(std::move(Name)), DSOHandleAddress(std::move(DSOHandleAddress)) {}
39
 
40
  std::string Name;
41
  ExecutorAddr DSOHandleAddress;
42
 
43
  StringMap<SectionList> InitSections;
44
};
45
 
46
class ELFNixJITDylibDeinitializers {};
47
 
48
using ELFNixJITDylibInitializerSequence =
49
    std::vector<ELFNixJITDylibInitializers>;
50
 
51
using ELFNixJITDylibDeinitializerSequence =
52
    std::vector<ELFNixJITDylibDeinitializers>;
53
 
54
/// Mediates between ELFNix initialization and ExecutionSession state.
55
class ELFNixPlatform : public Platform {
56
public:
57
  /// Try to create a ELFNixPlatform instance, adding the ORC runtime to the
58
  /// given JITDylib.
59
  ///
60
  /// The ORC runtime requires access to a number of symbols in
61
  /// libc++. It is up to the caller to ensure that the requried
62
  /// symbols can be referenced by code added to PlatformJD. The
63
  /// standard way to achieve this is to first attach dynamic library
64
  /// search generators for either the given process, or for the
65
  /// specific required libraries, to PlatformJD, then to create the
66
  /// platform instance:
67
  ///
68
  /// \code{.cpp}
69
  ///   auto &PlatformJD = ES.createBareJITDylib("stdlib");
70
  ///   PlatformJD.addGenerator(
71
  ///     ExitOnErr(EPCDynamicLibrarySearchGenerator
72
  ///                 ::GetForTargetProcess(EPC)));
73
  ///   ES.setPlatform(
74
  ///     ExitOnErr(ELFNixPlatform::Create(ES, ObjLayer, EPC, PlatformJD,
75
  ///                                     "/path/to/orc/runtime")));
76
  /// \endcode
77
  ///
78
  /// Alternatively, these symbols could be added to another JITDylib that
79
  /// PlatformJD links against.
80
  ///
81
  /// Clients are also responsible for ensuring that any JIT'd code that
82
  /// depends on runtime functions (including any code using TLV or static
83
  /// destructors) can reference the runtime symbols. This is usually achieved
84
  /// by linking any JITDylibs containing regular code against
85
  /// PlatformJD.
86
  ///
87
  /// By default, ELFNixPlatform will add the set of aliases returned by the
88
  /// standardPlatformAliases function. This includes both required aliases
89
  /// (e.g. __cxa_atexit -> __orc_rt_elf_cxa_atexit for static destructor
90
  /// support), and optional aliases that provide JIT versions of common
91
  /// functions (e.g. dlopen -> __orc_rt_elf_jit_dlopen). Clients can
92
  /// override these defaults by passing a non-None value for the
93
  /// RuntimeAliases function, in which case the client is responsible for
94
  /// setting up all aliases (including the required ones).
95
  static Expected<std::unique_ptr<ELFNixPlatform>>
96
  Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
97
         JITDylib &PlatformJD, const char *OrcRuntimePath,
98
         std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
99
 
100
  ExecutionSession &getExecutionSession() const { return ES; }
101
  ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
102
 
103
  Error setupJITDylib(JITDylib &JD) override;
104
  Error teardownJITDylib(JITDylib &JD) override;
105
  Error notifyAdding(ResourceTracker &RT,
106
                     const MaterializationUnit &MU) override;
107
  Error notifyRemoving(ResourceTracker &RT) override;
108
 
109
  /// Returns an AliasMap containing the default aliases for the ELFNixPlatform.
110
  /// This can be modified by clients when constructing the platform to add
111
  /// or remove aliases.
112
  static Expected<SymbolAliasMap> standardPlatformAliases(ExecutionSession &ES,
113
                                                          JITDylib &PlatformJD);
114
 
115
  /// Returns the array of required CXX aliases.
116
  static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases();
117
 
118
  /// Returns the array of standard runtime utility aliases for ELF.
119
  static ArrayRef<std::pair<const char *, const char *>>
120
  standardRuntimeUtilityAliases();
121
 
122
  /// Returns true if the given section name is an initializer section.
123
  static bool isInitializerSection(StringRef SecName);
124
 
125
private:
126
  // The ELFNixPlatformPlugin scans/modifies LinkGraphs to support ELF
127
  // platform features including initializers, exceptions, TLV, and language
128
  // runtime registration.
129
  class ELFNixPlatformPlugin : public ObjectLinkingLayer::Plugin {
130
  public:
131
    ELFNixPlatformPlugin(ELFNixPlatform &MP) : MP(MP) {}
132
 
133
    void modifyPassConfig(MaterializationResponsibility &MR,
134
                          jitlink::LinkGraph &G,
135
                          jitlink::PassConfiguration &Config) override;
136
 
137
    SyntheticSymbolDependenciesMap
138
    getSyntheticSymbolDependencies(MaterializationResponsibility &MR) override;
139
 
140
    // FIXME: We should be tentatively tracking scraped sections and discarding
141
    // if the MR fails.
142
    Error notifyFailed(MaterializationResponsibility &MR) override {
143
      return Error::success();
144
    }
145
 
146
    Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
147
      return Error::success();
148
    }
149
 
150
    void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
151
                                     ResourceKey SrcKey) override {}
152
 
153
  private:
154
    using InitSymbolDepMap =
155
        DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>;
156
 
157
    void addInitializerSupportPasses(MaterializationResponsibility &MR,
158
                                     jitlink::PassConfiguration &Config);
159
 
160
    void addDSOHandleSupportPasses(MaterializationResponsibility &MR,
161
                                   jitlink::PassConfiguration &Config);
162
 
163
    void addEHAndTLVSupportPasses(MaterializationResponsibility &MR,
164
                                  jitlink::PassConfiguration &Config);
165
 
166
    Error preserveInitSections(jitlink::LinkGraph &G,
167
                               MaterializationResponsibility &MR);
168
 
169
    Error registerInitSections(jitlink::LinkGraph &G, JITDylib &JD);
170
 
171
    Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
172
 
173
    std::mutex PluginMutex;
174
    ELFNixPlatform &MP;
175
    InitSymbolDepMap InitSymbolDeps;
176
  };
177
 
178
  using SendInitializerSequenceFn =
179
      unique_function<void(Expected<ELFNixJITDylibInitializerSequence>)>;
180
 
181
  using SendDeinitializerSequenceFn =
182
      unique_function<void(Expected<ELFNixJITDylibDeinitializerSequence>)>;
183
 
184
  using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>;
185
 
186
  static bool supportedTarget(const Triple &TT);
187
 
188
  ELFNixPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
189
                 JITDylib &PlatformJD,
190
                 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
191
                 Error &Err);
192
 
193
  // Associate ELFNixPlatform JIT-side runtime support functions with handlers.
194
  Error associateRuntimeSupportFunctions(JITDylib &PlatformJD);
195
 
196
  void getInitializersBuildSequencePhase(SendInitializerSequenceFn SendResult,
197
                                         JITDylib &JD,
198
                                         std::vector<JITDylibSP> DFSLinkOrder);
199
 
200
  void getInitializersLookupPhase(SendInitializerSequenceFn SendResult,
201
                                  JITDylib &JD);
202
 
203
  void rt_getInitializers(SendInitializerSequenceFn SendResult,
204
                          StringRef JDName);
205
 
206
  void rt_getDeinitializers(SendDeinitializerSequenceFn SendResult,
207
                            ExecutorAddr Handle);
208
 
209
  void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddr Handle,
210
                       StringRef SymbolName);
211
 
212
  // Records the addresses of runtime symbols used by the platform.
213
  Error bootstrapELFNixRuntime(JITDylib &PlatformJD);
214
 
215
  Error registerInitInfo(JITDylib &JD,
216
                         ArrayRef<jitlink::Section *> InitSections);
217
 
218
  Error registerPerObjectSections(const ELFPerObjectSectionsToRegister &POSR);
219
 
220
  Expected<uint64_t> createPThreadKey();
221
 
222
  ExecutionSession &ES;
223
  ObjectLinkingLayer &ObjLinkingLayer;
224
 
225
  SymbolStringPtr DSOHandleSymbol;
226
  std::atomic<bool> RuntimeBootstrapped{false};
227
 
228
  ExecutorAddr orc_rt_elfnix_platform_bootstrap;
229
  ExecutorAddr orc_rt_elfnix_platform_shutdown;
230
  ExecutorAddr orc_rt_elfnix_register_object_sections;
231
  ExecutorAddr orc_rt_elfnix_create_pthread_key;
232
 
233
  DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
234
 
235
  // InitSeqs gets its own mutex to avoid locking the whole session when
236
  // aggregating data from the jitlink.
237
  std::mutex PlatformMutex;
238
  DenseMap<JITDylib *, ELFNixJITDylibInitializers> InitSeqs;
239
  std::vector<ELFPerObjectSectionsToRegister> BootstrapPOSRs;
240
 
241
  DenseMap<ExecutorAddr, JITDylib *> HandleAddrToJITDylib;
242
  DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
243
};
244
 
245
namespace shared {
246
 
247
using SPSELFPerObjectSectionsToRegister =
248
    SPSTuple<SPSExecutorAddrRange, SPSExecutorAddrRange>;
249
 
250
template <>
251
class SPSSerializationTraits<SPSELFPerObjectSectionsToRegister,
252
                             ELFPerObjectSectionsToRegister> {
253
 
254
public:
255
  static size_t size(const ELFPerObjectSectionsToRegister &MOPOSR) {
256
    return SPSELFPerObjectSectionsToRegister::AsArgList::size(
257
        MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
258
  }
259
 
260
  static bool serialize(SPSOutputBuffer &OB,
261
                        const ELFPerObjectSectionsToRegister &MOPOSR) {
262
    return SPSELFPerObjectSectionsToRegister::AsArgList::serialize(
263
        OB, MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
264
  }
265
 
266
  static bool deserialize(SPSInputBuffer &IB,
267
                          ELFPerObjectSectionsToRegister &MOPOSR) {
268
    return SPSELFPerObjectSectionsToRegister::AsArgList::deserialize(
269
        IB, MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
270
  }
271
};
272
 
273
using SPSNamedExecutorAddrRangeSequenceMap =
274
    SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRangeSequence>>;
275
 
276
using SPSELFNixJITDylibInitializers =
277
    SPSTuple<SPSString, SPSExecutorAddr, SPSNamedExecutorAddrRangeSequenceMap>;
278
 
279
using SPSELFNixJITDylibInitializerSequence =
280
    SPSSequence<SPSELFNixJITDylibInitializers>;
281
 
282
/// Serialization traits for ELFNixJITDylibInitializers.
283
template <>
284
class SPSSerializationTraits<SPSELFNixJITDylibInitializers,
285
                             ELFNixJITDylibInitializers> {
286
public:
287
  static size_t size(const ELFNixJITDylibInitializers &MOJDIs) {
288
    return SPSELFNixJITDylibInitializers::AsArgList::size(
289
        MOJDIs.Name, MOJDIs.DSOHandleAddress, MOJDIs.InitSections);
290
  }
291
 
292
  static bool serialize(SPSOutputBuffer &OB,
293
                        const ELFNixJITDylibInitializers &MOJDIs) {
294
    return SPSELFNixJITDylibInitializers::AsArgList::serialize(
295
        OB, MOJDIs.Name, MOJDIs.DSOHandleAddress, MOJDIs.InitSections);
296
  }
297
 
298
  static bool deserialize(SPSInputBuffer &IB,
299
                          ELFNixJITDylibInitializers &MOJDIs) {
300
    return SPSELFNixJITDylibInitializers::AsArgList::deserialize(
301
        IB, MOJDIs.Name, MOJDIs.DSOHandleAddress, MOJDIs.InitSections);
302
  }
303
};
304
 
305
using SPSELFJITDylibDeinitializers = SPSEmpty;
306
 
307
using SPSELFJITDylibDeinitializerSequence =
308
    SPSSequence<SPSELFJITDylibDeinitializers>;
309
 
310
template <>
311
class SPSSerializationTraits<SPSELFJITDylibDeinitializers,
312
                             ELFNixJITDylibDeinitializers> {
313
public:
314
  static size_t size(const ELFNixJITDylibDeinitializers &MOJDDs) { return 0; }
315
 
316
  static bool serialize(SPSOutputBuffer &OB,
317
                        const ELFNixJITDylibDeinitializers &MOJDDs) {
318
    return true;
319
  }
320
 
321
  static bool deserialize(SPSInputBuffer &IB,
322
                          ELFNixJITDylibDeinitializers &MOJDDs) {
323
    MOJDDs = ELFNixJITDylibDeinitializers();
324
    return true;
325
  }
326
};
327
 
328
} // end namespace shared
329
} // end namespace orc
330
} // end namespace llvm
331
 
332
#endif // LLVM_EXECUTIONENGINE_ORC_ELFNIXPLATFORM_H