Home | History | Annotate | Line # | Download | only in Orc
      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/ExecutionUtils.h"
     19 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
     20 
     21 #include <future>
     22 #include <thread>
     23 #include <vector>
     24 
     25 namespace llvm {
     26 namespace orc {
     27 
     28 /// Enable registration of JIT'd ObjC classes and selectors.
     29 Error enableObjCRegistration(const char *PathToLibObjC);
     30 bool objCRegistrationEnabled();
     31 
     32 class MachOJITDylibInitializers {
     33 public:
     34   struct SectionExtent {
     35     SectionExtent() = default;
     36     SectionExtent(JITTargetAddress Address, uint64_t NumPtrs)
     37         : Address(Address), NumPtrs(NumPtrs) {}
     38     JITTargetAddress Address = 0;
     39     uint64_t NumPtrs = 0;
     40   };
     41 
     42   using RawPointerSectionList = std::vector<SectionExtent>;
     43 
     44   void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) {
     45     this->ObjCImageInfoAddr = ObjCImageInfoAddr;
     46   }
     47 
     48   void addModInitsSection(SectionExtent ModInit) {
     49     ModInitSections.push_back(std::move(ModInit));
     50   }
     51 
     52   const RawPointerSectionList &getModInitsSections() const {
     53     return ModInitSections;
     54   }
     55 
     56   void addObjCSelRefsSection(SectionExtent ObjCSelRefs) {
     57     ObjCSelRefsSections.push_back(std::move(ObjCSelRefs));
     58   }
     59 
     60   const RawPointerSectionList &getObjCSelRefsSections() const {
     61     return ObjCSelRefsSections;
     62   }
     63 
     64   void addObjCClassListSection(SectionExtent ObjCClassList) {
     65     ObjCClassListSections.push_back(std::move(ObjCClassList));
     66   }
     67 
     68   const RawPointerSectionList &getObjCClassListSections() const {
     69     return ObjCClassListSections;
     70   }
     71 
     72   void runModInits() const;
     73   void registerObjCSelectors() const;
     74   Error registerObjCClasses() const;
     75 
     76 private:
     77 
     78   JITTargetAddress ObjCImageInfoAddr;
     79   RawPointerSectionList ModInitSections;
     80   RawPointerSectionList ObjCSelRefsSections;
     81   RawPointerSectionList ObjCClassListSections;
     82 };
     83 
     84 class MachOJITDylibDeinitializers {};
     85 
     86 /// Mediates between MachO initialization and ExecutionSession state.
     87 class MachOPlatform : public Platform {
     88 public:
     89   using InitializerSequence =
     90       std::vector<std::pair<JITDylib *, MachOJITDylibInitializers>>;
     91 
     92   using DeinitializerSequence =
     93       std::vector<std::pair<JITDylib *, MachOJITDylibDeinitializers>>;
     94 
     95   MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
     96                 std::unique_ptr<MemoryBuffer> StandardSymbolsObject);
     97 
     98   ExecutionSession &getExecutionSession() const { return ES; }
     99 
    100   Error setupJITDylib(JITDylib &JD) override;
    101   Error notifyAdding(ResourceTracker &RT,
    102                      const MaterializationUnit &MU) override;
    103   Error notifyRemoving(ResourceTracker &RT) override;
    104 
    105   Expected<InitializerSequence> getInitializerSequence(JITDylib &JD);
    106 
    107   Expected<DeinitializerSequence> getDeinitializerSequence(JITDylib &JD);
    108 
    109 private:
    110   // This ObjectLinkingLayer plugin scans JITLink graphs for __mod_init_func,
    111   // __objc_classlist and __sel_ref sections and records their extents so that
    112   // they can be run in the target process.
    113   class InitScraperPlugin : public ObjectLinkingLayer::Plugin {
    114   public:
    115     InitScraperPlugin(MachOPlatform &MP) : MP(MP) {}
    116 
    117     void modifyPassConfig(MaterializationResponsibility &MR,
    118                           jitlink::LinkGraph &G,
    119                           jitlink::PassConfiguration &Config) override;
    120 
    121     LocalDependenciesMap getSyntheticSymbolLocalDependencies(
    122         MaterializationResponsibility &MR) override;
    123 
    124     // FIXME: We should be tentatively tracking scraped sections and discarding
    125     // if the MR fails.
    126     Error notifyFailed(MaterializationResponsibility &MR) override {
    127       return Error::success();
    128     }
    129 
    130     Error notifyRemovingResources(ResourceKey K) override {
    131       return Error::success();
    132     }
    133 
    134     void notifyTransferringResources(ResourceKey DstKey,
    135                                      ResourceKey SrcKey) override {}
    136 
    137   private:
    138     using InitSymbolDepMap =
    139         DenseMap<MaterializationResponsibility *, JITLinkSymbolVector>;
    140 
    141     void preserveInitSectionIfPresent(JITLinkSymbolVector &Syms,
    142                                       jitlink::LinkGraph &G,
    143                                       StringRef SectionName);
    144 
    145     Error processObjCImageInfo(jitlink::LinkGraph &G,
    146                                MaterializationResponsibility &MR);
    147 
    148     std::mutex InitScraperMutex;
    149     MachOPlatform &MP;
    150     DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
    151     InitSymbolDepMap InitSymbolDeps;
    152   };
    153 
    154   void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr,
    155                         MachOJITDylibInitializers::SectionExtent ModInits,
    156                         MachOJITDylibInitializers::SectionExtent ObjCSelRefs,
    157                         MachOJITDylibInitializers::SectionExtent ObjCClassList);
    158 
    159   ExecutionSession &ES;
    160   ObjectLinkingLayer &ObjLinkingLayer;
    161   std::unique_ptr<MemoryBuffer> StandardSymbolsObject;
    162 
    163   DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
    164 
    165   // InitSeqs gets its own mutex to avoid locking the whole session when
    166   // aggregating data from the jitlink.
    167   std::mutex InitSeqsMutex;
    168   DenseMap<JITDylib *, MachOJITDylibInitializers> InitSeqs;
    169 };
    170 
    171 } // end namespace orc
    172 } // end namespace llvm
    173 
    174 #endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
    175