LLVM  15.0.0git
ELFNixPlatform.h
Go to the documentation of this file.
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"
21 
22 #include <future>
23 #include <thread>
24 #include <vector>
25 
26 namespace llvm {
27 namespace orc {
28 
32 };
33 
35  using SectionList = std::vector<ExecutorAddrRange>;
36 
39 
40  std::string Name;
42 
44 };
45 
47 
49  std::vector<ELFNixJITDylibInitializers>;
50 
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).
96  Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
97  JITDylib &PlatformJD, const char *OrcRuntimePath,
98  Optional<SymbolAliasMap> RuntimeAliases = None);
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;
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.
113  JITDylib &PlatformJD);
114 
115  /// Returns the array of required CXX aliases.
117 
118  /// Returns the array of standard runtime utility aliases for ELF.
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,
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(ResourceKey K) override {
147  return Error::success();
148  }
149 
150  void notifyTransferringResources(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 
249 
250 template <>
253 
254 public:
255  static size_t size(const ELFPerObjectSectionsToRegister &MOPOSR) {
257  MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
258  }
259 
261  const ELFPerObjectSectionsToRegister &MOPOSR) {
262  return SPSELFPerObjectSectionsToRegister::AsArgList::serialize(
263  OB, MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
264  }
265 
266  static bool deserialize(SPSInputBuffer &IB,
268  return SPSELFPerObjectSectionsToRegister::AsArgList::deserialize(
269  IB, MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
270  }
271 };
272 
275 
278 
281 
282 /// Serialization traits for ELFNixJITDylibInitializers.
283 template <>
286 public:
287  static size_t size(const ELFNixJITDylibInitializers &MOJDIs) {
289  MOJDIs.Name, MOJDIs.DSOHandleAddress, MOJDIs.InitSections);
290  }
291 
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 
306 
309 
310 template <>
313 public:
314  static size_t size(const ELFNixJITDylibDeinitializers &MOJDDs) { return 0; }
315 
317  const ELFNixJITDylibDeinitializers &MOJDDs) {
318  return true;
319  }
320 
321  static bool deserialize(SPSInputBuffer &IB,
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
llvm::orc::ExecutorAddr
Represents an address in the executor process.
Definition: ExecutorAddress.h:30
llvm::orc::ResourceKey
uintptr_t ResourceKey
Definition: Core.h:50
llvm::orc::ELFNixPlatform::Create
static Expected< std::unique_ptr< ELFNixPlatform > > Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, const char *OrcRuntimePath, Optional< SymbolAliasMap > RuntimeAliases=None)
Try to create a ELFNixPlatform instance, adding the ORC runtime to the given JITDylib.
Definition: ELFNixPlatform.cpp:106
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::orc::JITDylib
Represents a JIT'd dynamic library.
Definition: Core.h:950
llvm::lltok::Error
@ Error
Definition: LLToken.h:21
llvm::orc::shared::SPSSequence
SPS tag type for sequences.
Definition: SimplePackedSerialization.h:204
llvm::orc::ELFNixPlatform::notifyRemoving
Error notifyRemoving(ResourceTracker &RT) override
This method will be called under the ExecutionSession lock when a ResourceTracker is removed.
Definition: ELFNixPlatform.cpp:182
llvm::orc::shared::SPSSerializationTraits
Specialize to describe how to serialize/deserialize to/from the given concrete type.
Definition: SimplePackedSerialization.h:104
StringRef.h
llvm::orc::shared::SPSOutputBuffer
Output char buffer with overflow check.
Definition: SimplePackedSerialization.h:54
llvm::orc::shared::SPSSerializationTraits< SPSELFPerObjectSectionsToRegister, ELFPerObjectSectionsToRegister >::deserialize
static bool deserialize(SPSInputBuffer &IB, ELFPerObjectSectionsToRegister &MOPOSR)
Definition: ELFNixPlatform.h:266
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::orc::ELFNixPlatform::requiredCXXAliases
static ArrayRef< std::pair< const char *, const char * > > requiredCXXAliases()
Returns the array of required CXX aliases.
Definition: ELFNixPlatform.cpp:247
llvm::orc::ELFNixPlatform::notifyAdding
Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) override
This method will be called under the ExecutionSession lock each time a MaterializationUnit is added t...
Definition: ELFNixPlatform.cpp:166
llvm::orc::shared::SPSSerializationTraits< SPSELFNixJITDylibInitializers, ELFNixJITDylibInitializers >::deserialize
static bool deserialize(SPSInputBuffer &IB, ELFNixJITDylibInitializers &MOJDIs)
Definition: ELFNixPlatform.h:298
llvm::orc::shared::SPSSerializationTraits< SPSELFNixJITDylibInitializers, ELFNixJITDylibInitializers >::size
static size_t size(const ELFNixJITDylibInitializers &MOJDIs)
Definition: ELFNixPlatform.h:287
llvm::orc::ResourceTracker
API to remove / transfer ownership of JIT resources.
Definition: Core.h:53
llvm::Optional
Definition: APInt.h:33
llvm::orc::shared::SPSSerializationTraits< SPSELFJITDylibDeinitializers, ELFNixJITDylibDeinitializers >::size
static size_t size(const ELFNixJITDylibDeinitializers &MOJDDs)
Definition: ELFNixPlatform.h:314
llvm::orc::shared::SPSInputBuffer
Input char buffer with underflow check.
Definition: SimplePackedSerialization.h:73
llvm::orc::ELFNixJITDylibInitializers::SectionList
std::vector< ExecutorAddrRange > SectionList
Definition: ELFNixPlatform.h:35
llvm::orc::shared::SPSSerializationTraits< SPSELFJITDylibDeinitializers, ELFNixJITDylibDeinitializers >::serialize
static bool serialize(SPSOutputBuffer &OB, const ELFNixJITDylibDeinitializers &MOJDDs)
Definition: ELFNixPlatform.h:316
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::orc::shared::SPSTuple
SPS tag type for tuples.
Definition: SimplePackedSerialization.h:194
llvm::orc::shared::SPSSerializationTraits< SPSELFPerObjectSectionsToRegister, ELFPerObjectSectionsToRegister >::size
static size_t size(const ELFPerObjectSectionsToRegister &MOPOSR)
Definition: ELFNixPlatform.h:255
llvm::orc::ELFNixJITDylibInitializers::Name
std::string Name
Definition: ELFNixPlatform.h:40
llvm::orc::MaterializationUnit
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Definition: Core.h:669
llvm::orc::ELFNixJITDylibDeinitializers
Definition: ELFNixPlatform.h:46
llvm::orc::shared::SPSEmpty
Definition: SimplePackedSerialization.h:188
llvm::orc::shared::SPSSerializationTraits< SPSELFPerObjectSectionsToRegister, ELFPerObjectSectionsToRegister >::serialize
static bool serialize(SPSOutputBuffer &OB, const ELFPerObjectSectionsToRegister &MOPOSR)
Definition: ELFNixPlatform.h:260
llvm::orc::ExecutorAddrRange
Represents an address range in the exceutor process.
Definition: ExecutorAddress.h:148
llvm::orc::ELFPerObjectSectionsToRegister::ThreadDataSection
ExecutorAddrRange ThreadDataSection
Definition: ELFNixPlatform.h:31
llvm::None
const NoneType None
Definition: None.h:24
llvm::orc::ELFNixJITDylibInitializers::ELFNixJITDylibInitializers
ELFNixJITDylibInitializers(std::string Name, ExecutorAddr DSOHandleAddress)
Definition: ELFNixPlatform.h:37
llvm::StringMap< SectionList >
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
llvm::orc::ELFNixPlatform::isInitializerSection
static bool isInitializerSection(StringRef SecName)
Returns true if the given section name is an initializer section.
Definition: ELFNixPlatform.cpp:266
llvm::orc::ELFNixPlatform::standardPlatformAliases
static Expected< SymbolAliasMap > standardPlatformAliases(ExecutionSession &ES, JITDylib &PlatformJD)
Returns an AliasMap containing the default aliases for the ELFNixPlatform.
Definition: ELFNixPlatform.cpp:197
llvm::orc::ELFNixJITDylibDeinitializerSequence
std::vector< ELFNixJITDylibDeinitializers > ELFNixJITDylibDeinitializerSequence
Definition: ELFNixPlatform.h:52
llvm::orc::shared::SPSSerializationTraits< SPSELFJITDylibDeinitializers, ELFNixJITDylibDeinitializers >::deserialize
static bool deserialize(SPSInputBuffer &IB, ELFNixJITDylibDeinitializers &MOJDDs)
Definition: ELFNixPlatform.h:321
llvm::orc::ELFPerObjectSectionsToRegister
Definition: ELFNixPlatform.h:29
size
i< reg-> size
Definition: README.txt:166
llvm::orc::ELFNixJITDylibInitializerSequence
std::vector< ELFNixJITDylibInitializers > ELFNixJITDylibInitializerSequence
Definition: ELFNixPlatform.h:49
llvm::orc::ELFNixPlatform::setupJITDylib
Error setupJITDylib(JITDylib &JD) override
This method will be called outside the session lock each time a JITDylib is created (unless it is cre...
Definition: ELFNixPlatform.cpp:157
llvm::move
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:1665
llvm::orc::ELFNixJITDylibInitializers
Definition: ELFNixPlatform.h:34
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::orc::ELFNixPlatform::standardRuntimeUtilityAliases
static ArrayRef< std::pair< const char *, const char * > > standardRuntimeUtilityAliases()
Returns the array of standard runtime utility aliases for ELF.
Definition: ELFNixPlatform.cpp:256
llvm::orc::Platform
Platforms set up standard symbols and mediate interactions between dynamic initializers (e....
Definition: Core.h:1306
llvm::orc::ELFNixPlatform
Mediates between ELFNix initialization and ExecutionSession state.
Definition: ELFNixPlatform.h:55
llvm::orc::ELFNixJITDylibInitializers::DSOHandleAddress
ExecutorAddr DSOHandleAddress
Definition: ELFNixPlatform.h:41
llvm::orc::ELFNixPlatform::getObjectLinkingLayer
ObjectLinkingLayer & getObjectLinkingLayer() const
Definition: ELFNixPlatform.h:101
llvm::orc::ObjectLinkingLayer
An ObjectLayer implementation built on JITLink.
Definition: ObjectLinkingLayer.h:50
llvm::AMDGPU::HSAMD::Kernel::Key::SymbolName
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Definition: AMDGPUMetadata.h:386
llvm::orc::shared::SPSNamedExecutorAddrRangeSequenceMap
SPSSequence< SPSTuple< SPSString, SPSExecutorAddrRangeSequence > > SPSNamedExecutorAddrRangeSequenceMap
Definition: ELFNixPlatform.h:274
std
Definition: BitVector.h:851
ExecutorAddress.h
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::orc::ExecutionSession
An ExecutionSession represents a running JIT program.
Definition: Core.h:1362
llvm::X86II::OB
@ OB
Definition: X86BaseInfo.h:801
llvm::orc::shared::SPSSerializationTraits< SPSELFNixJITDylibInitializers, ELFNixJITDylibInitializers >::serialize
static bool serialize(SPSOutputBuffer &OB, const ELFNixJITDylibInitializers &MOJDIs)
Definition: ELFNixPlatform.h:292
Core.h
llvm::orc::ObjectLinkingLayer::Plugin
Plugin instances can be added to the ObjectLinkingLayer to receive callbacks when code is loaded or e...
Definition: ObjectLinkingLayer.h:60
ExecutorProcessControl.h
ObjectLinkingLayer.h
llvm::orc::ELFNixPlatform::getExecutionSession
ExecutionSession & getExecutionSession() const
Definition: ELFNixPlatform.h:100
llvm::orc::ELFPerObjectSectionsToRegister::EHFrameSection
ExecutorAddrRange EHFrameSection
Definition: ELFNixPlatform.h:30
llvm::orc::ELFNixJITDylibInitializers::InitSections
StringMap< SectionList > InitSections
Definition: ELFNixPlatform.h:43
llvm::orc::ELFNixPlatform::teardownJITDylib
Error teardownJITDylib(JITDylib &JD) override
This method will be called outside the session lock each time a JITDylib is removed to allow the Plat...
Definition: ELFNixPlatform.cpp:162