- //===-- ELFNixPlatform.h -- Utilities for executing ELF in Orc --*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // Linux/BSD support for executing JIT'd ELF in Orc. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_EXECUTIONENGINE_ORC_ELFNIXPLATFORM_H 
- #define LLVM_EXECUTIONENGINE_ORC_ELFNIXPLATFORM_H 
-   
- #include "llvm/ADT/StringRef.h" 
- #include "llvm/ExecutionEngine/Orc/Core.h" 
- #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" 
- #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 
- #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" 
-   
- #include <future> 
- #include <thread> 
- #include <vector> 
-   
- namespace llvm { 
- namespace orc { 
-   
- struct ELFPerObjectSectionsToRegister { 
-   ExecutorAddrRange EHFrameSection; 
-   ExecutorAddrRange ThreadDataSection; 
- }; 
-   
- struct ELFNixJITDylibInitializers { 
-   using SectionList = std::vector<ExecutorAddrRange>; 
-   
-   ELFNixJITDylibInitializers(std::string Name, ExecutorAddr DSOHandleAddress) 
-       : Name(std::move(Name)), DSOHandleAddress(std::move(DSOHandleAddress)) {} 
-   
-   std::string Name; 
-   ExecutorAddr DSOHandleAddress; 
-   
-   StringMap<SectionList> InitSections; 
- }; 
-   
- class ELFNixJITDylibDeinitializers {}; 
-   
- using ELFNixJITDylibInitializerSequence = 
-     std::vector<ELFNixJITDylibInitializers>; 
-   
- using ELFNixJITDylibDeinitializerSequence = 
-     std::vector<ELFNixJITDylibDeinitializers>; 
-   
- /// Mediates between ELFNix initialization and ExecutionSession state. 
- class ELFNixPlatform : public Platform { 
- public: 
-   /// Try to create a ELFNixPlatform instance, adding the ORC runtime to the 
-   /// given JITDylib. 
-   /// 
-   /// The ORC runtime requires access to a number of symbols in 
-   /// libc++. It is up to the caller to ensure that the requried 
-   /// symbols can be referenced by code added to PlatformJD. The 
-   /// standard way to achieve this is to first attach dynamic library 
-   /// search generators for either the given process, or for the 
-   /// specific required libraries, to PlatformJD, then to create the 
-   /// platform instance: 
-   /// 
-   /// \code{.cpp} 
-   ///   auto &PlatformJD = ES.createBareJITDylib("stdlib"); 
-   ///   PlatformJD.addGenerator( 
-   ///     ExitOnErr(EPCDynamicLibrarySearchGenerator 
-   ///                 ::GetForTargetProcess(EPC))); 
-   ///   ES.setPlatform( 
-   ///     ExitOnErr(ELFNixPlatform::Create(ES, ObjLayer, EPC, PlatformJD, 
-   ///                                     "/path/to/orc/runtime"))); 
-   /// \endcode 
-   /// 
-   /// Alternatively, these symbols could be added to another JITDylib that 
-   /// PlatformJD links against. 
-   /// 
-   /// Clients are also responsible for ensuring that any JIT'd code that 
-   /// depends on runtime functions (including any code using TLV or static 
-   /// destructors) can reference the runtime symbols. This is usually achieved 
-   /// by linking any JITDylibs containing regular code against 
-   /// PlatformJD. 
-   /// 
-   /// By default, ELFNixPlatform will add the set of aliases returned by the 
-   /// standardPlatformAliases function. This includes both required aliases 
-   /// (e.g. __cxa_atexit -> __orc_rt_elf_cxa_atexit for static destructor 
-   /// support), and optional aliases that provide JIT versions of common 
-   /// functions (e.g. dlopen -> __orc_rt_elf_jit_dlopen). Clients can 
-   /// override these defaults by passing a non-None value for the 
-   /// RuntimeAliases function, in which case the client is responsible for 
-   /// setting up all aliases (including the required ones). 
-   static Expected<std::unique_ptr<ELFNixPlatform>> 
-   Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 
-          JITDylib &PlatformJD, const char *OrcRuntimePath, 
-          std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt); 
-   
-   ExecutionSession &getExecutionSession() const { return ES; } 
-   ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; } 
-   
-   Error setupJITDylib(JITDylib &JD) override; 
-   Error teardownJITDylib(JITDylib &JD) override; 
-   Error notifyAdding(ResourceTracker &RT, 
-                      const MaterializationUnit &MU) override; 
-   Error notifyRemoving(ResourceTracker &RT) override; 
-   
-   /// Returns an AliasMap containing the default aliases for the ELFNixPlatform. 
-   /// This can be modified by clients when constructing the platform to add 
-   /// or remove aliases. 
-   static Expected<SymbolAliasMap> standardPlatformAliases(ExecutionSession &ES, 
-                                                           JITDylib &PlatformJD); 
-   
-   /// Returns the array of required CXX aliases. 
-   static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases(); 
-   
-   /// Returns the array of standard runtime utility aliases for ELF. 
-   static ArrayRef<std::pair<const char *, const char *>> 
-   standardRuntimeUtilityAliases(); 
-   
-   /// Returns true if the given section name is an initializer section. 
-   static bool isInitializerSection(StringRef SecName); 
-   
- private: 
-   // The ELFNixPlatformPlugin scans/modifies LinkGraphs to support ELF 
-   // platform features including initializers, exceptions, TLV, and language 
-   // runtime registration. 
-   class ELFNixPlatformPlugin : public ObjectLinkingLayer::Plugin { 
-   public: 
-     ELFNixPlatformPlugin(ELFNixPlatform &MP) : MP(MP) {} 
-   
-     void modifyPassConfig(MaterializationResponsibility &MR, 
-                           jitlink::LinkGraph &G, 
-                           jitlink::PassConfiguration &Config) override; 
-   
-     SyntheticSymbolDependenciesMap 
-     getSyntheticSymbolDependencies(MaterializationResponsibility &MR) override; 
-   
-     // FIXME: We should be tentatively tracking scraped sections and discarding 
-     // if the MR fails. 
-     Error notifyFailed(MaterializationResponsibility &MR) override { 
-       return Error::success(); 
-     } 
-   
-     Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override { 
-       return Error::success(); 
-     } 
-   
-     void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, 
-                                      ResourceKey SrcKey) override {} 
-   
-   private: 
-     using InitSymbolDepMap = 
-         DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>; 
-   
-     void addInitializerSupportPasses(MaterializationResponsibility &MR, 
-                                      jitlink::PassConfiguration &Config); 
-   
-     void addDSOHandleSupportPasses(MaterializationResponsibility &MR, 
-                                    jitlink::PassConfiguration &Config); 
-   
-     void addEHAndTLVSupportPasses(MaterializationResponsibility &MR, 
-                                   jitlink::PassConfiguration &Config); 
-   
-     Error preserveInitSections(jitlink::LinkGraph &G, 
-                                MaterializationResponsibility &MR); 
-   
-     Error registerInitSections(jitlink::LinkGraph &G, JITDylib &JD); 
-   
-     Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD); 
-   
-     std::mutex PluginMutex; 
-     ELFNixPlatform &MP; 
-     InitSymbolDepMap InitSymbolDeps; 
-   }; 
-   
-   using SendInitializerSequenceFn = 
-       unique_function<void(Expected<ELFNixJITDylibInitializerSequence>)>; 
-   
-   using SendDeinitializerSequenceFn = 
-       unique_function<void(Expected<ELFNixJITDylibDeinitializerSequence>)>; 
-   
-   using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>; 
-   
-   static bool supportedTarget(const Triple &TT); 
-   
-   ELFNixPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 
-                  JITDylib &PlatformJD, 
-                  std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, 
-                  Error &Err); 
-   
-   // Associate ELFNixPlatform JIT-side runtime support functions with handlers. 
-   Error associateRuntimeSupportFunctions(JITDylib &PlatformJD); 
-   
-   void getInitializersBuildSequencePhase(SendInitializerSequenceFn SendResult, 
-                                          JITDylib &JD, 
-                                          std::vector<JITDylibSP> DFSLinkOrder); 
-   
-   void getInitializersLookupPhase(SendInitializerSequenceFn SendResult, 
-                                   JITDylib &JD); 
-   
-   void rt_getInitializers(SendInitializerSequenceFn SendResult, 
-                           StringRef JDName); 
-   
-   void rt_getDeinitializers(SendDeinitializerSequenceFn SendResult, 
-                             ExecutorAddr Handle); 
-   
-   void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddr Handle, 
-                        StringRef SymbolName); 
-   
-   // Records the addresses of runtime symbols used by the platform. 
-   Error bootstrapELFNixRuntime(JITDylib &PlatformJD); 
-   
-   Error registerInitInfo(JITDylib &JD, 
-                          ArrayRef<jitlink::Section *> InitSections); 
-   
-   Error registerPerObjectSections(const ELFPerObjectSectionsToRegister &POSR); 
-   
-   Expected<uint64_t> createPThreadKey(); 
-   
-   ExecutionSession &ES; 
-   ObjectLinkingLayer &ObjLinkingLayer; 
-   
-   SymbolStringPtr DSOHandleSymbol; 
-   std::atomic<bool> RuntimeBootstrapped{false}; 
-   
-   ExecutorAddr orc_rt_elfnix_platform_bootstrap; 
-   ExecutorAddr orc_rt_elfnix_platform_shutdown; 
-   ExecutorAddr orc_rt_elfnix_register_object_sections; 
-   ExecutorAddr orc_rt_elfnix_create_pthread_key; 
-   
-   DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols; 
-   
-   // InitSeqs gets its own mutex to avoid locking the whole session when 
-   // aggregating data from the jitlink. 
-   std::mutex PlatformMutex; 
-   DenseMap<JITDylib *, ELFNixJITDylibInitializers> InitSeqs; 
-   std::vector<ELFPerObjectSectionsToRegister> BootstrapPOSRs; 
-   
-   DenseMap<ExecutorAddr, JITDylib *> HandleAddrToJITDylib; 
-   DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey; 
- }; 
-   
- namespace shared { 
-   
- using SPSELFPerObjectSectionsToRegister = 
-     SPSTuple<SPSExecutorAddrRange, SPSExecutorAddrRange>; 
-   
- template <> 
- class SPSSerializationTraits<SPSELFPerObjectSectionsToRegister, 
-                              ELFPerObjectSectionsToRegister> { 
-   
- public: 
-   static size_t size(const ELFPerObjectSectionsToRegister &MOPOSR) { 
-     return SPSELFPerObjectSectionsToRegister::AsArgList::size( 
-         MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection); 
-   } 
-   
-   static bool serialize(SPSOutputBuffer &OB, 
-                         const ELFPerObjectSectionsToRegister &MOPOSR) { 
-     return SPSELFPerObjectSectionsToRegister::AsArgList::serialize( 
-         OB, MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection); 
-   } 
-   
-   static bool deserialize(SPSInputBuffer &IB, 
-                           ELFPerObjectSectionsToRegister &MOPOSR) { 
-     return SPSELFPerObjectSectionsToRegister::AsArgList::deserialize( 
-         IB, MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection); 
-   } 
- }; 
-   
- using SPSNamedExecutorAddrRangeSequenceMap = 
-     SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRangeSequence>>; 
-   
- using SPSELFNixJITDylibInitializers = 
-     SPSTuple<SPSString, SPSExecutorAddr, SPSNamedExecutorAddrRangeSequenceMap>; 
-   
- using SPSELFNixJITDylibInitializerSequence = 
-     SPSSequence<SPSELFNixJITDylibInitializers>; 
-   
- /// Serialization traits for ELFNixJITDylibInitializers. 
- template <> 
- class SPSSerializationTraits<SPSELFNixJITDylibInitializers, 
-                              ELFNixJITDylibInitializers> { 
- public: 
-   static size_t size(const ELFNixJITDylibInitializers &MOJDIs) { 
-     return SPSELFNixJITDylibInitializers::AsArgList::size( 
-         MOJDIs.Name, MOJDIs.DSOHandleAddress, MOJDIs.InitSections); 
-   } 
-   
-   static bool serialize(SPSOutputBuffer &OB, 
-                         const ELFNixJITDylibInitializers &MOJDIs) { 
-     return SPSELFNixJITDylibInitializers::AsArgList::serialize( 
-         OB, MOJDIs.Name, MOJDIs.DSOHandleAddress, MOJDIs.InitSections); 
-   } 
-   
-   static bool deserialize(SPSInputBuffer &IB, 
-                           ELFNixJITDylibInitializers &MOJDIs) { 
-     return SPSELFNixJITDylibInitializers::AsArgList::deserialize( 
-         IB, MOJDIs.Name, MOJDIs.DSOHandleAddress, MOJDIs.InitSections); 
-   } 
- }; 
-   
- using SPSELFJITDylibDeinitializers = SPSEmpty; 
-   
- using SPSELFJITDylibDeinitializerSequence = 
-     SPSSequence<SPSELFJITDylibDeinitializers>; 
-   
- template <> 
- class SPSSerializationTraits<SPSELFJITDylibDeinitializers, 
-                              ELFNixJITDylibDeinitializers> { 
- public: 
-   static size_t size(const ELFNixJITDylibDeinitializers &MOJDDs) { return 0; } 
-   
-   static bool serialize(SPSOutputBuffer &OB, 
-                         const ELFNixJITDylibDeinitializers &MOJDDs) { 
-     return true; 
-   } 
-   
-   static bool deserialize(SPSInputBuffer &IB, 
-                           ELFNixJITDylibDeinitializers &MOJDDs) { 
-     MOJDDs = ELFNixJITDylibDeinitializers(); 
-     return true; 
-   } 
- }; 
-   
- } // end namespace shared 
- } // end namespace orc 
- } // end namespace llvm 
-   
- #endif // LLVM_EXECUTIONENGINE_ORC_ELFNIXPLATFORM_H 
-