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;
SectionExtentSectionExtent36     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 
setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr)44   void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) {
45     this->ObjCImageInfoAddr = ObjCImageInfoAddr;
46   }
47 
addModInitsSection(SectionExtent ModInit)48   void addModInitsSection(SectionExtent ModInit) {
49     ModInitSections.push_back(std::move(ModInit));
50   }
51 
getModInitsSections()52   const RawPointerSectionList &getModInitsSections() const {
53     return ModInitSections;
54   }
55 
addObjCSelRefsSection(SectionExtent ObjCSelRefs)56   void addObjCSelRefsSection(SectionExtent ObjCSelRefs) {
57     ObjCSelRefsSections.push_back(std::move(ObjCSelRefs));
58   }
59 
getObjCSelRefsSections()60   const RawPointerSectionList &getObjCSelRefsSections() const {
61     return ObjCSelRefsSections;
62   }
63 
addObjCClassListSection(SectionExtent ObjCClassList)64   void addObjCClassListSection(SectionExtent ObjCClassList) {
65     ObjCClassListSections.push_back(std::move(ObjCClassList));
66   }
67 
getObjCClassListSections()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 
getExecutionSession()98   ExecutionSession &getExecutionSession() const { return ES; }
99 
100   Error setupJITDylib(JITDylib &JD) override;
101   Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) override;
102   Error notifyRemoving(JITDylib &JD, VModuleKey K) override;
103 
104   Expected<InitializerSequence> getInitializerSequence(JITDylib &JD);
105 
106   Expected<DeinitializerSequence> getDeinitializerSequence(JITDylib &JD);
107 
108 private:
109   // This ObjectLinkingLayer plugin scans JITLink graphs for __mod_init_func,
110   // __objc_classlist and __sel_ref sections and records their extents so that
111   // they can be run in the target process.
112   class InitScraperPlugin : public ObjectLinkingLayer::Plugin {
113   public:
InitScraperPlugin(MachOPlatform & MP)114     InitScraperPlugin(MachOPlatform &MP) : MP(MP) {}
115 
116     void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
117                           jitlink::PassConfiguration &Config) override;
118 
119     LocalDependenciesMap getSyntheticSymbolLocalDependencies(
120         MaterializationResponsibility &MR) override;
121 
122   private:
123     using InitSymbolDepMap =
124         DenseMap<MaterializationResponsibility *, JITLinkSymbolVector>;
125 
126     void preserveInitSectionIfPresent(JITLinkSymbolVector &Syms,
127                                       jitlink::LinkGraph &G,
128                                       StringRef SectionName);
129 
130     Error processObjCImageInfo(jitlink::LinkGraph &G,
131                                MaterializationResponsibility &MR);
132 
133     std::mutex InitScraperMutex;
134     MachOPlatform &MP;
135     DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
136     InitSymbolDepMap InitSymbolDeps;
137   };
138 
139   static std::vector<JITDylib *> getDFSLinkOrder(JITDylib &JD);
140 
141   void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr,
142                         MachOJITDylibInitializers::SectionExtent ModInits,
143                         MachOJITDylibInitializers::SectionExtent ObjCSelRefs,
144                         MachOJITDylibInitializers::SectionExtent ObjCClassList);
145 
146   ExecutionSession &ES;
147   ObjectLinkingLayer &ObjLinkingLayer;
148   std::unique_ptr<MemoryBuffer> StandardSymbolsObject;
149 
150   DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
151 
152   // InitSeqs gets its own mutex to avoid locking the whole session when
153   // aggregating data from the jitlink.
154   std::mutex InitSeqsMutex;
155   DenseMap<JITDylib *, MachOJITDylibInitializers> InitSeqs;
156 };
157 
158 } // end namespace orc
159 } // end namespace llvm
160 
161 #endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
162