Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  333.